Annotation of elwix/files/sqlite/dist/shell.c, revision 1.6.2.1
1.5 misho 1: /* DO NOT EDIT!
2: ** This file is automatically generated by the script in the canonical
3: ** SQLite source tree at tool/mkshellc.tcl. That script combines source
4: ** code from various constituent source files of SQLite into this single
5: ** "shell.c" file used to implement the SQLite command-line shell.
6: **
7: ** Most of the code found below comes from the "src/shell.c.in" file in
8: ** the canonical SQLite source tree. That main file contains "INCLUDE"
9: ** lines that specify other files in the canonical source tree that are
10: ** inserted to getnerate this complete program source file.
11: **
12: ** The code from multiple files is combined into this single "shell.c"
13: ** source file to help make the command-line program easier to compile.
14: **
15: ** To modify this program, get a copy of the canonical SQLite source tree,
16: ** edit the src/shell.c.in" and/or some of the other files that are included
17: ** by "src/shell.c.in", then rerun the tool/mkshellc.tcl script.
18: */
1.2 misho 19: /*
20: ** 2001 September 15
21: **
22: ** The author disclaims copyright to this source code. In place of
23: ** a legal notice, here is a blessing:
24: **
25: ** May you do good and not evil.
26: ** May you find forgiveness for yourself and forgive others.
27: ** May you share freely, never taking more than you give.
28: **
29: *************************************************************************
30: ** This file contains code to implement the "sqlite" command line
31: ** utility for accessing SQLite databases.
32: */
33: #if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
34: /* This needs to come before any includes for MSVC compiler */
35: #define _CRT_SECURE_NO_WARNINGS
36: #endif
1.6.2.1 ! misho 37: typedef unsigned int u32;
! 38: typedef unsigned short int u16;
! 39:
! 40: /*
! 41: ** Optionally #include a user-defined header, whereby compilation options
! 42: ** may be set prior to where they take effect, but after platform setup.
! 43: ** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include
! 44: ** file. Note that this macro has a like effect on sqlite3.c compilation.
! 45: */
! 46: # define SHELL_STRINGIFY_(f) #f
! 47: # define SHELL_STRINGIFY(f) SHELL_STRINGIFY_(f)
! 48: #ifdef SQLITE_CUSTOM_INCLUDE
! 49: # include SHELL_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
! 50: #endif
1.2 misho 51:
52: /*
1.5 misho 53: ** Determine if we are dealing with WinRT, which provides only a subset of
54: ** the full Win32 API.
1.4 misho 55: */
1.5 misho 56: #if !defined(SQLITE_OS_WINRT)
57: # define SQLITE_OS_WINRT 0
1.4 misho 58: #endif
59:
60: /*
1.6.2.1 ! misho 61: ** If SQLITE_SHELL_FIDDLE is defined then the shell is modified
! 62: ** somewhat for use as a WASM module in a web browser. This flag
! 63: ** should only be used when building the "fiddle" web application, as
! 64: ** the browser-mode build has much different user input requirements
! 65: ** and this build mode rewires the user input subsystem to account for
! 66: ** that.
! 67: */
! 68:
! 69: /*
1.5 misho 70: ** Warning pragmas copied from msvc.h in the core.
71: */
72: #if defined(_MSC_VER)
73: #pragma warning(disable : 4054)
74: #pragma warning(disable : 4055)
75: #pragma warning(disable : 4100)
76: #pragma warning(disable : 4127)
77: #pragma warning(disable : 4130)
78: #pragma warning(disable : 4152)
79: #pragma warning(disable : 4189)
80: #pragma warning(disable : 4206)
81: #pragma warning(disable : 4210)
82: #pragma warning(disable : 4232)
83: #pragma warning(disable : 4244)
84: #pragma warning(disable : 4305)
85: #pragma warning(disable : 4306)
86: #pragma warning(disable : 4702)
87: #pragma warning(disable : 4706)
88: #endif /* defined(_MSC_VER) */
89:
90: /*
1.4 misho 91: ** No support for loadable extensions in VxWorks.
92: */
93: #if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION
94: # define SQLITE_OMIT_LOAD_EXTENSION 1
95: #endif
96:
97: /*
1.2 misho 98: ** Enable large-file support for fopen() and friends on unix.
99: */
100: #ifndef SQLITE_DISABLE_LFS
101: # define _LARGE_FILE 1
102: # ifndef _FILE_OFFSET_BITS
103: # define _FILE_OFFSET_BITS 64
104: # endif
105: # define _LARGEFILE_SOURCE 1
106: #endif
107:
1.6.2.1 ! misho 108: #if defined(SQLITE_SHELL_FIDDLE) && !defined(_POSIX_SOURCE)
! 109: /*
! 110: ** emcc requires _POSIX_SOURCE (or one of several similar defines)
! 111: ** to expose strdup().
! 112: */
! 113: # define _POSIX_SOURCE
! 114: #endif
! 115:
1.2 misho 116: #include <stdlib.h>
117: #include <string.h>
118: #include <stdio.h>
119: #include <assert.h>
1.6.2.1 ! misho 120: #include <math.h>
1.2 misho 121: #include "sqlite3.h"
1.5 misho 122: typedef sqlite3_int64 i64;
123: typedef sqlite3_uint64 u64;
124: typedef unsigned char u8;
1.4 misho 125: #if SQLITE_USER_AUTHENTICATION
126: # include "sqlite3userauth.h"
127: #endif
1.2 misho 128: #include <ctype.h>
129: #include <stdarg.h>
130:
1.3 misho 131: #if !defined(_WIN32) && !defined(WIN32)
1.2 misho 132: # include <signal.h>
1.6.2.1 ! misho 133: # if !defined(__RTP__) && !defined(_WRS_KERNEL) && !defined(SQLITE_WASI)
1.2 misho 134: # include <pwd.h>
135: # endif
1.5 misho 136: #endif
137: #if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__)
1.2 misho 138: # include <unistd.h>
1.5 misho 139: # include <dirent.h>
140: # define GETPID getpid
141: # if defined(__MINGW32__)
142: # define DIRENT dirent
143: # ifndef S_ISLNK
144: # define S_ISLNK(mode) (0)
145: # endif
146: # endif
147: #else
148: # define GETPID (int)GetCurrentProcessId
1.2 misho 149: #endif
1.5 misho 150: #include <sys/types.h>
151: #include <sys/stat.h>
1.2 misho 152:
1.4 misho 153: #if HAVE_READLINE
1.2 misho 154: # include <readline/readline.h>
155: # include <readline/history.h>
156: #endif
1.4 misho 157:
158: #if HAVE_EDITLINE
159: # include <editline/readline.h>
160: #endif
161:
162: #if HAVE_EDITLINE || HAVE_READLINE
163:
164: # define shell_add_history(X) add_history(X)
165: # define shell_read_history(X) read_history(X)
166: # define shell_write_history(X) write_history(X)
167: # define shell_stifle_history(X) stifle_history(X)
168: # define shell_readline(X) readline(X)
169:
170: #elif HAVE_LINENOISE
171:
172: # include "linenoise.h"
173: # define shell_add_history(X) linenoiseHistoryAdd(X)
174: # define shell_read_history(X) linenoiseHistoryLoad(X)
175: # define shell_write_history(X) linenoiseHistorySave(X)
176: # define shell_stifle_history(X) linenoiseHistorySetMaxLen(X)
177: # define shell_readline(X) linenoise(X)
178:
179: #else
180:
181: # define shell_read_history(X)
182: # define shell_write_history(X)
183: # define shell_stifle_history(X)
184:
185: # define SHELL_USE_LOCAL_GETLINE 1
1.2 misho 186: #endif
187:
1.6.2.1 ! misho 188: #ifndef deliberate_fall_through
! 189: /* Quiet some compilers about some of our intentional code. */
! 190: # if defined(GCC_VERSION) && GCC_VERSION>=7000000
! 191: # define deliberate_fall_through __attribute__((fallthrough));
! 192: # else
! 193: # define deliberate_fall_through
! 194: # endif
! 195: #endif
1.4 misho 196:
1.2 misho 197: #if defined(_WIN32) || defined(WIN32)
1.5 misho 198: # if SQLITE_OS_WINRT
199: # define SQLITE_OMIT_POPEN 1
200: # else
201: # include <io.h>
202: # include <fcntl.h>
203: # define isatty(h) _isatty(h)
204: # ifndef access
205: # define access(f,m) _access((f),(m))
206: # endif
207: # ifndef unlink
208: # define unlink _unlink
209: # endif
210: # ifndef strdup
211: # define strdup _strdup
212: # endif
213: # undef popen
214: # define popen _popen
215: # undef pclose
216: # define pclose _pclose
1.4 misho 217: # endif
1.2 misho 218: #else
1.4 misho 219: /* Make sure isatty() has a prototype. */
220: extern int isatty(int);
221:
1.6.2.1 ! misho 222: # if !defined(__RTP__) && !defined(_WRS_KERNEL) && !defined(SQLITE_WASI)
1.4 misho 223: /* popen and pclose are not C89 functions and so are
224: ** sometimes omitted from the <stdio.h> header */
225: extern FILE *popen(const char*,const char*);
226: extern int pclose(FILE*);
227: # else
228: # define SQLITE_OMIT_POPEN 1
229: # endif
1.2 misho 230: #endif
231:
232: #if defined(_WIN32_WCE)
233: /* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty()
234: * thus we always assume that we have a console. That can be
235: * overridden with the -batch command line option.
236: */
237: #define isatty(x) 1
238: #endif
239:
240: /* ctype macros that work with signed characters */
241: #define IsSpace(X) isspace((unsigned char)X)
242: #define IsDigit(X) isdigit((unsigned char)X)
243: #define ToLower(X) (char)tolower((unsigned char)X)
244:
1.4 misho 245: #if defined(_WIN32) || defined(WIN32)
1.5 misho 246: #if SQLITE_OS_WINRT
247: #include <intrin.h>
248: #endif
1.6.2.1 ! misho 249: #undef WIN32_LEAN_AND_MEAN
! 250: #define WIN32_LEAN_AND_MEAN
1.4 misho 251: #include <windows.h>
252:
253: /* string conversion routines only needed on Win32 */
254: extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
255: extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int);
256: extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int);
1.5 misho 257: extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
1.4 misho 258: #endif
259:
260: /* On Windows, we normally run with output mode of TEXT so that \n characters
261: ** are automatically translated into \r\n. However, this behavior needs
262: ** to be disabled in some cases (ex: when generating CSV output and when
263: ** rendering quoted strings that contain \n characters). The following
264: ** routines take care of that.
265: */
1.5 misho 266: #if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
1.4 misho 267: static void setBinaryMode(FILE *file, int isOutput){
268: if( isOutput ) fflush(file);
269: _setmode(_fileno(file), _O_BINARY);
270: }
271: static void setTextMode(FILE *file, int isOutput){
272: if( isOutput ) fflush(file);
273: _setmode(_fileno(file), _O_TEXT);
274: }
275: #else
276: # define setBinaryMode(X,Y)
277: # define setTextMode(X,Y)
278: #endif
279:
280: /* True if the timer is enabled */
281: static int enableTimer = 0;
282:
1.6.2.1 ! misho 283: /* A version of strcmp() that works with NULL values */
! 284: static int cli_strcmp(const char *a, const char *b){
! 285: if( a==0 ) a = "";
! 286: if( b==0 ) b = "";
! 287: return strcmp(a,b);
! 288: }
! 289: static int cli_strncmp(const char *a, const char *b, size_t n){
! 290: if( a==0 ) a = "";
! 291: if( b==0 ) b = "";
! 292: return strncmp(a,b,n);
! 293: }
! 294:
1.4 misho 295: /* Return the current wall-clock time */
296: static sqlite3_int64 timeOfDay(void){
297: static sqlite3_vfs *clockVfs = 0;
298: sqlite3_int64 t;
299: if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
1.6.2.1 ! misho 300: if( clockVfs==0 ) return 0; /* Never actually happens */
1.4 misho 301: if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
302: clockVfs->xCurrentTimeInt64(clockVfs, &t);
303: }else{
304: double r;
305: clockVfs->xCurrentTime(clockVfs, &r);
306: t = (sqlite3_int64)(r*86400000.0);
307: }
308: return t;
309: }
310:
311: #if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
1.2 misho 312: #include <sys/time.h>
313: #include <sys/resource.h>
314:
1.4 misho 315: /* VxWorks does not support getrusage() as far as we can determine */
316: #if defined(_WRS_KERNEL) || defined(__RTP__)
317: struct rusage {
318: struct timeval ru_utime; /* user CPU time used */
319: struct timeval ru_stime; /* system CPU time used */
320: };
321: #define getrusage(A,B) memset(B,0,sizeof(*B))
322: #endif
323:
1.2 misho 324: /* Saved resource information for the beginning of an operation */
1.4 misho 325: static struct rusage sBegin; /* CPU time at start */
326: static sqlite3_int64 iBegin; /* Wall-clock time at start */
1.2 misho 327:
328: /*
329: ** Begin timing an operation
330: */
331: static void beginTimer(void){
332: if( enableTimer ){
333: getrusage(RUSAGE_SELF, &sBegin);
1.4 misho 334: iBegin = timeOfDay();
1.2 misho 335: }
336: }
337:
338: /* Return the difference of two time_structs in seconds */
339: static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
1.4 misho 340: return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
1.2 misho 341: (double)(pEnd->tv_sec - pStart->tv_sec);
342: }
343:
344: /*
345: ** Print the timing results.
346: */
347: static void endTimer(void){
348: if( enableTimer ){
1.4 misho 349: sqlite3_int64 iEnd = timeOfDay();
1.2 misho 350: struct rusage sEnd;
351: getrusage(RUSAGE_SELF, &sEnd);
1.4 misho 352: printf("Run Time: real %.3f user %f sys %f\n",
353: (iEnd - iBegin)*0.001,
1.2 misho 354: timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
355: timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
356: }
357: }
358:
359: #define BEGIN_TIMER beginTimer()
360: #define END_TIMER endTimer()
361: #define HAS_TIMER 1
362:
363: #elif (defined(_WIN32) || defined(WIN32))
364:
365: /* Saved resource information for the beginning of an operation */
366: static HANDLE hProcess;
367: static FILETIME ftKernelBegin;
368: static FILETIME ftUserBegin;
1.4 misho 369: static sqlite3_int64 ftWallBegin;
370: typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
371: LPFILETIME, LPFILETIME);
1.2 misho 372: static GETPROCTIMES getProcessTimesAddr = NULL;
373:
374: /*
375: ** Check to see if we have timer support. Return 1 if necessary
376: ** support found (or found previously).
377: */
378: static int hasTimer(void){
379: if( getProcessTimesAddr ){
380: return 1;
381: } else {
1.5 misho 382: #if !SQLITE_OS_WINRT
1.4 misho 383: /* GetProcessTimes() isn't supported in WIN95 and some other Windows
384: ** versions. See if the version we are running on has it, and if it
385: ** does, save off a pointer to it and the current process handle.
1.2 misho 386: */
387: hProcess = GetCurrentProcess();
388: if( hProcess ){
389: HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
390: if( NULL != hinstLib ){
1.4 misho 391: getProcessTimesAddr =
392: (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
1.2 misho 393: if( NULL != getProcessTimesAddr ){
394: return 1;
395: }
1.4 misho 396: FreeLibrary(hinstLib);
1.2 misho 397: }
398: }
1.5 misho 399: #endif
1.2 misho 400: }
401: return 0;
402: }
403:
404: /*
405: ** Begin timing an operation
406: */
407: static void beginTimer(void){
408: if( enableTimer && getProcessTimesAddr ){
409: FILETIME ftCreation, ftExit;
1.4 misho 410: getProcessTimesAddr(hProcess,&ftCreation,&ftExit,
411: &ftKernelBegin,&ftUserBegin);
412: ftWallBegin = timeOfDay();
1.2 misho 413: }
414: }
415:
416: /* Return the difference of two FILETIME structs in seconds */
417: static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
418: sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
419: sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
420: return (double) ((i64End - i64Start) / 10000000.0);
421: }
422:
423: /*
424: ** Print the timing results.
425: */
426: static void endTimer(void){
427: if( enableTimer && getProcessTimesAddr){
428: FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
1.4 misho 429: sqlite3_int64 ftWallEnd = timeOfDay();
430: getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
431: printf("Run Time: real %.3f user %f sys %f\n",
432: (ftWallEnd - ftWallBegin)*0.001,
1.2 misho 433: timeDiff(&ftUserBegin, &ftUserEnd),
434: timeDiff(&ftKernelBegin, &ftKernelEnd));
435: }
436: }
437:
438: #define BEGIN_TIMER beginTimer()
439: #define END_TIMER endTimer()
440: #define HAS_TIMER hasTimer()
441:
442: #else
1.4 misho 443: #define BEGIN_TIMER
1.2 misho 444: #define END_TIMER
445: #define HAS_TIMER 0
446: #endif
447:
448: /*
449: ** Used to prevent warnings about unused parameters
450: */
451: #define UNUSED_PARAMETER(x) (void)(x)
452:
453: /*
1.5 misho 454: ** Number of elements in an array
455: */
456: #define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
457:
458: /*
1.2 misho 459: ** If the following flag is set, then command execution stops
460: ** at an error if we are not interactive.
461: */
462: static int bail_on_error = 0;
463:
464: /*
1.6.2.1 ! misho 465: ** Treat stdin as an interactive input if the following variable
1.2 misho 466: ** is true. Otherwise, assume stdin is connected to a file or pipe.
467: */
468: static int stdin_is_interactive = 1;
469:
1.6.2.1 ! misho 470: #if (defined(_WIN32) || defined(WIN32)) && SHELL_USE_LOCAL_GETLINE \
! 471: && !defined(SHELL_OMIT_WIN_UTF8)
! 472: # define SHELL_WIN_UTF8_OPT 1
! 473: #else
! 474: # define SHELL_WIN_UTF8_OPT 0
! 475: #endif
! 476:
! 477: #if SHELL_WIN_UTF8_OPT
! 478: /*
! 479: ** Setup console for UTF-8 input/output when following variable true.
! 480: */
! 481: static int console_utf8 = 0;
! 482: #endif
! 483:
1.2 misho 484: /*
1.4 misho 485: ** On Windows systems we have to know if standard output is a console
486: ** in order to translate UTF-8 into MBCS. The following variable is
487: ** true if translation is required.
488: */
489: static int stdout_is_console = 1;
490:
491: /*
1.2 misho 492: ** The following is the open SQLite database. We make a pointer
493: ** to this database a static variable so that it can be accessed
494: ** by the SIGINT handler to interrupt database processing.
495: */
1.4 misho 496: static sqlite3 *globalDb = 0;
1.2 misho 497:
498: /*
499: ** True if an interrupt (Control-C) has been received.
500: */
501: static volatile int seenInterrupt = 0;
502:
503: /*
504: ** This is the name of our program. It is set in main(), used
505: ** in a number of other places, mostly for error messages.
506: */
507: static char *Argv0;
508:
509: /*
510: ** Prompt strings. Initialized in main. Settable with
511: ** .prompt main continue
512: */
1.6.2.1 ! misho 513: #define PROMPT_LEN_MAX 20
! 514: /* First line prompt. default: "sqlite> " */
! 515: static char mainPrompt[PROMPT_LEN_MAX];
! 516: /* Continuation prompt. default: " ...> " */
! 517: static char continuePrompt[PROMPT_LEN_MAX];
! 518:
! 519: /* This is variant of the standard-library strncpy() routine with the
! 520: ** one change that the destination string is always zero-terminated, even
! 521: ** if there is no zero-terminator in the first n-1 characters of the source
! 522: ** string.
! 523: */
! 524: static char *shell_strncpy(char *dest, const char *src, size_t n){
! 525: size_t i;
! 526: for(i=0; i<n-1 && src[i]!=0; i++) dest[i] = src[i];
! 527: dest[i] = 0;
! 528: return dest;
! 529: }
! 530:
! 531: /*
! 532: ** Optionally disable dynamic continuation prompt.
! 533: ** Unless disabled, the continuation prompt shows open SQL lexemes if any,
! 534: ** or open parentheses level if non-zero, or continuation prompt as set.
! 535: ** This facility interacts with the scanner and process_input() where the
! 536: ** below 5 macros are used.
! 537: */
! 538: #ifdef SQLITE_OMIT_DYNAPROMPT
! 539: # define CONTINUATION_PROMPT continuePrompt
! 540: # define CONTINUE_PROMPT_RESET
! 541: # define CONTINUE_PROMPT_AWAITS(p,s)
! 542: # define CONTINUE_PROMPT_AWAITC(p,c)
! 543: # define CONTINUE_PAREN_INCR(p,n)
! 544: # define CONTINUE_PROMPT_PSTATE 0
! 545: typedef void *t_NoDynaPrompt;
! 546: # define SCAN_TRACKER_REFTYPE t_NoDynaPrompt
! 547: #else
! 548: # define CONTINUATION_PROMPT dynamicContinuePrompt()
! 549: # define CONTINUE_PROMPT_RESET \
! 550: do {setLexemeOpen(&dynPrompt,0,0); trackParenLevel(&dynPrompt,0);} while(0)
! 551: # define CONTINUE_PROMPT_AWAITS(p,s) \
! 552: if(p && stdin_is_interactive) setLexemeOpen(p, s, 0)
! 553: # define CONTINUE_PROMPT_AWAITC(p,c) \
! 554: if(p && stdin_is_interactive) setLexemeOpen(p, 0, c)
! 555: # define CONTINUE_PAREN_INCR(p,n) \
! 556: if(p && stdin_is_interactive) (trackParenLevel(p,n))
! 557: # define CONTINUE_PROMPT_PSTATE (&dynPrompt)
! 558: typedef struct DynaPrompt *t_DynaPromptRef;
! 559: # define SCAN_TRACKER_REFTYPE t_DynaPromptRef
! 560:
! 561: static struct DynaPrompt {
! 562: char dynamicPrompt[PROMPT_LEN_MAX];
! 563: char acAwait[2];
! 564: int inParenLevel;
! 565: char *zScannerAwaits;
! 566: } dynPrompt = { {0}, {0}, 0, 0 };
! 567:
! 568: /* Record parenthesis nesting level change, or force level to 0. */
! 569: static void trackParenLevel(struct DynaPrompt *p, int ni){
! 570: p->inParenLevel += ni;
! 571: if( ni==0 ) p->inParenLevel = 0;
! 572: p->zScannerAwaits = 0;
! 573: }
! 574:
! 575: /* Record that a lexeme is opened, or closed with args==0. */
! 576: static void setLexemeOpen(struct DynaPrompt *p, char *s, char c){
! 577: if( s!=0 || c==0 ){
! 578: p->zScannerAwaits = s;
! 579: p->acAwait[0] = 0;
! 580: }else{
! 581: p->acAwait[0] = c;
! 582: p->zScannerAwaits = p->acAwait;
! 583: }
! 584: }
! 585:
! 586: /* Upon demand, derive the continuation prompt to display. */
! 587: static char *dynamicContinuePrompt(void){
! 588: if( continuePrompt[0]==0
! 589: || (dynPrompt.zScannerAwaits==0 && dynPrompt.inParenLevel == 0) ){
! 590: return continuePrompt;
! 591: }else{
! 592: if( dynPrompt.zScannerAwaits ){
! 593: size_t ncp = strlen(continuePrompt);
! 594: size_t ndp = strlen(dynPrompt.zScannerAwaits);
! 595: if( ndp > ncp-3 ) return continuePrompt;
! 596: strcpy(dynPrompt.dynamicPrompt, dynPrompt.zScannerAwaits);
! 597: while( ndp<3 ) dynPrompt.dynamicPrompt[ndp++] = ' ';
! 598: shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3,
! 599: PROMPT_LEN_MAX-4);
! 600: }else{
! 601: if( dynPrompt.inParenLevel>9 ){
! 602: shell_strncpy(dynPrompt.dynamicPrompt, "(..", 4);
! 603: }else if( dynPrompt.inParenLevel<0 ){
! 604: shell_strncpy(dynPrompt.dynamicPrompt, ")x!", 4);
! 605: }else{
! 606: shell_strncpy(dynPrompt.dynamicPrompt, "(x.", 4);
! 607: dynPrompt.dynamicPrompt[2] = (char)('0'+dynPrompt.inParenLevel);
! 608: }
! 609: shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3, PROMPT_LEN_MAX-4);
! 610: }
! 611: }
! 612: return dynPrompt.dynamicPrompt;
! 613: }
! 614: #endif /* !defined(SQLITE_OMIT_DYNAPROMPT) */
! 615:
! 616: #if SHELL_WIN_UTF8_OPT
! 617: /* Following struct is used for -utf8 operation. */
! 618: static struct ConsoleState {
! 619: int stdinEof; /* EOF has been seen on console input */
! 620: int infsMode; /* Input file stream mode upon shell start */
! 621: UINT inCodePage; /* Input code page upon shell start */
! 622: UINT outCodePage; /* Output code page upon shell start */
! 623: HANDLE hConsoleIn; /* Console input handle */
! 624: DWORD consoleMode; /* Console mode upon shell start */
! 625: } conState = { 0, 0, 0, 0, INVALID_HANDLE_VALUE, 0 };
! 626:
! 627: #ifndef _O_U16TEXT /* For build environments lacking this constant: */
! 628: # define _O_U16TEXT 0x20000
! 629: #endif
! 630:
! 631: /*
! 632: ** Prepare console, (if known to be a WIN32 console), for UTF-8
! 633: ** input (from either typing or suitable paste operations) and for
! 634: ** UTF-8 rendering. This may "fail" with a message to stderr, where
! 635: ** the preparation is not done and common "code page" issues occur.
! 636: */
! 637: static void console_prepare(void){
! 638: HANDLE hCI = GetStdHandle(STD_INPUT_HANDLE);
! 639: DWORD consoleMode = 0;
! 640: if( isatty(0) && GetFileType(hCI)==FILE_TYPE_CHAR
! 641: && GetConsoleMode( hCI, &consoleMode) ){
! 642: if( !IsValidCodePage(CP_UTF8) ){
! 643: fprintf(stderr, "Cannot use UTF-8 code page.\n");
! 644: console_utf8 = 0;
! 645: return;
! 646: }
! 647: conState.hConsoleIn = hCI;
! 648: conState.consoleMode = consoleMode;
! 649: conState.inCodePage = GetConsoleCP();
! 650: conState.outCodePage = GetConsoleOutputCP();
! 651: SetConsoleCP(CP_UTF8);
! 652: SetConsoleOutputCP(CP_UTF8);
! 653: consoleMode |= ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
! 654: SetConsoleMode(conState.hConsoleIn, consoleMode);
! 655: conState.infsMode = _setmode(_fileno(stdin), _O_U16TEXT);
! 656: console_utf8 = 1;
! 657: }else{
! 658: console_utf8 = 0;
! 659: }
! 660: }
! 661:
! 662: /*
! 663: ** Undo the effects of console_prepare(), if any.
! 664: */
! 665: static void SQLITE_CDECL console_restore(void){
! 666: if( console_utf8 && conState.inCodePage!=0
! 667: && conState.hConsoleIn!=INVALID_HANDLE_VALUE ){
! 668: _setmode(_fileno(stdin), conState.infsMode);
! 669: SetConsoleCP(conState.inCodePage);
! 670: SetConsoleOutputCP(conState.outCodePage);
! 671: SetConsoleMode(conState.hConsoleIn, conState.consoleMode);
! 672: /* Avoid multiple calls. */
! 673: conState.hConsoleIn = INVALID_HANDLE_VALUE;
! 674: conState.consoleMode = 0;
! 675: console_utf8 = 0;
! 676: }
! 677: }
! 678:
! 679: /*
! 680: ** Collect input like fgets(...) with special provisions for input
! 681: ** from the Windows console to get around its strange coding issues.
! 682: ** Defers to plain fgets() when input is not interactive or when the
! 683: ** startup option, -utf8, has not been provided or taken effect.
! 684: */
! 685: static char* utf8_fgets(char *buf, int ncmax, FILE *fin){
! 686: if( fin==0 ) fin = stdin;
! 687: if( fin==stdin && stdin_is_interactive && console_utf8 ){
! 688: # define SQLITE_IALIM 150
! 689: wchar_t wbuf[SQLITE_IALIM];
! 690: int lend = 0;
! 691: int noc = 0;
! 692: if( ncmax==0 || conState.stdinEof ) return 0;
! 693: buf[0] = 0;
! 694: while( noc<ncmax-7-1 && !lend ){
! 695: /* There is room for at least 2 more characters and a 0-terminator. */
! 696: int na = (ncmax > SQLITE_IALIM*4+1 + noc)
! 697: ? SQLITE_IALIM : (ncmax-1 - noc)/4;
! 698: # undef SQLITE_IALIM
! 699: DWORD nbr = 0;
! 700: BOOL bRC = ReadConsoleW(conState.hConsoleIn, wbuf, na, &nbr, 0);
! 701: if( !bRC || (noc==0 && nbr==0) ) return 0;
! 702: if( nbr > 0 ){
! 703: int nmb = WideCharToMultiByte(CP_UTF8,WC_COMPOSITECHECK|WC_DEFAULTCHAR,
! 704: wbuf,nbr,0,0,0,0);
! 705: if( nmb !=0 && noc+nmb <= ncmax ){
! 706: int iseg = noc;
! 707: nmb = WideCharToMultiByte(CP_UTF8,WC_COMPOSITECHECK|WC_DEFAULTCHAR,
! 708: wbuf,nbr,buf+noc,nmb,0,0);
! 709: noc += nmb;
! 710: /* Fixup line-ends as coded by Windows for CR (or "Enter".)*/
! 711: if( noc > 0 ){
! 712: if( buf[noc-1]=='\n' ){
! 713: lend = 1;
! 714: if( noc > 1 && buf[noc-2]=='\r' ){
! 715: buf[noc-2] = '\n';
! 716: --noc;
! 717: }
! 718: }
! 719: }
! 720: /* Check for ^Z (anywhere in line) too. */
! 721: while( iseg < noc ){
! 722: if( buf[iseg]==0x1a ){
! 723: conState.stdinEof = 1;
! 724: noc = iseg; /* Chop ^Z and anything following. */
! 725: break;
! 726: }
! 727: ++iseg;
! 728: }
! 729: }else break; /* Drop apparent garbage in. (Could assert.) */
! 730: }else break;
! 731: }
! 732: /* If got nothing, (after ^Z chop), must be at end-of-file. */
! 733: if( noc == 0 ) return 0;
! 734: buf[noc] = 0;
! 735: return buf;
! 736: }else{
! 737: return fgets(buf, ncmax, fin);
! 738: }
! 739: }
! 740:
! 741: # define fgets(b,n,f) utf8_fgets(b,n,f)
! 742: #endif /* SHELL_WIN_UTF8_OPT */
1.2 misho 743:
744: /*
1.4 misho 745: ** Render output like fprintf(). Except, if the output is going to the
1.6.2.1 ! misho 746: ** console and if this is running on a Windows machine, and if the -utf8
! 747: ** option is unavailable or (available and inactive), translate the
! 748: ** output from UTF-8 into MBCS for output through 8-bit stdout stream.
! 749: ** (With -utf8 active, no translation is needed and must not be done.)
1.4 misho 750: */
751: #if defined(_WIN32) || defined(WIN32)
752: void utf8_printf(FILE *out, const char *zFormat, ...){
753: va_list ap;
754: va_start(ap, zFormat);
1.6.2.1 ! misho 755: if( stdout_is_console && (out==stdout || out==stderr)
! 756: # if SHELL_WIN_UTF8_OPT
! 757: && !console_utf8
! 758: # endif
! 759: ){
1.4 misho 760: char *z1 = sqlite3_vmprintf(zFormat, ap);
761: char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0);
762: sqlite3_free(z1);
763: fputs(z2, out);
764: sqlite3_free(z2);
765: }else{
766: vfprintf(out, zFormat, ap);
767: }
768: va_end(ap);
769: }
770: #elif !defined(utf8_printf)
771: # define utf8_printf fprintf
772: #endif
773:
774: /*
775: ** Render output like fprintf(). This should not be used on anything that
776: ** includes string formatting (e.g. "%s").
777: */
778: #if !defined(raw_printf)
779: # define raw_printf fprintf
780: #endif
781:
1.5 misho 782: /* Indicate out-of-memory and exit. */
783: static void shell_out_of_memory(void){
784: raw_printf(stderr,"Error: out of memory\n");
785: exit(1);
786: }
787:
1.6.2.1 ! misho 788: /* Check a pointer to see if it is NULL. If it is NULL, exit with an
! 789: ** out-of-memory error.
1.5 misho 790: */
1.6.2.1 ! misho 791: static void shell_check_oom(const void *p){
! 792: if( p==0 ) shell_out_of_memory();
1.5 misho 793: }
794:
1.4 misho 795: /*
1.2 misho 796: ** Write I/O traces to the following stream.
797: */
798: #ifdef SQLITE_ENABLE_IOTRACE
799: static FILE *iotrace = 0;
800: #endif
801:
802: /*
803: ** This routine works like printf in that its first argument is a
804: ** format string and subsequent arguments are values to be substituted
805: ** in place of % fields. The result of formatting this string
806: ** is written to iotrace.
807: */
808: #ifdef SQLITE_ENABLE_IOTRACE
1.4 misho 809: static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
1.2 misho 810: va_list ap;
811: char *z;
812: if( iotrace==0 ) return;
813: va_start(ap, zFormat);
814: z = sqlite3_vmprintf(zFormat, ap);
815: va_end(ap);
1.4 misho 816: utf8_printf(iotrace, "%s", z);
1.2 misho 817: sqlite3_free(z);
818: }
819: #endif
820:
1.5 misho 821: /*
822: ** Output string zUtf to stream pOut as w characters. If w is negative,
823: ** then right-justify the text. W is the width in UTF-8 characters, not
824: ** in bytes. This is different from the %*.*s specification in printf
825: ** since with %*.*s the width is measured in bytes, not characters.
826: */
827: static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
828: int i;
829: int n;
830: int aw = w<0 ? -w : w;
1.6.2.1 ! misho 831: if( zUtf==0 ) zUtf = "";
1.5 misho 832: for(i=n=0; zUtf[i]; i++){
833: if( (zUtf[i]&0xc0)!=0x80 ){
834: n++;
835: if( n==aw ){
836: do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
837: break;
838: }
839: }
840: }
841: if( n>=aw ){
842: utf8_printf(pOut, "%.*s", i, zUtf);
843: }else if( w<0 ){
844: utf8_printf(pOut, "%*s%s", aw-n, "", zUtf);
845: }else{
846: utf8_printf(pOut, "%s%*s", zUtf, aw-n, "");
847: }
848: }
849:
1.2 misho 850:
851: /*
852: ** Determines if a string is a number of not.
853: */
854: static int isNumber(const char *z, int *realnum){
855: if( *z=='-' || *z=='+' ) z++;
856: if( !IsDigit(*z) ){
857: return 0;
858: }
859: z++;
860: if( realnum ) *realnum = 0;
861: while( IsDigit(*z) ){ z++; }
862: if( *z=='.' ){
863: z++;
864: if( !IsDigit(*z) ) return 0;
865: while( IsDigit(*z) ){ z++; }
866: if( realnum ) *realnum = 1;
867: }
868: if( *z=='e' || *z=='E' ){
869: z++;
870: if( *z=='+' || *z=='-' ) z++;
871: if( !IsDigit(*z) ) return 0;
872: while( IsDigit(*z) ){ z++; }
873: if( realnum ) *realnum = 1;
874: }
875: return *z==0;
876: }
877:
878: /*
1.4 misho 879: ** Compute a string length that is limited to what can be stored in
880: ** lower 30 bits of a 32-bit signed integer.
881: */
882: static int strlen30(const char *z){
883: const char *z2 = z;
884: while( *z2 ){ z2++; }
885: return 0x3fffffff & (int)(z2 - z);
886: }
887:
888: /*
1.5 misho 889: ** Return the length of a string in characters. Multibyte UTF8 characters
890: ** count as a single character.
891: */
892: static int strlenChar(const char *z){
893: int n = 0;
894: while( *z ){
895: if( (0xc0&*(z++))!=0x80 ) n++;
896: }
897: return n;
898: }
899:
900: /*
1.6.2.1 ! misho 901: ** Return open FILE * if zFile exists, can be opened for read
! 902: ** and is an ordinary file or a character stream source.
! 903: ** Otherwise return 0.
1.5 misho 904: */
1.6.2.1 ! misho 905: static FILE * openChrSource(const char *zFile){
1.5 misho 906: #ifdef _WIN32
1.6.2.1 ! misho 907: struct _stat x = {0};
! 908: # define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0)
! 909: /* On Windows, open first, then check the stream nature. This order
! 910: ** is necessary because _stat() and sibs, when checking a named pipe,
! 911: ** effectively break the pipe as its supplier sees it. */
! 912: FILE *rv = fopen(zFile, "rb");
! 913: if( rv==0 ) return 0;
! 914: if( _fstat(_fileno(rv), &x) != 0
! 915: || !STAT_CHR_SRC(x.st_mode)){
! 916: fclose(rv);
! 917: rv = 0;
! 918: }
! 919: return rv;
1.5 misho 920: #else
1.6.2.1 ! misho 921: struct stat x = {0};
! 922: int rc = stat(zFile, &x);
! 923: # define STAT_CHR_SRC(mode) (S_ISREG(mode)||S_ISFIFO(mode)||S_ISCHR(mode))
! 924: if( rc!=0 ) return 0;
! 925: if( STAT_CHR_SRC(x.st_mode) ){
! 926: return fopen(zFile, "rb");
! 927: }else{
! 928: return 0;
! 929: }
1.5 misho 930: #endif
1.6.2.1 ! misho 931: #undef STAT_CHR_SRC
! 932: }
1.5 misho 933:
934: /*
1.2 misho 935: ** This routine reads a line of text from FILE in, stores
936: ** the text in memory obtained from malloc() and returns a pointer
937: ** to the text. NULL is returned at end of file, or if malloc()
938: ** fails.
939: **
1.4 misho 940: ** If zLine is not NULL then it is a malloced buffer returned from
941: ** a previous call to this routine that may be reused.
1.2 misho 942: */
1.4 misho 943: static char *local_getline(char *zLine, FILE *in){
944: int nLine = zLine==0 ? 0 : 100;
945: int n = 0;
1.2 misho 946:
947: while( 1 ){
948: if( n+100>nLine ){
949: nLine = nLine*2 + 100;
950: zLine = realloc(zLine, nLine);
1.6.2.1 ! misho 951: shell_check_oom(zLine);
1.2 misho 952: }
953: if( fgets(&zLine[n], nLine - n, in)==0 ){
954: if( n==0 ){
955: free(zLine);
956: return 0;
957: }
958: zLine[n] = 0;
959: break;
960: }
1.4 misho 961: while( zLine[n] ) n++;
962: if( n>0 && zLine[n-1]=='\n' ){
1.2 misho 963: n--;
964: if( n>0 && zLine[n-1]=='\r' ) n--;
965: zLine[n] = 0;
966: break;
967: }
968: }
1.4 misho 969: #if defined(_WIN32) || defined(WIN32)
1.6.2.1 ! misho 970: /* For interactive input on Windows systems, without -utf8,
! 971: ** translate the multi-byte characterset characters into UTF-8.
! 972: ** This is the translation that predates the -utf8 option. */
! 973: if( stdin_is_interactive && in==stdin
! 974: # if SHELL_WIN_UTF8_OPT
! 975: && !console_utf8
! 976: # endif /* SHELL_WIN_UTF8_OPT */
! 977: ){
1.4 misho 978: char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
979: if( zTrans ){
1.6.2.1 ! misho 980: i64 nTrans = strlen(zTrans)+1;
1.4 misho 981: if( nTrans>nLine ){
982: zLine = realloc(zLine, nTrans);
1.6.2.1 ! misho 983: shell_check_oom(zLine);
1.4 misho 984: }
985: memcpy(zLine, zTrans, nTrans);
986: sqlite3_free(zTrans);
987: }
988: }
989: #endif /* defined(_WIN32) || defined(WIN32) */
1.2 misho 990: return zLine;
991: }
992:
993: /*
994: ** Retrieve a single line of input text.
995: **
1.4 misho 996: ** If in==0 then read from standard input and prompt before each line.
997: ** If isContinuation is true, then a continuation prompt is appropriate.
998: ** If isContinuation is zero, then the main prompt should be used.
999: **
1000: ** If zPrior is not NULL then it is a buffer from a prior call to this
1001: ** routine that can be reused.
1002: **
1003: ** The result is stored in space obtained from malloc() and must either
1004: ** be freed by the caller or else passed back into this routine via the
1005: ** zPrior argument for reuse.
1.2 misho 1006: */
1.6.2.1 ! misho 1007: #ifndef SQLITE_SHELL_FIDDLE
1.4 misho 1008: static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
1.2 misho 1009: char *zPrompt;
1010: char *zResult;
1011: if( in!=0 ){
1.4 misho 1012: zResult = local_getline(zPrior, in);
1.2 misho 1013: }else{
1.6.2.1 ! misho 1014: zPrompt = isContinuation ? CONTINUATION_PROMPT : mainPrompt;
1.4 misho 1015: #if SHELL_USE_LOCAL_GETLINE
1016: printf("%s", zPrompt);
1017: fflush(stdout);
1.6.2.1 ! misho 1018: do{
! 1019: zResult = local_getline(zPrior, stdin);
! 1020: zPrior = 0;
! 1021: /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */
! 1022: if( zResult==0 ) sqlite3_sleep(50);
! 1023: }while( zResult==0 && seenInterrupt>0 );
1.4 misho 1024: #else
1025: free(zPrior);
1026: zResult = shell_readline(zPrompt);
1.6.2.1 ! misho 1027: while( zResult==0 ){
! 1028: /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */
! 1029: sqlite3_sleep(50);
! 1030: if( seenInterrupt==0 ) break;
! 1031: zResult = shell_readline("");
! 1032: }
1.4 misho 1033: if( zResult && *zResult ) shell_add_history(zResult);
1034: #endif
1.2 misho 1035: }
1036: return zResult;
1037: }
1.6.2.1 ! misho 1038: #endif /* !SQLITE_SHELL_FIDDLE */
1.5 misho 1039:
1.4 misho 1040: /*
1.5 misho 1041: ** Return the value of a hexadecimal digit. Return -1 if the input
1042: ** is not a hex digit.
1.4 misho 1043: */
1.5 misho 1044: static int hexDigitValue(char c){
1045: if( c>='0' && c<='9' ) return c - '0';
1046: if( c>='a' && c<='f' ) return c - 'a' + 10;
1047: if( c>='A' && c<='F' ) return c - 'A' + 10;
1048: return -1;
1049: }
1.4 misho 1050:
1051: /*
1.5 misho 1052: ** Interpret zArg as an integer value, possibly with suffixes.
1.4 misho 1053: */
1.5 misho 1054: static sqlite3_int64 integerValue(const char *zArg){
1055: sqlite3_int64 v = 0;
1056: static const struct { char *zSuffix; int iMult; } aMult[] = {
1057: { "KiB", 1024 },
1058: { "MiB", 1024*1024 },
1059: { "GiB", 1024*1024*1024 },
1060: { "KB", 1000 },
1061: { "MB", 1000000 },
1062: { "GB", 1000000000 },
1063: { "K", 1000 },
1064: { "M", 1000000 },
1065: { "G", 1000000000 },
1066: };
1067: int i;
1068: int isNeg = 0;
1069: if( zArg[0]=='-' ){
1070: isNeg = 1;
1071: zArg++;
1072: }else if( zArg[0]=='+' ){
1073: zArg++;
1074: }
1075: if( zArg[0]=='0' && zArg[1]=='x' ){
1076: int x;
1077: zArg += 2;
1078: while( (x = hexDigitValue(zArg[0]))>=0 ){
1079: v = (v<<4) + x;
1080: zArg++;
1081: }
1082: }else{
1083: while( IsDigit(zArg[0]) ){
1084: v = v*10 + zArg[0] - '0';
1085: zArg++;
1086: }
1087: }
1088: for(i=0; i<ArraySize(aMult); i++){
1089: if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
1090: v *= aMult[i].iMult;
1091: break;
1092: }
1093: }
1094: return isNeg? -v : v;
1095: }
1.2 misho 1096:
1097: /*
1.5 misho 1098: ** A variable length string to which one can append text.
1.2 misho 1099: */
1.5 misho 1100: typedef struct ShellText ShellText;
1101: struct ShellText {
1102: char *z;
1103: int n;
1104: int nAlloc;
1.2 misho 1105: };
1106:
1107: /*
1.5 misho 1108: ** Initialize and destroy a ShellText object
1.4 misho 1109: */
1.5 misho 1110: static void initText(ShellText *p){
1111: memset(p, 0, sizeof(*p));
1112: }
1113: static void freeText(ShellText *p){
1114: free(p->z);
1115: initText(p);
1116: }
1.4 misho 1117:
1.5 misho 1118: /* zIn is either a pointer to a NULL-terminated string in memory obtained
1119: ** from malloc(), or a NULL pointer. The string pointed to by zAppend is
1120: ** added to zIn, and the result returned in memory obtained from malloc().
1121: ** zIn, if it was not NULL, is freed.
1122: **
1123: ** If the third argument, quote, is not '\0', then it is used as a
1124: ** quote character for zAppend.
1.2 misho 1125: */
1.6.2.1 ! misho 1126: static void appendText(ShellText *p, const char *zAppend, char quote){
! 1127: i64 len;
! 1128: i64 i;
! 1129: i64 nAppend = strlen30(zAppend);
1.5 misho 1130:
1131: len = nAppend+p->n+1;
1132: if( quote ){
1133: len += 2;
1134: for(i=0; i<nAppend; i++){
1135: if( zAppend[i]==quote ) len++;
1136: }
1137: }
1.2 misho 1138:
1.6.2.1 ! misho 1139: if( p->z==0 || p->n+len>=p->nAlloc ){
1.5 misho 1140: p->nAlloc = p->nAlloc*2 + len + 20;
1141: p->z = realloc(p->z, p->nAlloc);
1.6.2.1 ! misho 1142: shell_check_oom(p->z);
1.5 misho 1143: }
1.2 misho 1144:
1.5 misho 1145: if( quote ){
1146: char *zCsr = p->z+p->n;
1147: *zCsr++ = quote;
1148: for(i=0; i<nAppend; i++){
1149: *zCsr++ = zAppend[i];
1150: if( zAppend[i]==quote ) *zCsr++ = quote;
1151: }
1152: *zCsr++ = quote;
1153: p->n = (int)(zCsr - p->z);
1154: *zCsr = '\0';
1155: }else{
1156: memcpy(p->z+p->n, zAppend, nAppend);
1157: p->n += nAppend;
1158: p->z[p->n] = '\0';
1159: }
1160: }
1.2 misho 1161:
1162: /*
1.5 misho 1163: ** Attempt to determine if identifier zName needs to be quoted, either
1164: ** because it contains non-alphanumeric characters, or because it is an
1165: ** SQLite keyword. Be conservative in this estimate: When in doubt assume
1166: ** that quoting is required.
1167: **
1168: ** Return '"' if quoting is required. Return 0 if no quoting is required.
1.2 misho 1169: */
1.5 misho 1170: static char quoteChar(const char *zName){
1171: int i;
1.6.2.1 ! misho 1172: if( zName==0 ) return '"';
1.5 misho 1173: if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
1174: for(i=0; zName[i]; i++){
1175: if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
1176: }
1177: return sqlite3_keyword_check(zName, i) ? '"' : 0;
1178: }
1.2 misho 1179:
1180: /*
1.5 misho 1181: ** Construct a fake object name and column list to describe the structure
1182: ** of the view, virtual table, or table valued function zSchema.zName.
1.2 misho 1183: */
1.5 misho 1184: static char *shellFakeSchema(
1185: sqlite3 *db, /* The database connection containing the vtab */
1186: const char *zSchema, /* Schema of the database holding the vtab */
1187: const char *zName /* The name of the virtual table */
1188: ){
1189: sqlite3_stmt *pStmt = 0;
1190: char *zSql;
1191: ShellText s;
1192: char cQuote;
1193: char *zDiv = "(";
1194: int nRow = 0;
1195:
1196: zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
1197: zSchema ? zSchema : "main", zName);
1.6.2.1 ! misho 1198: shell_check_oom(zSql);
1.5 misho 1199: sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
1200: sqlite3_free(zSql);
1201: initText(&s);
1202: if( zSchema ){
1203: cQuote = quoteChar(zSchema);
1204: if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0;
1205: appendText(&s, zSchema, cQuote);
1206: appendText(&s, ".", 0);
1207: }
1208: cQuote = quoteChar(zName);
1209: appendText(&s, zName, cQuote);
1210: while( sqlite3_step(pStmt)==SQLITE_ROW ){
1211: const char *zCol = (const char*)sqlite3_column_text(pStmt, 1);
1212: nRow++;
1213: appendText(&s, zDiv, 0);
1214: zDiv = ",";
1.6.2.1 ! misho 1215: if( zCol==0 ) zCol = "";
1.5 misho 1216: cQuote = quoteChar(zCol);
1217: appendText(&s, zCol, cQuote);
1218: }
1219: appendText(&s, ")", 0);
1220: sqlite3_finalize(pStmt);
1221: if( nRow==0 ){
1222: freeText(&s);
1223: s.z = 0;
1224: }
1225: return s.z;
1.2 misho 1226: }
1227:
1228: /*
1.6.2.1 ! misho 1229: ** SQL function: strtod(X)
! 1230: **
! 1231: ** Use the C-library strtod() function to convert string X into a double.
! 1232: ** Used for comparing the accuracy of SQLite's internal text-to-float conversion
! 1233: ** routines against the C-library.
! 1234: */
! 1235: static void shellStrtod(
! 1236: sqlite3_context *pCtx,
! 1237: int nVal,
! 1238: sqlite3_value **apVal
! 1239: ){
! 1240: char *z = (char*)sqlite3_value_text(apVal[0]);
! 1241: UNUSED_PARAMETER(nVal);
! 1242: if( z==0 ) return;
! 1243: sqlite3_result_double(pCtx, strtod(z,0));
! 1244: }
! 1245:
! 1246: /*
! 1247: ** SQL function: dtostr(X)
! 1248: **
! 1249: ** Use the C-library printf() function to convert real value X into a string.
! 1250: ** Used for comparing the accuracy of SQLite's internal float-to-text conversion
! 1251: ** routines against the C-library.
! 1252: */
! 1253: static void shellDtostr(
! 1254: sqlite3_context *pCtx,
! 1255: int nVal,
! 1256: sqlite3_value **apVal
! 1257: ){
! 1258: double r = sqlite3_value_double(apVal[0]);
! 1259: int n = nVal>=2 ? sqlite3_value_int(apVal[1]) : 26;
! 1260: char z[400];
! 1261: if( n<1 ) n = 1;
! 1262: if( n>350 ) n = 350;
! 1263: sprintf(z, "%#+.*e", n, r);
! 1264: sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
! 1265: }
! 1266:
! 1267:
! 1268: /*
1.5 misho 1269: ** SQL function: shell_module_schema(X)
1270: **
1271: ** Return a fake schema for the table-valued function or eponymous virtual
1272: ** table X.
1.2 misho 1273: */
1.5 misho 1274: static void shellModuleSchema(
1275: sqlite3_context *pCtx,
1276: int nVal,
1277: sqlite3_value **apVal
1278: ){
1.6.2.1 ! misho 1279: const char *zName;
! 1280: char *zFake;
1.5 misho 1281: UNUSED_PARAMETER(nVal);
1.6.2.1 ! misho 1282: zName = (const char*)sqlite3_value_text(apVal[0]);
! 1283: zFake = zName? shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName) : 0;
1.5 misho 1284: if( zFake ){
1285: sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
1286: -1, sqlite3_free);
1287: free(zFake);
1288: }
1.2 misho 1289: }
1290:
1291: /*
1.5 misho 1292: ** SQL function: shell_add_schema(S,X)
1293: **
1294: ** Add the schema name X to the CREATE statement in S and return the result.
1295: ** Examples:
1296: **
1297: ** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x);
1298: **
1299: ** Also works on
1300: **
1301: ** CREATE INDEX
1302: ** CREATE UNIQUE INDEX
1303: ** CREATE VIEW
1304: ** CREATE TRIGGER
1305: ** CREATE VIRTUAL TABLE
1306: **
1307: ** This UDF is used by the .schema command to insert the schema name of
1308: ** attached databases into the middle of the sqlite_schema.sql field.
1.2 misho 1309: */
1.5 misho 1310: static void shellAddSchemaName(
1311: sqlite3_context *pCtx,
1312: int nVal,
1313: sqlite3_value **apVal
1314: ){
1315: static const char *aPrefix[] = {
1316: "TABLE",
1317: "INDEX",
1318: "UNIQUE INDEX",
1319: "VIEW",
1320: "TRIGGER",
1321: "VIRTUAL TABLE"
1322: };
1323: int i = 0;
1324: const char *zIn = (const char*)sqlite3_value_text(apVal[0]);
1325: const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
1326: const char *zName = (const char*)sqlite3_value_text(apVal[2]);
1327: sqlite3 *db = sqlite3_context_db_handle(pCtx);
1328: UNUSED_PARAMETER(nVal);
1.6.2.1 ! misho 1329: if( zIn!=0 && cli_strncmp(zIn, "CREATE ", 7)==0 ){
! 1330: for(i=0; i<ArraySize(aPrefix); i++){
1.5 misho 1331: int n = strlen30(aPrefix[i]);
1.6.2.1 ! misho 1332: if( cli_strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
1.5 misho 1333: char *z = 0;
1334: char *zFake = 0;
1335: if( zSchema ){
1336: char cQuote = quoteChar(zSchema);
1337: if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){
1338: z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8);
1339: }else{
1340: z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8);
1341: }
1342: }
1343: if( zName
1344: && aPrefix[i][0]=='V'
1345: && (zFake = shellFakeSchema(db, zSchema, zName))!=0
1346: ){
1347: if( z==0 ){
1348: z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake);
1349: }else{
1350: z = sqlite3_mprintf("%z\n/* %s */", z, zFake);
1351: }
1352: free(zFake);
1353: }
1354: if( z ){
1355: sqlite3_result_text(pCtx, z, -1, sqlite3_free);
1356: return;
1357: }
1.2 misho 1358: }
1359: }
1360: }
1.5 misho 1361: sqlite3_result_value(pCtx, apVal[0]);
1.2 misho 1362: }
1363:
1364: /*
1.5 misho 1365: ** The source code for several run-time loadable extensions is inserted
1366: ** below by the ../tool/mkshellc.tcl script. Before processing that included
1367: ** code, we need to override some macros to make the included program code
1368: ** work here in the middle of this regular program.
1369: */
1370: #define SQLITE_EXTENSION_INIT1
1371: #define SQLITE_EXTENSION_INIT2(X) (void)(X)
1372:
1373: #if defined(_WIN32) && defined(_MSC_VER)
1374: /************************* Begin test_windirent.h ******************/
1375: /*
1376: ** 2015 November 30
1377: **
1378: ** The author disclaims copyright to this source code. In place of
1379: ** a legal notice, here is a blessing:
1380: **
1381: ** May you do good and not evil.
1382: ** May you find forgiveness for yourself and forgive others.
1383: ** May you share freely, never taking more than you give.
1384: **
1385: *************************************************************************
1386: ** This file contains declarations for most of the opendir() family of
1387: ** POSIX functions on Win32 using the MSVCRT.
1388: */
1389:
1390: #if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H)
1391: #define SQLITE_WINDIRENT_H
1392:
1393: /*
1394: ** We need several data types from the Windows SDK header.
1395: */
1396:
1397: #ifndef WIN32_LEAN_AND_MEAN
1398: #define WIN32_LEAN_AND_MEAN
1399: #endif
1400:
1401: #include "windows.h"
1402:
1403: /*
1404: ** We need several support functions from the SQLite core.
1.2 misho 1405: */
1.5 misho 1406:
1407: /* #include "sqlite3.h" */
1.2 misho 1408:
1409: /*
1.5 misho 1410: ** We need several things from the ANSI and MSVCRT headers.
1.2 misho 1411: */
1.5 misho 1412:
1413: #include <stdio.h>
1414: #include <stdlib.h>
1415: #include <errno.h>
1416: #include <io.h>
1417: #include <limits.h>
1418: #include <sys/types.h>
1419: #include <sys/stat.h>
1.2 misho 1420:
1421: /*
1.5 misho 1422: ** We may need several defines that should have been in "sys/stat.h".
1.2 misho 1423: */
1.5 misho 1424:
1425: #ifndef S_ISREG
1426: #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
1427: #endif
1428:
1429: #ifndef S_ISDIR
1430: #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
1431: #endif
1432:
1433: #ifndef S_ISLNK
1434: #define S_ISLNK(mode) (0)
1435: #endif
1.2 misho 1436:
1437: /*
1.5 misho 1438: ** We may need to provide the "mode_t" type.
1.2 misho 1439: */
1440:
1.5 misho 1441: #ifndef MODE_T_DEFINED
1442: #define MODE_T_DEFINED
1443: typedef unsigned short mode_t;
1444: #endif
1445:
1.2 misho 1446: /*
1.5 misho 1447: ** We may need to provide the "ino_t" type.
1.2 misho 1448: */
1.5 misho 1449:
1450: #ifndef INO_T_DEFINED
1451: #define INO_T_DEFINED
1452: typedef unsigned short ino_t;
1.2 misho 1453: #endif
1454:
1455: /*
1.5 misho 1456: ** We need to define "NAME_MAX" if it was not present in "limits.h".
1.4 misho 1457: */
1.5 misho 1458:
1459: #ifndef NAME_MAX
1460: # ifdef FILENAME_MAX
1461: # define NAME_MAX (FILENAME_MAX)
1462: # else
1463: # define NAME_MAX (260)
1464: # endif
1465: #endif
1.4 misho 1466:
1467: /*
1.5 misho 1468: ** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T".
1.2 misho 1469: */
1470:
1.5 misho 1471: #ifndef NULL_INTPTR_T
1472: # define NULL_INTPTR_T ((intptr_t)(0))
1473: #endif
1474:
1475: #ifndef BAD_INTPTR_T
1476: # define BAD_INTPTR_T ((intptr_t)(-1))
1477: #endif
1478:
1479: /*
1480: ** We need to provide the necessary structures and related types.
1481: */
1482:
1483: #ifndef DIRENT_DEFINED
1484: #define DIRENT_DEFINED
1485: typedef struct DIRENT DIRENT;
1486: typedef DIRENT *LPDIRENT;
1487: struct DIRENT {
1488: ino_t d_ino; /* Sequence number, do not use. */
1489: unsigned d_attributes; /* Win32 file attributes. */
1490: char d_name[NAME_MAX + 1]; /* Name within the directory. */
1491: };
1492: #endif
1493:
1494: #ifndef DIR_DEFINED
1495: #define DIR_DEFINED
1496: typedef struct DIR DIR;
1497: typedef DIR *LPDIR;
1498: struct DIR {
1499: intptr_t d_handle; /* Value returned by "_findfirst". */
1500: DIRENT d_first; /* DIRENT constructed based on "_findfirst". */
1501: DIRENT d_next; /* DIRENT constructed based on "_findnext". */
1502: };
1503: #endif
1504:
1505: /*
1506: ** Provide a macro, for use by the implementation, to determine if a
1507: ** particular directory entry should be skipped over when searching for
1508: ** the next directory entry that should be returned by the readdir() or
1509: ** readdir_r() functions.
1510: */
1511:
1512: #ifndef is_filtered
1513: # define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM))
1514: #endif
1515:
1516: /*
1.6.2.1 ! misho 1517: ** Provide the function prototype for the POSIX compatible getenv()
1.5 misho 1518: ** function. This function is not thread-safe.
1519: */
1520:
1521: extern const char *windirent_getenv(const char *name);
1522:
1523: /*
1524: ** Finally, we can provide the function prototypes for the opendir(),
1525: ** readdir(), readdir_r(), and closedir() POSIX functions.
1526: */
1527:
1528: extern LPDIR opendir(const char *dirname);
1529: extern LPDIRENT readdir(LPDIR dirp);
1530: extern INT readdir_r(LPDIR dirp, LPDIRENT entry, LPDIRENT *result);
1531: extern INT closedir(LPDIR dirp);
1532:
1533: #endif /* defined(WIN32) && defined(_MSC_VER) */
1534:
1535: /************************* End test_windirent.h ********************/
1536: /************************* Begin test_windirent.c ******************/
1537: /*
1538: ** 2015 November 30
1539: **
1540: ** The author disclaims copyright to this source code. In place of
1541: ** a legal notice, here is a blessing:
1542: **
1543: ** May you do good and not evil.
1544: ** May you find forgiveness for yourself and forgive others.
1545: ** May you share freely, never taking more than you give.
1546: **
1547: *************************************************************************
1548: ** This file contains code to implement most of the opendir() family of
1549: ** POSIX functions on Win32 using the MSVCRT.
1550: */
1551:
1552: #if defined(_WIN32) && defined(_MSC_VER)
1553: /* #include "test_windirent.h" */
1554:
1555: /*
1556: ** Implementation of the POSIX getenv() function using the Win32 API.
1557: ** This function is not thread-safe.
1558: */
1559: const char *windirent_getenv(
1560: const char *name
1561: ){
1562: static char value[32768]; /* Maximum length, per MSDN */
1563: DWORD dwSize = sizeof(value) / sizeof(char); /* Size in chars */
1564: DWORD dwRet; /* Value returned by GetEnvironmentVariableA() */
1565:
1566: memset(value, 0, sizeof(value));
1567: dwRet = GetEnvironmentVariableA(name, value, dwSize);
1568: if( dwRet==0 || dwRet>dwSize ){
1569: /*
1570: ** The function call to GetEnvironmentVariableA() failed -OR-
1571: ** the buffer is not large enough. Either way, return NULL.
1572: */
1573: return 0;
1574: }else{
1575: /*
1576: ** The function call to GetEnvironmentVariableA() succeeded
1577: ** -AND- the buffer contains the entire value.
1578: */
1579: return value;
1580: }
1581: }
1582:
1583: /*
1584: ** Implementation of the POSIX opendir() function using the MSVCRT.
1585: */
1586: LPDIR opendir(
1587: const char *dirname
1588: ){
1589: struct _finddata_t data;
1590: LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR));
1591: SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]);
1592:
1593: if( dirp==NULL ) return NULL;
1594: memset(dirp, 0, sizeof(DIR));
1595:
1596: /* TODO: Remove this if Unix-style root paths are not used. */
1597: if( sqlite3_stricmp(dirname, "/")==0 ){
1598: dirname = windirent_getenv("SystemDrive");
1599: }
1600:
1601: memset(&data, 0, sizeof(struct _finddata_t));
1602: _snprintf(data.name, namesize, "%s\\*", dirname);
1603: dirp->d_handle = _findfirst(data.name, &data);
1604:
1605: if( dirp->d_handle==BAD_INTPTR_T ){
1606: closedir(dirp);
1607: return NULL;
1608: }
1609:
1610: /* TODO: Remove this block to allow hidden and/or system files. */
1611: if( is_filtered(data) ){
1612: next:
1613:
1614: memset(&data, 0, sizeof(struct _finddata_t));
1615: if( _findnext(dirp->d_handle, &data)==-1 ){
1616: closedir(dirp);
1617: return NULL;
1618: }
1619:
1620: /* TODO: Remove this block to allow hidden and/or system files. */
1621: if( is_filtered(data) ) goto next;
1622: }
1623:
1624: dirp->d_first.d_attributes = data.attrib;
1625: strncpy(dirp->d_first.d_name, data.name, NAME_MAX);
1626: dirp->d_first.d_name[NAME_MAX] = '\0';
1627:
1628: return dirp;
1629: }
1630:
1631: /*
1632: ** Implementation of the POSIX readdir() function using the MSVCRT.
1633: */
1634: LPDIRENT readdir(
1635: LPDIR dirp
1636: ){
1637: struct _finddata_t data;
1638:
1639: if( dirp==NULL ) return NULL;
1640:
1641: if( dirp->d_first.d_ino==0 ){
1642: dirp->d_first.d_ino++;
1643: dirp->d_next.d_ino++;
1644:
1645: return &dirp->d_first;
1646: }
1647:
1648: next:
1649:
1650: memset(&data, 0, sizeof(struct _finddata_t));
1651: if( _findnext(dirp->d_handle, &data)==-1 ) return NULL;
1652:
1653: /* TODO: Remove this block to allow hidden and/or system files. */
1654: if( is_filtered(data) ) goto next;
1655:
1656: dirp->d_next.d_ino++;
1657: dirp->d_next.d_attributes = data.attrib;
1658: strncpy(dirp->d_next.d_name, data.name, NAME_MAX);
1659: dirp->d_next.d_name[NAME_MAX] = '\0';
1660:
1661: return &dirp->d_next;
1662: }
1663:
1664: /*
1665: ** Implementation of the POSIX readdir_r() function using the MSVCRT.
1666: */
1667: INT readdir_r(
1668: LPDIR dirp,
1669: LPDIRENT entry,
1670: LPDIRENT *result
1671: ){
1672: struct _finddata_t data;
1673:
1674: if( dirp==NULL ) return EBADF;
1675:
1676: if( dirp->d_first.d_ino==0 ){
1677: dirp->d_first.d_ino++;
1678: dirp->d_next.d_ino++;
1679:
1680: entry->d_ino = dirp->d_first.d_ino;
1681: entry->d_attributes = dirp->d_first.d_attributes;
1682: strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX);
1683: entry->d_name[NAME_MAX] = '\0';
1684:
1685: *result = entry;
1686: return 0;
1687: }
1688:
1689: next:
1690:
1691: memset(&data, 0, sizeof(struct _finddata_t));
1692: if( _findnext(dirp->d_handle, &data)==-1 ){
1693: *result = NULL;
1694: return ENOENT;
1695: }
1696:
1697: /* TODO: Remove this block to allow hidden and/or system files. */
1698: if( is_filtered(data) ) goto next;
1699:
1700: entry->d_ino = (ino_t)-1; /* not available */
1701: entry->d_attributes = data.attrib;
1702: strncpy(entry->d_name, data.name, NAME_MAX);
1703: entry->d_name[NAME_MAX] = '\0';
1704:
1705: *result = entry;
1706: return 0;
1707: }
1708:
1709: /*
1710: ** Implementation of the POSIX closedir() function using the MSVCRT.
1711: */
1712: INT closedir(
1713: LPDIR dirp
1714: ){
1715: INT result = 0;
1716:
1717: if( dirp==NULL ) return EINVAL;
1718:
1719: if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){
1720: result = _findclose(dirp->d_handle);
1721: }
1722:
1723: sqlite3_free(dirp);
1724: return result;
1725: }
1726:
1727: #endif /* defined(WIN32) && defined(_MSC_VER) */
1728:
1729: /************************* End test_windirent.c ********************/
1730: #define dirent DIRENT
1731: #endif
1.6.2.1 ! misho 1732: /************************* Begin ../ext/misc/memtrace.c ******************/
1.5 misho 1733: /*
1.6.2.1 ! misho 1734: ** 2019-01-21
1.5 misho 1735: **
1736: ** The author disclaims copyright to this source code. In place of
1737: ** a legal notice, here is a blessing:
1738: **
1739: ** May you do good and not evil.
1740: ** May you find forgiveness for yourself and forgive others.
1741: ** May you share freely, never taking more than you give.
1742: **
1.6.2.1 ! misho 1743: *************************************************************************
1.5 misho 1744: **
1.6.2.1 ! misho 1745: ** This file implements an extension that uses the SQLITE_CONFIG_MALLOC
! 1746: ** mechanism to add a tracing layer on top of SQLite. If this extension
! 1747: ** is registered prior to sqlite3_initialize(), it will cause all memory
! 1748: ** allocation activities to be logged on standard output, or to some other
! 1749: ** FILE specified by the initializer.
1.5 misho 1750: **
1.6.2.1 ! misho 1751: ** This file needs to be compiled into the application that uses it.
1.5 misho 1752: **
1.6.2.1 ! misho 1753: ** This extension is used to implement the --memtrace option of the
! 1754: ** command-line shell.
1.5 misho 1755: */
1756: #include <assert.h>
1757: #include <string.h>
1.6.2.1 ! misho 1758: #include <stdio.h>
1.5 misho 1759:
1.6.2.1 ! misho 1760: /* The original memory allocation routines */
! 1761: static sqlite3_mem_methods memtraceBase;
! 1762: static FILE *memtraceOut;
1.5 misho 1763:
1.6.2.1 ! misho 1764: /* Methods that trace memory allocations */
! 1765: static void *memtraceMalloc(int n){
! 1766: if( memtraceOut ){
! 1767: fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n",
! 1768: memtraceBase.xRoundup(n));
! 1769: }
! 1770: return memtraceBase.xMalloc(n);
! 1771: }
! 1772: static void memtraceFree(void *p){
! 1773: if( p==0 ) return;
! 1774: if( memtraceOut ){
! 1775: fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p));
! 1776: }
! 1777: memtraceBase.xFree(p);
! 1778: }
! 1779: static void *memtraceRealloc(void *p, int n){
! 1780: if( p==0 ) return memtraceMalloc(n);
! 1781: if( n==0 ){
! 1782: memtraceFree(p);
! 1783: return 0;
! 1784: }
! 1785: if( memtraceOut ){
! 1786: fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n",
! 1787: memtraceBase.xSize(p), memtraceBase.xRoundup(n));
! 1788: }
! 1789: return memtraceBase.xRealloc(p, n);
! 1790: }
! 1791: static int memtraceSize(void *p){
! 1792: return memtraceBase.xSize(p);
! 1793: }
! 1794: static int memtraceRoundup(int n){
! 1795: return memtraceBase.xRoundup(n);
! 1796: }
! 1797: static int memtraceInit(void *p){
! 1798: return memtraceBase.xInit(p);
! 1799: }
! 1800: static void memtraceShutdown(void *p){
! 1801: memtraceBase.xShutdown(p);
! 1802: }
1.5 misho 1803:
1.6.2.1 ! misho 1804: /* The substitute memory allocator */
! 1805: static sqlite3_mem_methods ersaztMethods = {
! 1806: memtraceMalloc,
! 1807: memtraceFree,
! 1808: memtraceRealloc,
! 1809: memtraceSize,
! 1810: memtraceRoundup,
! 1811: memtraceInit,
! 1812: memtraceShutdown,
! 1813: 0
1.5 misho 1814: };
1815:
1.6.2.1 ! misho 1816: /* Begin tracing memory allocations to out. */
! 1817: int sqlite3MemTraceActivate(FILE *out){
! 1818: int rc = SQLITE_OK;
! 1819: if( memtraceBase.xMalloc==0 ){
! 1820: rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase);
! 1821: if( rc==SQLITE_OK ){
! 1822: rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods);
! 1823: }
! 1824: }
! 1825: memtraceOut = out;
! 1826: return rc;
! 1827: }
! 1828:
! 1829: /* Deactivate memory tracing */
! 1830: int sqlite3MemTraceDeactivate(void){
! 1831: int rc = SQLITE_OK;
! 1832: if( memtraceBase.xMalloc!=0 ){
! 1833: rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase);
! 1834: if( rc==SQLITE_OK ){
! 1835: memset(&memtraceBase, 0, sizeof(memtraceBase));
! 1836: }
! 1837: }
! 1838: memtraceOut = 0;
! 1839: return rc;
! 1840: }
! 1841:
! 1842: /************************* End ../ext/misc/memtrace.c ********************/
! 1843: /************************* Begin ../ext/misc/pcachetrace.c ******************/
! 1844: /*
! 1845: ** 2023-06-21
! 1846: **
! 1847: ** The author disclaims copyright to this source code. In place of
! 1848: ** a legal notice, here is a blessing:
! 1849: **
! 1850: ** May you do good and not evil.
! 1851: ** May you find forgiveness for yourself and forgive others.
! 1852: ** May you share freely, never taking more than you give.
! 1853: **
! 1854: *************************************************************************
! 1855: **
! 1856: ** This file implements an extension that uses the SQLITE_CONFIG_PCACHE2
! 1857: ** mechanism to add a tracing layer on top of pluggable page cache of
! 1858: ** SQLite. If this extension is registered prior to sqlite3_initialize(),
! 1859: ** it will cause all page cache activities to be logged on standard output,
! 1860: ** or to some other FILE specified by the initializer.
! 1861: **
! 1862: ** This file needs to be compiled into the application that uses it.
! 1863: **
! 1864: ** This extension is used to implement the --pcachetrace option of the
! 1865: ** command-line shell.
! 1866: */
! 1867: #include <assert.h>
! 1868: #include <string.h>
! 1869: #include <stdio.h>
! 1870:
! 1871: /* The original page cache routines */
! 1872: static sqlite3_pcache_methods2 pcacheBase;
! 1873: static FILE *pcachetraceOut;
! 1874:
! 1875: /* Methods that trace pcache activity */
! 1876: static int pcachetraceInit(void *pArg){
! 1877: int nRes;
! 1878: if( pcachetraceOut ){
! 1879: fprintf(pcachetraceOut, "PCACHETRACE: xInit(%p)\n", pArg);
! 1880: }
! 1881: nRes = pcacheBase.xInit(pArg);
! 1882: if( pcachetraceOut ){
! 1883: fprintf(pcachetraceOut, "PCACHETRACE: xInit(%p) -> %d\n", pArg, nRes);
! 1884: }
! 1885: return nRes;
! 1886: }
! 1887: static void pcachetraceShutdown(void *pArg){
! 1888: if( pcachetraceOut ){
! 1889: fprintf(pcachetraceOut, "PCACHETRACE: xShutdown(%p)\n", pArg);
! 1890: }
! 1891: pcacheBase.xShutdown(pArg);
! 1892: }
! 1893: static sqlite3_pcache *pcachetraceCreate(int szPage, int szExtra, int bPurge){
! 1894: sqlite3_pcache *pRes;
! 1895: if( pcachetraceOut ){
! 1896: fprintf(pcachetraceOut, "PCACHETRACE: xCreate(%d,%d,%d)\n",
! 1897: szPage, szExtra, bPurge);
! 1898: }
! 1899: pRes = pcacheBase.xCreate(szPage, szExtra, bPurge);
! 1900: if( pcachetraceOut ){
! 1901: fprintf(pcachetraceOut, "PCACHETRACE: xCreate(%d,%d,%d) -> %p\n",
! 1902: szPage, szExtra, bPurge, pRes);
! 1903: }
! 1904: return pRes;
! 1905: }
! 1906: static void pcachetraceCachesize(sqlite3_pcache *p, int nCachesize){
! 1907: if( pcachetraceOut ){
! 1908: fprintf(pcachetraceOut, "PCACHETRACE: xCachesize(%p, %d)\n", p, nCachesize);
! 1909: }
! 1910: pcacheBase.xCachesize(p, nCachesize);
! 1911: }
! 1912: static int pcachetracePagecount(sqlite3_pcache *p){
! 1913: int nRes;
! 1914: if( pcachetraceOut ){
! 1915: fprintf(pcachetraceOut, "PCACHETRACE: xPagecount(%p)\n", p);
! 1916: }
! 1917: nRes = pcacheBase.xPagecount(p);
! 1918: if( pcachetraceOut ){
! 1919: fprintf(pcachetraceOut, "PCACHETRACE: xPagecount(%p) -> %d\n", p, nRes);
! 1920: }
! 1921: return nRes;
! 1922: }
! 1923: static sqlite3_pcache_page *pcachetraceFetch(
! 1924: sqlite3_pcache *p,
! 1925: unsigned key,
! 1926: int crFg
! 1927: ){
! 1928: sqlite3_pcache_page *pRes;
! 1929: if( pcachetraceOut ){
! 1930: fprintf(pcachetraceOut, "PCACHETRACE: xFetch(%p,%u,%d)\n", p, key, crFg);
! 1931: }
! 1932: pRes = pcacheBase.xFetch(p, key, crFg);
! 1933: if( pcachetraceOut ){
! 1934: fprintf(pcachetraceOut, "PCACHETRACE: xFetch(%p,%u,%d) -> %p\n",
! 1935: p, key, crFg, pRes);
! 1936: }
! 1937: return pRes;
! 1938: }
! 1939: static void pcachetraceUnpin(
! 1940: sqlite3_pcache *p,
! 1941: sqlite3_pcache_page *pPg,
! 1942: int bDiscard
! 1943: ){
! 1944: if( pcachetraceOut ){
! 1945: fprintf(pcachetraceOut, "PCACHETRACE: xUnpin(%p, %p, %d)\n",
! 1946: p, pPg, bDiscard);
! 1947: }
! 1948: pcacheBase.xUnpin(p, pPg, bDiscard);
! 1949: }
! 1950: static void pcachetraceRekey(
! 1951: sqlite3_pcache *p,
! 1952: sqlite3_pcache_page *pPg,
! 1953: unsigned oldKey,
! 1954: unsigned newKey
! 1955: ){
! 1956: if( pcachetraceOut ){
! 1957: fprintf(pcachetraceOut, "PCACHETRACE: xRekey(%p, %p, %u, %u)\n",
! 1958: p, pPg, oldKey, newKey);
! 1959: }
! 1960: pcacheBase.xRekey(p, pPg, oldKey, newKey);
! 1961: }
! 1962: static void pcachetraceTruncate(sqlite3_pcache *p, unsigned n){
! 1963: if( pcachetraceOut ){
! 1964: fprintf(pcachetraceOut, "PCACHETRACE: xTruncate(%p, %u)\n", p, n);
! 1965: }
! 1966: pcacheBase.xTruncate(p, n);
! 1967: }
! 1968: static void pcachetraceDestroy(sqlite3_pcache *p){
! 1969: if( pcachetraceOut ){
! 1970: fprintf(pcachetraceOut, "PCACHETRACE: xDestroy(%p)\n", p);
! 1971: }
! 1972: pcacheBase.xDestroy(p);
! 1973: }
! 1974: static void pcachetraceShrink(sqlite3_pcache *p){
! 1975: if( pcachetraceOut ){
! 1976: fprintf(pcachetraceOut, "PCACHETRACE: xShrink(%p)\n", p);
! 1977: }
! 1978: pcacheBase.xShrink(p);
! 1979: }
! 1980:
! 1981: /* The substitute pcache methods */
! 1982: static sqlite3_pcache_methods2 ersaztPcacheMethods = {
! 1983: 0,
! 1984: 0,
! 1985: pcachetraceInit,
! 1986: pcachetraceShutdown,
! 1987: pcachetraceCreate,
! 1988: pcachetraceCachesize,
! 1989: pcachetracePagecount,
! 1990: pcachetraceFetch,
! 1991: pcachetraceUnpin,
! 1992: pcachetraceRekey,
! 1993: pcachetraceTruncate,
! 1994: pcachetraceDestroy,
! 1995: pcachetraceShrink
! 1996: };
! 1997:
! 1998: /* Begin tracing memory allocations to out. */
! 1999: int sqlite3PcacheTraceActivate(FILE *out){
! 2000: int rc = SQLITE_OK;
! 2001: if( pcacheBase.xFetch==0 ){
! 2002: rc = sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &pcacheBase);
! 2003: if( rc==SQLITE_OK ){
! 2004: rc = sqlite3_config(SQLITE_CONFIG_PCACHE2, &ersaztPcacheMethods);
! 2005: }
! 2006: }
! 2007: pcachetraceOut = out;
! 2008: return rc;
! 2009: }
! 2010:
! 2011: /* Deactivate memory tracing */
! 2012: int sqlite3PcacheTraceDeactivate(void){
! 2013: int rc = SQLITE_OK;
! 2014: if( pcacheBase.xFetch!=0 ){
! 2015: rc = sqlite3_config(SQLITE_CONFIG_PCACHE2, &pcacheBase);
! 2016: if( rc==SQLITE_OK ){
! 2017: memset(&pcacheBase, 0, sizeof(pcacheBase));
! 2018: }
! 2019: }
! 2020: pcachetraceOut = 0;
! 2021: return rc;
! 2022: }
! 2023:
! 2024: /************************* End ../ext/misc/pcachetrace.c ********************/
! 2025: /************************* Begin ../ext/misc/shathree.c ******************/
! 2026: /*
! 2027: ** 2017-03-08
! 2028: **
! 2029: ** The author disclaims copyright to this source code. In place of
! 2030: ** a legal notice, here is a blessing:
! 2031: **
! 2032: ** May you do good and not evil.
! 2033: ** May you find forgiveness for yourself and forgive others.
! 2034: ** May you share freely, never taking more than you give.
! 2035: **
! 2036: ******************************************************************************
! 2037: **
! 2038: ** This SQLite extension implements functions that compute SHA3 hashes
! 2039: ** in the way described by the (U.S.) NIST FIPS 202 SHA-3 Standard.
! 2040: ** Two SQL functions are implemented:
! 2041: **
! 2042: ** sha3(X,SIZE)
! 2043: ** sha3_query(Y,SIZE)
! 2044: **
! 2045: ** The sha3(X) function computes the SHA3 hash of the input X, or NULL if
! 2046: ** X is NULL.
! 2047: **
! 2048: ** The sha3_query(Y) function evaluates all queries in the SQL statements of Y
! 2049: ** and returns a hash of their results.
! 2050: **
! 2051: ** The SIZE argument is optional. If omitted, the SHA3-256 hash algorithm
! 2052: ** is used. If SIZE is included it must be one of the integers 224, 256,
! 2053: ** 384, or 512, to determine SHA3 hash variant that is computed.
! 2054: */
! 2055: /* #include "sqlite3ext.h" */
! 2056: SQLITE_EXTENSION_INIT1
! 2057: #include <assert.h>
! 2058: #include <string.h>
! 2059: #include <stdarg.h>
! 2060:
! 2061: #ifndef SQLITE_AMALGAMATION
! 2062: /* typedef sqlite3_uint64 u64; */
! 2063: #endif /* SQLITE_AMALGAMATION */
! 2064:
! 2065: /******************************************************************************
! 2066: ** The Hash Engine
! 2067: */
! 2068: /*
! 2069: ** Macros to determine whether the machine is big or little endian,
! 2070: ** and whether or not that determination is run-time or compile-time.
! 2071: **
! 2072: ** For best performance, an attempt is made to guess at the byte-order
! 2073: ** using C-preprocessor macros. If that is unsuccessful, or if
! 2074: ** -DSHA3_BYTEORDER=0 is set, then byte-order is determined
! 2075: ** at run-time.
! 2076: */
! 2077: #ifndef SHA3_BYTEORDER
! 2078: # if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
! 2079: defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
! 2080: defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
! 2081: defined(__arm__)
! 2082: # define SHA3_BYTEORDER 1234
! 2083: # elif defined(sparc) || defined(__ppc__)
! 2084: # define SHA3_BYTEORDER 4321
! 2085: # else
! 2086: # define SHA3_BYTEORDER 0
! 2087: # endif
! 2088: #endif
! 2089:
! 2090:
! 2091: /*
! 2092: ** State structure for a SHA3 hash in progress
! 2093: */
! 2094: typedef struct SHA3Context SHA3Context;
! 2095: struct SHA3Context {
! 2096: union {
! 2097: u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */
! 2098: unsigned char x[1600]; /* ... or 1600 bytes */
! 2099: } u;
! 2100: unsigned nRate; /* Bytes of input accepted per Keccak iteration */
! 2101: unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */
! 2102: unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */
! 2103: };
! 2104:
! 2105: /*
! 2106: ** A single step of the Keccak mixing function for a 1600-bit state
! 2107: */
! 2108: static void KeccakF1600Step(SHA3Context *p){
! 2109: int i;
! 2110: u64 b0, b1, b2, b3, b4;
! 2111: u64 c0, c1, c2, c3, c4;
! 2112: u64 d0, d1, d2, d3, d4;
! 2113: static const u64 RC[] = {
! 2114: 0x0000000000000001ULL, 0x0000000000008082ULL,
! 2115: 0x800000000000808aULL, 0x8000000080008000ULL,
! 2116: 0x000000000000808bULL, 0x0000000080000001ULL,
! 2117: 0x8000000080008081ULL, 0x8000000000008009ULL,
! 2118: 0x000000000000008aULL, 0x0000000000000088ULL,
! 2119: 0x0000000080008009ULL, 0x000000008000000aULL,
! 2120: 0x000000008000808bULL, 0x800000000000008bULL,
! 2121: 0x8000000000008089ULL, 0x8000000000008003ULL,
! 2122: 0x8000000000008002ULL, 0x8000000000000080ULL,
! 2123: 0x000000000000800aULL, 0x800000008000000aULL,
! 2124: 0x8000000080008081ULL, 0x8000000000008080ULL,
! 2125: 0x0000000080000001ULL, 0x8000000080008008ULL
! 2126: };
! 2127: # define a00 (p->u.s[0])
1.5 misho 2128: # define a01 (p->u.s[1])
2129: # define a02 (p->u.s[2])
2130: # define a03 (p->u.s[3])
2131: # define a04 (p->u.s[4])
2132: # define a10 (p->u.s[5])
2133: # define a11 (p->u.s[6])
2134: # define a12 (p->u.s[7])
2135: # define a13 (p->u.s[8])
2136: # define a14 (p->u.s[9])
2137: # define a20 (p->u.s[10])
2138: # define a21 (p->u.s[11])
2139: # define a22 (p->u.s[12])
2140: # define a23 (p->u.s[13])
2141: # define a24 (p->u.s[14])
2142: # define a30 (p->u.s[15])
2143: # define a31 (p->u.s[16])
2144: # define a32 (p->u.s[17])
2145: # define a33 (p->u.s[18])
2146: # define a34 (p->u.s[19])
2147: # define a40 (p->u.s[20])
2148: # define a41 (p->u.s[21])
2149: # define a42 (p->u.s[22])
2150: # define a43 (p->u.s[23])
2151: # define a44 (p->u.s[24])
2152: # define ROL64(a,x) ((a<<x)|(a>>(64-x)))
2153:
2154: for(i=0; i<24; i+=4){
2155: c0 = a00^a10^a20^a30^a40;
2156: c1 = a01^a11^a21^a31^a41;
2157: c2 = a02^a12^a22^a32^a42;
2158: c3 = a03^a13^a23^a33^a43;
2159: c4 = a04^a14^a24^a34^a44;
2160: d0 = c4^ROL64(c1, 1);
2161: d1 = c0^ROL64(c2, 1);
2162: d2 = c1^ROL64(c3, 1);
2163: d3 = c2^ROL64(c4, 1);
2164: d4 = c3^ROL64(c0, 1);
2165:
2166: b0 = (a00^d0);
2167: b1 = ROL64((a11^d1), 44);
2168: b2 = ROL64((a22^d2), 43);
2169: b3 = ROL64((a33^d3), 21);
2170: b4 = ROL64((a44^d4), 14);
2171: a00 = b0 ^((~b1)& b2 );
2172: a00 ^= RC[i];
2173: a11 = b1 ^((~b2)& b3 );
2174: a22 = b2 ^((~b3)& b4 );
2175: a33 = b3 ^((~b4)& b0 );
2176: a44 = b4 ^((~b0)& b1 );
2177:
2178: b2 = ROL64((a20^d0), 3);
2179: b3 = ROL64((a31^d1), 45);
2180: b4 = ROL64((a42^d2), 61);
2181: b0 = ROL64((a03^d3), 28);
2182: b1 = ROL64((a14^d4), 20);
2183: a20 = b0 ^((~b1)& b2 );
2184: a31 = b1 ^((~b2)& b3 );
2185: a42 = b2 ^((~b3)& b4 );
2186: a03 = b3 ^((~b4)& b0 );
2187: a14 = b4 ^((~b0)& b1 );
2188:
2189: b4 = ROL64((a40^d0), 18);
2190: b0 = ROL64((a01^d1), 1);
2191: b1 = ROL64((a12^d2), 6);
2192: b2 = ROL64((a23^d3), 25);
2193: b3 = ROL64((a34^d4), 8);
2194: a40 = b0 ^((~b1)& b2 );
2195: a01 = b1 ^((~b2)& b3 );
2196: a12 = b2 ^((~b3)& b4 );
2197: a23 = b3 ^((~b4)& b0 );
2198: a34 = b4 ^((~b0)& b1 );
2199:
2200: b1 = ROL64((a10^d0), 36);
2201: b2 = ROL64((a21^d1), 10);
2202: b3 = ROL64((a32^d2), 15);
2203: b4 = ROL64((a43^d3), 56);
2204: b0 = ROL64((a04^d4), 27);
2205: a10 = b0 ^((~b1)& b2 );
2206: a21 = b1 ^((~b2)& b3 );
2207: a32 = b2 ^((~b3)& b4 );
2208: a43 = b3 ^((~b4)& b0 );
2209: a04 = b4 ^((~b0)& b1 );
2210:
2211: b3 = ROL64((a30^d0), 41);
2212: b4 = ROL64((a41^d1), 2);
2213: b0 = ROL64((a02^d2), 62);
2214: b1 = ROL64((a13^d3), 55);
2215: b2 = ROL64((a24^d4), 39);
2216: a30 = b0 ^((~b1)& b2 );
2217: a41 = b1 ^((~b2)& b3 );
2218: a02 = b2 ^((~b3)& b4 );
2219: a13 = b3 ^((~b4)& b0 );
2220: a24 = b4 ^((~b0)& b1 );
2221:
2222: c0 = a00^a20^a40^a10^a30;
2223: c1 = a11^a31^a01^a21^a41;
2224: c2 = a22^a42^a12^a32^a02;
2225: c3 = a33^a03^a23^a43^a13;
2226: c4 = a44^a14^a34^a04^a24;
2227: d0 = c4^ROL64(c1, 1);
2228: d1 = c0^ROL64(c2, 1);
2229: d2 = c1^ROL64(c3, 1);
2230: d3 = c2^ROL64(c4, 1);
2231: d4 = c3^ROL64(c0, 1);
2232:
2233: b0 = (a00^d0);
2234: b1 = ROL64((a31^d1), 44);
2235: b2 = ROL64((a12^d2), 43);
2236: b3 = ROL64((a43^d3), 21);
2237: b4 = ROL64((a24^d4), 14);
2238: a00 = b0 ^((~b1)& b2 );
2239: a00 ^= RC[i+1];
2240: a31 = b1 ^((~b2)& b3 );
2241: a12 = b2 ^((~b3)& b4 );
2242: a43 = b3 ^((~b4)& b0 );
2243: a24 = b4 ^((~b0)& b1 );
2244:
2245: b2 = ROL64((a40^d0), 3);
2246: b3 = ROL64((a21^d1), 45);
2247: b4 = ROL64((a02^d2), 61);
2248: b0 = ROL64((a33^d3), 28);
2249: b1 = ROL64((a14^d4), 20);
2250: a40 = b0 ^((~b1)& b2 );
2251: a21 = b1 ^((~b2)& b3 );
2252: a02 = b2 ^((~b3)& b4 );
2253: a33 = b3 ^((~b4)& b0 );
2254: a14 = b4 ^((~b0)& b1 );
2255:
2256: b4 = ROL64((a30^d0), 18);
2257: b0 = ROL64((a11^d1), 1);
2258: b1 = ROL64((a42^d2), 6);
2259: b2 = ROL64((a23^d3), 25);
2260: b3 = ROL64((a04^d4), 8);
2261: a30 = b0 ^((~b1)& b2 );
2262: a11 = b1 ^((~b2)& b3 );
2263: a42 = b2 ^((~b3)& b4 );
2264: a23 = b3 ^((~b4)& b0 );
2265: a04 = b4 ^((~b0)& b1 );
2266:
2267: b1 = ROL64((a20^d0), 36);
2268: b2 = ROL64((a01^d1), 10);
2269: b3 = ROL64((a32^d2), 15);
2270: b4 = ROL64((a13^d3), 56);
2271: b0 = ROL64((a44^d4), 27);
2272: a20 = b0 ^((~b1)& b2 );
2273: a01 = b1 ^((~b2)& b3 );
2274: a32 = b2 ^((~b3)& b4 );
2275: a13 = b3 ^((~b4)& b0 );
2276: a44 = b4 ^((~b0)& b1 );
2277:
2278: b3 = ROL64((a10^d0), 41);
2279: b4 = ROL64((a41^d1), 2);
2280: b0 = ROL64((a22^d2), 62);
2281: b1 = ROL64((a03^d3), 55);
2282: b2 = ROL64((a34^d4), 39);
2283: a10 = b0 ^((~b1)& b2 );
2284: a41 = b1 ^((~b2)& b3 );
2285: a22 = b2 ^((~b3)& b4 );
2286: a03 = b3 ^((~b4)& b0 );
2287: a34 = b4 ^((~b0)& b1 );
2288:
2289: c0 = a00^a40^a30^a20^a10;
2290: c1 = a31^a21^a11^a01^a41;
2291: c2 = a12^a02^a42^a32^a22;
2292: c3 = a43^a33^a23^a13^a03;
2293: c4 = a24^a14^a04^a44^a34;
2294: d0 = c4^ROL64(c1, 1);
2295: d1 = c0^ROL64(c2, 1);
2296: d2 = c1^ROL64(c3, 1);
2297: d3 = c2^ROL64(c4, 1);
2298: d4 = c3^ROL64(c0, 1);
2299:
2300: b0 = (a00^d0);
2301: b1 = ROL64((a21^d1), 44);
2302: b2 = ROL64((a42^d2), 43);
2303: b3 = ROL64((a13^d3), 21);
2304: b4 = ROL64((a34^d4), 14);
2305: a00 = b0 ^((~b1)& b2 );
2306: a00 ^= RC[i+2];
2307: a21 = b1 ^((~b2)& b3 );
2308: a42 = b2 ^((~b3)& b4 );
2309: a13 = b3 ^((~b4)& b0 );
2310: a34 = b4 ^((~b0)& b1 );
2311:
2312: b2 = ROL64((a30^d0), 3);
2313: b3 = ROL64((a01^d1), 45);
2314: b4 = ROL64((a22^d2), 61);
2315: b0 = ROL64((a43^d3), 28);
2316: b1 = ROL64((a14^d4), 20);
2317: a30 = b0 ^((~b1)& b2 );
2318: a01 = b1 ^((~b2)& b3 );
2319: a22 = b2 ^((~b3)& b4 );
2320: a43 = b3 ^((~b4)& b0 );
2321: a14 = b4 ^((~b0)& b1 );
2322:
2323: b4 = ROL64((a10^d0), 18);
2324: b0 = ROL64((a31^d1), 1);
2325: b1 = ROL64((a02^d2), 6);
2326: b2 = ROL64((a23^d3), 25);
2327: b3 = ROL64((a44^d4), 8);
2328: a10 = b0 ^((~b1)& b2 );
2329: a31 = b1 ^((~b2)& b3 );
2330: a02 = b2 ^((~b3)& b4 );
2331: a23 = b3 ^((~b4)& b0 );
2332: a44 = b4 ^((~b0)& b1 );
2333:
2334: b1 = ROL64((a40^d0), 36);
2335: b2 = ROL64((a11^d1), 10);
2336: b3 = ROL64((a32^d2), 15);
2337: b4 = ROL64((a03^d3), 56);
2338: b0 = ROL64((a24^d4), 27);
2339: a40 = b0 ^((~b1)& b2 );
2340: a11 = b1 ^((~b2)& b3 );
2341: a32 = b2 ^((~b3)& b4 );
2342: a03 = b3 ^((~b4)& b0 );
2343: a24 = b4 ^((~b0)& b1 );
2344:
2345: b3 = ROL64((a20^d0), 41);
2346: b4 = ROL64((a41^d1), 2);
2347: b0 = ROL64((a12^d2), 62);
2348: b1 = ROL64((a33^d3), 55);
2349: b2 = ROL64((a04^d4), 39);
2350: a20 = b0 ^((~b1)& b2 );
2351: a41 = b1 ^((~b2)& b3 );
2352: a12 = b2 ^((~b3)& b4 );
2353: a33 = b3 ^((~b4)& b0 );
2354: a04 = b4 ^((~b0)& b1 );
2355:
2356: c0 = a00^a30^a10^a40^a20;
2357: c1 = a21^a01^a31^a11^a41;
2358: c2 = a42^a22^a02^a32^a12;
2359: c3 = a13^a43^a23^a03^a33;
2360: c4 = a34^a14^a44^a24^a04;
2361: d0 = c4^ROL64(c1, 1);
2362: d1 = c0^ROL64(c2, 1);
2363: d2 = c1^ROL64(c3, 1);
2364: d3 = c2^ROL64(c4, 1);
2365: d4 = c3^ROL64(c0, 1);
2366:
2367: b0 = (a00^d0);
2368: b1 = ROL64((a01^d1), 44);
2369: b2 = ROL64((a02^d2), 43);
2370: b3 = ROL64((a03^d3), 21);
2371: b4 = ROL64((a04^d4), 14);
2372: a00 = b0 ^((~b1)& b2 );
2373: a00 ^= RC[i+3];
2374: a01 = b1 ^((~b2)& b3 );
2375: a02 = b2 ^((~b3)& b4 );
2376: a03 = b3 ^((~b4)& b0 );
2377: a04 = b4 ^((~b0)& b1 );
2378:
2379: b2 = ROL64((a10^d0), 3);
2380: b3 = ROL64((a11^d1), 45);
2381: b4 = ROL64((a12^d2), 61);
2382: b0 = ROL64((a13^d3), 28);
2383: b1 = ROL64((a14^d4), 20);
2384: a10 = b0 ^((~b1)& b2 );
2385: a11 = b1 ^((~b2)& b3 );
2386: a12 = b2 ^((~b3)& b4 );
2387: a13 = b3 ^((~b4)& b0 );
2388: a14 = b4 ^((~b0)& b1 );
2389:
2390: b4 = ROL64((a20^d0), 18);
2391: b0 = ROL64((a21^d1), 1);
2392: b1 = ROL64((a22^d2), 6);
2393: b2 = ROL64((a23^d3), 25);
2394: b3 = ROL64((a24^d4), 8);
2395: a20 = b0 ^((~b1)& b2 );
2396: a21 = b1 ^((~b2)& b3 );
2397: a22 = b2 ^((~b3)& b4 );
2398: a23 = b3 ^((~b4)& b0 );
2399: a24 = b4 ^((~b0)& b1 );
2400:
2401: b1 = ROL64((a30^d0), 36);
2402: b2 = ROL64((a31^d1), 10);
2403: b3 = ROL64((a32^d2), 15);
2404: b4 = ROL64((a33^d3), 56);
2405: b0 = ROL64((a34^d4), 27);
2406: a30 = b0 ^((~b1)& b2 );
2407: a31 = b1 ^((~b2)& b3 );
2408: a32 = b2 ^((~b3)& b4 );
2409: a33 = b3 ^((~b4)& b0 );
2410: a34 = b4 ^((~b0)& b1 );
2411:
2412: b3 = ROL64((a40^d0), 41);
2413: b4 = ROL64((a41^d1), 2);
2414: b0 = ROL64((a42^d2), 62);
2415: b1 = ROL64((a43^d3), 55);
2416: b2 = ROL64((a44^d4), 39);
2417: a40 = b0 ^((~b1)& b2 );
2418: a41 = b1 ^((~b2)& b3 );
2419: a42 = b2 ^((~b3)& b4 );
2420: a43 = b3 ^((~b4)& b0 );
2421: a44 = b4 ^((~b0)& b1 );
2422: }
2423: }
2424:
2425: /*
2426: ** Initialize a new hash. iSize determines the size of the hash
2427: ** in bits and should be one of 224, 256, 384, or 512. Or iSize
2428: ** can be zero to use the default hash size of 256 bits.
2429: */
2430: static void SHA3Init(SHA3Context *p, int iSize){
2431: memset(p, 0, sizeof(*p));
2432: if( iSize>=128 && iSize<=512 ){
2433: p->nRate = (1600 - ((iSize + 31)&~31)*2)/8;
2434: }else{
2435: p->nRate = (1600 - 2*256)/8;
2436: }
2437: #if SHA3_BYTEORDER==1234
2438: /* Known to be little-endian at compile-time. No-op */
2439: #elif SHA3_BYTEORDER==4321
2440: p->ixMask = 7; /* Big-endian */
2441: #else
2442: {
2443: static unsigned int one = 1;
2444: if( 1==*(unsigned char*)&one ){
2445: /* Little endian. No byte swapping. */
2446: p->ixMask = 0;
2447: }else{
2448: /* Big endian. Byte swap. */
2449: p->ixMask = 7;
2450: }
2451: }
2452: #endif
2453: }
2454:
2455: /*
2456: ** Make consecutive calls to the SHA3Update function to add new content
2457: ** to the hash
2458: */
2459: static void SHA3Update(
2460: SHA3Context *p,
2461: const unsigned char *aData,
2462: unsigned int nData
2463: ){
2464: unsigned int i = 0;
1.6.2.1 ! misho 2465: if( aData==0 ) return;
1.5 misho 2466: #if SHA3_BYTEORDER==1234
2467: if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
2468: for(; i+7<nData; i+=8){
2469: p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i];
2470: p->nLoaded += 8;
2471: if( p->nLoaded>=p->nRate ){
2472: KeccakF1600Step(p);
2473: p->nLoaded = 0;
1.2 misho 2474: }
2475: }
1.5 misho 2476: }
2477: #endif
2478: for(; i<nData; i++){
2479: #if SHA3_BYTEORDER==1234
2480: p->u.x[p->nLoaded] ^= aData[i];
2481: #elif SHA3_BYTEORDER==4321
2482: p->u.x[p->nLoaded^0x07] ^= aData[i];
2483: #else
2484: p->u.x[p->nLoaded^p->ixMask] ^= aData[i];
2485: #endif
2486: p->nLoaded++;
2487: if( p->nLoaded==p->nRate ){
2488: KeccakF1600Step(p);
2489: p->nLoaded = 0;
2490: }
2491: }
2492: }
2493:
2494: /*
2495: ** After all content has been added, invoke SHA3Final() to compute
2496: ** the final hash. The function returns a pointer to the binary
2497: ** hash value.
2498: */
2499: static unsigned char *SHA3Final(SHA3Context *p){
2500: unsigned int i;
2501: if( p->nLoaded==p->nRate-1 ){
2502: const unsigned char c1 = 0x86;
2503: SHA3Update(p, &c1, 1);
2504: }else{
2505: const unsigned char c2 = 0x06;
2506: const unsigned char c3 = 0x80;
2507: SHA3Update(p, &c2, 1);
2508: p->nLoaded = p->nRate - 1;
2509: SHA3Update(p, &c3, 1);
2510: }
2511: for(i=0; i<p->nRate; i++){
2512: p->u.x[i+p->nRate] = p->u.x[i^p->ixMask];
2513: }
2514: return &p->u.x[p->nRate];
2515: }
2516: /* End of the hashing logic
2517: *****************************************************************************/
2518:
2519: /*
2520: ** Implementation of the sha3(X,SIZE) function.
2521: **
2522: ** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default
2523: ** size is 256. If X is a BLOB, it is hashed as is.
2524: ** For all other non-NULL types of input, X is converted into a UTF-8 string
2525: ** and the string is hashed without the trailing 0x00 terminator. The hash
2526: ** of a NULL value is NULL.
2527: */
2528: static void sha3Func(
2529: sqlite3_context *context,
2530: int argc,
2531: sqlite3_value **argv
2532: ){
2533: SHA3Context cx;
2534: int eType = sqlite3_value_type(argv[0]);
2535: int nByte = sqlite3_value_bytes(argv[0]);
2536: int iSize;
2537: if( argc==1 ){
2538: iSize = 256;
2539: }else{
2540: iSize = sqlite3_value_int(argv[1]);
2541: if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
2542: sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
2543: "384 512", -1);
2544: return;
2545: }
2546: }
2547: if( eType==SQLITE_NULL ) return;
2548: SHA3Init(&cx, iSize);
2549: if( eType==SQLITE_BLOB ){
2550: SHA3Update(&cx, sqlite3_value_blob(argv[0]), nByte);
2551: }else{
2552: SHA3Update(&cx, sqlite3_value_text(argv[0]), nByte);
2553: }
2554: sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
2555: }
2556:
2557: /* Compute a string using sqlite3_vsnprintf() with a maximum length
2558: ** of 50 bytes and add it to the hash.
2559: */
1.6.2.1 ! misho 2560: static void sha3_step_vformat(
1.5 misho 2561: SHA3Context *p, /* Add content to this context */
2562: const char *zFormat,
2563: ...
2564: ){
2565: va_list ap;
2566: int n;
2567: char zBuf[50];
2568: va_start(ap, zFormat);
2569: sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
2570: va_end(ap);
2571: n = (int)strlen(zBuf);
2572: SHA3Update(p, (unsigned char*)zBuf, n);
2573: }
2574:
2575: /*
2576: ** Implementation of the sha3_query(SQL,SIZE) function.
2577: **
2578: ** This function compiles and runs the SQL statement(s) given in the
2579: ** argument. The results are hashed using a SIZE-bit SHA3. The default
2580: ** size is 256.
2581: **
2582: ** The format of the byte stream that is hashed is summarized as follows:
2583: **
2584: ** S<n>:<sql>
2585: ** R
2586: ** N
2587: ** I<int>
2588: ** F<ieee-float>
2589: ** B<size>:<bytes>
2590: ** T<size>:<text>
2591: **
2592: ** <sql> is the original SQL text for each statement run and <n> is
2593: ** the size of that text. The SQL text is UTF-8. A single R character
2594: ** occurs before the start of each row. N means a NULL value.
2595: ** I mean an 8-byte little-endian integer <int>. F is a floating point
2596: ** number with an 8-byte little-endian IEEE floating point value <ieee-float>.
2597: ** B means blobs of <size> bytes. T means text rendered as <size>
2598: ** bytes of UTF-8. The <n> and <size> values are expressed as an ASCII
2599: ** text integers.
2600: **
2601: ** For each SQL statement in the X input, there is one S segment. Each
2602: ** S segment is followed by zero or more R segments, one for each row in the
2603: ** result set. After each R, there are one or more N, I, F, B, or T segments,
2604: ** one for each column in the result set. Segments are concatentated directly
2605: ** with no delimiters of any kind.
2606: */
2607: static void sha3QueryFunc(
2608: sqlite3_context *context,
2609: int argc,
2610: sqlite3_value **argv
2611: ){
2612: sqlite3 *db = sqlite3_context_db_handle(context);
2613: const char *zSql = (const char*)sqlite3_value_text(argv[0]);
2614: sqlite3_stmt *pStmt = 0;
2615: int nCol; /* Number of columns in the result set */
2616: int i; /* Loop counter */
2617: int rc;
2618: int n;
2619: const char *z;
2620: SHA3Context cx;
2621: int iSize;
2622:
2623: if( argc==1 ){
2624: iSize = 256;
2625: }else{
2626: iSize = sqlite3_value_int(argv[1]);
2627: if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
2628: sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
2629: "384 512", -1);
2630: return;
2631: }
2632: }
2633: if( zSql==0 ) return;
2634: SHA3Init(&cx, iSize);
2635: while( zSql[0] ){
2636: rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
2637: if( rc ){
2638: char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s",
2639: zSql, sqlite3_errmsg(db));
2640: sqlite3_finalize(pStmt);
2641: sqlite3_result_error(context, zMsg, -1);
2642: sqlite3_free(zMsg);
2643: return;
2644: }
2645: if( !sqlite3_stmt_readonly(pStmt) ){
2646: char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt));
2647: sqlite3_finalize(pStmt);
2648: sqlite3_result_error(context, zMsg, -1);
2649: sqlite3_free(zMsg);
2650: return;
2651: }
2652: nCol = sqlite3_column_count(pStmt);
2653: z = sqlite3_sql(pStmt);
1.6 misho 2654: if( z ){
2655: n = (int)strlen(z);
1.6.2.1 ! misho 2656: sha3_step_vformat(&cx,"S%d:",n);
1.6 misho 2657: SHA3Update(&cx,(unsigned char*)z,n);
2658: }
1.5 misho 2659:
2660: /* Compute a hash over the result of the query */
2661: while( SQLITE_ROW==sqlite3_step(pStmt) ){
2662: SHA3Update(&cx,(const unsigned char*)"R",1);
2663: for(i=0; i<nCol; i++){
2664: switch( sqlite3_column_type(pStmt,i) ){
2665: case SQLITE_NULL: {
2666: SHA3Update(&cx, (const unsigned char*)"N",1);
2667: break;
1.2 misho 2668: }
1.5 misho 2669: case SQLITE_INTEGER: {
2670: sqlite3_uint64 u;
2671: int j;
2672: unsigned char x[9];
2673: sqlite3_int64 v = sqlite3_column_int64(pStmt,i);
2674: memcpy(&u, &v, 8);
2675: for(j=8; j>=1; j--){
2676: x[j] = u & 0xff;
2677: u >>= 8;
1.3 misho 2678: }
1.5 misho 2679: x[0] = 'I';
2680: SHA3Update(&cx, x, 9);
2681: break;
1.2 misho 2682: }
1.5 misho 2683: case SQLITE_FLOAT: {
2684: sqlite3_uint64 u;
2685: int j;
2686: unsigned char x[9];
2687: double r = sqlite3_column_double(pStmt,i);
2688: memcpy(&u, &r, 8);
2689: for(j=8; j>=1; j--){
2690: x[j] = u & 0xff;
2691: u >>= 8;
1.2 misho 2692: }
1.5 misho 2693: x[0] = 'F';
2694: SHA3Update(&cx,x,9);
2695: break;
2696: }
2697: case SQLITE_TEXT: {
2698: int n2 = sqlite3_column_bytes(pStmt, i);
2699: const unsigned char *z2 = sqlite3_column_text(pStmt, i);
1.6.2.1 ! misho 2700: sha3_step_vformat(&cx,"T%d:",n2);
1.5 misho 2701: SHA3Update(&cx, z2, n2);
2702: break;
2703: }
2704: case SQLITE_BLOB: {
2705: int n2 = sqlite3_column_bytes(pStmt, i);
2706: const unsigned char *z2 = sqlite3_column_blob(pStmt, i);
1.6.2.1 ! misho 2707: sha3_step_vformat(&cx,"B%d:",n2);
1.5 misho 2708: SHA3Update(&cx, z2, n2);
2709: break;
1.2 misho 2710: }
2711: }
2712: }
1.5 misho 2713: }
2714: sqlite3_finalize(pStmt);
2715: }
2716: sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
2717: }
2718:
2719:
2720: #ifdef _WIN32
2721:
2722: #endif
2723: int sqlite3_shathree_init(
2724: sqlite3 *db,
2725: char **pzErrMsg,
2726: const sqlite3_api_routines *pApi
2727: ){
2728: int rc = SQLITE_OK;
2729: SQLITE_EXTENSION_INIT2(pApi);
2730: (void)pzErrMsg; /* Unused parameter */
2731: rc = sqlite3_create_function(db, "sha3", 1,
2732: SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
2733: 0, sha3Func, 0, 0);
2734: if( rc==SQLITE_OK ){
2735: rc = sqlite3_create_function(db, "sha3", 2,
2736: SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
2737: 0, sha3Func, 0, 0);
2738: }
2739: if( rc==SQLITE_OK ){
2740: rc = sqlite3_create_function(db, "sha3_query", 1,
2741: SQLITE_UTF8 | SQLITE_DIRECTONLY,
2742: 0, sha3QueryFunc, 0, 0);
2743: }
2744: if( rc==SQLITE_OK ){
2745: rc = sqlite3_create_function(db, "sha3_query", 2,
2746: SQLITE_UTF8 | SQLITE_DIRECTONLY,
2747: 0, sha3QueryFunc, 0, 0);
2748: }
2749: return rc;
2750: }
2751:
2752: /************************* End ../ext/misc/shathree.c ********************/
1.6.2.1 ! misho 2753: /************************* Begin ../ext/misc/uint.c ******************/
1.5 misho 2754: /*
1.6.2.1 ! misho 2755: ** 2020-04-14
1.5 misho 2756: **
2757: ** The author disclaims copyright to this source code. In place of
2758: ** a legal notice, here is a blessing:
2759: **
2760: ** May you do good and not evil.
2761: ** May you find forgiveness for yourself and forgive others.
2762: ** May you share freely, never taking more than you give.
2763: **
2764: ******************************************************************************
2765: **
1.6.2.1 ! misho 2766: ** This SQLite extension implements the UINT collating sequence.
1.5 misho 2767: **
1.6.2.1 ! misho 2768: ** UINT works like BINARY for text, except that embedded strings
! 2769: ** of digits compare in numeric order.
1.5 misho 2770: **
1.6.2.1 ! misho 2771: ** * Leading zeros are handled properly, in the sense that
! 2772: ** they do not mess of the maginitude comparison of embedded
! 2773: ** strings of digits. "x00123y" is equal to "x123y".
1.5 misho 2774: **
1.6.2.1 ! misho 2775: ** * Only unsigned integers are recognized. Plus and minus
! 2776: ** signs are ignored. Decimal points and exponential notation
! 2777: ** are ignored.
1.5 misho 2778: **
1.6.2.1 ! misho 2779: ** * Embedded integers can be of arbitrary length. Comparison
! 2780: ** is *not* limited integers that can be expressed as a
! 2781: ** 64-bit machine integer.
1.5 misho 2782: */
2783: /* #include "sqlite3ext.h" */
2784: SQLITE_EXTENSION_INIT1
2785: #include <assert.h>
1.6.2.1 ! misho 2786: #include <string.h>
! 2787: #include <ctype.h>
1.5 misho 2788:
2789: /*
1.6.2.1 ! misho 2790: ** Compare text in lexicographic order, except strings of digits
! 2791: ** compare in numeric order.
1.5 misho 2792: */
1.6.2.1 ! misho 2793: static int uintCollFunc(
! 2794: void *notUsed,
! 2795: int nKey1, const void *pKey1,
! 2796: int nKey2, const void *pKey2
! 2797: ){
! 2798: const unsigned char *zA = (const unsigned char*)pKey1;
! 2799: const unsigned char *zB = (const unsigned char*)pKey2;
! 2800: int i=0, j=0, x;
! 2801: (void)notUsed;
! 2802: while( i<nKey1 && j<nKey2 ){
! 2803: x = zA[i] - zB[j];
! 2804: if( isdigit(zA[i]) ){
! 2805: int k;
! 2806: if( !isdigit(zB[j]) ) return x;
! 2807: while( i<nKey1 && zA[i]=='0' ){ i++; }
! 2808: while( j<nKey2 && zB[j]=='0' ){ j++; }
! 2809: k = 0;
! 2810: while( i+k<nKey1 && isdigit(zA[i+k])
! 2811: && j+k<nKey2 && isdigit(zB[j+k]) ){
! 2812: k++;
! 2813: }
! 2814: if( i+k<nKey1 && isdigit(zA[i+k]) ){
! 2815: return +1;
! 2816: }else if( j+k<nKey2 && isdigit(zB[j+k]) ){
! 2817: return -1;
! 2818: }else{
! 2819: x = memcmp(zA+i, zB+j, k);
! 2820: if( x ) return x;
! 2821: i += k;
! 2822: j += k;
! 2823: }
! 2824: }else if( x ){
! 2825: return x;
! 2826: }else{
! 2827: i++;
! 2828: j++;
! 2829: }
1.5 misho 2830: }
1.6.2.1 ! misho 2831: return (nKey1 - i) - (nKey2 - j);
1.5 misho 2832: }
2833:
1.6.2.1 ! misho 2834: #ifdef _WIN32
! 2835:
! 2836: #endif
! 2837: int sqlite3_uint_init(
! 2838: sqlite3 *db,
! 2839: char **pzErrMsg,
! 2840: const sqlite3_api_routines *pApi
1.5 misho 2841: ){
1.6.2.1 ! misho 2842: SQLITE_EXTENSION_INIT2(pApi);
! 2843: (void)pzErrMsg; /* Unused parameter */
! 2844: return sqlite3_create_collation(db, "uint", SQLITE_UTF8, 0, uintCollFunc);
1.5 misho 2845: }
2846:
1.6.2.1 ! misho 2847: /************************* End ../ext/misc/uint.c ********************/
! 2848: /************************* Begin ../ext/misc/decimal.c ******************/
1.5 misho 2849: /*
1.6.2.1 ! misho 2850: ** 2020-06-22
! 2851: **
! 2852: ** The author disclaims copyright to this source code. In place of
! 2853: ** a legal notice, here is a blessing:
! 2854: **
! 2855: ** May you do good and not evil.
! 2856: ** May you find forgiveness for yourself and forgive others.
! 2857: ** May you share freely, never taking more than you give.
! 2858: **
! 2859: ******************************************************************************
! 2860: **
! 2861: ** Routines to implement arbitrary-precision decimal math.
! 2862: **
! 2863: ** The focus here is on simplicity and correctness, not performance.
1.5 misho 2864: */
1.6.2.1 ! misho 2865: /* #include "sqlite3ext.h" */
! 2866: SQLITE_EXTENSION_INIT1
! 2867: #include <assert.h>
! 2868: #include <string.h>
! 2869: #include <ctype.h>
! 2870: #include <stdlib.h>
1.5 misho 2871:
1.6.2.1 ! misho 2872: /* Mark a function parameter as unused, to suppress nuisance compiler
! 2873: ** warnings. */
! 2874: #ifndef UNUSED_PARAMETER
! 2875: # define UNUSED_PARAMETER(X) (void)(X)
! 2876: #endif
1.5 misho 2877:
2878:
1.6.2.1 ! misho 2879: /* A decimal object */
! 2880: typedef struct Decimal Decimal;
! 2881: struct Decimal {
! 2882: char sign; /* 0 for positive, 1 for negative */
! 2883: char oom; /* True if an OOM is encountered */
! 2884: char isNull; /* True if holds a NULL rather than a number */
! 2885: char isInit; /* True upon initialization */
! 2886: int nDigit; /* Total number of digits */
! 2887: int nFrac; /* Number of digits to the right of the decimal point */
! 2888: signed char *a; /* Array of digits. Most significant first. */
! 2889: };
1.5 misho 2890:
1.6.2.1 ! misho 2891: /*
! 2892: ** Release memory held by a Decimal, but do not free the object itself.
! 2893: */
! 2894: static void decimal_clear(Decimal *p){
! 2895: sqlite3_free(p->a);
1.5 misho 2896: }
2897:
2898: /*
1.6.2.1 ! misho 2899: ** Destroy a Decimal object
1.5 misho 2900: */
1.6.2.1 ! misho 2901: static void decimal_free(Decimal *p){
! 2902: if( p ){
! 2903: decimal_clear(p);
! 2904: sqlite3_free(p);
1.5 misho 2905: }
2906: }
2907:
2908: /*
1.6.2.1 ! misho 2909: ** Allocate a new Decimal object initialized to the text in zIn[].
! 2910: ** Return NULL if any kind of error occurs.
1.5 misho 2911: */
1.6.2.1 ! misho 2912: static Decimal *decimalNewFromText(const char *zIn, int n){
! 2913: Decimal *p = 0;
! 2914: int i;
! 2915: int iExp = 0;
1.5 misho 2916:
1.6.2.1 ! misho 2917: p = sqlite3_malloc( sizeof(*p) );
! 2918: if( p==0 ) goto new_from_text_failed;
! 2919: p->sign = 0;
! 2920: p->oom = 0;
! 2921: p->isInit = 1;
! 2922: p->isNull = 0;
! 2923: p->nDigit = 0;
! 2924: p->nFrac = 0;
! 2925: p->a = sqlite3_malloc64( n+1 );
! 2926: if( p->a==0 ) goto new_from_text_failed;
! 2927: for(i=0; isspace(zIn[i]); i++){}
! 2928: if( zIn[i]=='-' ){
! 2929: p->sign = 1;
! 2930: i++;
! 2931: }else if( zIn[i]=='+' ){
! 2932: i++;
1.5 misho 2933: }
1.6.2.1 ! misho 2934: while( i<n && zIn[i]=='0' ) i++;
! 2935: while( i<n ){
! 2936: char c = zIn[i];
! 2937: if( c>='0' && c<='9' ){
! 2938: p->a[p->nDigit++] = c - '0';
! 2939: }else if( c=='.' ){
! 2940: p->nFrac = p->nDigit + 1;
! 2941: }else if( c=='e' || c=='E' ){
! 2942: int j = i+1;
! 2943: int neg = 0;
! 2944: if( j>=n ) break;
! 2945: if( zIn[j]=='-' ){
! 2946: neg = 1;
! 2947: j++;
! 2948: }else if( zIn[j]=='+' ){
! 2949: j++;
1.5 misho 2950: }
1.6.2.1 ! misho 2951: while( j<n && iExp<1000000 ){
! 2952: if( zIn[j]>='0' && zIn[j]<='9' ){
! 2953: iExp = iExp*10 + zIn[j] - '0';
1.2 misho 2954: }
1.6.2.1 ! misho 2955: j++;
1.5 misho 2956: }
1.6.2.1 ! misho 2957: if( neg ) iExp = -iExp;
! 2958: break;
1.5 misho 2959: }
1.6.2.1 ! misho 2960: i++;
1.5 misho 2961: }
1.6.2.1 ! misho 2962: if( p->nFrac ){
! 2963: p->nFrac = p->nDigit - (p->nFrac - 1);
! 2964: }
! 2965: if( iExp>0 ){
! 2966: if( p->nFrac>0 ){
! 2967: if( iExp<=p->nFrac ){
! 2968: p->nFrac -= iExp;
! 2969: iExp = 0;
! 2970: }else{
! 2971: iExp -= p->nFrac;
! 2972: p->nFrac = 0;
! 2973: }
1.5 misho 2974: }
1.6.2.1 ! misho 2975: if( iExp>0 ){
! 2976: p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 );
! 2977: if( p->a==0 ) goto new_from_text_failed;
! 2978: memset(p->a+p->nDigit, 0, iExp);
! 2979: p->nDigit += iExp;
1.5 misho 2980: }
1.6.2.1 ! misho 2981: }else if( iExp<0 ){
! 2982: int nExtra;
! 2983: iExp = -iExp;
! 2984: nExtra = p->nDigit - p->nFrac - 1;
! 2985: if( nExtra ){
! 2986: if( nExtra>=iExp ){
! 2987: p->nFrac += iExp;
! 2988: iExp = 0;
! 2989: }else{
! 2990: iExp -= nExtra;
! 2991: p->nFrac = p->nDigit - 1;
! 2992: }
1.5 misho 2993: }
1.6.2.1 ! misho 2994: if( iExp>0 ){
! 2995: p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 );
! 2996: if( p->a==0 ) goto new_from_text_failed;
! 2997: memmove(p->a+iExp, p->a, p->nDigit);
! 2998: memset(p->a, 0, iExp);
! 2999: p->nDigit += iExp;
! 3000: p->nFrac += iExp;
1.5 misho 3001: }
3002: }
1.6.2.1 ! misho 3003: return p;
1.5 misho 3004:
1.6.2.1 ! misho 3005: new_from_text_failed:
! 3006: if( p ){
! 3007: if( p->a ) sqlite3_free(p->a);
! 3008: sqlite3_free(p);
! 3009: }
1.5 misho 3010: return 0;
3011: }
3012:
1.6.2.1 ! misho 3013: /* Forward reference */
! 3014: static Decimal *decimalFromDouble(double);
! 3015:
1.5 misho 3016: /*
1.6.2.1 ! misho 3017: ** Allocate a new Decimal object from an sqlite3_value. Return a pointer
! 3018: ** to the new object, or NULL if there is an error. If the pCtx argument
! 3019: ** is not NULL, then errors are reported on it as well.
! 3020: **
! 3021: ** If the pIn argument is SQLITE_TEXT or SQLITE_INTEGER, it is converted
! 3022: ** directly into a Decimal. For SQLITE_FLOAT or for SQLITE_BLOB of length
! 3023: ** 8 bytes, the resulting double value is expanded into its decimal equivalent.
! 3024: ** If pIn is NULL or if it is a BLOB that is not exactly 8 bytes in length,
! 3025: ** then NULL is returned.
1.5 misho 3026: */
1.6.2.1 ! misho 3027: static Decimal *decimal_new(
! 3028: sqlite3_context *pCtx, /* Report error here, if not null */
! 3029: sqlite3_value *pIn, /* Construct the decimal object from this */
! 3030: int bTextOnly /* Always interpret pIn as text if true */
! 3031: ){
! 3032: Decimal *p = 0;
! 3033: int eType = sqlite3_value_type(pIn);
! 3034: if( bTextOnly && (eType==SQLITE_FLOAT || eType==SQLITE_BLOB) ){
! 3035: eType = SQLITE_TEXT;
! 3036: }
! 3037: switch( eType ){
! 3038: case SQLITE_TEXT:
! 3039: case SQLITE_INTEGER: {
! 3040: const char *zIn = (const char*)sqlite3_value_text(pIn);
! 3041: int n = sqlite3_value_bytes(pIn);
! 3042: p = decimalNewFromText(zIn, n);
! 3043: if( p==0 ) goto new_failed;
! 3044: break;
! 3045: }
1.5 misho 3046:
1.6.2.1 ! misho 3047: case SQLITE_FLOAT: {
! 3048: p = decimalFromDouble(sqlite3_value_double(pIn));
! 3049: break;
! 3050: }
1.5 misho 3051:
1.6.2.1 ! misho 3052: case SQLITE_BLOB: {
! 3053: const unsigned char *x;
! 3054: unsigned int i;
! 3055: sqlite3_uint64 v = 0;
! 3056: double r;
1.5 misho 3057:
1.6.2.1 ! misho 3058: if( sqlite3_value_bytes(pIn)!=sizeof(r) ) break;
! 3059: x = sqlite3_value_blob(pIn);
! 3060: for(i=0; i<sizeof(r); i++){
! 3061: v = (v<<8) | x[i];
! 3062: }
! 3063: memcpy(&r, &v, sizeof(r));
! 3064: p = decimalFromDouble(r);
! 3065: break;
1.5 misho 3066: }
3067:
1.6.2.1 ! misho 3068: case SQLITE_NULL: {
! 3069: break;
1.5 misho 3070: }
3071: }
1.6.2.1 ! misho 3072: return p;
! 3073:
! 3074: new_failed:
! 3075: if( pCtx ) sqlite3_result_error_nomem(pCtx);
! 3076: sqlite3_free(p);
! 3077: return 0;
1.5 misho 3078: }
3079:
3080: /*
1.6.2.1 ! misho 3081: ** Make the given Decimal the result.
1.5 misho 3082: */
1.6.2.1 ! misho 3083: static void decimal_result(sqlite3_context *pCtx, Decimal *p){
! 3084: char *z;
! 3085: int i, j;
! 3086: int n;
! 3087: if( p==0 || p->oom ){
! 3088: sqlite3_result_error_nomem(pCtx);
! 3089: return;
! 3090: }
! 3091: if( p->isNull ){
! 3092: sqlite3_result_null(pCtx);
! 3093: return;
! 3094: }
! 3095: z = sqlite3_malloc( p->nDigit+4 );
! 3096: if( z==0 ){
! 3097: sqlite3_result_error_nomem(pCtx);
! 3098: return;
! 3099: }
! 3100: i = 0;
! 3101: if( p->nDigit==0 || (p->nDigit==1 && p->a[0]==0) ){
! 3102: p->sign = 0;
! 3103: }
! 3104: if( p->sign ){
1.5 misho 3105: z[0] = '-';
1.6.2.1 ! misho 3106: i = 1;
1.5 misho 3107: }
1.6.2.1 ! misho 3108: n = p->nDigit - p->nFrac;
! 3109: if( n<=0 ){
! 3110: z[i++] = '0';
1.5 misho 3111: }
1.6.2.1 ! misho 3112: j = 0;
! 3113: while( n>1 && p->a[j]==0 ){
! 3114: j++;
! 3115: n--;
! 3116: }
! 3117: while( n>0 ){
! 3118: z[i++] = p->a[j] + '0';
! 3119: j++;
! 3120: n--;
! 3121: }
! 3122: if( p->nFrac ){
! 3123: z[i++] = '.';
! 3124: do{
! 3125: z[i++] = p->a[j] + '0';
! 3126: j++;
! 3127: }while( j<p->nDigit );
! 3128: }
! 3129: z[i] = 0;
! 3130: sqlite3_result_text(pCtx, z, i, sqlite3_free);
1.5 misho 3131: }
3132:
1.6.2.1 ! misho 3133: /*
! 3134: ** Make the given Decimal the result in an format similar to '%+#e'.
! 3135: ** In other words, show exponential notation with leading and trailing
! 3136: ** zeros omitted.
! 3137: */
! 3138: static void decimal_result_sci(sqlite3_context *pCtx, Decimal *p){
! 3139: char *z; /* The output buffer */
! 3140: int i; /* Loop counter */
! 3141: int nZero; /* Number of leading zeros */
! 3142: int nDigit; /* Number of digits not counting trailing zeros */
! 3143: int nFrac; /* Digits to the right of the decimal point */
! 3144: int exp; /* Exponent value */
! 3145: signed char zero; /* Zero value */
! 3146: signed char *a; /* Array of digits */
1.5 misho 3147:
1.6.2.1 ! misho 3148: if( p==0 || p->oom ){
! 3149: sqlite3_result_error_nomem(pCtx);
! 3150: return;
! 3151: }
! 3152: if( p->isNull ){
! 3153: sqlite3_result_null(pCtx);
! 3154: return;
! 3155: }
! 3156: for(nDigit=p->nDigit; nDigit>0 && p->a[nDigit-1]==0; nDigit--){}
! 3157: for(nZero=0; nZero<nDigit && p->a[nZero]==0; nZero++){}
! 3158: nFrac = p->nFrac + (nDigit - p->nDigit);
! 3159: nDigit -= nZero;
! 3160: z = sqlite3_malloc( nDigit+20 );
! 3161: if( z==0 ){
! 3162: sqlite3_result_error_nomem(pCtx);
! 3163: return;
! 3164: }
! 3165: if( nDigit==0 ){
! 3166: zero = 0;
! 3167: a = &zero;
! 3168: nDigit = 1;
! 3169: nFrac = 0;
! 3170: }else{
! 3171: a = &p->a[nZero];
! 3172: }
! 3173: if( p->sign && nDigit>0 ){
! 3174: z[0] = '-';
! 3175: }else{
! 3176: z[0] = '+';
! 3177: }
! 3178: z[1] = a[0]+'0';
! 3179: z[2] = '.';
! 3180: if( nDigit==1 ){
! 3181: z[3] = '0';
! 3182: i = 4;
! 3183: }else{
! 3184: for(i=1; i<nDigit; i++){
! 3185: z[2+i] = a[i]+'0';
! 3186: }
! 3187: i = nDigit+2;
! 3188: }
! 3189: exp = nDigit - nFrac - 1;
! 3190: sqlite3_snprintf(nDigit+20-i, &z[i], "e%+03d", exp);
! 3191: sqlite3_result_text(pCtx, z, -1, sqlite3_free);
! 3192: }
1.5 misho 3193:
3194: /*
1.6.2.1 ! misho 3195: ** Compare to Decimal objects. Return negative, 0, or positive if the
! 3196: ** first object is less than, equal to, or greater than the second.
! 3197: **
! 3198: ** Preconditions for this routine:
! 3199: **
! 3200: ** pA!=0
! 3201: ** pA->isNull==0
! 3202: ** pB!=0
! 3203: ** pB->isNull==0
1.5 misho 3204: */
1.6.2.1 ! misho 3205: static int decimal_cmp(const Decimal *pA, const Decimal *pB){
! 3206: int nASig, nBSig, rc, n;
! 3207: if( pA->sign!=pB->sign ){
! 3208: return pA->sign ? -1 : +1;
! 3209: }
! 3210: if( pA->sign ){
! 3211: const Decimal *pTemp = pA;
! 3212: pA = pB;
! 3213: pB = pTemp;
! 3214: }
! 3215: nASig = pA->nDigit - pA->nFrac;
! 3216: nBSig = pB->nDigit - pB->nFrac;
! 3217: if( nASig!=nBSig ){
! 3218: return nASig - nBSig;
! 3219: }
! 3220: n = pA->nDigit;
! 3221: if( n>pB->nDigit ) n = pB->nDigit;
! 3222: rc = memcmp(pA->a, pB->a, n);
! 3223: if( rc==0 ){
! 3224: rc = pA->nDigit - pB->nDigit;
1.5 misho 3225: }
3226: return rc;
3227: }
3228:
3229: /*
1.6.2.1 ! misho 3230: ** SQL Function: decimal_cmp(X, Y)
! 3231: **
! 3232: ** Return negative, zero, or positive if X is less then, equal to, or
! 3233: ** greater than Y.
1.5 misho 3234: */
1.6.2.1 ! misho 3235: static void decimalCmpFunc(
! 3236: sqlite3_context *context,
! 3237: int argc,
! 3238: sqlite3_value **argv
! 3239: ){
! 3240: Decimal *pA = 0, *pB = 0;
! 3241: int rc;
1.5 misho 3242:
1.6.2.1 ! misho 3243: UNUSED_PARAMETER(argc);
! 3244: pA = decimal_new(context, argv[0], 1);
! 3245: if( pA==0 || pA->isNull ) goto cmp_done;
! 3246: pB = decimal_new(context, argv[1], 1);
! 3247: if( pB==0 || pB->isNull ) goto cmp_done;
! 3248: rc = decimal_cmp(pA, pB);
! 3249: if( rc<0 ) rc = -1;
! 3250: else if( rc>0 ) rc = +1;
! 3251: sqlite3_result_int(context, rc);
! 3252: cmp_done:
! 3253: decimal_free(pA);
! 3254: decimal_free(pB);
1.5 misho 3255: }
3256:
3257: /*
1.6.2.1 ! misho 3258: ** Expand the Decimal so that it has a least nDigit digits and nFrac
! 3259: ** digits to the right of the decimal point.
! 3260: */
! 3261: static void decimal_expand(Decimal *p, int nDigit, int nFrac){
! 3262: int nAddSig;
! 3263: int nAddFrac;
! 3264: if( p==0 ) return;
! 3265: nAddFrac = nFrac - p->nFrac;
! 3266: nAddSig = (nDigit - p->nDigit) - nAddFrac;
! 3267: if( nAddFrac==0 && nAddSig==0 ) return;
! 3268: p->a = sqlite3_realloc64(p->a, nDigit+1);
! 3269: if( p->a==0 ){
! 3270: p->oom = 1;
! 3271: return;
! 3272: }
! 3273: if( nAddSig ){
! 3274: memmove(p->a+nAddSig, p->a, p->nDigit);
! 3275: memset(p->a, 0, nAddSig);
! 3276: p->nDigit += nAddSig;
! 3277: }
! 3278: if( nAddFrac ){
! 3279: memset(p->a+p->nDigit, 0, nAddFrac);
! 3280: p->nDigit += nAddFrac;
! 3281: p->nFrac += nAddFrac;
1.5 misho 3282: }
3283: }
3284:
3285: /*
1.6.2.1 ! misho 3286: ** Add the value pB into pA. A := A + B.
! 3287: **
! 3288: ** Both pA and pB might become denormalized by this routine.
1.5 misho 3289: */
1.6.2.1 ! misho 3290: static void decimal_add(Decimal *pA, Decimal *pB){
! 3291: int nSig, nFrac, nDigit;
! 3292: int i, rc;
! 3293: if( pA==0 ){
! 3294: return;
! 3295: }
! 3296: if( pA->oom || pB==0 || pB->oom ){
! 3297: pA->oom = 1;
! 3298: return;
! 3299: }
! 3300: if( pA->isNull || pB->isNull ){
! 3301: pA->isNull = 1;
! 3302: return;
! 3303: }
! 3304: nSig = pA->nDigit - pA->nFrac;
! 3305: if( nSig && pA->a[0]==0 ) nSig--;
! 3306: if( nSig<pB->nDigit-pB->nFrac ){
! 3307: nSig = pB->nDigit - pB->nFrac;
! 3308: }
! 3309: nFrac = pA->nFrac;
! 3310: if( nFrac<pB->nFrac ) nFrac = pB->nFrac;
! 3311: nDigit = nSig + nFrac + 1;
! 3312: decimal_expand(pA, nDigit, nFrac);
! 3313: decimal_expand(pB, nDigit, nFrac);
! 3314: if( pA->oom || pB->oom ){
! 3315: pA->oom = 1;
! 3316: }else{
! 3317: if( pA->sign==pB->sign ){
! 3318: int carry = 0;
! 3319: for(i=nDigit-1; i>=0; i--){
! 3320: int x = pA->a[i] + pB->a[i] + carry;
! 3321: if( x>=10 ){
! 3322: carry = 1;
! 3323: pA->a[i] = x - 10;
! 3324: }else{
! 3325: carry = 0;
! 3326: pA->a[i] = x;
! 3327: }
! 3328: }
! 3329: }else{
! 3330: signed char *aA, *aB;
! 3331: int borrow = 0;
! 3332: rc = memcmp(pA->a, pB->a, nDigit);
! 3333: if( rc<0 ){
! 3334: aA = pB->a;
! 3335: aB = pA->a;
! 3336: pA->sign = !pA->sign;
! 3337: }else{
! 3338: aA = pA->a;
! 3339: aB = pB->a;
! 3340: }
! 3341: for(i=nDigit-1; i>=0; i--){
! 3342: int x = aA[i] - aB[i] - borrow;
! 3343: if( x<0 ){
! 3344: pA->a[i] = x+10;
! 3345: borrow = 1;
! 3346: }else{
! 3347: pA->a[i] = x;
! 3348: borrow = 0;
! 3349: }
! 3350: }
! 3351: }
! 3352: }
1.5 misho 3353: }
3354:
3355: /*
1.6.2.1 ! misho 3356: ** Multiply A by B. A := A * B
! 3357: **
! 3358: ** All significant digits after the decimal point are retained.
! 3359: ** Trailing zeros after the decimal point are omitted as long as
! 3360: ** the number of digits after the decimal point is no less than
! 3361: ** either the number of digits in either input.
1.5 misho 3362: */
1.6.2.1 ! misho 3363: static void decimalMul(Decimal *pA, Decimal *pB){
! 3364: signed char *acc = 0;
! 3365: int i, j, k;
! 3366: int minFrac;
! 3367:
! 3368: if( pA==0 || pA->oom || pA->isNull
! 3369: || pB==0 || pB->oom || pB->isNull
! 3370: ){
! 3371: goto mul_end;
! 3372: }
! 3373: acc = sqlite3_malloc64( pA->nDigit + pB->nDigit + 2 );
! 3374: if( acc==0 ){
! 3375: pA->oom = 1;
! 3376: goto mul_end;
! 3377: }
! 3378: memset(acc, 0, pA->nDigit + pB->nDigit + 2);
! 3379: minFrac = pA->nFrac;
! 3380: if( pB->nFrac<minFrac ) minFrac = pB->nFrac;
! 3381: for(i=pA->nDigit-1; i>=0; i--){
! 3382: signed char f = pA->a[i];
! 3383: int carry = 0, x;
! 3384: for(j=pB->nDigit-1, k=i+j+3; j>=0; j--, k--){
! 3385: x = acc[k] + f*pB->a[j] + carry;
! 3386: acc[k] = x%10;
! 3387: carry = x/10;
! 3388: }
! 3389: x = acc[k] + carry;
! 3390: acc[k] = x%10;
! 3391: acc[k-1] += x/10;
! 3392: }
! 3393: sqlite3_free(pA->a);
! 3394: pA->a = acc;
! 3395: acc = 0;
! 3396: pA->nDigit += pB->nDigit + 2;
! 3397: pA->nFrac += pB->nFrac;
! 3398: pA->sign ^= pB->sign;
! 3399: while( pA->nFrac>minFrac && pA->a[pA->nDigit-1]==0 ){
! 3400: pA->nFrac--;
! 3401: pA->nDigit--;
! 3402: }
1.5 misho 3403:
1.6.2.1 ! misho 3404: mul_end:
! 3405: sqlite3_free(acc);
! 3406: }
1.5 misho 3407:
3408: /*
1.6.2.1 ! misho 3409: ** Create a new Decimal object that contains an integer power of 2.
1.5 misho 3410: */
1.6.2.1 ! misho 3411: static Decimal *decimalPow2(int N){
! 3412: Decimal *pA = 0; /* The result to be returned */
! 3413: Decimal *pX = 0; /* Multiplier */
! 3414: if( N<-20000 || N>20000 ) goto pow2_fault;
! 3415: pA = decimalNewFromText("1.0", 3);
! 3416: if( pA==0 || pA->oom ) goto pow2_fault;
! 3417: if( N==0 ) return pA;
! 3418: if( N>0 ){
! 3419: pX = decimalNewFromText("2.0", 3);
! 3420: }else{
! 3421: N = -N;
! 3422: pX = decimalNewFromText("0.5", 3);
! 3423: }
! 3424: if( pX==0 || pX->oom ) goto pow2_fault;
! 3425: while( 1 /* Exit by break */ ){
! 3426: if( N & 1 ){
! 3427: decimalMul(pA, pX);
! 3428: if( pA->oom ) goto pow2_fault;
! 3429: }
! 3430: N >>= 1;
! 3431: if( N==0 ) break;
! 3432: decimalMul(pX, pX);
! 3433: }
! 3434: decimal_free(pX);
! 3435: return pA;
1.5 misho 3436:
1.6.2.1 ! misho 3437: pow2_fault:
! 3438: decimal_free(pA);
! 3439: decimal_free(pX);
! 3440: return 0;
! 3441: }
! 3442:
! 3443: /*
! 3444: ** Use an IEEE754 binary64 ("double") to generate a new Decimal object.
! 3445: */
! 3446: static Decimal *decimalFromDouble(double r){
! 3447: sqlite3_int64 m, a;
! 3448: int e;
! 3449: int isNeg;
! 3450: Decimal *pA;
! 3451: Decimal *pX;
! 3452: char zNum[100];
! 3453: if( r<0.0 ){
! 3454: isNeg = 1;
! 3455: r = -r;
! 3456: }else{
! 3457: isNeg = 0;
! 3458: }
! 3459: memcpy(&a,&r,sizeof(a));
! 3460: if( a==0 ){
! 3461: e = 0;
! 3462: m = 0;
! 3463: }else{
! 3464: e = a>>52;
! 3465: m = a & ((((sqlite3_int64)1)<<52)-1);
! 3466: if( e==0 ){
! 3467: m <<= 1;
! 3468: }else{
! 3469: m |= ((sqlite3_int64)1)<<52;
1.5 misho 3470: }
1.6.2.1 ! misho 3471: while( e<1075 && m>0 && (m&1)==0 ){
! 3472: m >>= 1;
! 3473: e++;
1.5 misho 3474: }
1.6.2.1 ! misho 3475: if( isNeg ) m = -m;
! 3476: e = e - 1075;
! 3477: if( e>971 ){
! 3478: return 0; /* A NaN or an Infinity */
1.5 misho 3479: }
3480: }
3481:
1.6.2.1 ! misho 3482: /* At this point m is the integer significand and e is the exponent */
! 3483: sqlite3_snprintf(sizeof(zNum), zNum, "%lld", m);
! 3484: pA = decimalNewFromText(zNum, (int)strlen(zNum));
! 3485: pX = decimalPow2(e);
! 3486: decimalMul(pA, pX);
! 3487: decimal_free(pX);
! 3488: return pA;
1.5 misho 3489: }
3490:
3491: /*
1.6.2.1 ! misho 3492: ** SQL Function: decimal(X)
! 3493: ** OR: decimal_exp(X)
! 3494: **
! 3495: ** Convert input X into decimal and then back into text.
! 3496: **
! 3497: ** If X is originally a float, then a full decimal expansion of that floating
! 3498: ** point value is done. Or if X is an 8-byte blob, it is interpreted
! 3499: ** as a float and similarly expanded.
! 3500: **
! 3501: ** The decimal_exp(X) function returns the result in exponential notation.
! 3502: ** decimal(X) returns a complete decimal, without the e+NNN at the end.
1.5 misho 3503: */
1.6.2.1 ! misho 3504: static void decimalFunc(
! 3505: sqlite3_context *context,
! 3506: int argc,
! 3507: sqlite3_value **argv
1.5 misho 3508: ){
1.6.2.1 ! misho 3509: Decimal *p = decimal_new(context, argv[0], 0);
! 3510: UNUSED_PARAMETER(argc);
! 3511: if( p ){
! 3512: if( sqlite3_user_data(context)!=0 ){
! 3513: decimal_result_sci(context, p);
! 3514: }else{
! 3515: decimal_result(context, p);
1.5 misho 3516: }
1.6.2.1 ! misho 3517: decimal_free(p);
1.5 misho 3518: }
3519: }
3520:
3521: /*
1.6.2.1 ! misho 3522: ** Compare text in decimal order.
1.5 misho 3523: */
1.6.2.1 ! misho 3524: static int decimalCollFunc(
! 3525: void *notUsed,
! 3526: int nKey1, const void *pKey1,
! 3527: int nKey2, const void *pKey2
! 3528: ){
! 3529: const unsigned char *zA = (const unsigned char*)pKey1;
! 3530: const unsigned char *zB = (const unsigned char*)pKey2;
! 3531: Decimal *pA = decimalNewFromText((const char*)zA, nKey1);
! 3532: Decimal *pB = decimalNewFromText((const char*)zB, nKey2);
! 3533: int rc;
! 3534: UNUSED_PARAMETER(notUsed);
! 3535: if( pA==0 || pB==0 ){
! 3536: rc = 0;
! 3537: }else{
! 3538: rc = decimal_cmp(pA, pB);
! 3539: }
! 3540: decimal_free(pA);
! 3541: decimal_free(pB);
! 3542: return rc;
1.5 misho 3543: }
3544:
3545:
3546: /*
1.6.2.1 ! misho 3547: ** SQL Function: decimal_add(X, Y)
! 3548: ** decimal_sub(X, Y)
1.5 misho 3549: **
1.6.2.1 ! misho 3550: ** Return the sum or difference of X and Y.
1.5 misho 3551: */
1.6.2.1 ! misho 3552: static void decimalAddFunc(
! 3553: sqlite3_context *context,
! 3554: int argc,
! 3555: sqlite3_value **argv
1.5 misho 3556: ){
1.6.2.1 ! misho 3557: Decimal *pA = decimal_new(context, argv[0], 1);
! 3558: Decimal *pB = decimal_new(context, argv[1], 1);
! 3559: UNUSED_PARAMETER(argc);
! 3560: decimal_add(pA, pB);
! 3561: decimal_result(context, pA);
! 3562: decimal_free(pA);
! 3563: decimal_free(pB);
! 3564: }
! 3565: static void decimalSubFunc(
! 3566: sqlite3_context *context,
! 3567: int argc,
! 3568: sqlite3_value **argv
! 3569: ){
! 3570: Decimal *pA = decimal_new(context, argv[0], 1);
! 3571: Decimal *pB = decimal_new(context, argv[1], 1);
! 3572: UNUSED_PARAMETER(argc);
! 3573: if( pB ){
! 3574: pB->sign = !pB->sign;
! 3575: decimal_add(pA, pB);
! 3576: decimal_result(context, pA);
1.5 misho 3577: }
1.6.2.1 ! misho 3578: decimal_free(pA);
! 3579: decimal_free(pB);
! 3580: }
1.5 misho 3581:
1.6.2.1 ! misho 3582: /* Aggregate funcion: decimal_sum(X)
! 3583: **
! 3584: ** Works like sum() except that it uses decimal arithmetic for unlimited
! 3585: ** precision.
! 3586: */
! 3587: static void decimalSumStep(
! 3588: sqlite3_context *context,
! 3589: int argc,
! 3590: sqlite3_value **argv
! 3591: ){
! 3592: Decimal *p;
! 3593: Decimal *pArg;
! 3594: UNUSED_PARAMETER(argc);
! 3595: p = sqlite3_aggregate_context(context, sizeof(*p));
! 3596: if( p==0 ) return;
! 3597: if( !p->isInit ){
! 3598: p->isInit = 1;
! 3599: p->a = sqlite3_malloc(2);
! 3600: if( p->a==0 ){
! 3601: p->oom = 1;
! 3602: }else{
! 3603: p->a[0] = 0;
! 3604: }
! 3605: p->nDigit = 1;
! 3606: p->nFrac = 0;
1.5 misho 3607: }
1.6.2.1 ! misho 3608: if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
! 3609: pArg = decimal_new(context, argv[0], 1);
! 3610: decimal_add(p, pArg);
! 3611: decimal_free(pArg);
! 3612: }
! 3613: static void decimalSumInverse(
! 3614: sqlite3_context *context,
! 3615: int argc,
! 3616: sqlite3_value **argv
! 3617: ){
! 3618: Decimal *p;
! 3619: Decimal *pArg;
! 3620: UNUSED_PARAMETER(argc);
! 3621: p = sqlite3_aggregate_context(context, sizeof(*p));
! 3622: if( p==0 ) return;
! 3623: if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
! 3624: pArg = decimal_new(context, argv[0], 1);
! 3625: if( pArg ) pArg->sign = !pArg->sign;
! 3626: decimal_add(p, pArg);
! 3627: decimal_free(pArg);
! 3628: }
! 3629: static void decimalSumValue(sqlite3_context *context){
! 3630: Decimal *p = sqlite3_aggregate_context(context, 0);
! 3631: if( p==0 ) return;
! 3632: decimal_result(context, p);
! 3633: }
! 3634: static void decimalSumFinalize(sqlite3_context *context){
! 3635: Decimal *p = sqlite3_aggregate_context(context, 0);
! 3636: if( p==0 ) return;
! 3637: decimal_result(context, p);
! 3638: decimal_clear(p);
! 3639: }
1.5 misho 3640:
1.6.2.1 ! misho 3641: /*
! 3642: ** SQL Function: decimal_mul(X, Y)
! 3643: **
! 3644: ** Return the product of X and Y.
! 3645: */
! 3646: static void decimalMulFunc(
! 3647: sqlite3_context *context,
! 3648: int argc,
! 3649: sqlite3_value **argv
! 3650: ){
! 3651: Decimal *pA = decimal_new(context, argv[0], 1);
! 3652: Decimal *pB = decimal_new(context, argv[1], 1);
! 3653: UNUSED_PARAMETER(argc);
! 3654: if( pA==0 || pA->oom || pA->isNull
! 3655: || pB==0 || pB->oom || pB->isNull
! 3656: ){
! 3657: goto mul_end;
1.5 misho 3658: }
1.6.2.1 ! misho 3659: decimalMul(pA, pB);
! 3660: if( pA->oom ){
! 3661: goto mul_end;
1.5 misho 3662: }
1.6.2.1 ! misho 3663: decimal_result(context, pA);
1.5 misho 3664:
1.6.2.1 ! misho 3665: mul_end:
! 3666: decimal_free(pA);
! 3667: decimal_free(pB);
1.5 misho 3668: }
3669:
3670: /*
1.6.2.1 ! misho 3671: ** SQL Function: decimal_pow2(N)
1.5 misho 3672: **
1.6.2.1 ! misho 3673: ** Return the N-th power of 2. N must be an integer.
1.5 misho 3674: */
1.6.2.1 ! misho 3675: static void decimalPow2Func(
! 3676: sqlite3_context *context,
! 3677: int argc,
! 3678: sqlite3_value **argv
1.5 misho 3679: ){
1.6.2.1 ! misho 3680: UNUSED_PARAMETER(argc);
! 3681: if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){
! 3682: Decimal *pA = decimalPow2(sqlite3_value_int(argv[0]));
! 3683: decimal_result_sci(context, pA);
! 3684: decimal_free(pA);
! 3685: }
! 3686: }
1.5 misho 3687:
3688: #ifdef _WIN32
3689:
3690: #endif
1.6.2.1 ! misho 3691: int sqlite3_decimal_init(
1.5 misho 3692: sqlite3 *db,
3693: char **pzErrMsg,
3694: const sqlite3_api_routines *pApi
3695: ){
3696: int rc = SQLITE_OK;
1.6.2.1 ! misho 3697: static const struct {
! 3698: const char *zFuncName;
! 3699: int nArg;
! 3700: int iArg;
! 3701: void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
! 3702: } aFunc[] = {
! 3703: { "decimal", 1, 0, decimalFunc },
! 3704: { "decimal_exp", 1, 1, decimalFunc },
! 3705: { "decimal_cmp", 2, 0, decimalCmpFunc },
! 3706: { "decimal_add", 2, 0, decimalAddFunc },
! 3707: { "decimal_sub", 2, 0, decimalSubFunc },
! 3708: { "decimal_mul", 2, 0, decimalMulFunc },
! 3709: { "decimal_pow2", 1, 0, decimalPow2Func },
! 3710: };
! 3711: unsigned int i;
1.5 misho 3712: (void)pzErrMsg; /* Unused parameter */
1.6.2.1 ! misho 3713:
! 3714: SQLITE_EXTENSION_INIT2(pApi);
! 3715:
! 3716: for(i=0; i<(int)(sizeof(aFunc)/sizeof(aFunc[0])) && rc==SQLITE_OK; i++){
! 3717: rc = sqlite3_create_function(db, aFunc[i].zFuncName, aFunc[i].nArg,
! 3718: SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
! 3719: aFunc[i].iArg ? db : 0, aFunc[i].xFunc, 0, 0);
1.5 misho 3720: }
3721: if( rc==SQLITE_OK ){
1.6.2.1 ! misho 3722: rc = sqlite3_create_window_function(db, "decimal_sum", 1,
! 3723: SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, 0,
! 3724: decimalSumStep, decimalSumFinalize,
! 3725: decimalSumValue, decimalSumInverse, 0);
1.5 misho 3726: }
3727: if( rc==SQLITE_OK ){
1.6.2.1 ! misho 3728: rc = sqlite3_create_collation(db, "decimal", SQLITE_UTF8,
! 3729: 0, decimalCollFunc);
1.5 misho 3730: }
3731: return rc;
3732: }
3733:
1.6.2.1 ! misho 3734: /************************* End ../ext/misc/decimal.c ********************/
! 3735: #undef sqlite3_base_init
! 3736: #define sqlite3_base_init sqlite3_base64_init
! 3737: /************************* Begin ../ext/misc/base64.c ******************/
1.5 misho 3738: /*
1.6.2.1 ! misho 3739: ** 2022-11-18
1.5 misho 3740: **
3741: ** The author disclaims copyright to this source code. In place of
3742: ** a legal notice, here is a blessing:
3743: **
3744: ** May you do good and not evil.
3745: ** May you find forgiveness for yourself and forgive others.
3746: ** May you share freely, never taking more than you give.
3747: **
3748: *************************************************************************
3749: **
1.6.2.1 ! misho 3750: ** This is a SQLite extension for converting in either direction
! 3751: ** between a (binary) blob and base64 text. Base64 can transit a
! 3752: ** sane USASCII channel unmolested. It also plays nicely in CSV or
! 3753: ** written as TCL brace-enclosed literals or SQL string literals,
! 3754: ** and can be used unmodified in XML-like documents.
! 3755: **
! 3756: ** This is an independent implementation of conversions specified in
! 3757: ** RFC 4648, done on the above date by the author (Larry Brasfield)
! 3758: ** who thereby has the right to put this into the public domain.
! 3759: **
! 3760: ** The conversions meet RFC 4648 requirements, provided that this
! 3761: ** C source specifies that line-feeds are included in the encoded
! 3762: ** data to limit visible line lengths to 72 characters and to
! 3763: ** terminate any encoded blob having non-zero length.
! 3764: **
! 3765: ** Length limitations are not imposed except that the runtime
! 3766: ** SQLite string or blob length limits are respected. Otherwise,
! 3767: ** any length binary sequence can be represented and recovered.
! 3768: ** Generated base64 sequences, with their line-feeds included,
! 3769: ** can be concatenated; the result converted back to binary will
! 3770: ** be the concatenation of the represented binary sequences.
! 3771: **
! 3772: ** This SQLite3 extension creates a function, base64(x), which
! 3773: ** either: converts text x containing base64 to a returned blob;
! 3774: ** or converts a blob x to returned text containing base64. An
! 3775: ** error will be thrown for other input argument types.
! 3776: **
! 3777: ** This code relies on UTF-8 encoding only with respect to the
! 3778: ** meaning of the first 128 (7-bit) codes matching that of USASCII.
! 3779: ** It will fail miserably if somehow made to try to convert EBCDIC.
! 3780: ** Because it is table-driven, it could be enhanced to handle that,
! 3781: ** but the world and SQLite have moved on from that anachronism.
! 3782: **
! 3783: ** To build the extension:
! 3784: ** Set shell variable SQDIR=<your favorite SQLite checkout directory>
! 3785: ** *Nix: gcc -O2 -shared -I$SQDIR -fPIC -o base64.so base64.c
! 3786: ** OSX: gcc -O2 -dynamiclib -fPIC -I$SQDIR -o base64.dylib base64.c
! 3787: ** Win32: gcc -O2 -shared -I%SQDIR% -o base64.dll base64.c
! 3788: ** Win32: cl /Os -I%SQDIR% base64.c -link -dll -out:base64.dll
1.5 misho 3789: */
1.6.2.1 ! misho 3790:
1.5 misho 3791: #include <assert.h>
3792:
1.6.2.1 ! misho 3793: /* #include "sqlite3ext.h" */
1.5 misho 3794:
1.6.2.1 ! misho 3795: #ifndef deliberate_fall_through
! 3796: /* Quiet some compilers about some of our intentional code. */
! 3797: # if GCC_VERSION>=7000000
! 3798: # define deliberate_fall_through __attribute__((fallthrough));
! 3799: # else
! 3800: # define deliberate_fall_through
! 3801: # endif
! 3802: #endif
1.5 misho 3803:
1.6.2.1 ! misho 3804: SQLITE_EXTENSION_INIT1;
! 3805:
! 3806: #define PC 0x80 /* pad character */
! 3807: #define WS 0x81 /* whitespace */
! 3808: #define ND 0x82 /* Not above or digit-value */
! 3809: #define PAD_CHAR '='
! 3810:
! 3811: #ifndef U8_TYPEDEF
! 3812: /* typedef unsigned char u8; */
! 3813: #define U8_TYPEDEF
! 3814: #endif
! 3815:
! 3816: /* Decoding table, ASCII (7-bit) value to base 64 digit value or other */
! 3817: static const u8 b64DigitValues[128] = {
! 3818: /* HT LF VT FF CR */
! 3819: ND,ND,ND,ND, ND,ND,ND,ND, ND,WS,WS,WS, WS,WS,ND,ND,
! 3820: /* US */
! 3821: ND,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,ND,
! 3822: /*sp + / */
! 3823: WS,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,62, ND,ND,ND,63,
! 3824: /* 0 1 5 9 = */
! 3825: 52,53,54,55, 56,57,58,59, 60,61,ND,ND, ND,PC,ND,ND,
! 3826: /* A O */
! 3827: ND, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
! 3828: /* P Z */
! 3829: 15,16,17,18, 19,20,21,22, 23,24,25,ND, ND,ND,ND,ND,
! 3830: /* a o */
! 3831: ND,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
! 3832: /* p z */
! 3833: 41,42,43,44, 45,46,47,48, 49,50,51,ND, ND,ND,ND,ND
1.5 misho 3834: };
3835:
1.6.2.1 ! misho 3836: static const char b64Numerals[64+1]
! 3837: = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1.5 misho 3838:
1.6.2.1 ! misho 3839: #define BX_DV_PROTO(c) \
! 3840: ((((u8)(c))<0x80)? (u8)(b64DigitValues[(u8)(c)]) : 0x80)
! 3841: #define IS_BX_DIGIT(bdp) (((u8)(bdp))<0x80)
! 3842: #define IS_BX_WS(bdp) ((bdp)==WS)
! 3843: #define IS_BX_PAD(bdp) ((bdp)==PC)
! 3844: #define BX_NUMERAL(dv) (b64Numerals[(u8)(dv)])
! 3845: /* Width of base64 lines. Should be an integer multiple of 4. */
! 3846: #define B64_DARK_MAX 72
! 3847:
! 3848: /* Encode a byte buffer into base64 text with linefeeds appended to limit
! 3849: ** encoded group lengths to B64_DARK_MAX or to terminate the last group.
1.5 misho 3850: */
1.6.2.1 ! misho 3851: static char* toBase64( u8 *pIn, int nbIn, char *pOut ){
! 3852: int nCol = 0;
! 3853: while( nbIn >= 3 ){
! 3854: /* Do the bit-shuffle, exploiting unsigned input to avoid masking. */
! 3855: pOut[0] = BX_NUMERAL(pIn[0]>>2);
! 3856: pOut[1] = BX_NUMERAL(((pIn[0]<<4)|(pIn[1]>>4))&0x3f);
! 3857: pOut[2] = BX_NUMERAL(((pIn[1]&0xf)<<2)|(pIn[2]>>6));
! 3858: pOut[3] = BX_NUMERAL(pIn[2]&0x3f);
! 3859: pOut += 4;
! 3860: nbIn -= 3;
! 3861: pIn += 3;
! 3862: if( (nCol += 4)>=B64_DARK_MAX || nbIn<=0 ){
! 3863: *pOut++ = '\n';
! 3864: nCol = 0;
! 3865: }
! 3866: }
! 3867: if( nbIn > 0 ){
! 3868: signed char nco = nbIn+1;
! 3869: int nbe;
! 3870: unsigned long qv = *pIn++;
! 3871: for( nbe=1; nbe<3; ++nbe ){
! 3872: qv <<= 8;
! 3873: if( nbe<nbIn ) qv |= *pIn++;
! 3874: }
! 3875: for( nbe=3; nbe>=0; --nbe ){
! 3876: char ce = (nbe<nco)? BX_NUMERAL((u8)(qv & 0x3f)) : PAD_CHAR;
! 3877: qv >>= 6;
! 3878: pOut[nbe] = ce;
! 3879: }
! 3880: pOut += 4;
! 3881: *pOut++ = '\n';
! 3882: }
! 3883: *pOut = 0;
! 3884: return pOut;
! 3885: }
1.5 misho 3886:
1.6.2.1 ! misho 3887: /* Skip over text which is not base64 numeral(s). */
! 3888: static char * skipNonB64( char *s, int nc ){
! 3889: char c;
! 3890: while( nc-- > 0 && (c = *s) && !IS_BX_DIGIT(BX_DV_PROTO(c)) ) ++s;
! 3891: return s;
! 3892: }
1.5 misho 3893:
1.6.2.1 ! misho 3894: /* Decode base64 text into a byte buffer. */
! 3895: static u8* fromBase64( char *pIn, int ncIn, u8 *pOut ){
! 3896: if( ncIn>0 && pIn[ncIn-1]=='\n' ) --ncIn;
! 3897: while( ncIn>0 && *pIn!=PAD_CHAR ){
! 3898: static signed char nboi[] = { 0, 0, 1, 2, 3 };
! 3899: char *pUse = skipNonB64(pIn, ncIn);
! 3900: unsigned long qv = 0L;
! 3901: int nti, nbo, nac;
! 3902: ncIn -= (pUse - pIn);
! 3903: pIn = pUse;
! 3904: nti = (ncIn>4)? 4 : ncIn;
! 3905: ncIn -= nti;
! 3906: nbo = nboi[nti];
! 3907: if( nbo==0 ) break;
! 3908: for( nac=0; nac<4; ++nac ){
! 3909: char c = (nac<nti)? *pIn++ : b64Numerals[0];
! 3910: u8 bdp = BX_DV_PROTO(c);
! 3911: switch( bdp ){
! 3912: case ND:
! 3913: /* Treat dark non-digits as pad, but they terminate decode too. */
! 3914: ncIn = 0;
! 3915: deliberate_fall_through;
! 3916: case WS:
! 3917: /* Treat whitespace as pad and terminate this group.*/
! 3918: nti = nac;
! 3919: deliberate_fall_through;
! 3920: case PC:
! 3921: bdp = 0;
! 3922: --nbo;
! 3923: deliberate_fall_through;
! 3924: default: /* bdp is the digit value. */
! 3925: qv = qv<<6 | bdp;
! 3926: break;
! 3927: }
! 3928: }
! 3929: switch( nbo ){
! 3930: case 3:
! 3931: pOut[2] = (qv) & 0xff;
! 3932: case 2:
! 3933: pOut[1] = (qv>>8) & 0xff;
! 3934: case 1:
! 3935: pOut[0] = (qv>>16) & 0xff;
! 3936: }
! 3937: pOut += nbo;
! 3938: }
! 3939: return pOut;
! 3940: }
1.5 misho 3941:
1.6.2.1 ! misho 3942: /* This function does the work for the SQLite base64(x) UDF. */
! 3943: static void base64(sqlite3_context *context, int na, sqlite3_value *av[]){
! 3944: int nb, nc, nv = sqlite3_value_bytes(av[0]);
! 3945: int nvMax = sqlite3_limit(sqlite3_context_db_handle(context),
! 3946: SQLITE_LIMIT_LENGTH, -1);
! 3947: char *cBuf;
! 3948: u8 *bBuf;
! 3949: assert(na==1);
! 3950: switch( sqlite3_value_type(av[0]) ){
! 3951: case SQLITE_BLOB:
! 3952: nb = nv;
! 3953: nc = 4*(nv+2/3); /* quads needed */
! 3954: nc += (nc+(B64_DARK_MAX-1))/B64_DARK_MAX + 1; /* LFs and a 0-terminator */
! 3955: if( nvMax < nc ){
! 3956: sqlite3_result_error(context, "blob expanded to base64 too big", -1);
! 3957: return;
! 3958: }
! 3959: bBuf = (u8*)sqlite3_value_blob(av[0]);
! 3960: if( !bBuf ){
! 3961: if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){
! 3962: goto memFail;
! 3963: }
! 3964: sqlite3_result_text(context,"",-1,SQLITE_STATIC);
! 3965: break;
! 3966: }
! 3967: cBuf = sqlite3_malloc(nc);
! 3968: if( !cBuf ) goto memFail;
! 3969: nc = (int)(toBase64(bBuf, nb, cBuf) - cBuf);
! 3970: sqlite3_result_text(context, cBuf, nc, sqlite3_free);
! 3971: break;
! 3972: case SQLITE_TEXT:
! 3973: nc = nv;
! 3974: nb = 3*((nv+3)/4); /* may overestimate due to LF and padding */
! 3975: if( nvMax < nb ){
! 3976: sqlite3_result_error(context, "blob from base64 may be too big", -1);
! 3977: return;
! 3978: }else if( nb<1 ){
! 3979: nb = 1;
! 3980: }
! 3981: cBuf = (char *)sqlite3_value_text(av[0]);
! 3982: if( !cBuf ){
! 3983: if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){
! 3984: goto memFail;
! 3985: }
! 3986: sqlite3_result_zeroblob(context, 0);
! 3987: break;
! 3988: }
! 3989: bBuf = sqlite3_malloc(nb);
! 3990: if( !bBuf ) goto memFail;
! 3991: nb = (int)(fromBase64(cBuf, nc, bBuf) - bBuf);
! 3992: sqlite3_result_blob(context, bBuf, nb, sqlite3_free);
! 3993: break;
! 3994: default:
! 3995: sqlite3_result_error(context, "base64 accepts only blob or text", -1);
! 3996: return;
1.5 misho 3997: }
1.6.2.1 ! misho 3998: return;
! 3999: memFail:
! 4000: sqlite3_result_error(context, "base64 OOM", -1);
1.5 misho 4001: }
4002:
4003: /*
1.6.2.1 ! misho 4004: ** Establish linkage to running SQLite library.
1.5 misho 4005: */
1.6.2.1 ! misho 4006: #ifndef SQLITE_SHELL_EXTFUNCS
! 4007: #ifdef _WIN32
! 4008:
! 4009: #endif
! 4010: int sqlite3_base_init
! 4011: #else
! 4012: static int sqlite3_base64_init
! 4013: #endif
! 4014: (sqlite3 *db, char **pzErr, const sqlite3_api_routines *pApi){
! 4015: SQLITE_EXTENSION_INIT2(pApi);
! 4016: (void)pzErr;
! 4017: return sqlite3_create_function
! 4018: (db, "base64", 1,
! 4019: SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|SQLITE_DIRECTONLY|SQLITE_UTF8,
! 4020: 0, base64, 0, 0);
1.5 misho 4021: }
4022:
4023: /*
1.6.2.1 ! misho 4024: ** Define some macros to allow this extension to be built into the shell
! 4025: ** conveniently, in conjunction with use of SQLITE_SHELL_EXTFUNCS. This
! 4026: ** allows shell.c, as distributed, to have this extension built in.
1.5 misho 4027: */
1.6.2.1 ! misho 4028: #define BASE64_INIT(db) sqlite3_base64_init(db, 0, 0)
! 4029: #define BASE64_EXPOSE(db, pzErr) /* Not needed, ..._init() does this. */
1.5 misho 4030:
1.6.2.1 ! misho 4031: /************************* End ../ext/misc/base64.c ********************/
! 4032: #undef sqlite3_base_init
! 4033: #define sqlite3_base_init sqlite3_base85_init
! 4034: #define OMIT_BASE85_CHECKER
! 4035: /************************* Begin ../ext/misc/base85.c ******************/
1.5 misho 4036: /*
1.6.2.1 ! misho 4037: ** 2022-11-16
! 4038: **
! 4039: ** The author disclaims copyright to this source code. In place of
! 4040: ** a legal notice, here is a blessing:
! 4041: **
! 4042: ** May you do good and not evil.
! 4043: ** May you find forgiveness for yourself and forgive others.
! 4044: ** May you share freely, never taking more than you give.
! 4045: **
! 4046: *************************************************************************
! 4047: **
! 4048: ** This is a utility for converting binary to base85 or vice-versa.
! 4049: ** It can be built as a standalone program or an SQLite3 extension.
! 4050: **
! 4051: ** Much like base64 representations, base85 can be sent through a
! 4052: ** sane USASCII channel unmolested. It also plays nicely in CSV or
! 4053: ** written as TCL brace-enclosed literals or SQL string literals.
! 4054: ** It is not suited for unmodified use in XML-like documents.
! 4055: **
! 4056: ** The encoding used resembles Ascii85, but was devised by the author
! 4057: ** (Larry Brasfield) before Mozilla, Adobe, ZMODEM or other Ascii85
! 4058: ** variant sources existed, in the 1984 timeframe on a VAX mainframe.
! 4059: ** Further, this is an independent implementation of a base85 system.
! 4060: ** Hence, the author has rightfully put this into the public domain.
! 4061: **
! 4062: ** Base85 numerals are taken from the set of 7-bit USASCII codes,
! 4063: ** excluding control characters and Space ! " ' ( ) { | } ~ Del
! 4064: ** in code order representing digit values 0 to 84 (base 10.)
! 4065: **
! 4066: ** Groups of 4 bytes, interpreted as big-endian 32-bit values,
! 4067: ** are represented as 5-digit base85 numbers with MS to LS digit
! 4068: ** order. Groups of 1-3 bytes are represented with 2-4 digits,
! 4069: ** still big-endian but 8-24 bit values. (Using big-endian yields
! 4070: ** the simplest transition to byte groups smaller than 4 bytes.
! 4071: ** These byte groups can also be considered base-256 numbers.)
! 4072: ** Groups of 0 bytes are represented with 0 digits and vice-versa.
! 4073: ** No pad characters are used; Encoded base85 numeral sequence
! 4074: ** (aka "group") length maps 1-to-1 to the decoded binary length.
! 4075: **
! 4076: ** Any character not in the base85 numeral set delimits groups.
! 4077: ** When base85 is streamed or stored in containers of indefinite
! 4078: ** size, newline is used to separate it into sub-sequences of no
! 4079: ** more than 80 digits so that fgets() can be used to read it.
! 4080: **
! 4081: ** Length limitations are not imposed except that the runtime
! 4082: ** SQLite string or blob length limits are respected. Otherwise,
! 4083: ** any length binary sequence can be represented and recovered.
! 4084: ** Base85 sequences can be concatenated by separating them with
! 4085: ** a non-base85 character; the conversion to binary will then
! 4086: ** be the concatenation of the represented binary sequences.
! 4087:
! 4088: ** The standalone program either converts base85 on stdin to create
! 4089: ** a binary file or converts a binary file to base85 on stdout.
! 4090: ** Read or make it blurt its help for invocation details.
! 4091: **
! 4092: ** The SQLite3 extension creates a function, base85(x), which will
! 4093: ** either convert text base85 to a blob or a blob to text base85
! 4094: ** and return the result (or throw an error for other types.)
! 4095: ** Unless built with OMIT_BASE85_CHECKER defined, it also creates a
! 4096: ** function, is_base85(t), which returns 1 iff the text t contains
! 4097: ** nothing other than base85 numerals and whitespace, or 0 otherwise.
! 4098: **
! 4099: ** To build the extension:
! 4100: ** Set shell variable SQDIR=<your favorite SQLite checkout directory>
! 4101: ** and variable OPTS to -DOMIT_BASE85_CHECKER if is_base85() unwanted.
! 4102: ** *Nix: gcc -O2 -shared -I$SQDIR $OPTS -fPIC -o base85.so base85.c
! 4103: ** OSX: gcc -O2 -dynamiclib -fPIC -I$SQDIR $OPTS -o base85.dylib base85.c
! 4104: ** Win32: gcc -O2 -shared -I%SQDIR% %OPTS% -o base85.dll base85.c
! 4105: ** Win32: cl /Os -I%SQDIR% %OPTS% base85.c -link -dll -out:base85.dll
! 4106: **
! 4107: ** To build the standalone program, define PP symbol BASE85_STANDALONE. Eg.
! 4108: ** *Nix or OSX: gcc -O2 -DBASE85_STANDALONE base85.c -o base85
! 4109: ** Win32: gcc -O2 -DBASE85_STANDALONE -o base85.exe base85.c
! 4110: ** Win32: cl /Os /MD -DBASE85_STANDALONE base85.c
1.5 misho 4111: */
1.6.2.1 ! misho 4112:
! 4113: #include <stdio.h>
! 4114: #include <memory.h>
! 4115: #include <string.h>
! 4116: #include <assert.h>
! 4117: #ifndef OMIT_BASE85_CHECKER
! 4118: # include <ctype.h>
! 4119: #endif
! 4120:
! 4121: #ifndef BASE85_STANDALONE
! 4122:
! 4123: /* # include "sqlite3ext.h" */
! 4124:
! 4125: SQLITE_EXTENSION_INIT1;
! 4126:
! 4127: #else
! 4128:
! 4129: # ifdef _WIN32
! 4130: # include <io.h>
! 4131: # include <fcntl.h>
! 4132: # else
! 4133: # define setmode(fd,m)
! 4134: # endif
! 4135:
! 4136: static char *zHelp =
! 4137: "Usage: base85 <dirFlag> <binFile>\n"
! 4138: " <dirFlag> is either -r to read or -w to write <binFile>,\n"
! 4139: " content to be converted to/from base85 on stdout/stdin.\n"
! 4140: " <binFile> names a binary file to be rendered or created.\n"
! 4141: " Or, the name '-' refers to the stdin or stdout stream.\n"
! 4142: ;
! 4143:
! 4144: static void sayHelp(){
! 4145: printf("%s", zHelp);
1.5 misho 4146: }
1.6.2.1 ! misho 4147: #endif
1.5 misho 4148:
1.6.2.1 ! misho 4149: #ifndef U8_TYPEDEF
! 4150: /* typedef unsigned char u8; */
! 4151: #define U8_TYPEDEF
! 4152: #endif
! 4153:
! 4154: /* Classify c according to interval within USASCII set w.r.t. base85
! 4155: * Values of 1 and 3 are base85 numerals. Values of 0, 2, or 4 are not.
! 4156: */
! 4157: #define B85_CLASS( c ) (((c)>='#')+((c)>'&')+((c)>='*')+((c)>'z'))
! 4158:
! 4159: /* Provide digitValue to b85Numeral offset as a function of above class. */
! 4160: static u8 b85_cOffset[] = { 0, '#', 0, '*'-4, 0 };
! 4161: #define B85_DNOS( c ) b85_cOffset[B85_CLASS(c)]
! 4162:
! 4163: /* Say whether c is a base85 numeral. */
! 4164: #define IS_B85( c ) (B85_CLASS(c) & 1)
! 4165:
! 4166: #if 0 /* Not used, */
! 4167: static u8 base85DigitValue( char c ){
! 4168: u8 dv = (u8)(c - '#');
! 4169: if( dv>87 ) return 0xff;
! 4170: return (dv > 3)? dv-3 : dv;
1.5 misho 4171: }
1.6.2.1 ! misho 4172: #endif
1.5 misho 4173:
1.6.2.1 ! misho 4174: /* Width of base64 lines. Should be an integer multiple of 5. */
! 4175: #define B85_DARK_MAX 80
! 4176:
! 4177:
! 4178: static char * skipNonB85( char *s, int nc ){
! 4179: char c;
! 4180: while( nc-- > 0 && (c = *s) && !IS_B85(c) ) ++s;
! 4181: return s;
! 4182: }
! 4183:
! 4184: /* Convert small integer, known to be in 0..84 inclusive, to base85 numeral.
! 4185: * Do not use the macro form with argument expression having a side-effect.*/
! 4186: #if 0
! 4187: static char base85Numeral( u8 b ){
! 4188: return (b < 4)? (char)(b + '#') : (char)(b - 4 + '*');
! 4189: }
! 4190: #else
! 4191: # define base85Numeral( dn )\
! 4192: ((char)(((dn) < 4)? (char)((dn) + '#') : (char)((dn) - 4 + '*')))
! 4193: #endif
! 4194:
! 4195: static char *putcs(char *pc, char *s){
! 4196: char c;
! 4197: while( (c = *s++)!=0 ) *pc++ = c;
! 4198: return pc;
! 4199: }
! 4200:
! 4201: /* Encode a byte buffer into base85 text. If pSep!=0, it's a C string
! 4202: ** to be appended to encoded groups to limit their length to B85_DARK_MAX
! 4203: ** or to terminate the last group (to aid concatenation.)
1.5 misho 4204: */
1.6.2.1 ! misho 4205: static char* toBase85( u8 *pIn, int nbIn, char *pOut, char *pSep ){
! 4206: int nCol = 0;
! 4207: while( nbIn >= 4 ){
! 4208: int nco = 5;
! 4209: unsigned long qbv = (((unsigned long)pIn[0])<<24) |
! 4210: (pIn[1]<<16) | (pIn[2]<<8) | pIn[3];
! 4211: while( nco > 0 ){
! 4212: unsigned nqv = (unsigned)(qbv/85UL);
! 4213: unsigned char dv = qbv - 85UL*nqv;
! 4214: qbv = nqv;
! 4215: pOut[--nco] = base85Numeral(dv);
! 4216: }
! 4217: nbIn -= 4;
! 4218: pIn += 4;
! 4219: pOut += 5;
! 4220: if( pSep && (nCol += 5)>=B85_DARK_MAX ){
! 4221: pOut = putcs(pOut, pSep);
! 4222: nCol = 0;
! 4223: }
! 4224: }
! 4225: if( nbIn > 0 ){
! 4226: int nco = nbIn + 1;
! 4227: unsigned long qv = *pIn++;
! 4228: int nbe = 1;
! 4229: while( nbe++ < nbIn ){
! 4230: qv = (qv<<8) | *pIn++;
! 4231: }
! 4232: nCol += nco;
! 4233: while( nco > 0 ){
! 4234: u8 dv = (u8)(qv % 85);
! 4235: qv /= 85;
! 4236: pOut[--nco] = base85Numeral(dv);
! 4237: }
! 4238: pOut += (nbIn+1);
! 4239: }
! 4240: if( pSep && nCol>0 ) pOut = putcs(pOut, pSep);
! 4241: *pOut = 0;
! 4242: return pOut;
! 4243: }
! 4244:
! 4245: /* Decode base85 text into a byte buffer. */
! 4246: static u8* fromBase85( char *pIn, int ncIn, u8 *pOut ){
! 4247: if( ncIn>0 && pIn[ncIn-1]=='\n' ) --ncIn;
! 4248: while( ncIn>0 ){
! 4249: static signed char nboi[] = { 0, 0, 1, 2, 3, 4 };
! 4250: char *pUse = skipNonB85(pIn, ncIn);
! 4251: unsigned long qv = 0L;
! 4252: int nti, nbo;
! 4253: ncIn -= (pUse - pIn);
! 4254: pIn = pUse;
! 4255: nti = (ncIn>5)? 5 : ncIn;
! 4256: nbo = nboi[nti];
! 4257: if( nbo==0 ) break;
! 4258: while( nti>0 ){
! 4259: char c = *pIn++;
! 4260: u8 cdo = B85_DNOS(c);
! 4261: --ncIn;
! 4262: if( cdo==0 ) break;
! 4263: qv = 85 * qv + (c - cdo);
! 4264: --nti;
1.5 misho 4265: }
1.6.2.1 ! misho 4266: nbo -= nti; /* Adjust for early (non-digit) end of group. */
! 4267: switch( nbo ){
! 4268: case 4:
! 4269: *pOut++ = (qv >> 24)&0xff;
! 4270: case 3:
! 4271: *pOut++ = (qv >> 16)&0xff;
! 4272: case 2:
! 4273: *pOut++ = (qv >> 8)&0xff;
! 4274: case 1:
! 4275: *pOut++ = qv&0xff;
! 4276: case 0:
1.5 misho 4277: break;
4278: }
4279: }
1.6.2.1 ! misho 4280: return pOut;
! 4281: }
1.5 misho 4282:
1.6.2.1 ! misho 4283: #ifndef OMIT_BASE85_CHECKER
! 4284: /* Say whether input char sequence is all (base85 and/or whitespace).*/
! 4285: static int allBase85( char *p, int len ){
! 4286: char c;
! 4287: while( len-- > 0 && (c = *p++) != 0 ){
! 4288: if( !IS_B85(c) && !isspace(c) ) return 0;
! 4289: }
! 4290: return 1;
1.5 misho 4291: }
1.6.2.1 ! misho 4292: #endif
1.5 misho 4293:
1.6.2.1 ! misho 4294: #ifndef BASE85_STANDALONE
! 4295:
! 4296: # ifndef OMIT_BASE85_CHECKER
! 4297: /* This function does the work for the SQLite is_base85(t) UDF. */
! 4298: static void is_base85(sqlite3_context *context, int na, sqlite3_value *av[]){
! 4299: assert(na==1);
! 4300: switch( sqlite3_value_type(av[0]) ){
! 4301: case SQLITE_TEXT:
! 4302: {
! 4303: int rv = allBase85( (char *)sqlite3_value_text(av[0]),
! 4304: sqlite3_value_bytes(av[0]) );
! 4305: sqlite3_result_int(context, rv);
! 4306: }
! 4307: break;
! 4308: case SQLITE_NULL:
! 4309: sqlite3_result_null(context);
! 4310: break;
! 4311: default:
! 4312: sqlite3_result_error(context, "is_base85 accepts only text or NULL", -1);
! 4313: return;
! 4314: }
! 4315: }
! 4316: # endif
! 4317:
! 4318: /* This function does the work for the SQLite base85(x) UDF. */
! 4319: static void base85(sqlite3_context *context, int na, sqlite3_value *av[]){
! 4320: int nb, nc, nv = sqlite3_value_bytes(av[0]);
! 4321: int nvMax = sqlite3_limit(sqlite3_context_db_handle(context),
! 4322: SQLITE_LIMIT_LENGTH, -1);
! 4323: char *cBuf;
! 4324: u8 *bBuf;
! 4325: assert(na==1);
! 4326: switch( sqlite3_value_type(av[0]) ){
! 4327: case SQLITE_BLOB:
! 4328: nb = nv;
! 4329: /* ulongs tail newlines tailenc+nul*/
! 4330: nc = 5*(nv/4) + nv%4 + nv/64+1 + 2;
! 4331: if( nvMax < nc ){
! 4332: sqlite3_result_error(context, "blob expanded to base85 too big", -1);
! 4333: return;
1.5 misho 4334: }
1.6.2.1 ! misho 4335: bBuf = (u8*)sqlite3_value_blob(av[0]);
! 4336: if( !bBuf ){
! 4337: if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){
! 4338: goto memFail;
! 4339: }
! 4340: sqlite3_result_text(context,"",-1,SQLITE_STATIC);
1.5 misho 4341: break;
4342: }
1.6.2.1 ! misho 4343: cBuf = sqlite3_malloc(nc);
! 4344: if( !cBuf ) goto memFail;
! 4345: nc = (int)(toBase85(bBuf, nb, cBuf, "\n") - cBuf);
! 4346: sqlite3_result_text(context, cBuf, nc, sqlite3_free);
! 4347: break;
! 4348: case SQLITE_TEXT:
! 4349: nc = nv;
! 4350: nb = 4*(nv/5) + nv%5; /* may overestimate */
! 4351: if( nvMax < nb ){
! 4352: sqlite3_result_error(context, "blob from base85 may be too big", -1);
! 4353: return;
! 4354: }else if( nb<1 ){
! 4355: nb = 1;
1.5 misho 4356: }
1.6.2.1 ! misho 4357: cBuf = (char *)sqlite3_value_text(av[0]);
! 4358: if( !cBuf ){
! 4359: if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){
! 4360: goto memFail;
! 4361: }
! 4362: sqlite3_result_zeroblob(context, 0);
1.5 misho 4363: break;
4364: }
1.6.2.1 ! misho 4365: bBuf = sqlite3_malloc(nb);
! 4366: if( !bBuf ) goto memFail;
! 4367: nb = (int)(fromBase85(cBuf, nc, bBuf) - bBuf);
! 4368: sqlite3_result_blob(context, bBuf, nb, sqlite3_free);
! 4369: break;
! 4370: default:
! 4371: sqlite3_result_error(context, "base85 accepts only blob or text.", -1);
! 4372: return;
1.5 misho 4373: }
1.6.2.1 ! misho 4374: return;
! 4375: memFail:
! 4376: sqlite3_result_error(context, "base85 OOM", -1);
1.5 misho 4377: }
4378:
4379: /*
1.6.2.1 ! misho 4380: ** Establish linkage to running SQLite library.
1.5 misho 4381: */
1.6.2.1 ! misho 4382: #ifndef SQLITE_SHELL_EXTFUNCS
! 4383: #ifdef _WIN32
! 4384:
! 4385: #endif
! 4386: int sqlite3_base_init
! 4387: #else
! 4388: static int sqlite3_base85_init
! 4389: #endif
! 4390: (sqlite3 *db, char **pzErr, const sqlite3_api_routines *pApi){
! 4391: SQLITE_EXTENSION_INIT2(pApi);
! 4392: (void)pzErr;
! 4393: # ifndef OMIT_BASE85_CHECKER
! 4394: {
! 4395: int rc = sqlite3_create_function
! 4396: (db, "is_base85", 1,
! 4397: SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|SQLITE_UTF8,
! 4398: 0, is_base85, 0, 0);
! 4399: if( rc!=SQLITE_OK ) return rc;
! 4400: }
! 4401: # endif
! 4402: return sqlite3_create_function
! 4403: (db, "base85", 1,
! 4404: SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|SQLITE_DIRECTONLY|SQLITE_UTF8,
! 4405: 0, base85, 0, 0);
1.5 misho 4406: }
4407:
4408: /*
1.6.2.1 ! misho 4409: ** Define some macros to allow this extension to be built into the shell
! 4410: ** conveniently, in conjunction with use of SQLITE_SHELL_EXTFUNCS. This
! 4411: ** allows shell.c, as distributed, to have this extension built in.
1.5 misho 4412: */
1.6.2.1 ! misho 4413: # define BASE85_INIT(db) sqlite3_base85_init(db, 0, 0)
! 4414: # define BASE85_EXPOSE(db, pzErr) /* Not needed, ..._init() does this. */
1.5 misho 4415:
1.6.2.1 ! misho 4416: #else /* standalone program */
! 4417:
! 4418: int main(int na, char *av[]){
! 4419: int cin;
! 4420: int rc = 0;
! 4421: u8 bBuf[4*(B85_DARK_MAX/5)];
! 4422: char cBuf[5*(sizeof(bBuf)/4)+2];
! 4423: size_t nio;
! 4424: # ifndef OMIT_BASE85_CHECKER
! 4425: int b85Clean = 1;
! 4426: # endif
! 4427: char rw;
! 4428: FILE *fb = 0, *foc = 0;
! 4429: char fmode[3] = "xb";
! 4430: if( na < 3 || av[1][0]!='-' || (rw = av[1][1])==0 || (rw!='r' && rw!='w') ){
! 4431: sayHelp();
! 4432: return 0;
1.5 misho 4433: }
1.6.2.1 ! misho 4434: fmode[0] = rw;
! 4435: if( av[2][0]=='-' && av[2][1]==0 ){
! 4436: switch( rw ){
! 4437: case 'r':
! 4438: fb = stdin;
! 4439: setmode(fileno(stdin), O_BINARY);
! 4440: break;
! 4441: case 'w':
! 4442: fb = stdout;
! 4443: setmode(fileno(stdout), O_BINARY);
! 4444: break;
1.5 misho 4445: }
1.6.2.1 ! misho 4446: }else{
! 4447: fb = fopen(av[2], fmode);
! 4448: foc = fb;
1.5 misho 4449: }
1.6.2.1 ! misho 4450: if( !fb ){
! 4451: fprintf(stderr, "Cannot open %s for %c\n", av[2], rw);
! 4452: rc = 1;
! 4453: }else{
! 4454: switch( rw ){
! 4455: case 'r':
! 4456: while( (nio = fread( bBuf, 1, sizeof(bBuf), fb))>0 ){
! 4457: toBase85( bBuf, (int)nio, cBuf, 0 );
! 4458: fprintf(stdout, "%s\n", cBuf);
! 4459: }
! 4460: break;
! 4461: case 'w':
! 4462: while( 0 != fgets(cBuf, sizeof(cBuf), stdin) ){
! 4463: int nc = strlen(cBuf);
! 4464: size_t nbo = fromBase85( cBuf, nc, bBuf ) - bBuf;
! 4465: if( 1 != fwrite(bBuf, nbo, 1, fb) ) rc = 1;
! 4466: # ifndef OMIT_BASE85_CHECKER
! 4467: b85Clean &= allBase85( cBuf, nc );
! 4468: # endif
! 4469: }
! 4470: break;
! 4471: default:
! 4472: sayHelp();
! 4473: rc = 1;
1.5 misho 4474: }
1.6.2.1 ! misho 4475: if( foc ) fclose(foc);
1.5 misho 4476: }
1.6.2.1 ! misho 4477: # ifndef OMIT_BASE85_CHECKER
! 4478: if( !b85Clean ){
! 4479: fprintf(stderr, "Base85 input had non-base85 dark or control content.\n");
1.5 misho 4480: }
1.6.2.1 ! misho 4481: # endif
1.5 misho 4482: return rc;
4483: }
4484:
4485: #endif
4486:
1.6.2.1 ! misho 4487: /************************* End ../ext/misc/base85.c ********************/
! 4488: /************************* Begin ../ext/misc/ieee754.c ******************/
1.5 misho 4489: /*
1.6.2.1 ! misho 4490: ** 2013-04-17
1.5 misho 4491: **
4492: ** The author disclaims copyright to this source code. In place of
4493: ** a legal notice, here is a blessing:
4494: **
4495: ** May you do good and not evil.
4496: ** May you find forgiveness for yourself and forgive others.
4497: ** May you share freely, never taking more than you give.
4498: **
4499: ******************************************************************************
4500: **
1.6.2.1 ! misho 4501: ** This SQLite extension implements functions for the exact display
! 4502: ** and input of IEEE754 Binary64 floating-point numbers.
1.5 misho 4503: **
1.6.2.1 ! misho 4504: ** ieee754(X)
! 4505: ** ieee754(Y,Z)
1.5 misho 4506: **
1.6.2.1 ! misho 4507: ** In the first form, the value X should be a floating-point number.
! 4508: ** The function will return a string of the form 'ieee754(Y,Z)' where
! 4509: ** Y and Z are integers such that X==Y*pow(2,Z).
1.6 misho 4510: **
1.6.2.1 ! misho 4511: ** In the second form, Y and Z are integers which are the mantissa and
! 4512: ** base-2 exponent of a new floating point number. The function returns
! 4513: ** a floating-point value equal to Y*pow(2,Z).
1.5 misho 4514: **
1.6.2.1 ! misho 4515: ** Examples:
1.5 misho 4516: **
1.6.2.1 ! misho 4517: ** ieee754(2.0) -> 'ieee754(2,0)'
! 4518: ** ieee754(45.25) -> 'ieee754(181,-2)'
! 4519: ** ieee754(2, 0) -> 2.0
! 4520: ** ieee754(181, -2) -> 45.25
1.5 misho 4521: **
1.6.2.1 ! misho 4522: ** Two additional functions break apart the one-argument ieee754()
! 4523: ** result into separate integer values:
1.5 misho 4524: **
1.6.2.1 ! misho 4525: ** ieee754_mantissa(45.25) -> 181
! 4526: ** ieee754_exponent(45.25) -> -2
1.5 misho 4527: **
1.6.2.1 ! misho 4528: ** These functions convert binary64 numbers into blobs and back again.
1.5 misho 4529: **
1.6.2.1 ! misho 4530: ** ieee754_from_blob(x'3ff0000000000000') -> 1.0
! 4531: ** ieee754_to_blob(1.0) -> x'3ff0000000000000'
1.5 misho 4532: **
1.6.2.1 ! misho 4533: ** In all single-argument functions, if the argument is an 8-byte blob
! 4534: ** then that blob is interpreted as a big-endian binary64 value.
! 4535: **
! 4536: **
! 4537: ** EXACT DECIMAL REPRESENTATION OF BINARY64 VALUES
! 4538: ** -----------------------------------------------
! 4539: **
! 4540: ** This extension in combination with the separate 'decimal' extension
! 4541: ** can be used to compute the exact decimal representation of binary64
! 4542: ** values. To begin, first compute a table of exponent values:
! 4543: **
! 4544: ** CREATE TABLE pow2(x INTEGER PRIMARY KEY, v TEXT);
! 4545: ** WITH RECURSIVE c(x,v) AS (
! 4546: ** VALUES(0,'1')
! 4547: ** UNION ALL
! 4548: ** SELECT x+1, decimal_mul(v,'2') FROM c WHERE x+1<=971
! 4549: ** ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
! 4550: ** WITH RECURSIVE c(x,v) AS (
! 4551: ** VALUES(-1,'0.5')
! 4552: ** UNION ALL
! 4553: ** SELECT x-1, decimal_mul(v,'0.5') FROM c WHERE x-1>=-1075
! 4554: ** ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
! 4555: **
! 4556: ** Then, to compute the exact decimal representation of a floating
! 4557: ** point value (the value 47.49 is used in the example) do:
! 4558: **
! 4559: ** WITH c(n) AS (VALUES(47.49))
! 4560: ** ---------------^^^^^---- Replace with whatever you want
! 4561: ** SELECT decimal_mul(ieee754_mantissa(c.n),pow2.v)
! 4562: ** FROM pow2, c WHERE pow2.x=ieee754_exponent(c.n);
! 4563: **
! 4564: ** Here is a query to show various boundry values for the binary64
! 4565: ** number format:
! 4566: **
! 4567: ** WITH c(name,bin) AS (VALUES
! 4568: ** ('minimum positive value', x'0000000000000001'),
! 4569: ** ('maximum subnormal value', x'000fffffffffffff'),
! 4570: ** ('mininum positive nornal value', x'0010000000000000'),
! 4571: ** ('maximum value', x'7fefffffffffffff'))
! 4572: ** SELECT c.name, decimal_mul(ieee754_mantissa(c.bin),pow2.v)
! 4573: ** FROM pow2, c WHERE pow2.x=ieee754_exponent(c.bin);
1.5 misho 4574: **
4575: */
1.6.2.1 ! misho 4576: /* #include "sqlite3ext.h" */
! 4577: SQLITE_EXTENSION_INIT1
! 4578: #include <assert.h>
! 4579: #include <string.h>
! 4580:
! 4581: /* Mark a function parameter as unused, to suppress nuisance compiler
! 4582: ** warnings. */
! 4583: #ifndef UNUSED_PARAMETER
! 4584: # define UNUSED_PARAMETER(X) (void)(X)
! 4585: #endif
1.5 misho 4586:
4587: /*
1.6.2.1 ! misho 4588: ** Implementation of the ieee754() function
1.5 misho 4589: */
1.6.2.1 ! misho 4590: static void ieee754func(
! 4591: sqlite3_context *context,
! 4592: int argc,
! 4593: sqlite3_value **argv
! 4594: ){
! 4595: if( argc==1 ){
! 4596: sqlite3_int64 m, a;
! 4597: double r;
! 4598: int e;
! 4599: int isNeg;
! 4600: char zResult[100];
! 4601: assert( sizeof(m)==sizeof(r) );
! 4602: if( sqlite3_value_type(argv[0])==SQLITE_BLOB
! 4603: && sqlite3_value_bytes(argv[0])==sizeof(r)
! 4604: ){
! 4605: const unsigned char *x = sqlite3_value_blob(argv[0]);
! 4606: unsigned int i;
! 4607: sqlite3_uint64 v = 0;
! 4608: for(i=0; i<sizeof(r); i++){
! 4609: v = (v<<8) | x[i];
! 4610: }
! 4611: memcpy(&r, &v, sizeof(r));
! 4612: }else{
! 4613: r = sqlite3_value_double(argv[0]);
! 4614: }
! 4615: if( r<0.0 ){
! 4616: isNeg = 1;
! 4617: r = -r;
! 4618: }else{
! 4619: isNeg = 0;
! 4620: }
! 4621: memcpy(&a,&r,sizeof(a));
! 4622: if( a==0 ){
! 4623: e = 0;
! 4624: m = 0;
! 4625: }else{
! 4626: e = a>>52;
! 4627: m = a & ((((sqlite3_int64)1)<<52)-1);
! 4628: if( e==0 ){
! 4629: m <<= 1;
! 4630: }else{
! 4631: m |= ((sqlite3_int64)1)<<52;
! 4632: }
! 4633: while( e<1075 && m>0 && (m&1)==0 ){
! 4634: m >>= 1;
! 4635: e++;
! 4636: }
! 4637: if( isNeg ) m = -m;
! 4638: }
! 4639: switch( *(int*)sqlite3_user_data(context) ){
! 4640: case 0:
! 4641: sqlite3_snprintf(sizeof(zResult), zResult, "ieee754(%lld,%d)",
! 4642: m, e-1075);
! 4643: sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT);
! 4644: break;
! 4645: case 1:
! 4646: sqlite3_result_int64(context, m);
! 4647: break;
! 4648: case 2:
! 4649: sqlite3_result_int(context, e-1075);
! 4650: break;
! 4651: }
! 4652: }else{
! 4653: sqlite3_int64 m, e, a;
! 4654: double r;
! 4655: int isNeg = 0;
! 4656: m = sqlite3_value_int64(argv[0]);
! 4657: e = sqlite3_value_int64(argv[1]);
1.5 misho 4658:
1.6.2.1 ! misho 4659: /* Limit the range of e. Ticket 22dea1cfdb9151e4 2021-03-02 */
! 4660: if( e>10000 ){
! 4661: e = 10000;
! 4662: }else if( e<-10000 ){
! 4663: e = -10000;
! 4664: }
1.5 misho 4665:
1.6.2.1 ! misho 4666: if( m<0 ){
! 4667: isNeg = 1;
! 4668: m = -m;
! 4669: if( m<0 ) return;
! 4670: }else if( m==0 && e>-1000 && e<1000 ){
! 4671: sqlite3_result_double(context, 0.0);
! 4672: return;
! 4673: }
! 4674: while( (m>>32)&0xffe00000 ){
! 4675: m >>= 1;
! 4676: e++;
! 4677: }
! 4678: while( m!=0 && ((m>>32)&0xfff00000)==0 ){
! 4679: m <<= 1;
! 4680: e--;
! 4681: }
! 4682: e += 1075;
! 4683: if( e<=0 ){
! 4684: /* Subnormal */
! 4685: if( 1-e >= 64 ){
! 4686: m = 0;
! 4687: }else{
! 4688: m >>= 1-e;
! 4689: }
! 4690: e = 0;
! 4691: }else if( e>0x7ff ){
! 4692: e = 0x7ff;
! 4693: }
! 4694: a = m & ((((sqlite3_int64)1)<<52)-1);
! 4695: a |= e<<52;
! 4696: if( isNeg ) a |= ((sqlite3_uint64)1)<<63;
! 4697: memcpy(&r, &a, sizeof(r));
! 4698: sqlite3_result_double(context, r);
! 4699: }
1.5 misho 4700: }
4701:
4702: /*
1.6.2.1 ! misho 4703: ** Functions to convert between blobs and floats.
1.5 misho 4704: */
1.6.2.1 ! misho 4705: static void ieee754func_from_blob(
! 4706: sqlite3_context *context,
! 4707: int argc,
! 4708: sqlite3_value **argv
1.6 misho 4709: ){
1.6.2.1 ! misho 4710: UNUSED_PARAMETER(argc);
! 4711: if( sqlite3_value_type(argv[0])==SQLITE_BLOB
! 4712: && sqlite3_value_bytes(argv[0])==sizeof(double)
! 4713: ){
! 4714: double r;
! 4715: const unsigned char *x = sqlite3_value_blob(argv[0]);
! 4716: unsigned int i;
! 4717: sqlite3_uint64 v = 0;
! 4718: for(i=0; i<sizeof(r); i++){
! 4719: v = (v<<8) | x[i];
! 4720: }
! 4721: memcpy(&r, &v, sizeof(r));
! 4722: sqlite3_result_double(context, r);
1.5 misho 4723: }
4724: }
1.6.2.1 ! misho 4725: static void ieee754func_to_blob(
! 4726: sqlite3_context *context,
! 4727: int argc,
! 4728: sqlite3_value **argv
1.5 misho 4729: ){
1.6.2.1 ! misho 4730: UNUSED_PARAMETER(argc);
! 4731: if( sqlite3_value_type(argv[0])==SQLITE_FLOAT
! 4732: || sqlite3_value_type(argv[0])==SQLITE_INTEGER
! 4733: ){
! 4734: double r = sqlite3_value_double(argv[0]);
! 4735: sqlite3_uint64 v;
! 4736: unsigned char a[sizeof(r)];
! 4737: unsigned int i;
! 4738: memcpy(&v, &r, sizeof(r));
! 4739: for(i=1; i<=sizeof(r); i++){
! 4740: a[sizeof(r)-i] = v&0xff;
! 4741: v >>= 8;
! 4742: }
! 4743: sqlite3_result_blob(context, a, sizeof(r), SQLITE_TRANSIENT);
1.5 misho 4744: }
4745: }
4746:
4747: /*
1.6.2.1 ! misho 4748: ** SQL Function: ieee754_inc(r,N)
! 4749: **
! 4750: ** Move the floating point value r by N quantums and return the new
! 4751: ** values.
! 4752: **
! 4753: ** Behind the scenes: this routine merely casts r into a 64-bit unsigned
! 4754: ** integer, adds N, then casts the value back into float.
! 4755: **
! 4756: ** Example: To find the smallest positive number:
! 4757: **
! 4758: ** SELECT ieee754_inc(0.0,+1);
1.5 misho 4759: */
1.6.2.1 ! misho 4760: static void ieee754inc(
! 4761: sqlite3_context *context,
! 4762: int argc,
! 4763: sqlite3_value **argv
! 4764: ){
! 4765: double r;
! 4766: sqlite3_int64 N;
! 4767: sqlite3_uint64 m1, m2;
! 4768: double r2;
! 4769: UNUSED_PARAMETER(argc);
! 4770: r = sqlite3_value_double(argv[0]);
! 4771: N = sqlite3_value_int64(argv[1]);
! 4772: memcpy(&m1, &r, 8);
! 4773: m2 = m1 + N;
! 4774: memcpy(&r2, &m2, 8);
! 4775: sqlite3_result_double(context, r2);
1.5 misho 4776: }
4777:
4778:
1.6.2.1 ! misho 4779: #ifdef _WIN32
1.5 misho 4780:
1.6.2.1 ! misho 4781: #endif
! 4782: int sqlite3_ieee_init(
! 4783: sqlite3 *db,
! 4784: char **pzErrMsg,
! 4785: const sqlite3_api_routines *pApi
! 4786: ){
! 4787: static const struct {
! 4788: char *zFName;
! 4789: int nArg;
! 4790: int iAux;
! 4791: void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
! 4792: } aFunc[] = {
! 4793: { "ieee754", 1, 0, ieee754func },
! 4794: { "ieee754", 2, 0, ieee754func },
! 4795: { "ieee754_mantissa", 1, 1, ieee754func },
! 4796: { "ieee754_exponent", 1, 2, ieee754func },
! 4797: { "ieee754_to_blob", 1, 0, ieee754func_to_blob },
! 4798: { "ieee754_from_blob", 1, 0, ieee754func_from_blob },
! 4799: { "ieee754_inc", 2, 0, ieee754inc },
! 4800: };
! 4801: unsigned int i;
! 4802: int rc = SQLITE_OK;
! 4803: SQLITE_EXTENSION_INIT2(pApi);
! 4804: (void)pzErrMsg; /* Unused parameter */
! 4805: for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
! 4806: rc = sqlite3_create_function(db, aFunc[i].zFName, aFunc[i].nArg,
! 4807: SQLITE_UTF8|SQLITE_INNOCUOUS,
! 4808: (void*)&aFunc[i].iAux,
! 4809: aFunc[i].xFunc, 0, 0);
! 4810: }
! 4811: return rc;
1.5 misho 4812: }
4813:
1.6.2.1 ! misho 4814: /************************* End ../ext/misc/ieee754.c ********************/
! 4815: /************************* Begin ../ext/misc/series.c ******************/
1.5 misho 4816: /*
1.6.2.1 ! misho 4817: ** 2015-08-18, 2023-04-28
! 4818: **
! 4819: ** The author disclaims copyright to this source code. In place of
! 4820: ** a legal notice, here is a blessing:
! 4821: **
! 4822: ** May you do good and not evil.
! 4823: ** May you find forgiveness for yourself and forgive others.
! 4824: ** May you share freely, never taking more than you give.
! 4825: **
! 4826: *************************************************************************
! 4827: **
! 4828: ** This file demonstrates how to create a table-valued-function using
! 4829: ** a virtual table. This demo implements the generate_series() function
! 4830: ** which gives the same results as the eponymous function in PostgreSQL,
! 4831: ** within the limitation that its arguments are signed 64-bit integers.
! 4832: **
! 4833: ** Considering its equivalents to generate_series(start,stop,step): A
! 4834: ** value V[n] sequence is produced for integer n ascending from 0 where
! 4835: ** ( V[n] == start + n * step && sgn(V[n] - stop) * sgn(step) >= 0 )
! 4836: ** for each produced value (independent of production time ordering.)
! 4837: **
! 4838: ** All parameters must be either integer or convertable to integer.
! 4839: ** The start parameter is required.
! 4840: ** The stop parameter defaults to (1<<32)-1 (aka 4294967295 or 0xffffffff)
! 4841: ** The step parameter defaults to 1 and 0 is treated as 1.
! 4842: **
! 4843: ** Examples:
! 4844: **
! 4845: ** SELECT * FROM generate_series(0,100,5);
! 4846: **
! 4847: ** The query above returns integers from 0 through 100 counting by steps
! 4848: ** of 5.
! 4849: **
! 4850: ** SELECT * FROM generate_series(0,100);
! 4851: **
! 4852: ** Integers from 0 through 100 with a step size of 1.
! 4853: **
! 4854: ** SELECT * FROM generate_series(20) LIMIT 10;
! 4855: **
! 4856: ** Integers 20 through 29.
! 4857: **
! 4858: ** SELECT * FROM generate_series(0,-100,-5);
! 4859: **
! 4860: ** Integers 0 -5 -10 ... -100.
! 4861: **
! 4862: ** SELECT * FROM generate_series(0,-1);
! 4863: **
! 4864: ** Empty sequence.
! 4865: **
! 4866: ** HOW IT WORKS
! 4867: **
! 4868: ** The generate_series "function" is really a virtual table with the
! 4869: ** following schema:
! 4870: **
! 4871: ** CREATE TABLE generate_series(
! 4872: ** value,
! 4873: ** start HIDDEN,
! 4874: ** stop HIDDEN,
! 4875: ** step HIDDEN
! 4876: ** );
! 4877: **
! 4878: ** The virtual table also has a rowid, logically equivalent to n+1 where
! 4879: ** "n" is the ascending integer in the aforesaid production definition.
! 4880: **
! 4881: ** Function arguments in queries against this virtual table are translated
! 4882: ** into equality constraints against successive hidden columns. In other
! 4883: ** words, the following pairs of queries are equivalent to each other:
! 4884: **
! 4885: ** SELECT * FROM generate_series(0,100,5);
! 4886: ** SELECT * FROM generate_series WHERE start=0 AND stop=100 AND step=5;
! 4887: **
! 4888: ** SELECT * FROM generate_series(0,100);
! 4889: ** SELECT * FROM generate_series WHERE start=0 AND stop=100;
! 4890: **
! 4891: ** SELECT * FROM generate_series(20) LIMIT 10;
! 4892: ** SELECT * FROM generate_series WHERE start=20 LIMIT 10;
! 4893: **
! 4894: ** The generate_series virtual table implementation leaves the xCreate method
! 4895: ** set to NULL. This means that it is not possible to do a CREATE VIRTUAL
! 4896: ** TABLE command with "generate_series" as the USING argument. Instead, there
! 4897: ** is a single generate_series virtual table that is always available without
! 4898: ** having to be created first.
! 4899: **
! 4900: ** The xBestIndex method looks for equality constraints against the hidden
! 4901: ** start, stop, and step columns, and if present, it uses those constraints
! 4902: ** to bound the sequence of generated values. If the equality constraints
! 4903: ** are missing, it uses 0 for start, 4294967295 for stop, and 1 for step.
! 4904: ** xBestIndex returns a small cost when both start and stop are available,
! 4905: ** and a very large cost if either start or stop are unavailable. This
! 4906: ** encourages the query planner to order joins such that the bounds of the
! 4907: ** series are well-defined.
1.5 misho 4908: */
1.6.2.1 ! misho 4909: /* #include "sqlite3ext.h" */
! 4910: SQLITE_EXTENSION_INIT1
! 4911: #include <assert.h>
! 4912: #include <string.h>
! 4913: #include <limits.h>
1.5 misho 4914:
1.6.2.1 ! misho 4915: #ifndef SQLITE_OMIT_VIRTUALTABLE
1.5 misho 4916: /*
1.6.2.1 ! misho 4917: ** Return that member of a generate_series(...) sequence whose 0-based
! 4918: ** index is ix. The 0th member is given by smBase. The sequence members
! 4919: ** progress per ix increment by smStep.
! 4920: */
! 4921: static sqlite3_int64 genSeqMember(sqlite3_int64 smBase,
! 4922: sqlite3_int64 smStep,
! 4923: sqlite3_uint64 ix){
! 4924: if( ix>=(sqlite3_uint64)LLONG_MAX ){
! 4925: /* Get ix into signed i64 range. */
! 4926: ix -= (sqlite3_uint64)LLONG_MAX;
! 4927: /* With 2's complement ALU, this next can be 1 step, but is split into
! 4928: * 2 for UBSAN's satisfaction (and hypothetical 1's complement ALUs.) */
! 4929: smBase += (LLONG_MAX/2) * smStep;
! 4930: smBase += (LLONG_MAX - LLONG_MAX/2) * smStep;
! 4931: }
! 4932: /* Under UBSAN (or on 1's complement machines), must do this last term
! 4933: * in steps to avoid the dreaded (and harmless) signed multiply overlow. */
! 4934: if( ix>=2 ){
! 4935: sqlite3_int64 ix2 = (sqlite3_int64)ix/2;
! 4936: smBase += ix2*smStep;
! 4937: ix -= ix2;
! 4938: }
! 4939: return smBase + ((sqlite3_int64)ix)*smStep;
1.5 misho 4940: }
4941:
1.6.2.1 ! misho 4942: /* typedef unsigned char u8; */
! 4943:
! 4944: typedef struct SequenceSpec {
! 4945: sqlite3_int64 iBase; /* Starting value ("start") */
! 4946: sqlite3_int64 iTerm; /* Given terminal value ("stop") */
! 4947: sqlite3_int64 iStep; /* Increment ("step") */
! 4948: sqlite3_uint64 uSeqIndexMax; /* maximum sequence index (aka "n") */
! 4949: sqlite3_uint64 uSeqIndexNow; /* Current index during generation */
! 4950: sqlite3_int64 iValueNow; /* Current value during generation */
! 4951: u8 isNotEOF; /* Sequence generation not exhausted */
! 4952: u8 isReversing; /* Sequence is being reverse generated */
! 4953: } SequenceSpec;
! 4954:
! 4955: /*
! 4956: ** Prepare a SequenceSpec for use in generating an integer series
! 4957: ** given initialized iBase, iTerm and iStep values. Sequence is
! 4958: ** initialized per given isReversing. Other members are computed.
! 4959: */
! 4960: static void setupSequence( SequenceSpec *pss ){
! 4961: int bSameSigns;
! 4962: pss->uSeqIndexMax = 0;
! 4963: pss->isNotEOF = 0;
! 4964: bSameSigns = (pss->iBase < 0)==(pss->iTerm < 0);
! 4965: if( pss->iTerm < pss->iBase ){
! 4966: sqlite3_uint64 nuspan = 0;
! 4967: if( bSameSigns ){
! 4968: nuspan = (sqlite3_uint64)(pss->iBase - pss->iTerm);
! 4969: }else{
! 4970: /* Under UBSAN (or on 1's complement machines), must do this in steps.
! 4971: * In this clause, iBase>=0 and iTerm<0 . */
! 4972: nuspan = 1;
! 4973: nuspan += pss->iBase;
! 4974: nuspan += -(pss->iTerm+1);
! 4975: }
! 4976: if( pss->iStep<0 ){
! 4977: pss->isNotEOF = 1;
! 4978: if( nuspan==ULONG_MAX ){
! 4979: pss->uSeqIndexMax = ( pss->iStep>LLONG_MIN )? nuspan/-pss->iStep : 1;
! 4980: }else if( pss->iStep>LLONG_MIN ){
! 4981: pss->uSeqIndexMax = nuspan/-pss->iStep;
! 4982: }
! 4983: }
! 4984: }else if( pss->iTerm > pss->iBase ){
! 4985: sqlite3_uint64 puspan = 0;
! 4986: if( bSameSigns ){
! 4987: puspan = (sqlite3_uint64)(pss->iTerm - pss->iBase);
! 4988: }else{
! 4989: /* Under UBSAN (or on 1's complement machines), must do this in steps.
! 4990: * In this clause, iTerm>=0 and iBase<0 . */
! 4991: puspan = 1;
! 4992: puspan += pss->iTerm;
! 4993: puspan += -(pss->iBase+1);
! 4994: }
! 4995: if( pss->iStep>0 ){
! 4996: pss->isNotEOF = 1;
! 4997: pss->uSeqIndexMax = puspan/pss->iStep;
! 4998: }
! 4999: }else if( pss->iTerm == pss->iBase ){
! 5000: pss->isNotEOF = 1;
! 5001: pss->uSeqIndexMax = 0;
! 5002: }
! 5003: pss->uSeqIndexNow = (pss->isReversing)? pss->uSeqIndexMax : 0;
! 5004: pss->iValueNow = (pss->isReversing)
! 5005: ? genSeqMember(pss->iBase, pss->iStep, pss->uSeqIndexMax)
! 5006: : pss->iBase;
! 5007: }
! 5008:
! 5009: /*
! 5010: ** Progress sequence generator to yield next value, if any.
! 5011: ** Leave its state to either yield next value or be at EOF.
! 5012: ** Return whether there is a next value, or 0 at EOF.
! 5013: */
! 5014: static int progressSequence( SequenceSpec *pss ){
! 5015: if( !pss->isNotEOF ) return 0;
! 5016: if( pss->isReversing ){
! 5017: if( pss->uSeqIndexNow > 0 ){
! 5018: pss->uSeqIndexNow--;
! 5019: pss->iValueNow -= pss->iStep;
! 5020: }else{
! 5021: pss->isNotEOF = 0;
! 5022: }
! 5023: }else{
! 5024: if( pss->uSeqIndexNow < pss->uSeqIndexMax ){
! 5025: pss->uSeqIndexNow++;
! 5026: pss->iValueNow += pss->iStep;
! 5027: }else{
! 5028: pss->isNotEOF = 0;
! 5029: }
1.5 misho 5030: }
1.6.2.1 ! misho 5031: return pss->isNotEOF;
1.5 misho 5032: }
5033:
1.6.2.1 ! misho 5034: /* series_cursor is a subclass of sqlite3_vtab_cursor which will
! 5035: ** serve as the underlying representation of a cursor that scans
! 5036: ** over rows of the result
1.5 misho 5037: */
1.6.2.1 ! misho 5038: typedef struct series_cursor series_cursor;
! 5039: struct series_cursor {
! 5040: sqlite3_vtab_cursor base; /* Base class - must be first */
! 5041: SequenceSpec ss; /* (this) Derived class data */
! 5042: };
1.5 misho 5043:
5044: /*
1.6.2.1 ! misho 5045: ** The seriesConnect() method is invoked to create a new
! 5046: ** series_vtab that describes the generate_series virtual table.
! 5047: **
! 5048: ** Think of this routine as the constructor for series_vtab objects.
! 5049: **
! 5050: ** All this routine needs to do is:
! 5051: **
! 5052: ** (1) Allocate the series_vtab object and initialize all fields.
! 5053: **
! 5054: ** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
! 5055: ** result set of queries against generate_series will look like.
1.5 misho 5056: */
1.6.2.1 ! misho 5057: static int seriesConnect(
! 5058: sqlite3 *db,
! 5059: void *pUnused,
! 5060: int argcUnused, const char *const*argvUnused,
! 5061: sqlite3_vtab **ppVtab,
! 5062: char **pzErrUnused
1.5 misho 5063: ){
1.6.2.1 ! misho 5064: sqlite3_vtab *pNew;
! 5065: int rc;
1.5 misho 5066:
1.6.2.1 ! misho 5067: /* Column numbers */
! 5068: #define SERIES_COLUMN_VALUE 0
! 5069: #define SERIES_COLUMN_START 1
! 5070: #define SERIES_COLUMN_STOP 2
! 5071: #define SERIES_COLUMN_STEP 3
1.5 misho 5072:
1.6.2.1 ! misho 5073: (void)pUnused;
! 5074: (void)argcUnused;
! 5075: (void)argvUnused;
! 5076: (void)pzErrUnused;
! 5077: rc = sqlite3_declare_vtab(db,
! 5078: "CREATE TABLE x(value,start hidden,stop hidden,step hidden)");
! 5079: if( rc==SQLITE_OK ){
! 5080: pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
! 5081: if( pNew==0 ) return SQLITE_NOMEM;
! 5082: memset(pNew, 0, sizeof(*pNew));
! 5083: sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
! 5084: }
! 5085: return rc;
1.5 misho 5086: }
5087:
1.6.2.1 ! misho 5088: /*
! 5089: ** This method is the destructor for series_cursor objects.
! 5090: */
! 5091: static int seriesDisconnect(sqlite3_vtab *pVtab){
! 5092: sqlite3_free(pVtab);
! 5093: return SQLITE_OK;
1.5 misho 5094: }
5095:
1.6.2.1 ! misho 5096: /*
! 5097: ** Constructor for a new series_cursor object.
! 5098: */
! 5099: static int seriesOpen(sqlite3_vtab *pUnused, sqlite3_vtab_cursor **ppCursor){
! 5100: series_cursor *pCur;
! 5101: (void)pUnused;
! 5102: pCur = sqlite3_malloc( sizeof(*pCur) );
! 5103: if( pCur==0 ) return SQLITE_NOMEM;
! 5104: memset(pCur, 0, sizeof(*pCur));
! 5105: *ppCursor = &pCur->base;
! 5106: return SQLITE_OK;
1.5 misho 5107: }
5108:
5109: /*
1.6.2.1 ! misho 5110: ** Destructor for a series_cursor.
1.5 misho 5111: */
1.6.2.1 ! misho 5112: static int seriesClose(sqlite3_vtab_cursor *cur){
! 5113: sqlite3_free(cur);
! 5114: return SQLITE_OK;
1.5 misho 5115: }
5116:
1.6.2.1 ! misho 5117:
1.6 misho 5118: /*
1.6.2.1 ! misho 5119: ** Advance a series_cursor to its next row of output.
1.6 misho 5120: */
1.6.2.1 ! misho 5121: static int seriesNext(sqlite3_vtab_cursor *cur){
! 5122: series_cursor *pCur = (series_cursor*)cur;
! 5123: progressSequence( & pCur->ss );
! 5124: return SQLITE_OK;
1.6 misho 5125: }
5126:
5127: /*
1.6.2.1 ! misho 5128: ** Return values of columns for the row at which the series_cursor
! 5129: ** is currently pointing.
1.6 misho 5130: */
1.6.2.1 ! misho 5131: static int seriesColumn(
! 5132: sqlite3_vtab_cursor *cur, /* The cursor */
! 5133: sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
! 5134: int i /* Which column to return */
! 5135: ){
! 5136: series_cursor *pCur = (series_cursor*)cur;
! 5137: sqlite3_int64 x = 0;
! 5138: switch( i ){
! 5139: case SERIES_COLUMN_START: x = pCur->ss.iBase; break;
! 5140: case SERIES_COLUMN_STOP: x = pCur->ss.iTerm; break;
! 5141: case SERIES_COLUMN_STEP: x = pCur->ss.iStep; break;
! 5142: default: x = pCur->ss.iValueNow; break;
1.6 misho 5143: }
1.6.2.1 ! misho 5144: sqlite3_result_int64(ctx, x);
! 5145: return SQLITE_OK;
1.6 misho 5146: }
5147:
1.6.2.1 ! misho 5148: #ifndef LARGEST_UINT64
! 5149: #define LARGEST_UINT64 (0xffffffff|(((sqlite3_uint64)0xffffffff)<<32))
! 5150: #endif
1.6 misho 5151:
1.5 misho 5152: /*
1.6.2.1 ! misho 5153: ** Return the rowid for the current row, logically equivalent to n+1 where
! 5154: ** "n" is the ascending integer in the aforesaid production definition.
1.5 misho 5155: */
1.6.2.1 ! misho 5156: static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
! 5157: series_cursor *pCur = (series_cursor*)cur;
! 5158: sqlite3_uint64 n = pCur->ss.uSeqIndexNow;
! 5159: *pRowid = (sqlite3_int64)((n<LARGEST_UINT64)? n+1 : 0);
! 5160: return SQLITE_OK;
1.5 misho 5161: }
5162:
5163: /*
1.6.2.1 ! misho 5164: ** Return TRUE if the cursor has been moved off of the last
! 5165: ** row of output.
1.5 misho 5166: */
1.6.2.1 ! misho 5167: static int seriesEof(sqlite3_vtab_cursor *cur){
! 5168: series_cursor *pCur = (series_cursor*)cur;
! 5169: return !pCur->ss.isNotEOF;
1.5 misho 5170: }
1.6 misho 5171:
1.6.2.1 ! misho 5172: /* True to cause run-time checking of the start=, stop=, and/or step=
! 5173: ** parameters. The only reason to do this is for testing the
! 5174: ** constraint checking logic for virtual tables in the SQLite core.
! 5175: */
! 5176: #ifndef SQLITE_SERIES_CONSTRAINT_VERIFY
! 5177: # define SQLITE_SERIES_CONSTRAINT_VERIFY 0
! 5178: #endif
! 5179:
1.6 misho 5180: /*
1.6.2.1 ! misho 5181: ** This method is called to "rewind" the series_cursor object back
! 5182: ** to the first row of output. This method is always called at least
! 5183: ** once prior to any call to seriesColumn() or seriesRowid() or
! 5184: ** seriesEof().
! 5185: **
! 5186: ** The query plan selected by seriesBestIndex is passed in the idxNum
! 5187: ** parameter. (idxStr is not used in this implementation.) idxNum
! 5188: ** is a bitmask showing which constraints are available:
! 5189: **
! 5190: ** 1: start=VALUE
! 5191: ** 2: stop=VALUE
! 5192: ** 4: step=VALUE
! 5193: **
! 5194: ** Also, if bit 8 is set, that means that the series should be output
! 5195: ** in descending order rather than in ascending order. If bit 16 is
! 5196: ** set, then output must appear in ascending order.
! 5197: **
! 5198: ** This routine should initialize the cursor and position it so that it
! 5199: ** is pointing at the first row, or pointing off the end of the table
! 5200: ** (so that seriesEof() will return true) if the table is empty.
1.6 misho 5201: */
1.6.2.1 ! misho 5202: static int seriesFilter(
! 5203: sqlite3_vtab_cursor *pVtabCursor,
! 5204: int idxNum, const char *idxStrUnused,
! 5205: int argc, sqlite3_value **argv
1.5 misho 5206: ){
1.6.2.1 ! misho 5207: series_cursor *pCur = (series_cursor *)pVtabCursor;
! 5208: int i = 0;
! 5209: (void)idxStrUnused;
! 5210: if( idxNum & 1 ){
! 5211: pCur->ss.iBase = sqlite3_value_int64(argv[i++]);
! 5212: }else{
! 5213: pCur->ss.iBase = 0;
! 5214: }
! 5215: if( idxNum & 2 ){
! 5216: pCur->ss.iTerm = sqlite3_value_int64(argv[i++]);
! 5217: }else{
! 5218: pCur->ss.iTerm = 0xffffffff;
! 5219: }
! 5220: if( idxNum & 4 ){
! 5221: pCur->ss.iStep = sqlite3_value_int64(argv[i++]);
! 5222: if( pCur->ss.iStep==0 ){
! 5223: pCur->ss.iStep = 1;
! 5224: }else if( pCur->ss.iStep<0 ){
! 5225: if( (idxNum & 16)==0 ) idxNum |= 8;
! 5226: }
! 5227: }else{
! 5228: pCur->ss.iStep = 1;
! 5229: }
! 5230: for(i=0; i<argc; i++){
! 5231: if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
! 5232: /* If any of the constraints have a NULL value, then return no rows.
! 5233: ** See ticket https://www.sqlite.org/src/info/fac496b61722daf2 */
! 5234: pCur->ss.iBase = 1;
! 5235: pCur->ss.iTerm = 0;
! 5236: pCur->ss.iStep = 1;
! 5237: break;
! 5238: }
! 5239: }
! 5240: if( idxNum & 8 ){
! 5241: pCur->ss.isReversing = pCur->ss.iStep > 0;
! 5242: }else{
! 5243: pCur->ss.isReversing = pCur->ss.iStep < 0;
! 5244: }
! 5245: setupSequence( &pCur->ss );
! 5246: return SQLITE_OK;
1.5 misho 5247: }
1.6.2.1 ! misho 5248:
! 5249: /*
! 5250: ** SQLite will invoke this method one or more times while planning a query
! 5251: ** that uses the generate_series virtual table. This routine needs to create
! 5252: ** a query plan for each invocation and compute an estimated cost for that
! 5253: ** plan.
! 5254: **
! 5255: ** In this implementation idxNum is used to represent the
! 5256: ** query plan. idxStr is unused.
! 5257: **
! 5258: ** The query plan is represented by bits in idxNum:
! 5259: **
! 5260: ** (1) start = $value -- constraint exists
! 5261: ** (2) stop = $value -- constraint exists
! 5262: ** (4) step = $value -- constraint exists
! 5263: ** (8) output in descending order
! 5264: */
! 5265: static int seriesBestIndex(
! 5266: sqlite3_vtab *pVTab,
! 5267: sqlite3_index_info *pIdxInfo
1.5 misho 5268: ){
1.6.2.1 ! misho 5269: int i, j; /* Loop over constraints */
! 5270: int idxNum = 0; /* The query plan bitmask */
! 5271: int bStartSeen = 0; /* EQ constraint seen on the START column */
! 5272: int unusableMask = 0; /* Mask of unusable constraints */
! 5273: int nArg = 0; /* Number of arguments that seriesFilter() expects */
! 5274: int aIdx[3]; /* Constraints on start, stop, and step */
! 5275: const struct sqlite3_index_constraint *pConstraint;
! 5276:
! 5277: /* This implementation assumes that the start, stop, and step columns
! 5278: ** are the last three columns in the virtual table. */
! 5279: assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
! 5280: assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
! 5281:
! 5282: aIdx[0] = aIdx[1] = aIdx[2] = -1;
! 5283: pConstraint = pIdxInfo->aConstraint;
! 5284: for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
! 5285: int iCol; /* 0 for start, 1 for stop, 2 for step */
! 5286: int iMask; /* bitmask for those column */
! 5287: if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
! 5288: iCol = pConstraint->iColumn - SERIES_COLUMN_START;
! 5289: assert( iCol>=0 && iCol<=2 );
! 5290: iMask = 1 << iCol;
! 5291: if( iCol==0 ) bStartSeen = 1;
! 5292: if( pConstraint->usable==0 ){
! 5293: unusableMask |= iMask;
! 5294: continue;
! 5295: }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
! 5296: idxNum |= iMask;
! 5297: aIdx[iCol] = i;
! 5298: }
! 5299: }
! 5300: for(i=0; i<3; i++){
! 5301: if( (j = aIdx[i])>=0 ){
! 5302: pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
! 5303: pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
! 5304: }
! 5305: }
! 5306: /* The current generate_column() implementation requires at least one
! 5307: ** argument (the START value). Legacy versions assumed START=0 if the
! 5308: ** first argument was omitted. Compile with -DZERO_ARGUMENT_GENERATE_SERIES
! 5309: ** to obtain the legacy behavior */
! 5310: #ifndef ZERO_ARGUMENT_GENERATE_SERIES
! 5311: if( !bStartSeen ){
! 5312: sqlite3_free(pVTab->zErrMsg);
! 5313: pVTab->zErrMsg = sqlite3_mprintf(
! 5314: "first argument to \"generate_series()\" missing or unusable");
! 5315: return SQLITE_ERROR;
! 5316: }
! 5317: #endif
! 5318: if( (unusableMask & ~idxNum)!=0 ){
! 5319: /* The start, stop, and step columns are inputs. Therefore if there
! 5320: ** are unusable constraints on any of start, stop, or step then
! 5321: ** this plan is unusable */
! 5322: return SQLITE_CONSTRAINT;
! 5323: }
! 5324: if( (idxNum & 3)==3 ){
! 5325: /* Both start= and stop= boundaries are available. This is the
! 5326: ** the preferred case */
! 5327: pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
! 5328: pIdxInfo->estimatedRows = 1000;
! 5329: if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn==0 ){
! 5330: if( pIdxInfo->aOrderBy[0].desc ){
! 5331: idxNum |= 8;
! 5332: }else{
! 5333: idxNum |= 16;
! 5334: }
! 5335: pIdxInfo->orderByConsumed = 1;
! 5336: }
! 5337: }else{
! 5338: /* If either boundary is missing, we have to generate a huge span
! 5339: ** of numbers. Make this case very expensive so that the query
! 5340: ** planner will work hard to avoid it. */
! 5341: pIdxInfo->estimatedRows = 2147483647;
! 5342: }
! 5343: pIdxInfo->idxNum = idxNum;
! 5344: return SQLITE_OK;
1.5 misho 5345: }
5346:
1.6.2.1 ! misho 5347: /*
! 5348: ** This following structure defines all the methods for the
! 5349: ** generate_series virtual table.
! 5350: */
! 5351: static sqlite3_module seriesModule = {
! 5352: 0, /* iVersion */
! 5353: 0, /* xCreate */
! 5354: seriesConnect, /* xConnect */
! 5355: seriesBestIndex, /* xBestIndex */
! 5356: seriesDisconnect, /* xDisconnect */
! 5357: 0, /* xDestroy */
! 5358: seriesOpen, /* xOpen - open a cursor */
! 5359: seriesClose, /* xClose - close a cursor */
! 5360: seriesFilter, /* xFilter - configure scan constraints */
! 5361: seriesNext, /* xNext - advance a cursor */
! 5362: seriesEof, /* xEof - check for end of scan */
! 5363: seriesColumn, /* xColumn - read data */
! 5364: seriesRowid, /* xRowid - read data */
! 5365: 0, /* xUpdate */
! 5366: 0, /* xBegin */
! 5367: 0, /* xSync */
! 5368: 0, /* xCommit */
! 5369: 0, /* xRollback */
! 5370: 0, /* xFindMethod */
! 5371: 0, /* xRename */
! 5372: 0, /* xSavepoint */
! 5373: 0, /* xRelease */
! 5374: 0, /* xRollbackTo */
! 5375: 0 /* xShadowName */
! 5376: };
! 5377:
! 5378: #endif /* SQLITE_OMIT_VIRTUALTABLE */
! 5379:
1.5 misho 5380: #ifdef _WIN32
5381:
5382: #endif
1.6.2.1 ! misho 5383: int sqlite3_series_init(
1.5 misho 5384: sqlite3 *db,
5385: char **pzErrMsg,
5386: const sqlite3_api_routines *pApi
5387: ){
5388: int rc = SQLITE_OK;
5389: SQLITE_EXTENSION_INIT2(pApi);
1.6.2.1 ! misho 5390: #ifndef SQLITE_OMIT_VIRTUALTABLE
! 5391: if( sqlite3_libversion_number()<3008012 && pzErrMsg!=0 ){
! 5392: *pzErrMsg = sqlite3_mprintf(
! 5393: "generate_series() requires SQLite 3.8.12 or later");
! 5394: return SQLITE_ERROR;
1.5 misho 5395: }
1.6.2.1 ! misho 5396: rc = sqlite3_create_module(db, "generate_series", &seriesModule, 0);
1.5 misho 5397: #endif
5398: return rc;
5399: }
5400:
1.6.2.1 ! misho 5401: /************************* End ../ext/misc/series.c ********************/
! 5402: /************************* Begin ../ext/misc/regexp.c ******************/
1.5 misho 5403: /*
1.6.2.1 ! misho 5404: ** 2012-11-13
1.5 misho 5405: **
5406: ** The author disclaims copyright to this source code. In place of
5407: ** a legal notice, here is a blessing:
5408: **
5409: ** May you do good and not evil.
5410: ** May you find forgiveness for yourself and forgive others.
5411: ** May you share freely, never taking more than you give.
5412: **
1.6.2.1 ! misho 5413: ******************************************************************************
1.5 misho 5414: **
1.6.2.1 ! misho 5415: ** The code in this file implements a compact but reasonably
! 5416: ** efficient regular-expression matcher for posix extended regular
! 5417: ** expressions against UTF8 text.
! 5418: **
! 5419: ** This file is an SQLite extension. It registers a single function
! 5420: ** named "regexp(A,B)" where A is the regular expression and B is the
! 5421: ** string to be matched. By registering this function, SQLite will also
! 5422: ** then implement the "B regexp A" operator. Note that with the function
! 5423: ** the regular expression comes first, but with the operator it comes
! 5424: ** second.
! 5425: **
! 5426: ** The following regular expression syntax is supported:
! 5427: **
! 5428: ** X* zero or more occurrences of X
! 5429: ** X+ one or more occurrences of X
! 5430: ** X? zero or one occurrences of X
! 5431: ** X{p,q} between p and q occurrences of X
! 5432: ** (X) match X
! 5433: ** X|Y X or Y
! 5434: ** ^X X occurring at the beginning of the string
! 5435: ** X$ X occurring at the end of the string
! 5436: ** . Match any single character
! 5437: ** \c Character c where c is one of \{}()[]|*+?.
! 5438: ** \c C-language escapes for c in afnrtv. ex: \t or \n
! 5439: ** \uXXXX Where XXXX is exactly 4 hex digits, unicode value XXXX
! 5440: ** \xXX Where XX is exactly 2 hex digits, unicode value XX
! 5441: ** [abc] Any single character from the set abc
! 5442: ** [^abc] Any single character not in the set abc
! 5443: ** [a-z] Any single character in the range a-z
! 5444: ** [^a-z] Any single character not in the range a-z
! 5445: ** \b Word boundary
! 5446: ** \w Word character. [A-Za-z0-9_]
! 5447: ** \W Non-word character
! 5448: ** \d Digit
! 5449: ** \D Non-digit
! 5450: ** \s Whitespace character
! 5451: ** \S Non-whitespace character
! 5452: **
! 5453: ** A nondeterministic finite automaton (NFA) is used for matching, so the
! 5454: ** performance is bounded by O(N*M) where N is the size of the regular
! 5455: ** expression and M is the size of the input string. The matcher never
! 5456: ** exhibits exponential behavior. Note that the X{p,q} operator expands
! 5457: ** to p copies of X following by q-p copies of X? and that the size of the
! 5458: ** regular expression in the O(N*M) performance bound is computed after
! 5459: ** this expansion.
1.5 misho 5460: */
5461: #include <string.h>
1.6.2.1 ! misho 5462: #include <stdlib.h>
! 5463: /* #include "sqlite3ext.h" */
! 5464: SQLITE_EXTENSION_INIT1
1.5 misho 5465:
1.6.2.1 ! misho 5466: /*
! 5467: ** The following #defines change the names of some functions implemented in
! 5468: ** this file to prevent name collisions with C-library functions of the
! 5469: ** same name.
! 5470: */
! 5471: #define re_match sqlite3re_match
! 5472: #define re_compile sqlite3re_compile
! 5473: #define re_free sqlite3re_free
! 5474:
! 5475: /* The end-of-input character */
! 5476: #define RE_EOF 0 /* End of input */
! 5477: #define RE_START 0xfffffff /* Start of input - larger than an UTF-8 */
! 5478:
! 5479: /* The NFA is implemented as sequence of opcodes taken from the following
! 5480: ** set. Each opcode has a single integer argument.
! 5481: */
! 5482: #define RE_OP_MATCH 1 /* Match the one character in the argument */
! 5483: #define RE_OP_ANY 2 /* Match any one character. (Implements ".") */
! 5484: #define RE_OP_ANYSTAR 3 /* Special optimized version of .* */
! 5485: #define RE_OP_FORK 4 /* Continue to both next and opcode at iArg */
! 5486: #define RE_OP_GOTO 5 /* Jump to opcode at iArg */
! 5487: #define RE_OP_ACCEPT 6 /* Halt and indicate a successful match */
! 5488: #define RE_OP_CC_INC 7 /* Beginning of a [...] character class */
! 5489: #define RE_OP_CC_EXC 8 /* Beginning of a [^...] character class */
! 5490: #define RE_OP_CC_VALUE 9 /* Single value in a character class */
! 5491: #define RE_OP_CC_RANGE 10 /* Range of values in a character class */
! 5492: #define RE_OP_WORD 11 /* Perl word character [A-Za-z0-9_] */
! 5493: #define RE_OP_NOTWORD 12 /* Not a perl word character */
! 5494: #define RE_OP_DIGIT 13 /* digit: [0-9] */
! 5495: #define RE_OP_NOTDIGIT 14 /* Not a digit */
! 5496: #define RE_OP_SPACE 15 /* space: [ \t\n\r\v\f] */
! 5497: #define RE_OP_NOTSPACE 16 /* Not a digit */
! 5498: #define RE_OP_BOUNDARY 17 /* Boundary between word and non-word */
! 5499: #define RE_OP_ATSTART 18 /* Currently at the start of the string */
! 5500:
! 5501: #if defined(SQLITE_DEBUG)
! 5502: /* Opcode names used for symbolic debugging */
! 5503: static const char *ReOpName[] = {
! 5504: "EOF",
! 5505: "MATCH",
! 5506: "ANY",
! 5507: "ANYSTAR",
! 5508: "FORK",
! 5509: "GOTO",
! 5510: "ACCEPT",
! 5511: "CC_INC",
! 5512: "CC_EXC",
! 5513: "CC_VALUE",
! 5514: "CC_RANGE",
! 5515: "WORD",
! 5516: "NOTWORD",
! 5517: "DIGIT",
! 5518: "NOTDIGIT",
! 5519: "SPACE",
! 5520: "NOTSPACE",
! 5521: "BOUNDARY",
! 5522: "ATSTART",
! 5523: };
! 5524: #endif /* SQLITE_DEBUG */
1.5 misho 5525:
1.6.2.1 ! misho 5526:
! 5527: /* Each opcode is a "state" in the NFA */
! 5528: typedef unsigned short ReStateNumber;
! 5529:
! 5530: /* Because this is an NFA and not a DFA, multiple states can be active at
! 5531: ** once. An instance of the following object records all active states in
! 5532: ** the NFA. The implementation is optimized for the common case where the
! 5533: ** number of actives states is small.
! 5534: */
! 5535: typedef struct ReStateSet {
! 5536: unsigned nState; /* Number of current states */
! 5537: ReStateNumber *aState; /* Current states */
! 5538: } ReStateSet;
! 5539:
! 5540: /* An input string read one character at a time.
! 5541: */
! 5542: typedef struct ReInput ReInput;
! 5543: struct ReInput {
! 5544: const unsigned char *z; /* All text */
! 5545: int i; /* Next byte to read */
! 5546: int mx; /* EOF when i>=mx */
! 5547: };
! 5548:
! 5549: /* A compiled NFA (or an NFA that is in the process of being compiled) is
! 5550: ** an instance of the following object.
! 5551: */
! 5552: typedef struct ReCompiled ReCompiled;
! 5553: struct ReCompiled {
! 5554: ReInput sIn; /* Regular expression text */
! 5555: const char *zErr; /* Error message to return */
! 5556: char *aOp; /* Operators for the virtual machine */
! 5557: int *aArg; /* Arguments to each operator */
! 5558: unsigned (*xNextChar)(ReInput*); /* Next character function */
! 5559: unsigned char zInit[12]; /* Initial text to match */
! 5560: int nInit; /* Number of bytes in zInit */
! 5561: unsigned nState; /* Number of entries in aOp[] and aArg[] */
! 5562: unsigned nAlloc; /* Slots allocated for aOp[] and aArg[] */
! 5563: };
! 5564:
! 5565: /* Add a state to the given state set if it is not already there */
! 5566: static void re_add_state(ReStateSet *pSet, int newState){
! 5567: unsigned i;
! 5568: for(i=0; i<pSet->nState; i++) if( pSet->aState[i]==newState ) return;
! 5569: pSet->aState[pSet->nState++] = (ReStateNumber)newState;
! 5570: }
! 5571:
! 5572: /* Extract the next unicode character from *pzIn and return it. Advance
! 5573: ** *pzIn to the first byte past the end of the character returned. To
! 5574: ** be clear: this routine converts utf8 to unicode. This routine is
! 5575: ** optimized for the common case where the next character is a single byte.
! 5576: */
! 5577: static unsigned re_next_char(ReInput *p){
! 5578: unsigned c;
! 5579: if( p->i>=p->mx ) return 0;
! 5580: c = p->z[p->i++];
! 5581: if( c>=0x80 ){
! 5582: if( (c&0xe0)==0xc0 && p->i<p->mx && (p->z[p->i]&0xc0)==0x80 ){
! 5583: c = (c&0x1f)<<6 | (p->z[p->i++]&0x3f);
! 5584: if( c<0x80 ) c = 0xfffd;
! 5585: }else if( (c&0xf0)==0xe0 && p->i+1<p->mx && (p->z[p->i]&0xc0)==0x80
! 5586: && (p->z[p->i+1]&0xc0)==0x80 ){
! 5587: c = (c&0x0f)<<12 | ((p->z[p->i]&0x3f)<<6) | (p->z[p->i+1]&0x3f);
! 5588: p->i += 2;
! 5589: if( c<=0x7ff || (c>=0xd800 && c<=0xdfff) ) c = 0xfffd;
! 5590: }else if( (c&0xf8)==0xf0 && p->i+2<p->mx && (p->z[p->i]&0xc0)==0x80
! 5591: && (p->z[p->i+1]&0xc0)==0x80 && (p->z[p->i+2]&0xc0)==0x80 ){
! 5592: c = (c&0x07)<<18 | ((p->z[p->i]&0x3f)<<12) | ((p->z[p->i+1]&0x3f)<<6)
! 5593: | (p->z[p->i+2]&0x3f);
! 5594: p->i += 3;
! 5595: if( c<=0xffff || c>0x10ffff ) c = 0xfffd;
! 5596: }else{
! 5597: c = 0xfffd;
! 5598: }
! 5599: }
! 5600: return c;
! 5601: }
! 5602: static unsigned re_next_char_nocase(ReInput *p){
! 5603: unsigned c = re_next_char(p);
! 5604: if( c>='A' && c<='Z' ) c += 'a' - 'A';
! 5605: return c;
! 5606: }
! 5607:
! 5608: /* Return true if c is a perl "word" character: [A-Za-z0-9_] */
! 5609: static int re_word_char(int c){
! 5610: return (c>='0' && c<='9') || (c>='a' && c<='z')
! 5611: || (c>='A' && c<='Z') || c=='_';
! 5612: }
! 5613:
! 5614: /* Return true if c is a "digit" character: [0-9] */
! 5615: static int re_digit_char(int c){
! 5616: return (c>='0' && c<='9');
! 5617: }
! 5618:
! 5619: /* Return true if c is a perl "space" character: [ \t\r\n\v\f] */
! 5620: static int re_space_char(int c){
! 5621: return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
! 5622: }
! 5623:
! 5624: /* Run a compiled regular expression on the zero-terminated input
! 5625: ** string zIn[]. Return true on a match and false if there is no match.
! 5626: */
! 5627: static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
! 5628: ReStateSet aStateSet[2], *pThis, *pNext;
! 5629: ReStateNumber aSpace[100];
! 5630: ReStateNumber *pToFree;
! 5631: unsigned int i = 0;
! 5632: unsigned int iSwap = 0;
! 5633: int c = RE_START;
! 5634: int cPrev = 0;
! 5635: int rc = 0;
! 5636: ReInput in;
! 5637:
! 5638: in.z = zIn;
! 5639: in.i = 0;
! 5640: in.mx = nIn>=0 ? nIn : (int)strlen((char const*)zIn);
! 5641:
! 5642: /* Look for the initial prefix match, if there is one. */
! 5643: if( pRe->nInit ){
! 5644: unsigned char x = pRe->zInit[0];
! 5645: while( in.i+pRe->nInit<=in.mx
! 5646: && (zIn[in.i]!=x ||
! 5647: strncmp((const char*)zIn+in.i, (const char*)pRe->zInit, pRe->nInit)!=0)
! 5648: ){
! 5649: in.i++;
! 5650: }
! 5651: if( in.i+pRe->nInit>in.mx ) return 0;
! 5652: c = RE_START-1;
1.5 misho 5653: }
1.6.2.1 ! misho 5654:
! 5655: if( pRe->nState<=(sizeof(aSpace)/(sizeof(aSpace[0])*2)) ){
! 5656: pToFree = 0;
! 5657: aStateSet[0].aState = aSpace;
! 5658: }else{
! 5659: pToFree = sqlite3_malloc64( sizeof(ReStateNumber)*2*pRe->nState );
! 5660: if( pToFree==0 ) return -1;
! 5661: aStateSet[0].aState = pToFree;
! 5662: }
! 5663: aStateSet[1].aState = &aStateSet[0].aState[pRe->nState];
! 5664: pNext = &aStateSet[1];
! 5665: pNext->nState = 0;
! 5666: re_add_state(pNext, 0);
! 5667: while( c!=RE_EOF && pNext->nState>0 ){
! 5668: cPrev = c;
! 5669: c = pRe->xNextChar(&in);
! 5670: pThis = pNext;
! 5671: pNext = &aStateSet[iSwap];
! 5672: iSwap = 1 - iSwap;
! 5673: pNext->nState = 0;
! 5674: for(i=0; i<pThis->nState; i++){
! 5675: int x = pThis->aState[i];
! 5676: switch( pRe->aOp[x] ){
! 5677: case RE_OP_MATCH: {
! 5678: if( pRe->aArg[x]==c ) re_add_state(pNext, x+1);
! 5679: break;
! 5680: }
! 5681: case RE_OP_ATSTART: {
! 5682: if( cPrev==RE_START ) re_add_state(pThis, x+1);
! 5683: break;
! 5684: }
! 5685: case RE_OP_ANY: {
! 5686: if( c!=0 ) re_add_state(pNext, x+1);
! 5687: break;
! 5688: }
! 5689: case RE_OP_WORD: {
! 5690: if( re_word_char(c) ) re_add_state(pNext, x+1);
! 5691: break;
! 5692: }
! 5693: case RE_OP_NOTWORD: {
! 5694: if( !re_word_char(c) && c!=0 ) re_add_state(pNext, x+1);
! 5695: break;
! 5696: }
! 5697: case RE_OP_DIGIT: {
! 5698: if( re_digit_char(c) ) re_add_state(pNext, x+1);
! 5699: break;
! 5700: }
! 5701: case RE_OP_NOTDIGIT: {
! 5702: if( !re_digit_char(c) && c!=0 ) re_add_state(pNext, x+1);
! 5703: break;
! 5704: }
! 5705: case RE_OP_SPACE: {
! 5706: if( re_space_char(c) ) re_add_state(pNext, x+1);
! 5707: break;
! 5708: }
! 5709: case RE_OP_NOTSPACE: {
! 5710: if( !re_space_char(c) && c!=0 ) re_add_state(pNext, x+1);
! 5711: break;
! 5712: }
! 5713: case RE_OP_BOUNDARY: {
! 5714: if( re_word_char(c)!=re_word_char(cPrev) ) re_add_state(pThis, x+1);
! 5715: break;
! 5716: }
! 5717: case RE_OP_ANYSTAR: {
! 5718: re_add_state(pNext, x);
! 5719: re_add_state(pThis, x+1);
! 5720: break;
! 5721: }
! 5722: case RE_OP_FORK: {
! 5723: re_add_state(pThis, x+pRe->aArg[x]);
! 5724: re_add_state(pThis, x+1);
! 5725: break;
! 5726: }
! 5727: case RE_OP_GOTO: {
! 5728: re_add_state(pThis, x+pRe->aArg[x]);
! 5729: break;
! 5730: }
! 5731: case RE_OP_ACCEPT: {
! 5732: rc = 1;
! 5733: goto re_match_end;
! 5734: }
! 5735: case RE_OP_CC_EXC: {
! 5736: if( c==0 ) break;
! 5737: /* fall-through */ goto re_op_cc_inc;
! 5738: }
! 5739: case RE_OP_CC_INC: re_op_cc_inc: {
! 5740: int j = 1;
! 5741: int n = pRe->aArg[x];
! 5742: int hit = 0;
! 5743: for(j=1; j>0 && j<n; j++){
! 5744: if( pRe->aOp[x+j]==RE_OP_CC_VALUE ){
! 5745: if( pRe->aArg[x+j]==c ){
! 5746: hit = 1;
! 5747: j = -1;
! 5748: }
! 5749: }else{
! 5750: if( pRe->aArg[x+j]<=c && pRe->aArg[x+j+1]>=c ){
! 5751: hit = 1;
! 5752: j = -1;
! 5753: }else{
! 5754: j++;
! 5755: }
! 5756: }
! 5757: }
! 5758: if( pRe->aOp[x]==RE_OP_CC_EXC ) hit = !hit;
! 5759: if( hit ) re_add_state(pNext, x+n);
! 5760: break;
! 5761: }
! 5762: }
! 5763: }
! 5764: }
! 5765: for(i=0; i<pNext->nState; i++){
! 5766: int x = pNext->aState[i];
! 5767: while( pRe->aOp[x]==RE_OP_GOTO ) x += pRe->aArg[x];
! 5768: if( pRe->aOp[x]==RE_OP_ACCEPT ){ rc = 1; break; }
! 5769: }
! 5770: re_match_end:
! 5771: sqlite3_free(pToFree);
! 5772: return rc;
1.5 misho 5773: }
1.6.2.1 ! misho 5774:
! 5775: /* Resize the opcode and argument arrays for an RE under construction.
! 5776: */
! 5777: static int re_resize(ReCompiled *p, int N){
! 5778: char *aOp;
! 5779: int *aArg;
! 5780: aOp = sqlite3_realloc64(p->aOp, N*sizeof(p->aOp[0]));
! 5781: if( aOp==0 ) return 1;
! 5782: p->aOp = aOp;
! 5783: aArg = sqlite3_realloc64(p->aArg, N*sizeof(p->aArg[0]));
! 5784: if( aArg==0 ) return 1;
! 5785: p->aArg = aArg;
! 5786: p->nAlloc = N;
! 5787: return 0;
! 5788: }
! 5789:
! 5790: /* Insert a new opcode and argument into an RE under construction. The
! 5791: ** insertion point is just prior to existing opcode iBefore.
! 5792: */
! 5793: static int re_insert(ReCompiled *p, int iBefore, int op, int arg){
! 5794: int i;
! 5795: if( p->nAlloc<=p->nState && re_resize(p, p->nAlloc*2) ) return 0;
! 5796: for(i=p->nState; i>iBefore; i--){
! 5797: p->aOp[i] = p->aOp[i-1];
! 5798: p->aArg[i] = p->aArg[i-1];
! 5799: }
! 5800: p->nState++;
! 5801: p->aOp[iBefore] = (char)op;
! 5802: p->aArg[iBefore] = arg;
! 5803: return iBefore;
! 5804: }
! 5805:
! 5806: /* Append a new opcode and argument to the end of the RE under construction.
! 5807: */
! 5808: static int re_append(ReCompiled *p, int op, int arg){
! 5809: return re_insert(p, p->nState, op, arg);
! 5810: }
! 5811:
! 5812: /* Make a copy of N opcodes starting at iStart onto the end of the RE
! 5813: ** under construction.
! 5814: */
! 5815: static void re_copy(ReCompiled *p, int iStart, int N){
! 5816: if( p->nState+N>=p->nAlloc && re_resize(p, p->nAlloc*2+N) ) return;
! 5817: memcpy(&p->aOp[p->nState], &p->aOp[iStart], N*sizeof(p->aOp[0]));
! 5818: memcpy(&p->aArg[p->nState], &p->aArg[iStart], N*sizeof(p->aArg[0]));
! 5819: p->nState += N;
! 5820: }
! 5821:
! 5822: /* Return true if c is a hexadecimal digit character: [0-9a-fA-F]
! 5823: ** If c is a hex digit, also set *pV = (*pV)*16 + valueof(c). If
! 5824: ** c is not a hex digit *pV is unchanged.
! 5825: */
! 5826: static int re_hex(int c, int *pV){
! 5827: if( c>='0' && c<='9' ){
! 5828: c -= '0';
! 5829: }else if( c>='a' && c<='f' ){
! 5830: c -= 'a' - 10;
! 5831: }else if( c>='A' && c<='F' ){
! 5832: c -= 'A' - 10;
! 5833: }else{
1.5 misho 5834: return 0;
5835: }
1.6.2.1 ! misho 5836: *pV = (*pV)*16 + (c & 0xff);
! 5837: return 1;
! 5838: }
! 5839:
! 5840: /* A backslash character has been seen, read the next character and
! 5841: ** return its interpretation.
! 5842: */
! 5843: static unsigned re_esc_char(ReCompiled *p){
! 5844: static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]";
! 5845: static const char zTrans[] = "\a\f\n\r\t\v";
! 5846: int i, v = 0;
! 5847: char c;
! 5848: if( p->sIn.i>=p->sIn.mx ) return 0;
! 5849: c = p->sIn.z[p->sIn.i];
! 5850: if( c=='u' && p->sIn.i+4<p->sIn.mx ){
! 5851: const unsigned char *zIn = p->sIn.z + p->sIn.i;
! 5852: if( re_hex(zIn[1],&v)
! 5853: && re_hex(zIn[2],&v)
! 5854: && re_hex(zIn[3],&v)
! 5855: && re_hex(zIn[4],&v)
! 5856: ){
! 5857: p->sIn.i += 5;
! 5858: return v;
! 5859: }
1.5 misho 5860: }
1.6.2.1 ! misho 5861: if( c=='x' && p->sIn.i+2<p->sIn.mx ){
! 5862: const unsigned char *zIn = p->sIn.z + p->sIn.i;
! 5863: if( re_hex(zIn[1],&v)
! 5864: && re_hex(zIn[2],&v)
! 5865: ){
! 5866: p->sIn.i += 3;
! 5867: return v;
! 5868: }
! 5869: }
! 5870: for(i=0; zEsc[i] && zEsc[i]!=c; i++){}
! 5871: if( zEsc[i] ){
! 5872: if( i<6 ) c = zTrans[i];
! 5873: p->sIn.i++;
! 5874: }else{
! 5875: p->zErr = "unknown \\ escape";
! 5876: }
! 5877: return c;
! 5878: }
! 5879:
! 5880: /* Forward declaration */
! 5881: static const char *re_subcompile_string(ReCompiled*);
! 5882:
! 5883: /* Peek at the next byte of input */
! 5884: static unsigned char rePeek(ReCompiled *p){
! 5885: return p->sIn.i<p->sIn.mx ? p->sIn.z[p->sIn.i] : 0;
! 5886: }
! 5887:
! 5888: /* Compile RE text into a sequence of opcodes. Continue up to the
! 5889: ** first unmatched ")" character, then return. If an error is found,
! 5890: ** return a pointer to the error message string.
! 5891: */
! 5892: static const char *re_subcompile_re(ReCompiled *p){
! 5893: const char *zErr;
! 5894: int iStart, iEnd, iGoto;
! 5895: iStart = p->nState;
! 5896: zErr = re_subcompile_string(p);
! 5897: if( zErr ) return zErr;
! 5898: while( rePeek(p)=='|' ){
! 5899: iEnd = p->nState;
! 5900: re_insert(p, iStart, RE_OP_FORK, iEnd + 2 - iStart);
! 5901: iGoto = re_append(p, RE_OP_GOTO, 0);
! 5902: p->sIn.i++;
! 5903: zErr = re_subcompile_string(p);
! 5904: if( zErr ) return zErr;
! 5905: p->aArg[iGoto] = p->nState - iGoto;
! 5906: }
! 5907: return 0;
1.5 misho 5908: }
1.6.2.1 ! misho 5909:
! 5910: /* Compile an element of regular expression text (anything that can be
! 5911: ** an operand to the "|" operator). Return NULL on success or a pointer
! 5912: ** to the error message if there is a problem.
! 5913: */
! 5914: static const char *re_subcompile_string(ReCompiled *p){
! 5915: int iPrev = -1;
! 5916: int iStart;
! 5917: unsigned c;
! 5918: const char *zErr;
! 5919: while( (c = p->xNextChar(&p->sIn))!=0 ){
! 5920: iStart = p->nState;
! 5921: switch( c ){
! 5922: case '|':
! 5923: case ')': {
! 5924: p->sIn.i--;
! 5925: return 0;
! 5926: }
! 5927: case '(': {
! 5928: zErr = re_subcompile_re(p);
! 5929: if( zErr ) return zErr;
! 5930: if( rePeek(p)!=')' ) return "unmatched '('";
! 5931: p->sIn.i++;
! 5932: break;
! 5933: }
! 5934: case '.': {
! 5935: if( rePeek(p)=='*' ){
! 5936: re_append(p, RE_OP_ANYSTAR, 0);
! 5937: p->sIn.i++;
! 5938: }else{
! 5939: re_append(p, RE_OP_ANY, 0);
! 5940: }
! 5941: break;
! 5942: }
! 5943: case '*': {
! 5944: if( iPrev<0 ) return "'*' without operand";
! 5945: re_insert(p, iPrev, RE_OP_GOTO, p->nState - iPrev + 1);
! 5946: re_append(p, RE_OP_FORK, iPrev - p->nState + 1);
! 5947: break;
! 5948: }
! 5949: case '+': {
! 5950: if( iPrev<0 ) return "'+' without operand";
! 5951: re_append(p, RE_OP_FORK, iPrev - p->nState);
! 5952: break;
! 5953: }
! 5954: case '?': {
! 5955: if( iPrev<0 ) return "'?' without operand";
! 5956: re_insert(p, iPrev, RE_OP_FORK, p->nState - iPrev+1);
! 5957: break;
! 5958: }
! 5959: case '$': {
! 5960: re_append(p, RE_OP_MATCH, RE_EOF);
! 5961: break;
! 5962: }
! 5963: case '^': {
! 5964: re_append(p, RE_OP_ATSTART, 0);
! 5965: break;
! 5966: }
! 5967: case '{': {
! 5968: int m = 0, n = 0;
! 5969: int sz, j;
! 5970: if( iPrev<0 ) return "'{m,n}' without operand";
! 5971: while( (c=rePeek(p))>='0' && c<='9' ){ m = m*10 + c - '0'; p->sIn.i++; }
! 5972: n = m;
! 5973: if( c==',' ){
! 5974: p->sIn.i++;
! 5975: n = 0;
! 5976: while( (c=rePeek(p))>='0' && c<='9' ){ n = n*10 + c-'0'; p->sIn.i++; }
! 5977: }
! 5978: if( c!='}' ) return "unmatched '{'";
! 5979: if( n>0 && n<m ) return "n less than m in '{m,n}'";
! 5980: p->sIn.i++;
! 5981: sz = p->nState - iPrev;
! 5982: if( m==0 ){
! 5983: if( n==0 ) return "both m and n are zero in '{m,n}'";
! 5984: re_insert(p, iPrev, RE_OP_FORK, sz+1);
! 5985: iPrev++;
! 5986: n--;
! 5987: }else{
! 5988: for(j=1; j<m; j++) re_copy(p, iPrev, sz);
! 5989: }
! 5990: for(j=m; j<n; j++){
! 5991: re_append(p, RE_OP_FORK, sz+1);
! 5992: re_copy(p, iPrev, sz);
! 5993: }
! 5994: if( n==0 && m>0 ){
! 5995: re_append(p, RE_OP_FORK, -sz);
! 5996: }
! 5997: break;
! 5998: }
! 5999: case '[': {
! 6000: unsigned int iFirst = p->nState;
! 6001: if( rePeek(p)=='^' ){
! 6002: re_append(p, RE_OP_CC_EXC, 0);
! 6003: p->sIn.i++;
! 6004: }else{
! 6005: re_append(p, RE_OP_CC_INC, 0);
! 6006: }
! 6007: while( (c = p->xNextChar(&p->sIn))!=0 ){
! 6008: if( c=='[' && rePeek(p)==':' ){
! 6009: return "POSIX character classes not supported";
! 6010: }
! 6011: if( c=='\\' ) c = re_esc_char(p);
! 6012: if( rePeek(p)=='-' ){
! 6013: re_append(p, RE_OP_CC_RANGE, c);
! 6014: p->sIn.i++;
! 6015: c = p->xNextChar(&p->sIn);
! 6016: if( c=='\\' ) c = re_esc_char(p);
! 6017: re_append(p, RE_OP_CC_RANGE, c);
! 6018: }else{
! 6019: re_append(p, RE_OP_CC_VALUE, c);
! 6020: }
! 6021: if( rePeek(p)==']' ){ p->sIn.i++; break; }
! 6022: }
! 6023: if( c==0 ) return "unclosed '['";
! 6024: if( p->nState>iFirst ) p->aArg[iFirst] = p->nState - iFirst;
! 6025: break;
! 6026: }
! 6027: case '\\': {
! 6028: int specialOp = 0;
! 6029: switch( rePeek(p) ){
! 6030: case 'b': specialOp = RE_OP_BOUNDARY; break;
! 6031: case 'd': specialOp = RE_OP_DIGIT; break;
! 6032: case 'D': specialOp = RE_OP_NOTDIGIT; break;
! 6033: case 's': specialOp = RE_OP_SPACE; break;
! 6034: case 'S': specialOp = RE_OP_NOTSPACE; break;
! 6035: case 'w': specialOp = RE_OP_WORD; break;
! 6036: case 'W': specialOp = RE_OP_NOTWORD; break;
! 6037: }
! 6038: if( specialOp ){
! 6039: p->sIn.i++;
! 6040: re_append(p, specialOp, 0);
! 6041: }else{
! 6042: c = re_esc_char(p);
! 6043: re_append(p, RE_OP_MATCH, c);
! 6044: }
! 6045: break;
! 6046: }
! 6047: default: {
! 6048: re_append(p, RE_OP_MATCH, c);
! 6049: break;
! 6050: }
! 6051: }
! 6052: iPrev = iStart;
! 6053: }
! 6054: return 0;
1.5 misho 6055: }
1.6.2.1 ! misho 6056:
! 6057: /* Free and reclaim all the memory used by a previously compiled
! 6058: ** regular expression. Applications should invoke this routine once
! 6059: ** for every call to re_compile() to avoid memory leaks.
! 6060: */
! 6061: static void re_free(ReCompiled *pRe){
! 6062: if( pRe ){
! 6063: sqlite3_free(pRe->aOp);
! 6064: sqlite3_free(pRe->aArg);
! 6065: sqlite3_free(pRe);
! 6066: }
1.5 misho 6067: }
1.6.2.1 ! misho 6068:
! 6069: /*
! 6070: ** Compile a textual regular expression in zIn[] into a compiled regular
! 6071: ** expression suitable for us by re_match() and return a pointer to the
! 6072: ** compiled regular expression in *ppRe. Return NULL on success or an
! 6073: ** error message if something goes wrong.
! 6074: */
! 6075: static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
! 6076: ReCompiled *pRe;
! 6077: const char *zErr;
! 6078: int i, j;
! 6079:
! 6080: *ppRe = 0;
! 6081: pRe = sqlite3_malloc( sizeof(*pRe) );
! 6082: if( pRe==0 ){
! 6083: return "out of memory";
! 6084: }
! 6085: memset(pRe, 0, sizeof(*pRe));
! 6086: pRe->xNextChar = noCase ? re_next_char_nocase : re_next_char;
! 6087: if( re_resize(pRe, 30) ){
! 6088: re_free(pRe);
! 6089: return "out of memory";
! 6090: }
! 6091: if( zIn[0]=='^' ){
! 6092: zIn++;
! 6093: }else{
! 6094: re_append(pRe, RE_OP_ANYSTAR, 0);
! 6095: }
! 6096: pRe->sIn.z = (unsigned char*)zIn;
! 6097: pRe->sIn.i = 0;
! 6098: pRe->sIn.mx = (int)strlen(zIn);
! 6099: zErr = re_subcompile_re(pRe);
! 6100: if( zErr ){
! 6101: re_free(pRe);
! 6102: return zErr;
! 6103: }
! 6104: if( pRe->sIn.i>=pRe->sIn.mx ){
! 6105: re_append(pRe, RE_OP_ACCEPT, 0);
! 6106: *ppRe = pRe;
! 6107: }else{
! 6108: re_free(pRe);
! 6109: return "unrecognized character";
! 6110: }
! 6111:
! 6112: /* The following is a performance optimization. If the regex begins with
! 6113: ** ".*" (if the input regex lacks an initial "^") and afterwards there are
! 6114: ** one or more matching characters, enter those matching characters into
! 6115: ** zInit[]. The re_match() routine can then search ahead in the input
! 6116: ** string looking for the initial match without having to run the whole
! 6117: ** regex engine over the string. Do not worry about trying to match
! 6118: ** unicode characters beyond plane 0 - those are very rare and this is
! 6119: ** just an optimization. */
! 6120: if( pRe->aOp[0]==RE_OP_ANYSTAR && !noCase ){
! 6121: for(j=0, i=1; j<(int)sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
! 6122: unsigned x = pRe->aArg[i];
! 6123: if( x<=0x7f ){
! 6124: pRe->zInit[j++] = (unsigned char)x;
! 6125: }else if( x<=0x7ff ){
! 6126: pRe->zInit[j++] = (unsigned char)(0xc0 | (x>>6));
! 6127: pRe->zInit[j++] = 0x80 | (x&0x3f);
! 6128: }else if( x<=0xffff ){
! 6129: pRe->zInit[j++] = (unsigned char)(0xe0 | (x>>12));
! 6130: pRe->zInit[j++] = 0x80 | ((x>>6)&0x3f);
! 6131: pRe->zInit[j++] = 0x80 | (x&0x3f);
! 6132: }else{
! 6133: break;
! 6134: }
! 6135: }
! 6136: if( j>0 && pRe->zInit[j-1]==0 ) j--;
! 6137: pRe->nInit = j;
! 6138: }
! 6139: return pRe->zErr;
1.5 misho 6140: }
1.6.2.1 ! misho 6141:
! 6142: /*
! 6143: ** Implementation of the regexp() SQL function. This function implements
! 6144: ** the build-in REGEXP operator. The first argument to the function is the
! 6145: ** pattern and the second argument is the string. So, the SQL statements:
! 6146: **
! 6147: ** A REGEXP B
! 6148: **
! 6149: ** is implemented as regexp(B,A).
! 6150: */
! 6151: static void re_sql_func(
! 6152: sqlite3_context *context,
! 6153: int argc,
! 6154: sqlite3_value **argv
! 6155: ){
! 6156: ReCompiled *pRe; /* Compiled regular expression */
! 6157: const char *zPattern; /* The regular expression */
! 6158: const unsigned char *zStr;/* String being searched */
! 6159: const char *zErr; /* Compile error message */
! 6160: int setAux = 0; /* True to invoke sqlite3_set_auxdata() */
! 6161:
! 6162: (void)argc; /* Unused */
! 6163: pRe = sqlite3_get_auxdata(context, 0);
! 6164: if( pRe==0 ){
! 6165: zPattern = (const char*)sqlite3_value_text(argv[0]);
! 6166: if( zPattern==0 ) return;
! 6167: zErr = re_compile(&pRe, zPattern, sqlite3_user_data(context)!=0);
! 6168: if( zErr ){
! 6169: re_free(pRe);
! 6170: sqlite3_result_error(context, zErr, -1);
! 6171: return;
! 6172: }
! 6173: if( pRe==0 ){
! 6174: sqlite3_result_error_nomem(context);
! 6175: return;
! 6176: }
! 6177: setAux = 1;
! 6178: }
! 6179: zStr = (const unsigned char*)sqlite3_value_text(argv[1]);
! 6180: if( zStr!=0 ){
! 6181: sqlite3_result_int(context, re_match(pRe, zStr, -1));
! 6182: }
! 6183: if( setAux ){
! 6184: sqlite3_set_auxdata(context, 0, pRe, (void(*)(void*))re_free);
! 6185: }
1.5 misho 6186: }
6187:
1.6.2.1 ! misho 6188: #if defined(SQLITE_DEBUG)
! 6189: /*
! 6190: ** This function is used for testing and debugging only. It is only available
! 6191: ** if the SQLITE_DEBUG compile-time option is used.
! 6192: **
! 6193: ** Compile a regular expression and then convert the compiled expression into
! 6194: ** text and return that text.
! 6195: */
! 6196: static void re_bytecode_func(
! 6197: sqlite3_context *context,
! 6198: int argc,
! 6199: sqlite3_value **argv
! 6200: ){
! 6201: const char *zPattern;
! 6202: const char *zErr;
! 6203: ReCompiled *pRe;
! 6204: sqlite3_str *pStr;
! 6205: int i;
! 6206: int n;
! 6207: char *z;
! 6208: (void)argc;
1.5 misho 6209:
1.6.2.1 ! misho 6210: zPattern = (const char*)sqlite3_value_text(argv[0]);
! 6211: if( zPattern==0 ) return;
! 6212: zErr = re_compile(&pRe, zPattern, sqlite3_user_data(context)!=0);
! 6213: if( zErr ){
! 6214: re_free(pRe);
! 6215: sqlite3_result_error(context, zErr, -1);
! 6216: return;
1.5 misho 6217: }
1.6.2.1 ! misho 6218: if( pRe==0 ){
! 6219: sqlite3_result_error_nomem(context);
! 6220: return;
! 6221: }
! 6222: pStr = sqlite3_str_new(0);
! 6223: if( pStr==0 ) goto re_bytecode_func_err;
! 6224: if( pRe->nInit>0 ){
! 6225: sqlite3_str_appendf(pStr, "INIT ");
! 6226: for(i=0; i<pRe->nInit; i++){
! 6227: sqlite3_str_appendf(pStr, "%02x", pRe->zInit[i]);
! 6228: }
! 6229: sqlite3_str_appendf(pStr, "\n");
! 6230: }
! 6231: for(i=0; (unsigned)i<pRe->nState; i++){
! 6232: sqlite3_str_appendf(pStr, "%-8s %4d\n",
! 6233: ReOpName[(unsigned char)pRe->aOp[i]], pRe->aArg[i]);
! 6234: }
! 6235: n = sqlite3_str_length(pStr);
! 6236: z = sqlite3_str_finish(pStr);
! 6237: if( n==0 ){
! 6238: sqlite3_free(z);
! 6239: }else{
! 6240: sqlite3_result_text(context, z, n-1, sqlite3_free);
! 6241: }
! 6242:
! 6243: re_bytecode_func_err:
! 6244: re_free(pRe);
1.5 misho 6245: }
6246:
1.6.2.1 ! misho 6247: #endif /* SQLITE_DEBUG */
! 6248:
! 6249:
! 6250: /*
! 6251: ** Invoke this routine to register the regexp() function with the
! 6252: ** SQLite database connection.
! 6253: */
! 6254: #ifdef _WIN32
! 6255:
! 6256: #endif
! 6257: int sqlite3_regexp_init(
! 6258: sqlite3 *db,
! 6259: char **pzErrMsg,
! 6260: const sqlite3_api_routines *pApi
! 6261: ){
1.5 misho 6262: int rc = SQLITE_OK;
1.6.2.1 ! misho 6263: SQLITE_EXTENSION_INIT2(pApi);
! 6264: (void)pzErrMsg; /* Unused */
! 6265: rc = sqlite3_create_function(db, "regexp", 2,
! 6266: SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
! 6267: 0, re_sql_func, 0, 0);
! 6268: if( rc==SQLITE_OK ){
! 6269: /* The regexpi(PATTERN,STRING) function is a case-insensitive version
! 6270: ** of regexp(PATTERN,STRING). */
! 6271: rc = sqlite3_create_function(db, "regexpi", 2,
! 6272: SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
! 6273: (void*)db, re_sql_func, 0, 0);
! 6274: #if defined(SQLITE_DEBUG)
1.5 misho 6275: if( rc==SQLITE_OK ){
1.6.2.1 ! misho 6276: rc = sqlite3_create_function(db, "regexp_bytecode", 1,
! 6277: SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
! 6278: 0, re_bytecode_func, 0, 0);
1.5 misho 6279: }
1.6.2.1 ! misho 6280: #endif /* SQLITE_DEBUG */
1.5 misho 6281: }
6282: return rc;
6283: }
6284:
1.6.2.1 ! misho 6285: /************************* End ../ext/misc/regexp.c ********************/
! 6286: #ifndef SQLITE_SHELL_FIDDLE
! 6287: /************************* Begin ../ext/misc/fileio.c ******************/
1.5 misho 6288: /*
1.6.2.1 ! misho 6289: ** 2014-06-13
1.5 misho 6290: **
6291: ** The author disclaims copyright to this source code. In place of
6292: ** a legal notice, here is a blessing:
6293: **
6294: ** May you do good and not evil.
6295: ** May you find forgiveness for yourself and forgive others.
6296: ** May you share freely, never taking more than you give.
6297: **
6298: ******************************************************************************
6299: **
1.6.2.1 ! misho 6300: ** This SQLite extension implements SQL functions readfile() and
! 6301: ** writefile(), and eponymous virtual type "fsdir".
1.5 misho 6302: **
1.6.2.1 ! misho 6303: ** WRITEFILE(FILE, DATA [, MODE [, MTIME]]):
1.5 misho 6304: **
1.6.2.1 ! misho 6305: ** If neither of the optional arguments is present, then this UDF
! 6306: ** function writes blob DATA to file FILE. If successful, the number
! 6307: ** of bytes written is returned. If an error occurs, NULL is returned.
1.5 misho 6308: **
1.6.2.1 ! misho 6309: ** If the first option argument - MODE - is present, then it must
! 6310: ** be passed an integer value that corresponds to a POSIX mode
! 6311: ** value (file type + permissions, as returned in the stat.st_mode
! 6312: ** field by the stat() system call). Three types of files may
! 6313: ** be written/created:
1.5 misho 6314: **
1.6.2.1 ! misho 6315: ** regular files: (mode & 0170000)==0100000
! 6316: ** symbolic links: (mode & 0170000)==0120000
! 6317: ** directories: (mode & 0170000)==0040000
1.5 misho 6318: **
1.6.2.1 ! misho 6319: ** For a directory, the DATA is ignored. For a symbolic link, it is
! 6320: ** interpreted as text and used as the target of the link. For a
! 6321: ** regular file, it is interpreted as a blob and written into the
! 6322: ** named file. Regardless of the type of file, its permissions are
! 6323: ** set to (mode & 0777) before returning.
1.5 misho 6324: **
1.6.2.1 ! misho 6325: ** If the optional MTIME argument is present, then it is interpreted
! 6326: ** as an integer - the number of seconds since the unix epoch. The
! 6327: ** modification-time of the target file is set to this value before
! 6328: ** returning.
1.5 misho 6329: **
1.6.2.1 ! misho 6330: ** If three or more arguments are passed to this function and an
! 6331: ** error is encountered, an exception is raised.
1.5 misho 6332: **
1.6.2.1 ! misho 6333: ** READFILE(FILE):
1.5 misho 6334: **
1.6.2.1 ! misho 6335: ** Read and return the contents of file FILE (type blob) from disk.
! 6336: **
! 6337: ** FSDIR:
! 6338: **
! 6339: ** Used as follows:
! 6340: **
! 6341: ** SELECT * FROM fsdir($path [, $dir]);
! 6342: **
! 6343: ** Parameter $path is an absolute or relative pathname. If the file that it
! 6344: ** refers to does not exist, it is an error. If the path refers to a regular
! 6345: ** file or symbolic link, it returns a single row. Or, if the path refers
! 6346: ** to a directory, it returns one row for the directory, and one row for each
! 6347: ** file within the hierarchy rooted at $path.
! 6348: **
! 6349: ** Each row has the following columns:
! 6350: **
! 6351: ** name: Path to file or directory (text value).
! 6352: ** mode: Value of stat.st_mode for directory entry (an integer).
! 6353: ** mtime: Value of stat.st_mtime for directory entry (an integer).
! 6354: ** data: For a regular file, a blob containing the file data. For a
! 6355: ** symlink, a text value containing the text of the link. For a
! 6356: ** directory, NULL.
! 6357: **
! 6358: ** If a non-NULL value is specified for the optional $dir parameter and
! 6359: ** $path is a relative path, then $path is interpreted relative to $dir.
! 6360: ** And the paths returned in the "name" column of the table are also
! 6361: ** relative to directory $dir.
! 6362: **
! 6363: ** Notes on building this extension for Windows:
! 6364: ** Unless linked statically with the SQLite library, a preprocessor
! 6365: ** symbol, FILEIO_WIN32_DLL, must be #define'd to create a stand-alone
! 6366: ** DLL form of this extension for WIN32. See its use below for details.
1.5 misho 6367: */
6368: /* #include "sqlite3ext.h" */
6369: SQLITE_EXTENSION_INIT1
1.6.2.1 ! misho 6370: #include <stdio.h>
1.5 misho 6371: #include <string.h>
1.6.2.1 ! misho 6372: #include <assert.h>
1.5 misho 6373:
1.6.2.1 ! misho 6374: #include <sys/types.h>
! 6375: #include <sys/stat.h>
! 6376: #include <fcntl.h>
! 6377: #if !defined(_WIN32) && !defined(WIN32)
! 6378: # include <unistd.h>
! 6379: # include <dirent.h>
! 6380: # include <utime.h>
! 6381: # include <sys/time.h>
! 6382: #else
! 6383: # include "windows.h"
! 6384: # include <io.h>
! 6385: # include <direct.h>
! 6386: /* # include "test_windirent.h" */
! 6387: # define dirent DIRENT
! 6388: # ifndef chmod
! 6389: # define chmod _chmod
! 6390: # endif
! 6391: # ifndef stat
! 6392: # define stat _stat
! 6393: # endif
! 6394: # define mkdir(path,mode) _mkdir(path)
! 6395: # define lstat(path,buf) stat(path,buf)
1.5 misho 6396: #endif
1.6.2.1 ! misho 6397: #include <time.h>
! 6398: #include <errno.h>
1.5 misho 6399:
6400:
6401: /*
1.6.2.1 ! misho 6402: ** Structure of the fsdir() table-valued function
1.5 misho 6403: */
1.6.2.1 ! misho 6404: /* 0 1 2 3 4 5 */
! 6405: #define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)"
! 6406: #define FSDIR_COLUMN_NAME 0 /* Name of the file */
! 6407: #define FSDIR_COLUMN_MODE 1 /* Access mode */
! 6408: #define FSDIR_COLUMN_MTIME 2 /* Last modification time */
! 6409: #define FSDIR_COLUMN_DATA 3 /* File content */
! 6410: #define FSDIR_COLUMN_PATH 4 /* Path to top of search */
! 6411: #define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */
! 6412:
1.5 misho 6413:
6414: /*
1.6.2.1 ! misho 6415: ** Set the result stored by context ctx to a blob containing the
! 6416: ** contents of file zName. Or, leave the result unchanged (NULL)
! 6417: ** if the file does not exist or is unreadable.
! 6418: **
! 6419: ** If the file exceeds the SQLite blob size limit, through an
! 6420: ** SQLITE_TOOBIG error.
! 6421: **
! 6422: ** Throw an SQLITE_IOERR if there are difficulties pulling the file
! 6423: ** off of disk.
1.5 misho 6424: */
1.6.2.1 ! misho 6425: static void readFileContents(sqlite3_context *ctx, const char *zName){
! 6426: FILE *in;
! 6427: sqlite3_int64 nIn;
! 6428: void *pBuf;
! 6429: sqlite3 *db;
! 6430: int mxBlob;
! 6431:
! 6432: in = fopen(zName, "rb");
! 6433: if( in==0 ){
! 6434: /* File does not exist or is unreadable. Leave the result set to NULL. */
! 6435: return;
! 6436: }
! 6437: fseek(in, 0, SEEK_END);
! 6438: nIn = ftell(in);
! 6439: rewind(in);
! 6440: db = sqlite3_context_db_handle(ctx);
! 6441: mxBlob = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1);
! 6442: if( nIn>mxBlob ){
! 6443: sqlite3_result_error_code(ctx, SQLITE_TOOBIG);
! 6444: fclose(in);
! 6445: return;
! 6446: }
! 6447: pBuf = sqlite3_malloc64( nIn ? nIn : 1 );
! 6448: if( pBuf==0 ){
! 6449: sqlite3_result_error_nomem(ctx);
! 6450: fclose(in);
! 6451: return;
! 6452: }
! 6453: if( nIn==(sqlite3_int64)fread(pBuf, 1, (size_t)nIn, in) ){
! 6454: sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
! 6455: }else{
! 6456: sqlite3_result_error_code(ctx, SQLITE_IOERR);
! 6457: sqlite3_free(pBuf);
1.5 misho 6458: }
1.6.2.1 ! misho 6459: fclose(in);
1.5 misho 6460: }
6461:
6462: /*
1.6.2.1 ! misho 6463: ** Implementation of the "readfile(X)" SQL function. The entire content
! 6464: ** of the file named X is read and returned as a BLOB. NULL is returned
! 6465: ** if the file does not exist or is unreadable.
1.5 misho 6466: */
1.6.2.1 ! misho 6467: static void readfileFunc(
! 6468: sqlite3_context *context,
! 6469: int argc,
! 6470: sqlite3_value **argv
1.5 misho 6471: ){
1.6.2.1 ! misho 6472: const char *zName;
! 6473: (void)(argc); /* Unused parameter */
! 6474: zName = (const char*)sqlite3_value_text(argv[0]);
! 6475: if( zName==0 ) return;
! 6476: readFileContents(context, zName);
1.5 misho 6477: }
6478:
6479: /*
1.6.2.1 ! misho 6480: ** Set the error message contained in context ctx to the results of
! 6481: ** vprintf(zFmt, ...).
1.5 misho 6482: */
1.6.2.1 ! misho 6483: static void ctxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
! 6484: char *zMsg = 0;
! 6485: va_list ap;
! 6486: va_start(ap, zFmt);
! 6487: zMsg = sqlite3_vmprintf(zFmt, ap);
! 6488: sqlite3_result_error(ctx, zMsg, -1);
! 6489: sqlite3_free(zMsg);
! 6490: va_end(ap);
1.5 misho 6491: }
6492:
1.6.2.1 ! misho 6493: #if defined(_WIN32)
1.5 misho 6494: /*
1.6.2.1 ! misho 6495: ** This function is designed to convert a Win32 FILETIME structure into the
! 6496: ** number of seconds since the Unix Epoch (1970-01-01 00:00:00 UTC).
1.5 misho 6497: */
1.6.2.1 ! misho 6498: static sqlite3_uint64 fileTimeToUnixTime(
! 6499: LPFILETIME pFileTime
1.5 misho 6500: ){
1.6.2.1 ! misho 6501: SYSTEMTIME epochSystemTime;
! 6502: ULARGE_INTEGER epochIntervals;
! 6503: FILETIME epochFileTime;
! 6504: ULARGE_INTEGER fileIntervals;
! 6505:
! 6506: memset(&epochSystemTime, 0, sizeof(SYSTEMTIME));
! 6507: epochSystemTime.wYear = 1970;
! 6508: epochSystemTime.wMonth = 1;
! 6509: epochSystemTime.wDay = 1;
! 6510: SystemTimeToFileTime(&epochSystemTime, &epochFileTime);
! 6511: epochIntervals.LowPart = epochFileTime.dwLowDateTime;
! 6512: epochIntervals.HighPart = epochFileTime.dwHighDateTime;
! 6513:
! 6514: fileIntervals.LowPart = pFileTime->dwLowDateTime;
! 6515: fileIntervals.HighPart = pFileTime->dwHighDateTime;
! 6516:
! 6517: return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000;
! 6518: }
! 6519:
! 6520:
! 6521: #if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32))
! 6522: # /* To allow a standalone DLL, use this next replacement function: */
! 6523: # undef sqlite3_win32_utf8_to_unicode
! 6524: # define sqlite3_win32_utf8_to_unicode utf8_to_utf16
! 6525: #
! 6526: LPWSTR utf8_to_utf16(const char *z){
! 6527: int nAllot = MultiByteToWideChar(CP_UTF8, 0, z, -1, NULL, 0);
! 6528: LPWSTR rv = sqlite3_malloc(nAllot * sizeof(WCHAR));
! 6529: if( rv!=0 && 0 < MultiByteToWideChar(CP_UTF8, 0, z, -1, rv, nAllot) )
! 6530: return rv;
! 6531: sqlite3_free(rv);
! 6532: return 0;
1.5 misho 6533: }
1.6.2.1 ! misho 6534: #endif
1.5 misho 6535:
6536: /*
1.6.2.1 ! misho 6537: ** This function attempts to normalize the time values found in the stat()
! 6538: ** buffer to UTC. This is necessary on Win32, where the runtime library
! 6539: ** appears to return these values as local times.
1.5 misho 6540: */
1.6.2.1 ! misho 6541: static void statTimesToUtc(
! 6542: const char *zPath,
! 6543: struct stat *pStatBuf
! 6544: ){
! 6545: HANDLE hFindFile;
! 6546: WIN32_FIND_DATAW fd;
! 6547: LPWSTR zUnicodeName;
! 6548: extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
! 6549: zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath);
! 6550: if( zUnicodeName ){
! 6551: memset(&fd, 0, sizeof(WIN32_FIND_DATAW));
! 6552: hFindFile = FindFirstFileW(zUnicodeName, &fd);
! 6553: if( hFindFile!=NULL ){
! 6554: pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime);
! 6555: pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime);
! 6556: pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime);
! 6557: FindClose(hFindFile);
! 6558: }
! 6559: sqlite3_free(zUnicodeName);
1.5 misho 6560: }
6561: }
1.6.2.1 ! misho 6562: #endif
1.5 misho 6563:
6564: /*
1.6.2.1 ! misho 6565: ** This function is used in place of stat(). On Windows, special handling
! 6566: ** is required in order for the included time to be returned as UTC. On all
! 6567: ** other systems, this function simply calls stat().
1.5 misho 6568: */
1.6.2.1 ! misho 6569: static int fileStat(
! 6570: const char *zPath,
! 6571: struct stat *pStatBuf
1.5 misho 6572: ){
1.6.2.1 ! misho 6573: #if defined(_WIN32)
! 6574: int rc = stat(zPath, pStatBuf);
! 6575: if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
! 6576: return rc;
! 6577: #else
! 6578: return stat(zPath, pStatBuf);
! 6579: #endif
! 6580: }
1.5 misho 6581:
6582: /*
1.6.2.1 ! misho 6583: ** This function is used in place of lstat(). On Windows, special handling
! 6584: ** is required in order for the included time to be returned as UTC. On all
! 6585: ** other systems, this function simply calls lstat().
1.5 misho 6586: */
1.6.2.1 ! misho 6587: static int fileLinkStat(
! 6588: const char *zPath,
! 6589: struct stat *pStatBuf
! 6590: ){
! 6591: #if defined(_WIN32)
! 6592: int rc = lstat(zPath, pStatBuf);
! 6593: if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
! 6594: return rc;
! 6595: #else
! 6596: return lstat(zPath, pStatBuf);
! 6597: #endif
1.5 misho 6598: }
6599:
6600: /*
1.6.2.1 ! misho 6601: ** Argument zFile is the name of a file that will be created and/or written
! 6602: ** by SQL function writefile(). This function ensures that the directory
! 6603: ** zFile will be written to exists, creating it if required. The permissions
! 6604: ** for any path components created by this function are set in accordance
! 6605: ** with the current umask.
1.5 misho 6606: **
1.6.2.1 ! misho 6607: ** If an OOM condition is encountered, SQLITE_NOMEM is returned. Otherwise,
! 6608: ** SQLITE_OK is returned if the directory is successfully created, or
! 6609: ** SQLITE_ERROR otherwise.
1.5 misho 6610: */
1.6.2.1 ! misho 6611: static int makeDirectory(
! 6612: const char *zFile
! 6613: ){
! 6614: char *zCopy = sqlite3_mprintf("%s", zFile);
! 6615: int rc = SQLITE_OK;
! 6616:
! 6617: if( zCopy==0 ){
! 6618: rc = SQLITE_NOMEM;
1.5 misho 6619: }else{
1.6.2.1 ! misho 6620: int nCopy = (int)strlen(zCopy);
! 6621: int i = 1;
! 6622:
! 6623: while( rc==SQLITE_OK ){
! 6624: struct stat sStat;
! 6625: int rc2;
! 6626:
! 6627: for(; zCopy[i]!='/' && i<nCopy; i++);
! 6628: if( i==nCopy ) break;
! 6629: zCopy[i] = '\0';
! 6630:
! 6631: rc2 = fileStat(zCopy, &sStat);
! 6632: if( rc2!=0 ){
! 6633: if( mkdir(zCopy, 0777) ) rc = SQLITE_ERROR;
1.5 misho 6634: }else{
1.6.2.1 ! misho 6635: if( !S_ISDIR(sStat.st_mode) ) rc = SQLITE_ERROR;
1.5 misho 6636: }
1.6.2.1 ! misho 6637: zCopy[i] = '/';
! 6638: i++;
1.5 misho 6639: }
6640:
1.6.2.1 ! misho 6641: sqlite3_free(zCopy);
1.5 misho 6642: }
1.6.2.1 ! misho 6643:
1.5 misho 6644: return rc;
6645: }
6646:
6647: /*
1.6.2.1 ! misho 6648: ** This function does the work for the writefile() UDF. Refer to
! 6649: ** header comments at the top of this file for details.
1.5 misho 6650: */
1.6.2.1 ! misho 6651: static int writeFile(
! 6652: sqlite3_context *pCtx, /* Context to return bytes written in */
! 6653: const char *zFile, /* File to write */
! 6654: sqlite3_value *pData, /* Data to write */
! 6655: mode_t mode, /* MODE parameter passed to writefile() */
! 6656: sqlite3_int64 mtime /* MTIME parameter (or -1 to not set time) */
1.5 misho 6657: ){
1.6.2.1 ! misho 6658: if( zFile==0 ) return 1;
! 6659: #if !defined(_WIN32) && !defined(WIN32)
! 6660: if( S_ISLNK(mode) ){
! 6661: const char *zTo = (const char*)sqlite3_value_text(pData);
! 6662: if( zTo==0 || symlink(zTo, zFile)<0 ) return 1;
! 6663: }else
! 6664: #endif
! 6665: {
! 6666: if( S_ISDIR(mode) ){
! 6667: if( mkdir(zFile, mode) ){
! 6668: /* The mkdir() call to create the directory failed. This might not
! 6669: ** be an error though - if there is already a directory at the same
! 6670: ** path and either the permissions already match or can be changed
! 6671: ** to do so using chmod(), it is not an error. */
! 6672: struct stat sStat;
! 6673: if( errno!=EEXIST
! 6674: || 0!=fileStat(zFile, &sStat)
! 6675: || !S_ISDIR(sStat.st_mode)
! 6676: || ((sStat.st_mode&0777)!=(mode&0777) && 0!=chmod(zFile, mode&0777))
! 6677: ){
! 6678: return 1;
! 6679: }
! 6680: }
1.5 misho 6681: }else{
1.6.2.1 ! misho 6682: sqlite3_int64 nWrite = 0;
! 6683: const char *z;
! 6684: int rc = 0;
! 6685: FILE *out = fopen(zFile, "wb");
! 6686: if( out==0 ) return 1;
! 6687: z = (const char*)sqlite3_value_blob(pData);
! 6688: if( z ){
! 6689: sqlite3_int64 n = fwrite(z, 1, sqlite3_value_bytes(pData), out);
! 6690: nWrite = sqlite3_value_bytes(pData);
! 6691: if( nWrite!=n ){
! 6692: rc = 1;
! 6693: }
! 6694: }
! 6695: fclose(out);
! 6696: if( rc==0 && mode && chmod(zFile, mode & 0777) ){
! 6697: rc = 1;
! 6698: }
! 6699: if( rc ) return 2;
! 6700: sqlite3_result_int64(pCtx, nWrite);
! 6701: }
! 6702: }
! 6703:
! 6704: if( mtime>=0 ){
! 6705: #if defined(_WIN32)
! 6706: #if !SQLITE_OS_WINRT
! 6707: /* Windows */
! 6708: FILETIME lastAccess;
! 6709: FILETIME lastWrite;
! 6710: SYSTEMTIME currentTime;
! 6711: LONGLONG intervals;
! 6712: HANDLE hFile;
! 6713: LPWSTR zUnicodeName;
! 6714: extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
! 6715:
! 6716: GetSystemTime(¤tTime);
! 6717: SystemTimeToFileTime(¤tTime, &lastAccess);
! 6718: intervals = Int32x32To64(mtime, 10000000) + 116444736000000000;
! 6719: lastWrite.dwLowDateTime = (DWORD)intervals;
! 6720: lastWrite.dwHighDateTime = intervals >> 32;
! 6721: zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile);
! 6722: if( zUnicodeName==0 ){
! 6723: return 1;
! 6724: }
! 6725: hFile = CreateFileW(
! 6726: zUnicodeName, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
! 6727: FILE_FLAG_BACKUP_SEMANTICS, NULL
! 6728: );
! 6729: sqlite3_free(zUnicodeName);
! 6730: if( hFile!=INVALID_HANDLE_VALUE ){
! 6731: BOOL bResult = SetFileTime(hFile, NULL, &lastAccess, &lastWrite);
! 6732: CloseHandle(hFile);
! 6733: return !bResult;
! 6734: }else{
! 6735: return 1;
! 6736: }
! 6737: #endif
! 6738: #elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
! 6739: /* Recent unix */
! 6740: struct timespec times[2];
! 6741: times[0].tv_nsec = times[1].tv_nsec = 0;
! 6742: times[0].tv_sec = time(0);
! 6743: times[1].tv_sec = mtime;
! 6744: if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){
! 6745: return 1;
! 6746: }
! 6747: #else
! 6748: /* Legacy unix */
! 6749: struct timeval times[2];
! 6750: times[0].tv_usec = times[1].tv_usec = 0;
! 6751: times[0].tv_sec = time(0);
! 6752: times[1].tv_sec = mtime;
! 6753: if( utimes(zFile, times) ){
! 6754: return 1;
! 6755: }
! 6756: #endif
! 6757: }
! 6758:
! 6759: return 0;
1.5 misho 6760: }
6761:
6762: /*
1.6.2.1 ! misho 6763: ** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function.
! 6764: ** Refer to header comments at the top of this file for details.
1.5 misho 6765: */
1.6.2.1 ! misho 6766: static void writefileFunc(
1.5 misho 6767: sqlite3_context *context,
6768: int argc,
6769: sqlite3_value **argv
6770: ){
1.6.2.1 ! misho 6771: const char *zFile;
! 6772: mode_t mode = 0;
! 6773: int res;
! 6774: sqlite3_int64 mtime = -1;
! 6775:
! 6776: if( argc<2 || argc>4 ){
! 6777: sqlite3_result_error(context,
! 6778: "wrong number of arguments to function writefile()", -1
! 6779: );
! 6780: return;
1.5 misho 6781: }
1.6.2.1 ! misho 6782:
! 6783: zFile = (const char*)sqlite3_value_text(argv[0]);
! 6784: if( zFile==0 ) return;
! 6785: if( argc>=3 ){
! 6786: mode = (mode_t)sqlite3_value_int(argv[2]);
1.5 misho 6787: }
1.6.2.1 ! misho 6788: if( argc==4 ){
! 6789: mtime = sqlite3_value_int64(argv[3]);
1.5 misho 6790: }
1.6.2.1 ! misho 6791:
! 6792: res = writeFile(context, zFile, argv[1], mode, mtime);
! 6793: if( res==1 && errno==ENOENT ){
! 6794: if( makeDirectory(zFile)==SQLITE_OK ){
! 6795: res = writeFile(context, zFile, argv[1], mode, mtime);
! 6796: }
1.5 misho 6797: }
6798:
1.6.2.1 ! misho 6799: if( argc>2 && res!=0 ){
! 6800: if( S_ISLNK(mode) ){
! 6801: ctxErrorMsg(context, "failed to create symlink: %s", zFile);
! 6802: }else if( S_ISDIR(mode) ){
! 6803: ctxErrorMsg(context, "failed to create directory: %s", zFile);
! 6804: }else{
! 6805: ctxErrorMsg(context, "failed to write file: %s", zFile);
! 6806: }
! 6807: }
1.5 misho 6808: }
6809:
1.6.2.1 ! misho 6810: /*
! 6811: ** SQL function: lsmode(MODE)
! 6812: **
! 6813: ** Given a numberic st_mode from stat(), convert it into a human-readable
! 6814: ** text string in the style of "ls -l".
! 6815: */
! 6816: static void lsModeFunc(
! 6817: sqlite3_context *context,
! 6818: int argc,
! 6819: sqlite3_value **argv
1.5 misho 6820: ){
1.6.2.1 ! misho 6821: int i;
! 6822: int iMode = sqlite3_value_int(argv[0]);
! 6823: char z[16];
! 6824: (void)argc;
! 6825: if( S_ISLNK(iMode) ){
! 6826: z[0] = 'l';
! 6827: }else if( S_ISREG(iMode) ){
! 6828: z[0] = '-';
! 6829: }else if( S_ISDIR(iMode) ){
! 6830: z[0] = 'd';
! 6831: }else{
! 6832: z[0] = '?';
1.5 misho 6833: }
1.6.2.1 ! misho 6834: for(i=0; i<3; i++){
! 6835: int m = (iMode >> ((2-i)*3));
! 6836: char *a = &z[1 + i*3];
! 6837: a[0] = (m & 0x4) ? 'r' : '-';
! 6838: a[1] = (m & 0x2) ? 'w' : '-';
! 6839: a[2] = (m & 0x1) ? 'x' : '-';
1.5 misho 6840: }
1.6.2.1 ! misho 6841: z[10] = '\0';
! 6842: sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
1.5 misho 6843: }
6844:
1.6.2.1 ! misho 6845: #ifndef SQLITE_OMIT_VIRTUALTABLE
! 6846:
! 6847: /*
! 6848: ** Cursor type for recursively iterating through a directory structure.
1.5 misho 6849: */
1.6.2.1 ! misho 6850: typedef struct fsdir_cursor fsdir_cursor;
! 6851: typedef struct FsdirLevel FsdirLevel;
1.5 misho 6852:
1.6.2.1 ! misho 6853: struct FsdirLevel {
! 6854: DIR *pDir; /* From opendir() */
! 6855: char *zDir; /* Name of directory (nul-terminated) */
! 6856: };
1.5 misho 6857:
1.6.2.1 ! misho 6858: struct fsdir_cursor {
! 6859: sqlite3_vtab_cursor base; /* Base class - must be first */
1.6 misho 6860:
1.6.2.1 ! misho 6861: int nLvl; /* Number of entries in aLvl[] array */
! 6862: int iLvl; /* Index of current entry */
! 6863: FsdirLevel *aLvl; /* Hierarchy of directories being traversed */
1.6 misho 6864:
1.6.2.1 ! misho 6865: const char *zBase;
! 6866: int nBase;
! 6867:
! 6868: struct stat sStat; /* Current lstat() results */
! 6869: char *zPath; /* Path to current entry */
! 6870: sqlite3_int64 iRowid; /* Current rowid */
! 6871: };
! 6872:
! 6873: typedef struct fsdir_tab fsdir_tab;
! 6874: struct fsdir_tab {
! 6875: sqlite3_vtab base; /* Base class - must be first */
! 6876: };
1.5 misho 6877:
6878: /*
1.6.2.1 ! misho 6879: ** Construct a new fsdir virtual table object.
1.5 misho 6880: */
1.6.2.1 ! misho 6881: static int fsdirConnect(
! 6882: sqlite3 *db,
! 6883: void *pAux,
! 6884: int argc, const char *const*argv,
! 6885: sqlite3_vtab **ppVtab,
! 6886: char **pzErr
1.5 misho 6887: ){
1.6.2.1 ! misho 6888: fsdir_tab *pNew = 0;
! 6889: int rc;
! 6890: (void)pAux;
! 6891: (void)argc;
! 6892: (void)argv;
! 6893: (void)pzErr;
! 6894: rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA);
! 6895: if( rc==SQLITE_OK ){
! 6896: pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) );
! 6897: if( pNew==0 ) return SQLITE_NOMEM;
! 6898: memset(pNew, 0, sizeof(*pNew));
! 6899: sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
1.5 misho 6900: }
1.6.2.1 ! misho 6901: *ppVtab = (sqlite3_vtab*)pNew;
! 6902: return rc;
1.6 misho 6903: }
6904:
6905: /*
1.6.2.1 ! misho 6906: ** This method is the destructor for fsdir vtab objects.
1.6 misho 6907: */
1.6.2.1 ! misho 6908: static int fsdirDisconnect(sqlite3_vtab *pVtab){
1.6 misho 6909: sqlite3_free(pVtab);
6910: return SQLITE_OK;
6911: }
6912:
6913: /*
1.6.2.1 ! misho 6914: ** Constructor for a new fsdir_cursor object.
1.6 misho 6915: */
1.6.2.1 ! misho 6916: static int fsdirOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
! 6917: fsdir_cursor *pCur;
! 6918: (void)p;
1.6 misho 6919: pCur = sqlite3_malloc( sizeof(*pCur) );
6920: if( pCur==0 ) return SQLITE_NOMEM;
6921: memset(pCur, 0, sizeof(*pCur));
1.6.2.1 ! misho 6922: pCur->iLvl = -1;
1.6 misho 6923: *ppCursor = &pCur->base;
6924: return SQLITE_OK;
6925: }
6926:
6927: /*
1.6.2.1 ! misho 6928: ** Reset a cursor back to the state it was in when first returned
! 6929: ** by fsdirOpen().
1.6 misho 6930: */
1.6.2.1 ! misho 6931: static void fsdirResetCursor(fsdir_cursor *pCur){
! 6932: int i;
! 6933: for(i=0; i<=pCur->iLvl; i++){
! 6934: FsdirLevel *pLvl = &pCur->aLvl[i];
! 6935: if( pLvl->pDir ) closedir(pLvl->pDir);
! 6936: sqlite3_free(pLvl->zDir);
! 6937: }
! 6938: sqlite3_free(pCur->zPath);
! 6939: sqlite3_free(pCur->aLvl);
! 6940: pCur->aLvl = 0;
! 6941: pCur->zPath = 0;
! 6942: pCur->zBase = 0;
! 6943: pCur->nBase = 0;
! 6944: pCur->nLvl = 0;
! 6945: pCur->iLvl = -1;
! 6946: pCur->iRowid = 1;
1.6 misho 6947: }
6948:
6949: /*
1.6.2.1 ! misho 6950: ** Destructor for an fsdir_cursor.
1.6 misho 6951: */
1.6.2.1 ! misho 6952: static int fsdirClose(sqlite3_vtab_cursor *cur){
! 6953: fsdir_cursor *pCur = (fsdir_cursor*)cur;
! 6954:
! 6955: fsdirResetCursor(pCur);
! 6956: sqlite3_free(pCur);
1.6 misho 6957: return SQLITE_OK;
6958: }
6959:
6960: /*
1.6.2.1 ! misho 6961: ** Set the error message for the virtual table associated with cursor
! 6962: ** pCur to the results of vprintf(zFmt, ...).
1.6 misho 6963: */
1.6.2.1 ! misho 6964: static void fsdirSetErrmsg(fsdir_cursor *pCur, const char *zFmt, ...){
! 6965: va_list ap;
! 6966: va_start(ap, zFmt);
! 6967: pCur->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
! 6968: va_end(ap);
! 6969: }
! 6970:
! 6971:
! 6972: /*
! 6973: ** Advance an fsdir_cursor to its next row of output.
! 6974: */
! 6975: static int fsdirNext(sqlite3_vtab_cursor *cur){
! 6976: fsdir_cursor *pCur = (fsdir_cursor*)cur;
! 6977: mode_t m = pCur->sStat.st_mode;
! 6978:
! 6979: pCur->iRowid++;
! 6980: if( S_ISDIR(m) ){
! 6981: /* Descend into this directory */
! 6982: int iNew = pCur->iLvl + 1;
! 6983: FsdirLevel *pLvl;
! 6984: if( iNew>=pCur->nLvl ){
! 6985: int nNew = iNew+1;
! 6986: sqlite3_int64 nByte = nNew*sizeof(FsdirLevel);
! 6987: FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc64(pCur->aLvl, nByte);
! 6988: if( aNew==0 ) return SQLITE_NOMEM;
! 6989: memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl));
! 6990: pCur->aLvl = aNew;
! 6991: pCur->nLvl = nNew;
! 6992: }
! 6993: pCur->iLvl = iNew;
! 6994: pLvl = &pCur->aLvl[iNew];
! 6995:
! 6996: pLvl->zDir = pCur->zPath;
! 6997: pCur->zPath = 0;
! 6998: pLvl->pDir = opendir(pLvl->zDir);
! 6999: if( pLvl->pDir==0 ){
! 7000: fsdirSetErrmsg(pCur, "cannot read directory: %s", pCur->zPath);
! 7001: return SQLITE_ERROR;
! 7002: }
! 7003: }
! 7004:
! 7005: while( pCur->iLvl>=0 ){
! 7006: FsdirLevel *pLvl = &pCur->aLvl[pCur->iLvl];
! 7007: struct dirent *pEntry = readdir(pLvl->pDir);
! 7008: if( pEntry ){
! 7009: if( pEntry->d_name[0]=='.' ){
! 7010: if( pEntry->d_name[1]=='.' && pEntry->d_name[2]=='\0' ) continue;
! 7011: if( pEntry->d_name[1]=='\0' ) continue;
! 7012: }
! 7013: sqlite3_free(pCur->zPath);
! 7014: pCur->zPath = sqlite3_mprintf("%s/%s", pLvl->zDir, pEntry->d_name);
! 7015: if( pCur->zPath==0 ) return SQLITE_NOMEM;
! 7016: if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
! 7017: fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
! 7018: return SQLITE_ERROR;
! 7019: }
! 7020: return SQLITE_OK;
! 7021: }
! 7022: closedir(pLvl->pDir);
! 7023: sqlite3_free(pLvl->zDir);
! 7024: pLvl->pDir = 0;
! 7025: pLvl->zDir = 0;
! 7026: pCur->iLvl--;
! 7027: }
! 7028:
! 7029: /* EOF */
! 7030: sqlite3_free(pCur->zPath);
! 7031: pCur->zPath = 0;
! 7032: return SQLITE_OK;
! 7033: }
! 7034:
! 7035: /*
! 7036: ** Return values of columns for the row at which the series_cursor
! 7037: ** is currently pointing.
! 7038: */
! 7039: static int fsdirColumn(
! 7040: sqlite3_vtab_cursor *cur, /* The cursor */
! 7041: sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
! 7042: int i /* Which column to return */
! 7043: ){
! 7044: fsdir_cursor *pCur = (fsdir_cursor*)cur;
! 7045: switch( i ){
! 7046: case FSDIR_COLUMN_NAME: {
! 7047: sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT);
! 7048: break;
! 7049: }
! 7050:
! 7051: case FSDIR_COLUMN_MODE:
! 7052: sqlite3_result_int64(ctx, pCur->sStat.st_mode);
! 7053: break;
! 7054:
! 7055: case FSDIR_COLUMN_MTIME:
! 7056: sqlite3_result_int64(ctx, pCur->sStat.st_mtime);
! 7057: break;
! 7058:
! 7059: case FSDIR_COLUMN_DATA: {
! 7060: mode_t m = pCur->sStat.st_mode;
! 7061: if( S_ISDIR(m) ){
! 7062: sqlite3_result_null(ctx);
! 7063: #if !defined(_WIN32) && !defined(WIN32)
! 7064: }else if( S_ISLNK(m) ){
! 7065: char aStatic[64];
! 7066: char *aBuf = aStatic;
! 7067: sqlite3_int64 nBuf = 64;
! 7068: int n;
! 7069:
! 7070: while( 1 ){
! 7071: n = readlink(pCur->zPath, aBuf, nBuf);
! 7072: if( n<nBuf ) break;
! 7073: if( aBuf!=aStatic ) sqlite3_free(aBuf);
! 7074: nBuf = nBuf*2;
! 7075: aBuf = sqlite3_malloc64(nBuf);
! 7076: if( aBuf==0 ){
! 7077: sqlite3_result_error_nomem(ctx);
! 7078: return SQLITE_NOMEM;
! 7079: }
! 7080: }
! 7081:
! 7082: sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT);
! 7083: if( aBuf!=aStatic ) sqlite3_free(aBuf);
! 7084: #endif
! 7085: }else{
! 7086: readFileContents(ctx, pCur->zPath);
! 7087: }
! 7088: }
! 7089: case FSDIR_COLUMN_PATH:
! 7090: default: {
! 7091: /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters.
! 7092: ** always return their values as NULL */
! 7093: break;
! 7094: }
! 7095: }
! 7096: return SQLITE_OK;
1.6 misho 7097: }
7098:
7099: /*
7100: ** Return the rowid for the current row. In this implementation, the
7101: ** first row returned is assigned rowid value 1, and each subsequent
7102: ** row a value 1 more than that of the previous.
7103: */
1.6.2.1 ! misho 7104: static int fsdirRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
! 7105: fsdir_cursor *pCur = (fsdir_cursor*)cur;
1.6 misho 7106: *pRowid = pCur->iRowid;
7107: return SQLITE_OK;
7108: }
7109:
7110: /*
7111: ** Return TRUE if the cursor has been moved off of the last
7112: ** row of output.
7113: */
1.6.2.1 ! misho 7114: static int fsdirEof(sqlite3_vtab_cursor *cur){
! 7115: fsdir_cursor *pCur = (fsdir_cursor*)cur;
! 7116: return (pCur->zPath==0);
1.6 misho 7117: }
7118:
7119: /*
1.6.2.1 ! misho 7120: ** xFilter callback.
1.6 misho 7121: **
1.6.2.1 ! misho 7122: ** idxNum==1 PATH parameter only
! 7123: ** idxNum==2 Both PATH and DIR supplied
1.6 misho 7124: */
1.6.2.1 ! misho 7125: static int fsdirFilter(
! 7126: sqlite3_vtab_cursor *cur,
! 7127: int idxNum, const char *idxStr,
1.6 misho 7128: int argc, sqlite3_value **argv
7129: ){
1.6.2.1 ! misho 7130: const char *zDir = 0;
! 7131: fsdir_cursor *pCur = (fsdir_cursor*)cur;
! 7132: (void)idxStr;
! 7133: fsdirResetCursor(pCur);
! 7134:
! 7135: if( idxNum==0 ){
! 7136: fsdirSetErrmsg(pCur, "table function fsdir requires an argument");
! 7137: return SQLITE_ERROR;
1.6 misho 7138: }
1.6.2.1 ! misho 7139:
! 7140: assert( argc==idxNum && (argc==1 || argc==2) );
! 7141: zDir = (const char*)sqlite3_value_text(argv[0]);
! 7142: if( zDir==0 ){
! 7143: fsdirSetErrmsg(pCur, "table function fsdir requires a non-NULL argument");
! 7144: return SQLITE_ERROR;
1.6 misho 7145: }
1.6.2.1 ! misho 7146: if( argc==2 ){
! 7147: pCur->zBase = (const char*)sqlite3_value_text(argv[1]);
! 7148: }
! 7149: if( pCur->zBase ){
! 7150: pCur->nBase = (int)strlen(pCur->zBase)+1;
! 7151: pCur->zPath = sqlite3_mprintf("%s/%s", pCur->zBase, zDir);
1.6 misho 7152: }else{
1.6.2.1 ! misho 7153: pCur->zPath = sqlite3_mprintf("%s", zDir);
1.6 misho 7154: }
1.6.2.1 ! misho 7155:
! 7156: if( pCur->zPath==0 ){
! 7157: return SQLITE_NOMEM;
1.6 misho 7158: }
1.6.2.1 ! misho 7159: if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
! 7160: fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
! 7161: return SQLITE_ERROR;
1.6 misho 7162: }
1.6.2.1 ! misho 7163:
1.6 misho 7164: return SQLITE_OK;
7165: }
7166:
7167: /*
7168: ** SQLite will invoke this method one or more times while planning a query
7169: ** that uses the generate_series virtual table. This routine needs to create
7170: ** a query plan for each invocation and compute an estimated cost for that
7171: ** plan.
7172: **
7173: ** In this implementation idxNum is used to represent the
7174: ** query plan. idxStr is unused.
7175: **
1.6.2.1 ! misho 7176: ** The query plan is represented by values of idxNum:
1.6 misho 7177: **
1.6.2.1 ! misho 7178: ** (1) The path value is supplied by argv[0]
! 7179: ** (2) Path is in argv[0] and dir is in argv[1]
1.6 misho 7180: */
1.6.2.1 ! misho 7181: static int fsdirBestIndex(
! 7182: sqlite3_vtab *tab,
1.6 misho 7183: sqlite3_index_info *pIdxInfo
7184: ){
1.6.2.1 ! misho 7185: int i; /* Loop over constraints */
! 7186: int idxPath = -1; /* Index in pIdxInfo->aConstraint of PATH= */
! 7187: int idxDir = -1; /* Index in pIdxInfo->aConstraint of DIR= */
! 7188: int seenPath = 0; /* True if an unusable PATH= constraint is seen */
! 7189: int seenDir = 0; /* True if an unusable DIR= constraint is seen */
1.6 misho 7190: const struct sqlite3_index_constraint *pConstraint;
7191:
1.6.2.1 ! misho 7192: (void)tab;
1.6 misho 7193: pConstraint = pIdxInfo->aConstraint;
7194: for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
1.6.2.1 ! misho 7195: if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
! 7196: switch( pConstraint->iColumn ){
! 7197: case FSDIR_COLUMN_PATH: {
! 7198: if( pConstraint->usable ){
! 7199: idxPath = i;
! 7200: seenPath = 0;
! 7201: }else if( idxPath<0 ){
! 7202: seenPath = 1;
! 7203: }
! 7204: break;
! 7205: }
! 7206: case FSDIR_COLUMN_DIR: {
! 7207: if( pConstraint->usable ){
! 7208: idxDir = i;
! 7209: seenDir = 0;
! 7210: }else if( idxDir<0 ){
! 7211: seenDir = 1;
! 7212: }
! 7213: break;
! 7214: }
! 7215: }
1.6 misho 7216: }
1.6.2.1 ! misho 7217: if( seenPath || seenDir ){
! 7218: /* If input parameters are unusable, disallow this plan */
1.6 misho 7219: return SQLITE_CONSTRAINT;
7220: }
1.6.2.1 ! misho 7221:
! 7222: if( idxPath<0 ){
! 7223: pIdxInfo->idxNum = 0;
! 7224: /* The pIdxInfo->estimatedCost should have been initialized to a huge
! 7225: ** number. Leave it unchanged. */
! 7226: pIdxInfo->estimatedRows = 0x7fffffff;
1.6 misho 7227: }else{
1.6.2.1 ! misho 7228: pIdxInfo->aConstraintUsage[idxPath].omit = 1;
! 7229: pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1;
! 7230: if( idxDir>=0 ){
! 7231: pIdxInfo->aConstraintUsage[idxDir].omit = 1;
! 7232: pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2;
! 7233: pIdxInfo->idxNum = 2;
! 7234: pIdxInfo->estimatedCost = 10.0;
! 7235: }else{
! 7236: pIdxInfo->idxNum = 1;
! 7237: pIdxInfo->estimatedCost = 100.0;
! 7238: }
1.6 misho 7239: }
1.6.2.1 ! misho 7240:
1.6 misho 7241: return SQLITE_OK;
7242: }
7243:
7244: /*
1.6.2.1 ! misho 7245: ** Register the "fsdir" virtual table.
1.6 misho 7246: */
1.6.2.1 ! misho 7247: static int fsdirRegister(sqlite3 *db){
! 7248: static sqlite3_module fsdirModule = {
! 7249: 0, /* iVersion */
! 7250: 0, /* xCreate */
! 7251: fsdirConnect, /* xConnect */
! 7252: fsdirBestIndex, /* xBestIndex */
! 7253: fsdirDisconnect, /* xDisconnect */
! 7254: 0, /* xDestroy */
! 7255: fsdirOpen, /* xOpen - open a cursor */
! 7256: fsdirClose, /* xClose - close a cursor */
! 7257: fsdirFilter, /* xFilter - configure scan constraints */
! 7258: fsdirNext, /* xNext - advance a cursor */
! 7259: fsdirEof, /* xEof - check for end of scan */
! 7260: fsdirColumn, /* xColumn - read data */
! 7261: fsdirRowid, /* xRowid - read data */
! 7262: 0, /* xUpdate */
! 7263: 0, /* xBegin */
! 7264: 0, /* xSync */
! 7265: 0, /* xCommit */
! 7266: 0, /* xRollback */
! 7267: 0, /* xFindMethod */
! 7268: 0, /* xRename */
! 7269: 0, /* xSavepoint */
! 7270: 0, /* xRelease */
! 7271: 0, /* xRollbackTo */
! 7272: 0, /* xShadowName */
! 7273: };
1.6 misho 7274:
1.6.2.1 ! misho 7275: int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
! 7276: return rc;
! 7277: }
! 7278: #else /* SQLITE_OMIT_VIRTUALTABLE */
! 7279: # define fsdirRegister(x) SQLITE_OK
! 7280: #endif
1.6 misho 7281:
7282: #ifdef _WIN32
7283:
7284: #endif
1.6.2.1 ! misho 7285: int sqlite3_fileio_init(
1.6 misho 7286: sqlite3 *db,
7287: char **pzErrMsg,
7288: const sqlite3_api_routines *pApi
7289: ){
7290: int rc = SQLITE_OK;
7291: SQLITE_EXTENSION_INIT2(pApi);
1.6.2.1 ! misho 7292: (void)pzErrMsg; /* Unused parameter */
! 7293: rc = sqlite3_create_function(db, "readfile", 1,
! 7294: SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
! 7295: readfileFunc, 0, 0);
! 7296: if( rc==SQLITE_OK ){
! 7297: rc = sqlite3_create_function(db, "writefile", -1,
! 7298: SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
! 7299: writefileFunc, 0, 0);
! 7300: }
! 7301: if( rc==SQLITE_OK ){
! 7302: rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0,
! 7303: lsModeFunc, 0, 0);
! 7304: }
! 7305: if( rc==SQLITE_OK ){
! 7306: rc = fsdirRegister(db);
1.6 misho 7307: }
7308: return rc;
7309: }
7310:
1.6.2.1 ! misho 7311: #if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32))
! 7312: /* To allow a standalone DLL, make test_windirent.c use the same
! 7313: * redefined SQLite API calls as the above extension code does.
! 7314: * Just pull in this .c to accomplish this. As a beneficial side
! 7315: * effect, this extension becomes a single translation unit. */
! 7316: # include "test_windirent.c"
! 7317: #endif
! 7318:
! 7319: /************************* End ../ext/misc/fileio.c ********************/
! 7320: /************************* Begin ../ext/misc/completion.c ******************/
1.5 misho 7321: /*
1.6.2.1 ! misho 7322: ** 2017-07-10
1.5 misho 7323: **
7324: ** The author disclaims copyright to this source code. In place of
7325: ** a legal notice, here is a blessing:
7326: **
7327: ** May you do good and not evil.
7328: ** May you find forgiveness for yourself and forgive others.
7329: ** May you share freely, never taking more than you give.
7330: **
1.6.2.1 ! misho 7331: *************************************************************************
1.5 misho 7332: **
1.6.2.1 ! misho 7333: ** This file implements an eponymous virtual table that returns suggested
! 7334: ** completions for a partial SQL input.
1.5 misho 7335: **
1.6.2.1 ! misho 7336: ** Suggested usage:
1.5 misho 7337: **
1.6.2.1 ! misho 7338: ** SELECT DISTINCT candidate COLLATE nocase
! 7339: ** FROM completion($prefix,$wholeline)
! 7340: ** ORDER BY 1;
1.5 misho 7341: **
1.6.2.1 ! misho 7342: ** The two query parameters are optional. $prefix is the text of the
! 7343: ** current word being typed and that is to be completed. $wholeline is
! 7344: ** the complete input line, used for context.
! 7345: **
! 7346: ** The raw completion() table might return the same candidate multiple
! 7347: ** times, for example if the same column name is used to two or more
! 7348: ** tables. And the candidates are returned in an arbitrary order. Hence,
! 7349: ** the DISTINCT and ORDER BY are recommended.
! 7350: **
! 7351: ** This virtual table operates at the speed of human typing, and so there
! 7352: ** is no attempt to make it fast. Even a slow implementation will be much
! 7353: ** faster than any human can type.
1.5 misho 7354: **
7355: */
7356: /* #include "sqlite3ext.h" */
7357: SQLITE_EXTENSION_INIT1
7358: #include <assert.h>
1.6.2.1 ! misho 7359: #include <string.h>
! 7360: #include <ctype.h>
1.5 misho 7361:
7362: #ifndef SQLITE_OMIT_VIRTUALTABLE
7363:
1.6.2.1 ! misho 7364: /* completion_vtab is a subclass of sqlite3_vtab which will
! 7365: ** serve as the underlying representation of a completion virtual table
! 7366: */
! 7367: typedef struct completion_vtab completion_vtab;
! 7368: struct completion_vtab {
! 7369: sqlite3_vtab base; /* Base class - must be first */
! 7370: sqlite3 *db; /* Database connection for this completion vtab */
! 7371: };
1.5 misho 7372:
1.6.2.1 ! misho 7373: /* completion_cursor is a subclass of sqlite3_vtab_cursor which will
! 7374: ** serve as the underlying representation of a cursor that scans
! 7375: ** over rows of the result
! 7376: */
! 7377: typedef struct completion_cursor completion_cursor;
! 7378: struct completion_cursor {
! 7379: sqlite3_vtab_cursor base; /* Base class - must be first */
! 7380: sqlite3 *db; /* Database connection for this cursor */
! 7381: int nPrefix, nLine; /* Number of bytes in zPrefix and zLine */
! 7382: char *zPrefix; /* The prefix for the word we want to complete */
! 7383: char *zLine; /* The whole that we want to complete */
! 7384: const char *zCurrentRow; /* Current output row */
! 7385: int szRow; /* Length of the zCurrentRow string */
! 7386: sqlite3_stmt *pStmt; /* Current statement */
! 7387: sqlite3_int64 iRowid; /* The rowid */
! 7388: int ePhase; /* Current phase */
! 7389: int j; /* inter-phase counter */
! 7390: };
1.5 misho 7391:
1.6.2.1 ! misho 7392: /* Values for ePhase:
1.5 misho 7393: */
1.6.2.1 ! misho 7394: #define COMPLETION_FIRST_PHASE 1
! 7395: #define COMPLETION_KEYWORDS 1
! 7396: #define COMPLETION_PRAGMAS 2
! 7397: #define COMPLETION_FUNCTIONS 3
! 7398: #define COMPLETION_COLLATIONS 4
! 7399: #define COMPLETION_INDEXES 5
! 7400: #define COMPLETION_TRIGGERS 6
! 7401: #define COMPLETION_DATABASES 7
! 7402: #define COMPLETION_TABLES 8 /* Also VIEWs and TRIGGERs */
! 7403: #define COMPLETION_COLUMNS 9
! 7404: #define COMPLETION_MODULES 10
! 7405: #define COMPLETION_EOF 11
1.5 misho 7406:
7407: /*
1.6.2.1 ! misho 7408: ** The completionConnect() method is invoked to create a new
! 7409: ** completion_vtab that describes the completion virtual table.
1.5 misho 7410: **
1.6.2.1 ! misho 7411: ** Think of this routine as the constructor for completion_vtab objects.
1.5 misho 7412: **
1.6.2.1 ! misho 7413: ** All this routine needs to do is:
1.5 misho 7414: **
1.6.2.1 ! misho 7415: ** (1) Allocate the completion_vtab object and initialize all fields.
1.5 misho 7416: **
1.6.2.1 ! misho 7417: ** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
! 7418: ** result set of queries against completion will look like.
1.5 misho 7419: */
1.6.2.1 ! misho 7420: static int completionConnect(
! 7421: sqlite3 *db,
! 7422: void *pAux,
! 7423: int argc, const char *const*argv,
! 7424: sqlite3_vtab **ppVtab,
! 7425: char **pzErr
! 7426: ){
! 7427: completion_vtab *pNew;
! 7428: int rc;
! 7429:
! 7430: (void)(pAux); /* Unused parameter */
! 7431: (void)(argc); /* Unused parameter */
! 7432: (void)(argv); /* Unused parameter */
! 7433: (void)(pzErr); /* Unused parameter */
! 7434:
! 7435: /* Column numbers */
! 7436: #define COMPLETION_COLUMN_CANDIDATE 0 /* Suggested completion of the input */
! 7437: #define COMPLETION_COLUMN_PREFIX 1 /* Prefix of the word to be completed */
! 7438: #define COMPLETION_COLUMN_WHOLELINE 2 /* Entire line seen so far */
! 7439: #define COMPLETION_COLUMN_PHASE 3 /* ePhase - used for debugging only */
! 7440:
! 7441: sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
! 7442: rc = sqlite3_declare_vtab(db,
! 7443: "CREATE TABLE x("
! 7444: " candidate TEXT,"
! 7445: " prefix TEXT HIDDEN,"
! 7446: " wholeline TEXT HIDDEN,"
! 7447: " phase INT HIDDEN" /* Used for debugging only */
! 7448: ")");
! 7449: if( rc==SQLITE_OK ){
! 7450: pNew = sqlite3_malloc( sizeof(*pNew) );
! 7451: *ppVtab = (sqlite3_vtab*)pNew;
! 7452: if( pNew==0 ) return SQLITE_NOMEM;
! 7453: memset(pNew, 0, sizeof(*pNew));
! 7454: pNew->db = db;
! 7455: }
! 7456: return rc;
! 7457: }
1.5 misho 7458:
7459: /*
1.6.2.1 ! misho 7460: ** This method is the destructor for completion_cursor objects.
1.5 misho 7461: */
1.6.2.1 ! misho 7462: static int completionDisconnect(sqlite3_vtab *pVtab){
! 7463: sqlite3_free(pVtab);
! 7464: return SQLITE_OK;
! 7465: }
1.5 misho 7466:
7467: /*
1.6.2.1 ! misho 7468: ** Constructor for a new completion_cursor object.
1.5 misho 7469: */
1.6.2.1 ! misho 7470: static int completionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
! 7471: completion_cursor *pCur;
! 7472: pCur = sqlite3_malloc( sizeof(*pCur) );
! 7473: if( pCur==0 ) return SQLITE_NOMEM;
! 7474: memset(pCur, 0, sizeof(*pCur));
! 7475: pCur->db = ((completion_vtab*)p)->db;
! 7476: *ppCursor = &pCur->base;
! 7477: return SQLITE_OK;
! 7478: }
1.5 misho 7479:
7480: /*
1.6.2.1 ! misho 7481: ** Reset the completion_cursor.
1.5 misho 7482: */
1.6.2.1 ! misho 7483: static void completionCursorReset(completion_cursor *pCur){
! 7484: sqlite3_free(pCur->zPrefix); pCur->zPrefix = 0; pCur->nPrefix = 0;
! 7485: sqlite3_free(pCur->zLine); pCur->zLine = 0; pCur->nLine = 0;
! 7486: sqlite3_finalize(pCur->pStmt); pCur->pStmt = 0;
! 7487: pCur->j = 0;
! 7488: }
! 7489:
! 7490: /*
! 7491: ** Destructor for a completion_cursor.
! 7492: */
! 7493: static int completionClose(sqlite3_vtab_cursor *cur){
! 7494: completionCursorReset((completion_cursor*)cur);
! 7495: sqlite3_free(cur);
! 7496: return SQLITE_OK;
! 7497: }
! 7498:
! 7499: /*
! 7500: ** Advance a completion_cursor to its next row of output.
! 7501: **
! 7502: ** The ->ePhase, ->j, and ->pStmt fields of the completion_cursor object
! 7503: ** record the current state of the scan. This routine sets ->zCurrentRow
! 7504: ** to the current row of output and then returns. If no more rows remain,
! 7505: ** then ->ePhase is set to COMPLETION_EOF which will signal the virtual
! 7506: ** table that has reached the end of its scan.
! 7507: **
! 7508: ** The current implementation just lists potential identifiers and
! 7509: ** keywords and filters them by zPrefix. Future enhancements should
! 7510: ** take zLine into account to try to restrict the set of identifiers and
! 7511: ** keywords based on what would be legal at the current point of input.
! 7512: */
! 7513: static int completionNext(sqlite3_vtab_cursor *cur){
! 7514: completion_cursor *pCur = (completion_cursor*)cur;
! 7515: int eNextPhase = 0; /* Next phase to try if current phase reaches end */
! 7516: int iCol = -1; /* If >=0, step pCur->pStmt and use the i-th column */
! 7517: pCur->iRowid++;
! 7518: while( pCur->ePhase!=COMPLETION_EOF ){
! 7519: switch( pCur->ePhase ){
! 7520: case COMPLETION_KEYWORDS: {
! 7521: if( pCur->j >= sqlite3_keyword_count() ){
! 7522: pCur->zCurrentRow = 0;
! 7523: pCur->ePhase = COMPLETION_DATABASES;
! 7524: }else{
! 7525: sqlite3_keyword_name(pCur->j++, &pCur->zCurrentRow, &pCur->szRow);
! 7526: }
! 7527: iCol = -1;
! 7528: break;
! 7529: }
! 7530: case COMPLETION_DATABASES: {
! 7531: if( pCur->pStmt==0 ){
! 7532: sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1,
! 7533: &pCur->pStmt, 0);
! 7534: }
! 7535: iCol = 1;
! 7536: eNextPhase = COMPLETION_TABLES;
! 7537: break;
! 7538: }
! 7539: case COMPLETION_TABLES: {
! 7540: if( pCur->pStmt==0 ){
! 7541: sqlite3_stmt *pS2;
! 7542: char *zSql = 0;
! 7543: const char *zSep = "";
! 7544: sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
! 7545: while( sqlite3_step(pS2)==SQLITE_ROW ){
! 7546: const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
! 7547: zSql = sqlite3_mprintf(
! 7548: "%z%s"
! 7549: "SELECT name FROM \"%w\".sqlite_schema",
! 7550: zSql, zSep, zDb
! 7551: );
! 7552: if( zSql==0 ) return SQLITE_NOMEM;
! 7553: zSep = " UNION ";
! 7554: }
! 7555: sqlite3_finalize(pS2);
! 7556: sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
! 7557: sqlite3_free(zSql);
! 7558: }
! 7559: iCol = 0;
! 7560: eNextPhase = COMPLETION_COLUMNS;
! 7561: break;
! 7562: }
! 7563: case COMPLETION_COLUMNS: {
! 7564: if( pCur->pStmt==0 ){
! 7565: sqlite3_stmt *pS2;
! 7566: char *zSql = 0;
! 7567: const char *zSep = "";
! 7568: sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
! 7569: while( sqlite3_step(pS2)==SQLITE_ROW ){
! 7570: const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
! 7571: zSql = sqlite3_mprintf(
! 7572: "%z%s"
! 7573: "SELECT pti.name FROM \"%w\".sqlite_schema AS sm"
! 7574: " JOIN pragma_table_info(sm.name,%Q) AS pti"
! 7575: " WHERE sm.type='table'",
! 7576: zSql, zSep, zDb, zDb
! 7577: );
! 7578: if( zSql==0 ) return SQLITE_NOMEM;
! 7579: zSep = " UNION ";
! 7580: }
! 7581: sqlite3_finalize(pS2);
! 7582: sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
! 7583: sqlite3_free(zSql);
! 7584: }
! 7585: iCol = 0;
! 7586: eNextPhase = COMPLETION_EOF;
! 7587: break;
! 7588: }
! 7589: }
! 7590: if( iCol<0 ){
! 7591: /* This case is when the phase presets zCurrentRow */
! 7592: if( pCur->zCurrentRow==0 ) continue;
! 7593: }else{
! 7594: if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){
! 7595: /* Extract the next row of content */
! 7596: pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol);
! 7597: pCur->szRow = sqlite3_column_bytes(pCur->pStmt, iCol);
! 7598: }else{
! 7599: /* When all rows are finished, advance to the next phase */
! 7600: sqlite3_finalize(pCur->pStmt);
! 7601: pCur->pStmt = 0;
! 7602: pCur->ePhase = eNextPhase;
! 7603: continue;
! 7604: }
! 7605: }
! 7606: if( pCur->nPrefix==0 ) break;
! 7607: if( pCur->nPrefix<=pCur->szRow
! 7608: && sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0
! 7609: ){
! 7610: break;
! 7611: }
! 7612: }
! 7613:
! 7614: return SQLITE_OK;
! 7615: }
! 7616:
! 7617: /*
! 7618: ** Return values of columns for the row at which the completion_cursor
! 7619: ** is currently pointing.
! 7620: */
! 7621: static int completionColumn(
! 7622: sqlite3_vtab_cursor *cur, /* The cursor */
! 7623: sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
! 7624: int i /* Which column to return */
! 7625: ){
! 7626: completion_cursor *pCur = (completion_cursor*)cur;
! 7627: switch( i ){
! 7628: case COMPLETION_COLUMN_CANDIDATE: {
! 7629: sqlite3_result_text(ctx, pCur->zCurrentRow, pCur->szRow,SQLITE_TRANSIENT);
! 7630: break;
! 7631: }
! 7632: case COMPLETION_COLUMN_PREFIX: {
! 7633: sqlite3_result_text(ctx, pCur->zPrefix, -1, SQLITE_TRANSIENT);
! 7634: break;
! 7635: }
! 7636: case COMPLETION_COLUMN_WHOLELINE: {
! 7637: sqlite3_result_text(ctx, pCur->zLine, -1, SQLITE_TRANSIENT);
! 7638: break;
! 7639: }
! 7640: case COMPLETION_COLUMN_PHASE: {
! 7641: sqlite3_result_int(ctx, pCur->ePhase);
! 7642: break;
! 7643: }
! 7644: }
! 7645: return SQLITE_OK;
! 7646: }
! 7647:
! 7648: /*
! 7649: ** Return the rowid for the current row. In this implementation, the
! 7650: ** rowid is the same as the output value.
! 7651: */
! 7652: static int completionRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
! 7653: completion_cursor *pCur = (completion_cursor*)cur;
! 7654: *pRowid = pCur->iRowid;
! 7655: return SQLITE_OK;
! 7656: }
! 7657:
! 7658: /*
! 7659: ** Return TRUE if the cursor has been moved off of the last
! 7660: ** row of output.
! 7661: */
! 7662: static int completionEof(sqlite3_vtab_cursor *cur){
! 7663: completion_cursor *pCur = (completion_cursor*)cur;
! 7664: return pCur->ePhase >= COMPLETION_EOF;
! 7665: }
! 7666:
! 7667: /*
! 7668: ** This method is called to "rewind" the completion_cursor object back
! 7669: ** to the first row of output. This method is always called at least
! 7670: ** once prior to any call to completionColumn() or completionRowid() or
! 7671: ** completionEof().
! 7672: */
! 7673: static int completionFilter(
! 7674: sqlite3_vtab_cursor *pVtabCursor,
! 7675: int idxNum, const char *idxStr,
! 7676: int argc, sqlite3_value **argv
! 7677: ){
! 7678: completion_cursor *pCur = (completion_cursor *)pVtabCursor;
! 7679: int iArg = 0;
! 7680: (void)(idxStr); /* Unused parameter */
! 7681: (void)(argc); /* Unused parameter */
! 7682: completionCursorReset(pCur);
! 7683: if( idxNum & 1 ){
! 7684: pCur->nPrefix = sqlite3_value_bytes(argv[iArg]);
! 7685: if( pCur->nPrefix>0 ){
! 7686: pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
! 7687: if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
! 7688: }
! 7689: iArg = 1;
! 7690: }
! 7691: if( idxNum & 2 ){
! 7692: pCur->nLine = sqlite3_value_bytes(argv[iArg]);
! 7693: if( pCur->nLine>0 ){
! 7694: pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
! 7695: if( pCur->zLine==0 ) return SQLITE_NOMEM;
! 7696: }
! 7697: }
! 7698: if( pCur->zLine!=0 && pCur->zPrefix==0 ){
! 7699: int i = pCur->nLine;
! 7700: while( i>0 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
! 7701: i--;
! 7702: }
! 7703: pCur->nPrefix = pCur->nLine - i;
! 7704: if( pCur->nPrefix>0 ){
! 7705: pCur->zPrefix = sqlite3_mprintf("%.*s", pCur->nPrefix, pCur->zLine + i);
! 7706: if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
! 7707: }
! 7708: }
! 7709: pCur->iRowid = 0;
! 7710: pCur->ePhase = COMPLETION_FIRST_PHASE;
! 7711: return completionNext(pVtabCursor);
! 7712: }
! 7713:
! 7714: /*
! 7715: ** SQLite will invoke this method one or more times while planning a query
! 7716: ** that uses the completion virtual table. This routine needs to create
! 7717: ** a query plan for each invocation and compute an estimated cost for that
! 7718: ** plan.
! 7719: **
! 7720: ** There are two hidden parameters that act as arguments to the table-valued
! 7721: ** function: "prefix" and "wholeline". Bit 0 of idxNum is set if "prefix"
! 7722: ** is available and bit 1 is set if "wholeline" is available.
! 7723: */
! 7724: static int completionBestIndex(
! 7725: sqlite3_vtab *tab,
! 7726: sqlite3_index_info *pIdxInfo
! 7727: ){
! 7728: int i; /* Loop over constraints */
! 7729: int idxNum = 0; /* The query plan bitmask */
! 7730: int prefixIdx = -1; /* Index of the start= constraint, or -1 if none */
! 7731: int wholelineIdx = -1; /* Index of the stop= constraint, or -1 if none */
! 7732: int nArg = 0; /* Number of arguments that completeFilter() expects */
! 7733: const struct sqlite3_index_constraint *pConstraint;
! 7734:
! 7735: (void)(tab); /* Unused parameter */
! 7736: pConstraint = pIdxInfo->aConstraint;
! 7737: for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
! 7738: if( pConstraint->usable==0 ) continue;
! 7739: if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
! 7740: switch( pConstraint->iColumn ){
! 7741: case COMPLETION_COLUMN_PREFIX:
! 7742: prefixIdx = i;
! 7743: idxNum |= 1;
! 7744: break;
! 7745: case COMPLETION_COLUMN_WHOLELINE:
! 7746: wholelineIdx = i;
! 7747: idxNum |= 2;
! 7748: break;
! 7749: }
! 7750: }
! 7751: if( prefixIdx>=0 ){
! 7752: pIdxInfo->aConstraintUsage[prefixIdx].argvIndex = ++nArg;
! 7753: pIdxInfo->aConstraintUsage[prefixIdx].omit = 1;
! 7754: }
! 7755: if( wholelineIdx>=0 ){
! 7756: pIdxInfo->aConstraintUsage[wholelineIdx].argvIndex = ++nArg;
! 7757: pIdxInfo->aConstraintUsage[wholelineIdx].omit = 1;
! 7758: }
! 7759: pIdxInfo->idxNum = idxNum;
! 7760: pIdxInfo->estimatedCost = (double)5000 - 1000*nArg;
! 7761: pIdxInfo->estimatedRows = 500 - 100*nArg;
! 7762: return SQLITE_OK;
! 7763: }
! 7764:
! 7765: /*
! 7766: ** This following structure defines all the methods for the
! 7767: ** completion virtual table.
! 7768: */
! 7769: static sqlite3_module completionModule = {
! 7770: 0, /* iVersion */
! 7771: 0, /* xCreate */
! 7772: completionConnect, /* xConnect */
! 7773: completionBestIndex, /* xBestIndex */
! 7774: completionDisconnect, /* xDisconnect */
! 7775: 0, /* xDestroy */
! 7776: completionOpen, /* xOpen - open a cursor */
! 7777: completionClose, /* xClose - close a cursor */
! 7778: completionFilter, /* xFilter - configure scan constraints */
! 7779: completionNext, /* xNext - advance a cursor */
! 7780: completionEof, /* xEof - check for end of scan */
! 7781: completionColumn, /* xColumn - read data */
! 7782: completionRowid, /* xRowid - read data */
! 7783: 0, /* xUpdate */
! 7784: 0, /* xBegin */
! 7785: 0, /* xSync */
! 7786: 0, /* xCommit */
! 7787: 0, /* xRollback */
! 7788: 0, /* xFindMethod */
! 7789: 0, /* xRename */
! 7790: 0, /* xSavepoint */
! 7791: 0, /* xRelease */
! 7792: 0, /* xRollbackTo */
! 7793: 0 /* xShadowName */
! 7794: };
! 7795:
! 7796: #endif /* SQLITE_OMIT_VIRTUALTABLE */
! 7797:
! 7798: int sqlite3CompletionVtabInit(sqlite3 *db){
! 7799: int rc = SQLITE_OK;
! 7800: #ifndef SQLITE_OMIT_VIRTUALTABLE
! 7801: rc = sqlite3_create_module(db, "completion", &completionModule, 0);
! 7802: #endif
! 7803: return rc;
! 7804: }
! 7805:
! 7806: #ifdef _WIN32
! 7807:
! 7808: #endif
! 7809: int sqlite3_completion_init(
! 7810: sqlite3 *db,
! 7811: char **pzErrMsg,
! 7812: const sqlite3_api_routines *pApi
! 7813: ){
! 7814: int rc = SQLITE_OK;
! 7815: SQLITE_EXTENSION_INIT2(pApi);
! 7816: (void)(pzErrMsg); /* Unused parameter */
! 7817: #ifndef SQLITE_OMIT_VIRTUALTABLE
! 7818: rc = sqlite3CompletionVtabInit(db);
! 7819: #endif
! 7820: return rc;
! 7821: }
! 7822:
! 7823: /************************* End ../ext/misc/completion.c ********************/
! 7824: /************************* Begin ../ext/misc/appendvfs.c ******************/
! 7825: /*
! 7826: ** 2017-10-20
! 7827: **
! 7828: ** The author disclaims copyright to this source code. In place of
! 7829: ** a legal notice, here is a blessing:
! 7830: **
! 7831: ** May you do good and not evil.
! 7832: ** May you find forgiveness for yourself and forgive others.
! 7833: ** May you share freely, never taking more than you give.
! 7834: **
! 7835: ******************************************************************************
! 7836: **
! 7837: ** This file implements a VFS shim that allows an SQLite database to be
! 7838: ** appended onto the end of some other file, such as an executable.
! 7839: **
! 7840: ** A special record must appear at the end of the file that identifies the
! 7841: ** file as an appended database and provides the offset to the first page
! 7842: ** of the exposed content. (Or, it is the length of the content prefix.)
! 7843: ** For best performance page 1 should be located at a disk page boundary,
! 7844: ** though that is not required.
! 7845: **
! 7846: ** When opening a database using this VFS, the connection might treat
! 7847: ** the file as an ordinary SQLite database, or it might treat it as a
! 7848: ** database appended onto some other file. The decision is made by
! 7849: ** applying the following rules in order:
! 7850: **
! 7851: ** (1) An empty file is an ordinary database.
! 7852: **
! 7853: ** (2) If the file ends with the appendvfs trailer string
! 7854: ** "Start-Of-SQLite3-NNNNNNNN" that file is an appended database.
! 7855: **
! 7856: ** (3) If the file begins with the standard SQLite prefix string
! 7857: ** "SQLite format 3", that file is an ordinary database.
! 7858: **
! 7859: ** (4) If none of the above apply and the SQLITE_OPEN_CREATE flag is
! 7860: ** set, then a new database is appended to the already existing file.
! 7861: **
! 7862: ** (5) Otherwise, SQLITE_CANTOPEN is returned.
! 7863: **
! 7864: ** To avoid unnecessary complications with the PENDING_BYTE, the size of
! 7865: ** the file containing the database is limited to 1GiB. (1073741824 bytes)
! 7866: ** This VFS will not read or write past the 1GiB mark. This restriction
! 7867: ** might be lifted in future versions. For now, if you need a larger
! 7868: ** database, then keep it in a separate file.
! 7869: **
! 7870: ** If the file being opened is a plain database (not an appended one), then
! 7871: ** this shim is a pass-through into the default underlying VFS. (rule 3)
! 7872: **/
! 7873: /* #include "sqlite3ext.h" */
! 7874: SQLITE_EXTENSION_INIT1
! 7875: #include <string.h>
! 7876: #include <assert.h>
! 7877:
! 7878: /* The append mark at the end of the database is:
! 7879: **
! 7880: ** Start-Of-SQLite3-NNNNNNNN
! 7881: ** 123456789 123456789 12345
! 7882: **
! 7883: ** The NNNNNNNN represents a 64-bit big-endian unsigned integer which is
! 7884: ** the offset to page 1, and also the length of the prefix content.
! 7885: */
! 7886: #define APND_MARK_PREFIX "Start-Of-SQLite3-"
! 7887: #define APND_MARK_PREFIX_SZ 17
! 7888: #define APND_MARK_FOS_SZ 8
! 7889: #define APND_MARK_SIZE (APND_MARK_PREFIX_SZ+APND_MARK_FOS_SZ)
! 7890:
! 7891: /*
! 7892: ** Maximum size of the combined prefix + database + append-mark. This
! 7893: ** must be less than 0x40000000 to avoid locking issues on Windows.
! 7894: */
! 7895: #define APND_MAX_SIZE (0x40000000)
! 7896:
! 7897: /*
! 7898: ** Try to align the database to an even multiple of APND_ROUNDUP bytes.
! 7899: */
! 7900: #ifndef APND_ROUNDUP
! 7901: #define APND_ROUNDUP 4096
! 7902: #endif
! 7903: #define APND_ALIGN_MASK ((sqlite3_int64)(APND_ROUNDUP-1))
! 7904: #define APND_START_ROUNDUP(fsz) (((fsz)+APND_ALIGN_MASK) & ~APND_ALIGN_MASK)
! 7905:
! 7906: /*
! 7907: ** Forward declaration of objects used by this utility
! 7908: */
! 7909: typedef struct sqlite3_vfs ApndVfs;
! 7910: typedef struct ApndFile ApndFile;
! 7911:
! 7912: /* Access to a lower-level VFS that (might) implement dynamic loading,
! 7913: ** access to randomness, etc.
! 7914: */
! 7915: #define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
! 7916: #define ORIGFILE(p) ((sqlite3_file*)(((ApndFile*)(p))+1))
! 7917:
! 7918: /* An open appendvfs file
! 7919: **
! 7920: ** An instance of this structure describes the appended database file.
! 7921: ** A separate sqlite3_file object is always appended. The appended
! 7922: ** sqlite3_file object (which can be accessed using ORIGFILE()) describes
! 7923: ** the entire file, including the prefix, the database, and the
! 7924: ** append-mark.
! 7925: **
! 7926: ** The structure of an AppendVFS database is like this:
! 7927: **
! 7928: ** +-------------+---------+----------+-------------+
! 7929: ** | prefix-file | padding | database | append-mark |
! 7930: ** +-------------+---------+----------+-------------+
! 7931: ** ^ ^
! 7932: ** | |
! 7933: ** iPgOne iMark
! 7934: **
! 7935: **
! 7936: ** "prefix file" - file onto which the database has been appended.
! 7937: ** "padding" - zero or more bytes inserted so that "database"
! 7938: ** starts on an APND_ROUNDUP boundary
! 7939: ** "database" - The SQLite database file
! 7940: ** "append-mark" - The 25-byte "Start-Of-SQLite3-NNNNNNNN" that indicates
! 7941: ** the offset from the start of prefix-file to the start
! 7942: ** of "database".
! 7943: **
! 7944: ** The size of the database is iMark - iPgOne.
! 7945: **
! 7946: ** The NNNNNNNN in the "Start-Of-SQLite3-NNNNNNNN" suffix is the value
! 7947: ** of iPgOne stored as a big-ending 64-bit integer.
! 7948: **
! 7949: ** iMark will be the size of the underlying file minus 25 (APND_MARKSIZE).
! 7950: ** Or, iMark is -1 to indicate that it has not yet been written.
! 7951: */
! 7952: struct ApndFile {
! 7953: sqlite3_file base; /* Subclass. MUST BE FIRST! */
! 7954: sqlite3_int64 iPgOne; /* Offset to the start of the database */
! 7955: sqlite3_int64 iMark; /* Offset of the append mark. -1 if unwritten */
! 7956: /* Always followed by another sqlite3_file that describes the whole file */
! 7957: };
! 7958:
! 7959: /*
! 7960: ** Methods for ApndFile
! 7961: */
! 7962: static int apndClose(sqlite3_file*);
! 7963: static int apndRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
! 7964: static int apndWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
! 7965: static int apndTruncate(sqlite3_file*, sqlite3_int64 size);
! 7966: static int apndSync(sqlite3_file*, int flags);
! 7967: static int apndFileSize(sqlite3_file*, sqlite3_int64 *pSize);
! 7968: static int apndLock(sqlite3_file*, int);
! 7969: static int apndUnlock(sqlite3_file*, int);
! 7970: static int apndCheckReservedLock(sqlite3_file*, int *pResOut);
! 7971: static int apndFileControl(sqlite3_file*, int op, void *pArg);
! 7972: static int apndSectorSize(sqlite3_file*);
! 7973: static int apndDeviceCharacteristics(sqlite3_file*);
! 7974: static int apndShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
! 7975: static int apndShmLock(sqlite3_file*, int offset, int n, int flags);
! 7976: static void apndShmBarrier(sqlite3_file*);
! 7977: static int apndShmUnmap(sqlite3_file*, int deleteFlag);
! 7978: static int apndFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
! 7979: static int apndUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
! 7980:
! 7981: /*
! 7982: ** Methods for ApndVfs
! 7983: */
! 7984: static int apndOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
! 7985: static int apndDelete(sqlite3_vfs*, const char *zName, int syncDir);
! 7986: static int apndAccess(sqlite3_vfs*, const char *zName, int flags, int *);
! 7987: static int apndFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
! 7988: static void *apndDlOpen(sqlite3_vfs*, const char *zFilename);
! 7989: static void apndDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
! 7990: static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
! 7991: static void apndDlClose(sqlite3_vfs*, void*);
! 7992: static int apndRandomness(sqlite3_vfs*, int nByte, char *zOut);
! 7993: static int apndSleep(sqlite3_vfs*, int microseconds);
! 7994: static int apndCurrentTime(sqlite3_vfs*, double*);
! 7995: static int apndGetLastError(sqlite3_vfs*, int, char *);
! 7996: static int apndCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
! 7997: static int apndSetSystemCall(sqlite3_vfs*, const char*,sqlite3_syscall_ptr);
! 7998: static sqlite3_syscall_ptr apndGetSystemCall(sqlite3_vfs*, const char *z);
! 7999: static const char *apndNextSystemCall(sqlite3_vfs*, const char *zName);
! 8000:
! 8001: static sqlite3_vfs apnd_vfs = {
! 8002: 3, /* iVersion (set when registered) */
! 8003: 0, /* szOsFile (set when registered) */
! 8004: 1024, /* mxPathname */
! 8005: 0, /* pNext */
! 8006: "apndvfs", /* zName */
! 8007: 0, /* pAppData (set when registered) */
! 8008: apndOpen, /* xOpen */
! 8009: apndDelete, /* xDelete */
! 8010: apndAccess, /* xAccess */
! 8011: apndFullPathname, /* xFullPathname */
! 8012: apndDlOpen, /* xDlOpen */
! 8013: apndDlError, /* xDlError */
! 8014: apndDlSym, /* xDlSym */
! 8015: apndDlClose, /* xDlClose */
! 8016: apndRandomness, /* xRandomness */
! 8017: apndSleep, /* xSleep */
! 8018: apndCurrentTime, /* xCurrentTime */
! 8019: apndGetLastError, /* xGetLastError */
! 8020: apndCurrentTimeInt64, /* xCurrentTimeInt64 */
! 8021: apndSetSystemCall, /* xSetSystemCall */
! 8022: apndGetSystemCall, /* xGetSystemCall */
! 8023: apndNextSystemCall /* xNextSystemCall */
! 8024: };
! 8025:
! 8026: static const sqlite3_io_methods apnd_io_methods = {
! 8027: 3, /* iVersion */
! 8028: apndClose, /* xClose */
! 8029: apndRead, /* xRead */
! 8030: apndWrite, /* xWrite */
! 8031: apndTruncate, /* xTruncate */
! 8032: apndSync, /* xSync */
! 8033: apndFileSize, /* xFileSize */
! 8034: apndLock, /* xLock */
! 8035: apndUnlock, /* xUnlock */
! 8036: apndCheckReservedLock, /* xCheckReservedLock */
! 8037: apndFileControl, /* xFileControl */
! 8038: apndSectorSize, /* xSectorSize */
! 8039: apndDeviceCharacteristics, /* xDeviceCharacteristics */
! 8040: apndShmMap, /* xShmMap */
! 8041: apndShmLock, /* xShmLock */
! 8042: apndShmBarrier, /* xShmBarrier */
! 8043: apndShmUnmap, /* xShmUnmap */
! 8044: apndFetch, /* xFetch */
! 8045: apndUnfetch /* xUnfetch */
! 8046: };
! 8047:
! 8048: /*
! 8049: ** Close an apnd-file.
! 8050: */
! 8051: static int apndClose(sqlite3_file *pFile){
! 8052: pFile = ORIGFILE(pFile);
! 8053: return pFile->pMethods->xClose(pFile);
! 8054: }
! 8055:
! 8056: /*
! 8057: ** Read data from an apnd-file.
! 8058: */
! 8059: static int apndRead(
! 8060: sqlite3_file *pFile,
! 8061: void *zBuf,
! 8062: int iAmt,
! 8063: sqlite_int64 iOfst
! 8064: ){
! 8065: ApndFile *paf = (ApndFile *)pFile;
! 8066: pFile = ORIGFILE(pFile);
! 8067: return pFile->pMethods->xRead(pFile, zBuf, iAmt, paf->iPgOne+iOfst);
! 8068: }
! 8069:
! 8070: /*
! 8071: ** Add the append-mark onto what should become the end of the file.
! 8072: * If and only if this succeeds, internal ApndFile.iMark is updated.
! 8073: * Parameter iWriteEnd is the appendvfs-relative offset of the new mark.
! 8074: */
! 8075: static int apndWriteMark(
! 8076: ApndFile *paf,
! 8077: sqlite3_file *pFile,
! 8078: sqlite_int64 iWriteEnd
! 8079: ){
! 8080: sqlite_int64 iPgOne = paf->iPgOne;
! 8081: unsigned char a[APND_MARK_SIZE];
! 8082: int i = APND_MARK_FOS_SZ;
! 8083: int rc;
! 8084: assert(pFile == ORIGFILE(paf));
! 8085: memcpy(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ);
! 8086: while( --i >= 0 ){
! 8087: a[APND_MARK_PREFIX_SZ+i] = (unsigned char)(iPgOne & 0xff);
! 8088: iPgOne >>= 8;
! 8089: }
! 8090: iWriteEnd += paf->iPgOne;
! 8091: if( SQLITE_OK==(rc = pFile->pMethods->xWrite
! 8092: (pFile, a, APND_MARK_SIZE, iWriteEnd)) ){
! 8093: paf->iMark = iWriteEnd;
! 8094: }
! 8095: return rc;
! 8096: }
! 8097:
! 8098: /*
! 8099: ** Write data to an apnd-file.
! 8100: */
! 8101: static int apndWrite(
! 8102: sqlite3_file *pFile,
! 8103: const void *zBuf,
! 8104: int iAmt,
! 8105: sqlite_int64 iOfst
! 8106: ){
! 8107: ApndFile *paf = (ApndFile *)pFile;
! 8108: sqlite_int64 iWriteEnd = iOfst + iAmt;
! 8109: if( iWriteEnd>=APND_MAX_SIZE ) return SQLITE_FULL;
! 8110: pFile = ORIGFILE(pFile);
! 8111: /* If append-mark is absent or will be overwritten, write it. */
! 8112: if( paf->iMark < 0 || paf->iPgOne + iWriteEnd > paf->iMark ){
! 8113: int rc = apndWriteMark(paf, pFile, iWriteEnd);
! 8114: if( SQLITE_OK!=rc ) return rc;
! 8115: }
! 8116: return pFile->pMethods->xWrite(pFile, zBuf, iAmt, paf->iPgOne+iOfst);
! 8117: }
! 8118:
! 8119: /*
! 8120: ** Truncate an apnd-file.
! 8121: */
! 8122: static int apndTruncate(sqlite3_file *pFile, sqlite_int64 size){
! 8123: ApndFile *paf = (ApndFile *)pFile;
! 8124: pFile = ORIGFILE(pFile);
! 8125: /* The append mark goes out first so truncate failure does not lose it. */
! 8126: if( SQLITE_OK!=apndWriteMark(paf, pFile, size) ) return SQLITE_IOERR;
! 8127: /* Truncate underlying file just past append mark */
! 8128: return pFile->pMethods->xTruncate(pFile, paf->iMark+APND_MARK_SIZE);
! 8129: }
! 8130:
! 8131: /*
! 8132: ** Sync an apnd-file.
! 8133: */
! 8134: static int apndSync(sqlite3_file *pFile, int flags){
! 8135: pFile = ORIGFILE(pFile);
! 8136: return pFile->pMethods->xSync(pFile, flags);
! 8137: }
! 8138:
! 8139: /*
! 8140: ** Return the current file-size of an apnd-file.
! 8141: ** If the append mark is not yet there, the file-size is 0.
! 8142: */
! 8143: static int apndFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
! 8144: ApndFile *paf = (ApndFile *)pFile;
! 8145: *pSize = ( paf->iMark >= 0 )? (paf->iMark - paf->iPgOne) : 0;
! 8146: return SQLITE_OK;
! 8147: }
! 8148:
! 8149: /*
! 8150: ** Lock an apnd-file.
! 8151: */
! 8152: static int apndLock(sqlite3_file *pFile, int eLock){
! 8153: pFile = ORIGFILE(pFile);
! 8154: return pFile->pMethods->xLock(pFile, eLock);
! 8155: }
! 8156:
! 8157: /*
! 8158: ** Unlock an apnd-file.
! 8159: */
! 8160: static int apndUnlock(sqlite3_file *pFile, int eLock){
! 8161: pFile = ORIGFILE(pFile);
! 8162: return pFile->pMethods->xUnlock(pFile, eLock);
! 8163: }
! 8164:
! 8165: /*
! 8166: ** Check if another file-handle holds a RESERVED lock on an apnd-file.
! 8167: */
! 8168: static int apndCheckReservedLock(sqlite3_file *pFile, int *pResOut){
! 8169: pFile = ORIGFILE(pFile);
! 8170: return pFile->pMethods->xCheckReservedLock(pFile, pResOut);
! 8171: }
! 8172:
! 8173: /*
! 8174: ** File control method. For custom operations on an apnd-file.
! 8175: */
! 8176: static int apndFileControl(sqlite3_file *pFile, int op, void *pArg){
! 8177: ApndFile *paf = (ApndFile *)pFile;
! 8178: int rc;
! 8179: pFile = ORIGFILE(pFile);
! 8180: if( op==SQLITE_FCNTL_SIZE_HINT ) *(sqlite3_int64*)pArg += paf->iPgOne;
! 8181: rc = pFile->pMethods->xFileControl(pFile, op, pArg);
! 8182: if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
! 8183: *(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", paf->iPgOne,*(char**)pArg);
! 8184: }
! 8185: return rc;
! 8186: }
! 8187:
! 8188: /*
! 8189: ** Return the sector-size in bytes for an apnd-file.
! 8190: */
! 8191: static int apndSectorSize(sqlite3_file *pFile){
! 8192: pFile = ORIGFILE(pFile);
! 8193: return pFile->pMethods->xSectorSize(pFile);
! 8194: }
! 8195:
! 8196: /*
! 8197: ** Return the device characteristic flags supported by an apnd-file.
! 8198: */
! 8199: static int apndDeviceCharacteristics(sqlite3_file *pFile){
! 8200: pFile = ORIGFILE(pFile);
! 8201: return pFile->pMethods->xDeviceCharacteristics(pFile);
! 8202: }
! 8203:
! 8204: /* Create a shared memory file mapping */
! 8205: static int apndShmMap(
! 8206: sqlite3_file *pFile,
! 8207: int iPg,
! 8208: int pgsz,
! 8209: int bExtend,
! 8210: void volatile **pp
! 8211: ){
! 8212: pFile = ORIGFILE(pFile);
! 8213: return pFile->pMethods->xShmMap(pFile,iPg,pgsz,bExtend,pp);
! 8214: }
! 8215:
! 8216: /* Perform locking on a shared-memory segment */
! 8217: static int apndShmLock(sqlite3_file *pFile, int offset, int n, int flags){
! 8218: pFile = ORIGFILE(pFile);
! 8219: return pFile->pMethods->xShmLock(pFile,offset,n,flags);
! 8220: }
! 8221:
! 8222: /* Memory barrier operation on shared memory */
! 8223: static void apndShmBarrier(sqlite3_file *pFile){
! 8224: pFile = ORIGFILE(pFile);
! 8225: pFile->pMethods->xShmBarrier(pFile);
! 8226: }
! 8227:
! 8228: /* Unmap a shared memory segment */
! 8229: static int apndShmUnmap(sqlite3_file *pFile, int deleteFlag){
! 8230: pFile = ORIGFILE(pFile);
! 8231: return pFile->pMethods->xShmUnmap(pFile,deleteFlag);
! 8232: }
! 8233:
! 8234: /* Fetch a page of a memory-mapped file */
! 8235: static int apndFetch(
! 8236: sqlite3_file *pFile,
! 8237: sqlite3_int64 iOfst,
! 8238: int iAmt,
! 8239: void **pp
! 8240: ){
! 8241: ApndFile *p = (ApndFile *)pFile;
! 8242: if( p->iMark < 0 || iOfst+iAmt > p->iMark ){
! 8243: return SQLITE_IOERR; /* Cannot read what is not yet there. */
! 8244: }
! 8245: pFile = ORIGFILE(pFile);
! 8246: return pFile->pMethods->xFetch(pFile, iOfst+p->iPgOne, iAmt, pp);
! 8247: }
! 8248:
! 8249: /* Release a memory-mapped page */
! 8250: static int apndUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
! 8251: ApndFile *p = (ApndFile *)pFile;
! 8252: pFile = ORIGFILE(pFile);
! 8253: return pFile->pMethods->xUnfetch(pFile, iOfst+p->iPgOne, pPage);
! 8254: }
! 8255:
! 8256: /*
! 8257: ** Try to read the append-mark off the end of a file. Return the
! 8258: ** start of the appended database if the append-mark is present.
! 8259: ** If there is no valid append-mark, return -1;
! 8260: **
! 8261: ** An append-mark is only valid if the NNNNNNNN start-of-database offset
! 8262: ** indicates that the appended database contains at least one page. The
! 8263: ** start-of-database value must be a multiple of 512.
! 8264: */
! 8265: static sqlite3_int64 apndReadMark(sqlite3_int64 sz, sqlite3_file *pFile){
! 8266: int rc, i;
! 8267: sqlite3_int64 iMark;
! 8268: int msbs = 8 * (APND_MARK_FOS_SZ-1);
! 8269: unsigned char a[APND_MARK_SIZE];
! 8270:
! 8271: if( APND_MARK_SIZE!=(sz & 0x1ff) ) return -1;
! 8272: rc = pFile->pMethods->xRead(pFile, a, APND_MARK_SIZE, sz-APND_MARK_SIZE);
! 8273: if( rc ) return -1;
! 8274: if( memcmp(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ)!=0 ) return -1;
! 8275: iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ] & 0x7f)) << msbs;
! 8276: for(i=1; i<8; i++){
! 8277: msbs -= 8;
! 8278: iMark |= (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]<<msbs;
! 8279: }
! 8280: if( iMark > (sz - APND_MARK_SIZE - 512) ) return -1;
! 8281: if( iMark & 0x1ff ) return -1;
! 8282: return iMark;
! 8283: }
! 8284:
! 8285: static const char apvfsSqliteHdr[] = "SQLite format 3";
! 8286: /*
! 8287: ** Check to see if the file is an appendvfs SQLite database file.
! 8288: ** Return true iff it is such. Parameter sz is the file's size.
! 8289: */
! 8290: static int apndIsAppendvfsDatabase(sqlite3_int64 sz, sqlite3_file *pFile){
! 8291: int rc;
! 8292: char zHdr[16];
! 8293: sqlite3_int64 iMark = apndReadMark(sz, pFile);
! 8294: if( iMark>=0 ){
! 8295: /* If file has the correct end-marker, the expected odd size, and the
! 8296: ** SQLite DB type marker where the end-marker puts it, then it
! 8297: ** is an appendvfs database.
! 8298: */
! 8299: rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), iMark);
! 8300: if( SQLITE_OK==rc
! 8301: && memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))==0
! 8302: && (sz & 0x1ff) == APND_MARK_SIZE
! 8303: && sz>=512+APND_MARK_SIZE
! 8304: ){
! 8305: return 1; /* It's an appendvfs database */
! 8306: }
! 8307: }
! 8308: return 0;
! 8309: }
! 8310:
! 8311: /*
! 8312: ** Check to see if the file is an ordinary SQLite database file.
! 8313: ** Return true iff so. Parameter sz is the file's size.
! 8314: */
! 8315: static int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){
! 8316: char zHdr[16];
! 8317: if( apndIsAppendvfsDatabase(sz, pFile) /* rule 2 */
! 8318: || (sz & 0x1ff) != 0
! 8319: || SQLITE_OK!=pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0)
! 8320: || memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))!=0
! 8321: ){
! 8322: return 0;
! 8323: }else{
! 8324: return 1;
! 8325: }
! 8326: }
! 8327:
! 8328: /*
! 8329: ** Open an apnd file handle.
! 8330: */
! 8331: static int apndOpen(
! 8332: sqlite3_vfs *pApndVfs,
! 8333: const char *zName,
! 8334: sqlite3_file *pFile,
! 8335: int flags,
! 8336: int *pOutFlags
! 8337: ){
! 8338: ApndFile *pApndFile = (ApndFile*)pFile;
! 8339: sqlite3_file *pBaseFile = ORIGFILE(pFile);
! 8340: sqlite3_vfs *pBaseVfs = ORIGVFS(pApndVfs);
! 8341: int rc;
! 8342: sqlite3_int64 sz = 0;
! 8343: if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
! 8344: /* The appendvfs is not to be used for transient or temporary databases.
! 8345: ** Just use the base VFS open to initialize the given file object and
! 8346: ** open the underlying file. (Appendvfs is then unused for this file.)
! 8347: */
! 8348: return pBaseVfs->xOpen(pBaseVfs, zName, pFile, flags, pOutFlags);
! 8349: }
! 8350: memset(pApndFile, 0, sizeof(ApndFile));
! 8351: pFile->pMethods = &apnd_io_methods;
! 8352: pApndFile->iMark = -1; /* Append mark not yet written */
! 8353:
! 8354: rc = pBaseVfs->xOpen(pBaseVfs, zName, pBaseFile, flags, pOutFlags);
! 8355: if( rc==SQLITE_OK ){
! 8356: rc = pBaseFile->pMethods->xFileSize(pBaseFile, &sz);
! 8357: if( rc ){
! 8358: pBaseFile->pMethods->xClose(pBaseFile);
! 8359: }
! 8360: }
! 8361: if( rc ){
! 8362: pFile->pMethods = 0;
! 8363: return rc;
! 8364: }
! 8365: if( apndIsOrdinaryDatabaseFile(sz, pBaseFile) ){
! 8366: /* The file being opened appears to be just an ordinary DB. Copy
! 8367: ** the base dispatch-table so this instance mimics the base VFS.
! 8368: */
! 8369: memmove(pApndFile, pBaseFile, pBaseVfs->szOsFile);
! 8370: return SQLITE_OK;
! 8371: }
! 8372: pApndFile->iPgOne = apndReadMark(sz, pFile);
! 8373: if( pApndFile->iPgOne>=0 ){
! 8374: pApndFile->iMark = sz - APND_MARK_SIZE; /* Append mark found */
! 8375: return SQLITE_OK;
! 8376: }
! 8377: if( (flags & SQLITE_OPEN_CREATE)==0 ){
! 8378: pBaseFile->pMethods->xClose(pBaseFile);
! 8379: rc = SQLITE_CANTOPEN;
! 8380: pFile->pMethods = 0;
! 8381: }else{
! 8382: /* Round newly added appendvfs location to #define'd page boundary.
! 8383: ** Note that nothing has yet been written to the underlying file.
! 8384: ** The append mark will be written along with first content write.
! 8385: ** Until then, paf->iMark value indicates it is not yet written.
! 8386: */
! 8387: pApndFile->iPgOne = APND_START_ROUNDUP(sz);
! 8388: }
! 8389: return rc;
! 8390: }
! 8391:
! 8392: /*
! 8393: ** Delete an apnd file.
! 8394: ** For an appendvfs, this could mean delete the appendvfs portion,
! 8395: ** leaving the appendee as it was before it gained an appendvfs.
! 8396: ** For now, this code deletes the underlying file too.
! 8397: */
! 8398: static int apndDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
! 8399: return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync);
! 8400: }
! 8401:
! 8402: /*
! 8403: ** All other VFS methods are pass-thrus.
! 8404: */
! 8405: static int apndAccess(
! 8406: sqlite3_vfs *pVfs,
! 8407: const char *zPath,
! 8408: int flags,
! 8409: int *pResOut
! 8410: ){
! 8411: return ORIGVFS(pVfs)->xAccess(ORIGVFS(pVfs), zPath, flags, pResOut);
! 8412: }
! 8413: static int apndFullPathname(
! 8414: sqlite3_vfs *pVfs,
! 8415: const char *zPath,
! 8416: int nOut,
! 8417: char *zOut
! 8418: ){
! 8419: return ORIGVFS(pVfs)->xFullPathname(ORIGVFS(pVfs),zPath,nOut,zOut);
! 8420: }
! 8421: static void *apndDlOpen(sqlite3_vfs *pVfs, const char *zPath){
! 8422: return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
! 8423: }
! 8424: static void apndDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
! 8425: ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
! 8426: }
! 8427: static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
! 8428: return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
! 8429: }
! 8430: static void apndDlClose(sqlite3_vfs *pVfs, void *pHandle){
! 8431: ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
! 8432: }
! 8433: static int apndRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
! 8434: return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
! 8435: }
! 8436: static int apndSleep(sqlite3_vfs *pVfs, int nMicro){
! 8437: return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
! 8438: }
! 8439: static int apndCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
! 8440: return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
! 8441: }
! 8442: static int apndGetLastError(sqlite3_vfs *pVfs, int a, char *b){
! 8443: return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
! 8444: }
! 8445: static int apndCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
! 8446: return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
! 8447: }
! 8448: static int apndSetSystemCall(
! 8449: sqlite3_vfs *pVfs,
! 8450: const char *zName,
! 8451: sqlite3_syscall_ptr pCall
! 8452: ){
! 8453: return ORIGVFS(pVfs)->xSetSystemCall(ORIGVFS(pVfs),zName,pCall);
! 8454: }
! 8455: static sqlite3_syscall_ptr apndGetSystemCall(
! 8456: sqlite3_vfs *pVfs,
! 8457: const char *zName
! 8458: ){
! 8459: return ORIGVFS(pVfs)->xGetSystemCall(ORIGVFS(pVfs),zName);
! 8460: }
! 8461: static const char *apndNextSystemCall(sqlite3_vfs *pVfs, const char *zName){
! 8462: return ORIGVFS(pVfs)->xNextSystemCall(ORIGVFS(pVfs), zName);
! 8463: }
! 8464:
! 8465:
! 8466: #ifdef _WIN32
! 8467:
! 8468: #endif
! 8469: /*
! 8470: ** This routine is called when the extension is loaded.
! 8471: ** Register the new VFS.
! 8472: */
! 8473: int sqlite3_appendvfs_init(
! 8474: sqlite3 *db,
! 8475: char **pzErrMsg,
! 8476: const sqlite3_api_routines *pApi
! 8477: ){
! 8478: int rc = SQLITE_OK;
! 8479: sqlite3_vfs *pOrig;
! 8480: SQLITE_EXTENSION_INIT2(pApi);
! 8481: (void)pzErrMsg;
! 8482: (void)db;
! 8483: pOrig = sqlite3_vfs_find(0);
! 8484: if( pOrig==0 ) return SQLITE_ERROR;
! 8485: apnd_vfs.iVersion = pOrig->iVersion;
! 8486: apnd_vfs.pAppData = pOrig;
! 8487: apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile);
! 8488: rc = sqlite3_vfs_register(&apnd_vfs, 0);
! 8489: #ifdef APPENDVFS_TEST
! 8490: if( rc==SQLITE_OK ){
! 8491: rc = sqlite3_auto_extension((void(*)(void))apndvfsRegister);
! 8492: }
! 8493: #endif
! 8494: if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
! 8495: return rc;
! 8496: }
! 8497:
! 8498: /************************* End ../ext/misc/appendvfs.c ********************/
! 8499: #endif
! 8500: #ifdef SQLITE_HAVE_ZLIB
! 8501: /************************* Begin ../ext/misc/zipfile.c ******************/
! 8502: /*
! 8503: ** 2017-12-26
! 8504: **
! 8505: ** The author disclaims copyright to this source code. In place of
! 8506: ** a legal notice, here is a blessing:
! 8507: **
! 8508: ** May you do good and not evil.
! 8509: ** May you find forgiveness for yourself and forgive others.
! 8510: ** May you share freely, never taking more than you give.
! 8511: **
! 8512: ******************************************************************************
! 8513: **
! 8514: ** This file implements a virtual table for reading and writing ZIP archive
! 8515: ** files.
! 8516: **
! 8517: ** Usage example:
! 8518: **
! 8519: ** SELECT name, sz, datetime(mtime,'unixepoch') FROM zipfile($filename);
! 8520: **
! 8521: ** Current limitations:
! 8522: **
! 8523: ** * No support for encryption
! 8524: ** * No support for ZIP archives spanning multiple files
! 8525: ** * No support for zip64 extensions
! 8526: ** * Only the "inflate/deflate" (zlib) compression method is supported
! 8527: */
! 8528: /* #include "sqlite3ext.h" */
! 8529: SQLITE_EXTENSION_INIT1
! 8530: #include <stdio.h>
! 8531: #include <string.h>
! 8532: #include <assert.h>
! 8533:
! 8534: #include <zlib.h>
! 8535:
! 8536: #ifndef SQLITE_OMIT_VIRTUALTABLE
! 8537:
! 8538: #ifndef SQLITE_AMALGAMATION
! 8539:
! 8540: #ifndef UINT32_TYPE
! 8541: # ifdef HAVE_UINT32_T
! 8542: # define UINT32_TYPE uint32_t
! 8543: # else
! 8544: # define UINT32_TYPE unsigned int
! 8545: # endif
! 8546: #endif
! 8547: #ifndef UINT16_TYPE
! 8548: # ifdef HAVE_UINT16_T
! 8549: # define UINT16_TYPE uint16_t
! 8550: # else
! 8551: # define UINT16_TYPE unsigned short int
! 8552: # endif
! 8553: #endif
! 8554: /* typedef sqlite3_int64 i64; */
! 8555: /* typedef unsigned char u8; */
! 8556: /* typedef UINT32_TYPE u32; // 4-byte unsigned integer // */
! 8557: /* typedef UINT16_TYPE u16; // 2-byte unsigned integer // */
! 8558: #define MIN(a,b) ((a)<(b) ? (a) : (b))
! 8559:
! 8560: #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
! 8561: # define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
! 8562: #endif
! 8563: #if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
! 8564: # define ALWAYS(X) (1)
! 8565: # define NEVER(X) (0)
! 8566: #elif !defined(NDEBUG)
! 8567: # define ALWAYS(X) ((X)?1:(assert(0),0))
! 8568: # define NEVER(X) ((X)?(assert(0),1):0)
! 8569: #else
! 8570: # define ALWAYS(X) (X)
! 8571: # define NEVER(X) (X)
! 8572: #endif
! 8573:
! 8574: #endif /* SQLITE_AMALGAMATION */
! 8575:
! 8576: /*
! 8577: ** Definitions for mode bitmasks S_IFDIR, S_IFREG and S_IFLNK.
! 8578: **
! 8579: ** In some ways it would be better to obtain these values from system
! 8580: ** header files. But, the dependency is undesirable and (a) these
! 8581: ** have been stable for decades, (b) the values are part of POSIX and
! 8582: ** are also made explicit in [man stat], and (c) are part of the
! 8583: ** file format for zip archives.
! 8584: */
! 8585: #ifndef S_IFDIR
! 8586: # define S_IFDIR 0040000
! 8587: #endif
! 8588: #ifndef S_IFREG
! 8589: # define S_IFREG 0100000
! 8590: #endif
! 8591: #ifndef S_IFLNK
! 8592: # define S_IFLNK 0120000
! 8593: #endif
! 8594:
! 8595: static const char ZIPFILE_SCHEMA[] =
! 8596: "CREATE TABLE y("
! 8597: "name PRIMARY KEY," /* 0: Name of file in zip archive */
! 8598: "mode," /* 1: POSIX mode for file */
! 8599: "mtime," /* 2: Last modification time (secs since 1970)*/
! 8600: "sz," /* 3: Size of object */
! 8601: "rawdata," /* 4: Raw data */
! 8602: "data," /* 5: Uncompressed data */
! 8603: "method," /* 6: Compression method (integer) */
! 8604: "z HIDDEN" /* 7: Name of zip file */
! 8605: ") WITHOUT ROWID;";
! 8606:
! 8607: #define ZIPFILE_F_COLUMN_IDX 7 /* Index of column "file" in the above */
! 8608: #define ZIPFILE_BUFFER_SIZE (64*1024)
! 8609:
! 8610:
! 8611: /*
! 8612: ** Magic numbers used to read and write zip files.
! 8613: **
! 8614: ** ZIPFILE_NEWENTRY_MADEBY:
! 8615: ** Use this value for the "version-made-by" field in new zip file
! 8616: ** entries. The upper byte indicates "unix", and the lower byte
! 8617: ** indicates that the zip file matches pkzip specification 3.0.
! 8618: ** This is what info-zip seems to do.
! 8619: **
! 8620: ** ZIPFILE_NEWENTRY_REQUIRED:
! 8621: ** Value for "version-required-to-extract" field of new entries.
! 8622: ** Version 2.0 is required to support folders and deflate compression.
! 8623: **
! 8624: ** ZIPFILE_NEWENTRY_FLAGS:
! 8625: ** Value for "general-purpose-bit-flags" field of new entries. Bit
! 8626: ** 11 means "utf-8 filename and comment".
! 8627: **
! 8628: ** ZIPFILE_SIGNATURE_CDS:
! 8629: ** First 4 bytes of a valid CDS record.
! 8630: **
! 8631: ** ZIPFILE_SIGNATURE_LFH:
! 8632: ** First 4 bytes of a valid LFH record.
! 8633: **
! 8634: ** ZIPFILE_SIGNATURE_EOCD
! 8635: ** First 4 bytes of a valid EOCD record.
! 8636: */
! 8637: #define ZIPFILE_EXTRA_TIMESTAMP 0x5455
! 8638: #define ZIPFILE_NEWENTRY_MADEBY ((3<<8) + 30)
! 8639: #define ZIPFILE_NEWENTRY_REQUIRED 20
! 8640: #define ZIPFILE_NEWENTRY_FLAGS 0x800
! 8641: #define ZIPFILE_SIGNATURE_CDS 0x02014b50
! 8642: #define ZIPFILE_SIGNATURE_LFH 0x04034b50
! 8643: #define ZIPFILE_SIGNATURE_EOCD 0x06054b50
! 8644:
! 8645: /*
! 8646: ** The sizes of the fixed-size part of each of the three main data
! 8647: ** structures in a zip archive.
! 8648: */
! 8649: #define ZIPFILE_LFH_FIXED_SZ 30
! 8650: #define ZIPFILE_EOCD_FIXED_SZ 22
! 8651: #define ZIPFILE_CDS_FIXED_SZ 46
! 8652:
! 8653: /*
! 8654: *** 4.3.16 End of central directory record:
! 8655: ***
! 8656: *** end of central dir signature 4 bytes (0x06054b50)
! 8657: *** number of this disk 2 bytes
! 8658: *** number of the disk with the
! 8659: *** start of the central directory 2 bytes
! 8660: *** total number of entries in the
! 8661: *** central directory on this disk 2 bytes
! 8662: *** total number of entries in
! 8663: *** the central directory 2 bytes
! 8664: *** size of the central directory 4 bytes
! 8665: *** offset of start of central
! 8666: *** directory with respect to
! 8667: *** the starting disk number 4 bytes
! 8668: *** .ZIP file comment length 2 bytes
! 8669: *** .ZIP file comment (variable size)
! 8670: */
! 8671: typedef struct ZipfileEOCD ZipfileEOCD;
! 8672: struct ZipfileEOCD {
! 8673: u16 iDisk;
! 8674: u16 iFirstDisk;
! 8675: u16 nEntry;
! 8676: u16 nEntryTotal;
! 8677: u32 nSize;
! 8678: u32 iOffset;
! 8679: };
! 8680:
! 8681: /*
! 8682: *** 4.3.12 Central directory structure:
! 8683: ***
! 8684: *** ...
! 8685: ***
! 8686: *** central file header signature 4 bytes (0x02014b50)
! 8687: *** version made by 2 bytes
! 8688: *** version needed to extract 2 bytes
! 8689: *** general purpose bit flag 2 bytes
! 8690: *** compression method 2 bytes
! 8691: *** last mod file time 2 bytes
! 8692: *** last mod file date 2 bytes
! 8693: *** crc-32 4 bytes
! 8694: *** compressed size 4 bytes
! 8695: *** uncompressed size 4 bytes
! 8696: *** file name length 2 bytes
! 8697: *** extra field length 2 bytes
! 8698: *** file comment length 2 bytes
! 8699: *** disk number start 2 bytes
! 8700: *** internal file attributes 2 bytes
! 8701: *** external file attributes 4 bytes
! 8702: *** relative offset of local header 4 bytes
! 8703: */
! 8704: typedef struct ZipfileCDS ZipfileCDS;
! 8705: struct ZipfileCDS {
! 8706: u16 iVersionMadeBy;
! 8707: u16 iVersionExtract;
! 8708: u16 flags;
! 8709: u16 iCompression;
! 8710: u16 mTime;
! 8711: u16 mDate;
! 8712: u32 crc32;
! 8713: u32 szCompressed;
! 8714: u32 szUncompressed;
! 8715: u16 nFile;
! 8716: u16 nExtra;
! 8717: u16 nComment;
! 8718: u16 iDiskStart;
! 8719: u16 iInternalAttr;
! 8720: u32 iExternalAttr;
! 8721: u32 iOffset;
! 8722: char *zFile; /* Filename (sqlite3_malloc()) */
! 8723: };
! 8724:
! 8725: /*
! 8726: *** 4.3.7 Local file header:
! 8727: ***
! 8728: *** local file header signature 4 bytes (0x04034b50)
! 8729: *** version needed to extract 2 bytes
! 8730: *** general purpose bit flag 2 bytes
! 8731: *** compression method 2 bytes
! 8732: *** last mod file time 2 bytes
! 8733: *** last mod file date 2 bytes
! 8734: *** crc-32 4 bytes
! 8735: *** compressed size 4 bytes
! 8736: *** uncompressed size 4 bytes
! 8737: *** file name length 2 bytes
! 8738: *** extra field length 2 bytes
! 8739: ***
! 8740: */
! 8741: typedef struct ZipfileLFH ZipfileLFH;
! 8742: struct ZipfileLFH {
! 8743: u16 iVersionExtract;
! 8744: u16 flags;
! 8745: u16 iCompression;
! 8746: u16 mTime;
! 8747: u16 mDate;
! 8748: u32 crc32;
! 8749: u32 szCompressed;
! 8750: u32 szUncompressed;
! 8751: u16 nFile;
! 8752: u16 nExtra;
! 8753: };
! 8754:
! 8755: typedef struct ZipfileEntry ZipfileEntry;
! 8756: struct ZipfileEntry {
! 8757: ZipfileCDS cds; /* Parsed CDS record */
! 8758: u32 mUnixTime; /* Modification time, in UNIX format */
! 8759: u8 *aExtra; /* cds.nExtra+cds.nComment bytes of extra data */
! 8760: i64 iDataOff; /* Offset to data in file (if aData==0) */
! 8761: u8 *aData; /* cds.szCompressed bytes of compressed data */
! 8762: ZipfileEntry *pNext; /* Next element in in-memory CDS */
! 8763: };
! 8764:
! 8765: /*
! 8766: ** Cursor type for zipfile tables.
! 8767: */
! 8768: typedef struct ZipfileCsr ZipfileCsr;
! 8769: struct ZipfileCsr {
! 8770: sqlite3_vtab_cursor base; /* Base class - must be first */
! 8771: i64 iId; /* Cursor ID */
! 8772: u8 bEof; /* True when at EOF */
! 8773: u8 bNoop; /* If next xNext() call is no-op */
! 8774:
! 8775: /* Used outside of write transactions */
! 8776: FILE *pFile; /* Zip file */
! 8777: i64 iNextOff; /* Offset of next record in central directory */
! 8778: ZipfileEOCD eocd; /* Parse of central directory record */
! 8779:
! 8780: ZipfileEntry *pFreeEntry; /* Free this list when cursor is closed or reset */
! 8781: ZipfileEntry *pCurrent; /* Current entry */
! 8782: ZipfileCsr *pCsrNext; /* Next cursor on same virtual table */
! 8783: };
! 8784:
! 8785: typedef struct ZipfileTab ZipfileTab;
! 8786: struct ZipfileTab {
! 8787: sqlite3_vtab base; /* Base class - must be first */
! 8788: char *zFile; /* Zip file this table accesses (may be NULL) */
! 8789: sqlite3 *db; /* Host database connection */
! 8790: u8 *aBuffer; /* Temporary buffer used for various tasks */
! 8791:
! 8792: ZipfileCsr *pCsrList; /* List of cursors */
! 8793: i64 iNextCsrid;
! 8794:
! 8795: /* The following are used by write transactions only */
! 8796: ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */
! 8797: ZipfileEntry *pLastEntry; /* Last element in pFirstEntry list */
! 8798: FILE *pWriteFd; /* File handle open on zip archive */
! 8799: i64 szCurrent; /* Current size of zip archive */
! 8800: i64 szOrig; /* Size of archive at start of transaction */
! 8801: };
! 8802:
! 8803: /*
! 8804: ** Set the error message contained in context ctx to the results of
! 8805: ** vprintf(zFmt, ...).
! 8806: */
! 8807: static void zipfileCtxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
! 8808: char *zMsg = 0;
! 8809: va_list ap;
! 8810: va_start(ap, zFmt);
! 8811: zMsg = sqlite3_vmprintf(zFmt, ap);
! 8812: sqlite3_result_error(ctx, zMsg, -1);
! 8813: sqlite3_free(zMsg);
! 8814: va_end(ap);
! 8815: }
! 8816:
! 8817: /*
! 8818: ** If string zIn is quoted, dequote it in place. Otherwise, if the string
! 8819: ** is not quoted, do nothing.
! 8820: */
! 8821: static void zipfileDequote(char *zIn){
! 8822: char q = zIn[0];
! 8823: if( q=='"' || q=='\'' || q=='`' || q=='[' ){
! 8824: int iIn = 1;
! 8825: int iOut = 0;
! 8826: if( q=='[' ) q = ']';
! 8827: while( ALWAYS(zIn[iIn]) ){
! 8828: char c = zIn[iIn++];
! 8829: if( c==q && zIn[iIn++]!=q ) break;
! 8830: zIn[iOut++] = c;
! 8831: }
! 8832: zIn[iOut] = '\0';
! 8833: }
! 8834: }
! 8835:
! 8836: /*
! 8837: ** Construct a new ZipfileTab virtual table object.
! 8838: **
! 8839: ** argv[0] -> module name ("zipfile")
! 8840: ** argv[1] -> database name
! 8841: ** argv[2] -> table name
! 8842: ** argv[...] -> "column name" and other module argument fields.
! 8843: */
! 8844: static int zipfileConnect(
! 8845: sqlite3 *db,
! 8846: void *pAux,
! 8847: int argc, const char *const*argv,
! 8848: sqlite3_vtab **ppVtab,
! 8849: char **pzErr
! 8850: ){
! 8851: int nByte = sizeof(ZipfileTab) + ZIPFILE_BUFFER_SIZE;
! 8852: int nFile = 0;
! 8853: const char *zFile = 0;
! 8854: ZipfileTab *pNew = 0;
! 8855: int rc;
! 8856: (void)pAux;
! 8857:
! 8858: /* If the table name is not "zipfile", require that the argument be
! 8859: ** specified. This stops zipfile tables from being created as:
! 8860: **
! 8861: ** CREATE VIRTUAL TABLE zzz USING zipfile();
! 8862: **
! 8863: ** It does not prevent:
! 8864: **
! 8865: ** CREATE VIRTUAL TABLE zipfile USING zipfile();
! 8866: */
! 8867: assert( 0==sqlite3_stricmp(argv[0], "zipfile") );
! 8868: if( (0!=sqlite3_stricmp(argv[2], "zipfile") && argc<4) || argc>4 ){
! 8869: *pzErr = sqlite3_mprintf("zipfile constructor requires one argument");
! 8870: return SQLITE_ERROR;
! 8871: }
! 8872:
! 8873: if( argc>3 ){
! 8874: zFile = argv[3];
! 8875: nFile = (int)strlen(zFile)+1;
! 8876: }
! 8877:
! 8878: rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
! 8879: if( rc==SQLITE_OK ){
! 8880: pNew = (ZipfileTab*)sqlite3_malloc64((sqlite3_int64)nByte+nFile);
! 8881: if( pNew==0 ) return SQLITE_NOMEM;
! 8882: memset(pNew, 0, nByte+nFile);
! 8883: pNew->db = db;
! 8884: pNew->aBuffer = (u8*)&pNew[1];
! 8885: if( zFile ){
! 8886: pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE];
! 8887: memcpy(pNew->zFile, zFile, nFile);
! 8888: zipfileDequote(pNew->zFile);
! 8889: }
! 8890: }
! 8891: sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
! 8892: *ppVtab = (sqlite3_vtab*)pNew;
! 8893: return rc;
! 8894: }
! 8895:
! 8896: /*
! 8897: ** Free the ZipfileEntry structure indicated by the only argument.
! 8898: */
! 8899: static void zipfileEntryFree(ZipfileEntry *p){
! 8900: if( p ){
! 8901: sqlite3_free(p->cds.zFile);
! 8902: sqlite3_free(p);
! 8903: }
! 8904: }
! 8905:
! 8906: /*
! 8907: ** Release resources that should be freed at the end of a write
! 8908: ** transaction.
! 8909: */
! 8910: static void zipfileCleanupTransaction(ZipfileTab *pTab){
! 8911: ZipfileEntry *pEntry;
! 8912: ZipfileEntry *pNext;
! 8913:
! 8914: if( pTab->pWriteFd ){
! 8915: fclose(pTab->pWriteFd);
! 8916: pTab->pWriteFd = 0;
! 8917: }
! 8918: for(pEntry=pTab->pFirstEntry; pEntry; pEntry=pNext){
! 8919: pNext = pEntry->pNext;
! 8920: zipfileEntryFree(pEntry);
! 8921: }
! 8922: pTab->pFirstEntry = 0;
! 8923: pTab->pLastEntry = 0;
! 8924: pTab->szCurrent = 0;
! 8925: pTab->szOrig = 0;
! 8926: }
! 8927:
! 8928: /*
! 8929: ** This method is the destructor for zipfile vtab objects.
! 8930: */
! 8931: static int zipfileDisconnect(sqlite3_vtab *pVtab){
! 8932: zipfileCleanupTransaction((ZipfileTab*)pVtab);
! 8933: sqlite3_free(pVtab);
! 8934: return SQLITE_OK;
! 8935: }
! 8936:
! 8937: /*
! 8938: ** Constructor for a new ZipfileCsr object.
! 8939: */
! 8940: static int zipfileOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){
! 8941: ZipfileTab *pTab = (ZipfileTab*)p;
! 8942: ZipfileCsr *pCsr;
! 8943: pCsr = sqlite3_malloc(sizeof(*pCsr));
! 8944: *ppCsr = (sqlite3_vtab_cursor*)pCsr;
! 8945: if( pCsr==0 ){
! 8946: return SQLITE_NOMEM;
! 8947: }
! 8948: memset(pCsr, 0, sizeof(*pCsr));
! 8949: pCsr->iId = ++pTab->iNextCsrid;
! 8950: pCsr->pCsrNext = pTab->pCsrList;
! 8951: pTab->pCsrList = pCsr;
! 8952: return SQLITE_OK;
! 8953: }
! 8954:
! 8955: /*
! 8956: ** Reset a cursor back to the state it was in when first returned
! 8957: ** by zipfileOpen().
! 8958: */
! 8959: static void zipfileResetCursor(ZipfileCsr *pCsr){
! 8960: ZipfileEntry *p;
! 8961: ZipfileEntry *pNext;
! 8962:
! 8963: pCsr->bEof = 0;
! 8964: if( pCsr->pFile ){
! 8965: fclose(pCsr->pFile);
! 8966: pCsr->pFile = 0;
! 8967: zipfileEntryFree(pCsr->pCurrent);
! 8968: pCsr->pCurrent = 0;
! 8969: }
! 8970:
! 8971: for(p=pCsr->pFreeEntry; p; p=pNext){
! 8972: pNext = p->pNext;
! 8973: zipfileEntryFree(p);
! 8974: }
! 8975: }
! 8976:
! 8977: /*
! 8978: ** Destructor for an ZipfileCsr.
! 8979: */
! 8980: static int zipfileClose(sqlite3_vtab_cursor *cur){
! 8981: ZipfileCsr *pCsr = (ZipfileCsr*)cur;
! 8982: ZipfileTab *pTab = (ZipfileTab*)(pCsr->base.pVtab);
! 8983: ZipfileCsr **pp;
! 8984: zipfileResetCursor(pCsr);
! 8985:
! 8986: /* Remove this cursor from the ZipfileTab.pCsrList list. */
! 8987: for(pp=&pTab->pCsrList; *pp!=pCsr; pp=&((*pp)->pCsrNext));
! 8988: *pp = pCsr->pCsrNext;
! 8989:
! 8990: sqlite3_free(pCsr);
! 8991: return SQLITE_OK;
! 8992: }
! 8993:
! 8994: /*
! 8995: ** Set the error message for the virtual table associated with cursor
! 8996: ** pCsr to the results of vprintf(zFmt, ...).
! 8997: */
! 8998: static void zipfileTableErr(ZipfileTab *pTab, const char *zFmt, ...){
! 8999: va_list ap;
! 9000: va_start(ap, zFmt);
! 9001: sqlite3_free(pTab->base.zErrMsg);
! 9002: pTab->base.zErrMsg = sqlite3_vmprintf(zFmt, ap);
! 9003: va_end(ap);
! 9004: }
! 9005: static void zipfileCursorErr(ZipfileCsr *pCsr, const char *zFmt, ...){
! 9006: va_list ap;
! 9007: va_start(ap, zFmt);
! 9008: sqlite3_free(pCsr->base.pVtab->zErrMsg);
! 9009: pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
! 9010: va_end(ap);
! 9011: }
! 9012:
! 9013: /*
! 9014: ** Read nRead bytes of data from offset iOff of file pFile into buffer
! 9015: ** aRead[]. Return SQLITE_OK if successful, or an SQLite error code
! 9016: ** otherwise.
! 9017: **
! 9018: ** If an error does occur, output variable (*pzErrmsg) may be set to point
! 9019: ** to an English language error message. It is the responsibility of the
! 9020: ** caller to eventually free this buffer using
! 9021: ** sqlite3_free().
! 9022: */
! 9023: static int zipfileReadData(
! 9024: FILE *pFile, /* Read from this file */
! 9025: u8 *aRead, /* Read into this buffer */
! 9026: int nRead, /* Number of bytes to read */
! 9027: i64 iOff, /* Offset to read from */
! 9028: char **pzErrmsg /* OUT: Error message (from sqlite3_malloc) */
! 9029: ){
! 9030: size_t n;
! 9031: fseek(pFile, (long)iOff, SEEK_SET);
! 9032: n = fread(aRead, 1, nRead, pFile);
! 9033: if( (int)n!=nRead ){
! 9034: *pzErrmsg = sqlite3_mprintf("error in fread()");
! 9035: return SQLITE_ERROR;
! 9036: }
! 9037: return SQLITE_OK;
! 9038: }
! 9039:
! 9040: static int zipfileAppendData(
! 9041: ZipfileTab *pTab,
! 9042: const u8 *aWrite,
! 9043: int nWrite
! 9044: ){
! 9045: if( nWrite>0 ){
! 9046: size_t n = nWrite;
! 9047: fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
! 9048: n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
! 9049: if( (int)n!=nWrite ){
! 9050: pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
! 9051: return SQLITE_ERROR;
! 9052: }
! 9053: pTab->szCurrent += nWrite;
! 9054: }
! 9055: return SQLITE_OK;
! 9056: }
! 9057:
! 9058: /*
! 9059: ** Read and return a 16-bit little-endian unsigned integer from buffer aBuf.
! 9060: */
! 9061: static u16 zipfileGetU16(const u8 *aBuf){
! 9062: return (aBuf[1] << 8) + aBuf[0];
! 9063: }
! 9064:
! 9065: /*
! 9066: ** Read and return a 32-bit little-endian unsigned integer from buffer aBuf.
! 9067: */
! 9068: static u32 zipfileGetU32(const u8 *aBuf){
! 9069: if( aBuf==0 ) return 0;
! 9070: return ((u32)(aBuf[3]) << 24)
! 9071: + ((u32)(aBuf[2]) << 16)
! 9072: + ((u32)(aBuf[1]) << 8)
! 9073: + ((u32)(aBuf[0]) << 0);
! 9074: }
! 9075:
! 9076: /*
! 9077: ** Write a 16-bit little endiate integer into buffer aBuf.
! 9078: */
! 9079: static void zipfilePutU16(u8 *aBuf, u16 val){
! 9080: aBuf[0] = val & 0xFF;
! 9081: aBuf[1] = (val>>8) & 0xFF;
! 9082: }
! 9083:
! 9084: /*
! 9085: ** Write a 32-bit little endiate integer into buffer aBuf.
! 9086: */
! 9087: static void zipfilePutU32(u8 *aBuf, u32 val){
! 9088: aBuf[0] = val & 0xFF;
! 9089: aBuf[1] = (val>>8) & 0xFF;
! 9090: aBuf[2] = (val>>16) & 0xFF;
! 9091: aBuf[3] = (val>>24) & 0xFF;
! 9092: }
! 9093:
! 9094: #define zipfileRead32(aBuf) ( aBuf+=4, zipfileGetU32(aBuf-4) )
! 9095: #define zipfileRead16(aBuf) ( aBuf+=2, zipfileGetU16(aBuf-2) )
! 9096:
! 9097: #define zipfileWrite32(aBuf,val) { zipfilePutU32(aBuf,val); aBuf+=4; }
! 9098: #define zipfileWrite16(aBuf,val) { zipfilePutU16(aBuf,val); aBuf+=2; }
! 9099:
! 9100: /*
! 9101: ** Magic numbers used to read CDS records.
! 9102: */
! 9103: #define ZIPFILE_CDS_NFILE_OFF 28
! 9104: #define ZIPFILE_CDS_SZCOMPRESSED_OFF 20
! 9105:
! 9106: /*
! 9107: ** Decode the CDS record in buffer aBuf into (*pCDS). Return SQLITE_ERROR
! 9108: ** if the record is not well-formed, or SQLITE_OK otherwise.
! 9109: */
! 9110: static int zipfileReadCDS(u8 *aBuf, ZipfileCDS *pCDS){
! 9111: u8 *aRead = aBuf;
! 9112: u32 sig = zipfileRead32(aRead);
! 9113: int rc = SQLITE_OK;
! 9114: if( sig!=ZIPFILE_SIGNATURE_CDS ){
! 9115: rc = SQLITE_ERROR;
! 9116: }else{
! 9117: pCDS->iVersionMadeBy = zipfileRead16(aRead);
! 9118: pCDS->iVersionExtract = zipfileRead16(aRead);
! 9119: pCDS->flags = zipfileRead16(aRead);
! 9120: pCDS->iCompression = zipfileRead16(aRead);
! 9121: pCDS->mTime = zipfileRead16(aRead);
! 9122: pCDS->mDate = zipfileRead16(aRead);
! 9123: pCDS->crc32 = zipfileRead32(aRead);
! 9124: pCDS->szCompressed = zipfileRead32(aRead);
! 9125: pCDS->szUncompressed = zipfileRead32(aRead);
! 9126: assert( aRead==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
! 9127: pCDS->nFile = zipfileRead16(aRead);
! 9128: pCDS->nExtra = zipfileRead16(aRead);
! 9129: pCDS->nComment = zipfileRead16(aRead);
! 9130: pCDS->iDiskStart = zipfileRead16(aRead);
! 9131: pCDS->iInternalAttr = zipfileRead16(aRead);
! 9132: pCDS->iExternalAttr = zipfileRead32(aRead);
! 9133: pCDS->iOffset = zipfileRead32(aRead);
! 9134: assert( aRead==&aBuf[ZIPFILE_CDS_FIXED_SZ] );
! 9135: }
! 9136:
! 9137: return rc;
! 9138: }
! 9139:
! 9140: /*
! 9141: ** Decode the LFH record in buffer aBuf into (*pLFH). Return SQLITE_ERROR
! 9142: ** if the record is not well-formed, or SQLITE_OK otherwise.
! 9143: */
! 9144: static int zipfileReadLFH(
! 9145: u8 *aBuffer,
! 9146: ZipfileLFH *pLFH
! 9147: ){
! 9148: u8 *aRead = aBuffer;
! 9149: int rc = SQLITE_OK;
! 9150:
! 9151: u32 sig = zipfileRead32(aRead);
! 9152: if( sig!=ZIPFILE_SIGNATURE_LFH ){
! 9153: rc = SQLITE_ERROR;
! 9154: }else{
! 9155: pLFH->iVersionExtract = zipfileRead16(aRead);
! 9156: pLFH->flags = zipfileRead16(aRead);
! 9157: pLFH->iCompression = zipfileRead16(aRead);
! 9158: pLFH->mTime = zipfileRead16(aRead);
! 9159: pLFH->mDate = zipfileRead16(aRead);
! 9160: pLFH->crc32 = zipfileRead32(aRead);
! 9161: pLFH->szCompressed = zipfileRead32(aRead);
! 9162: pLFH->szUncompressed = zipfileRead32(aRead);
! 9163: pLFH->nFile = zipfileRead16(aRead);
! 9164: pLFH->nExtra = zipfileRead16(aRead);
! 9165: }
! 9166: return rc;
! 9167: }
! 9168:
! 9169:
! 9170: /*
! 9171: ** Buffer aExtra (size nExtra bytes) contains zip archive "extra" fields.
! 9172: ** Scan through this buffer to find an "extra-timestamp" field. If one
! 9173: ** exists, extract the 32-bit modification-timestamp from it and store
! 9174: ** the value in output parameter *pmTime.
! 9175: **
! 9176: ** Zero is returned if no extra-timestamp record could be found (and so
! 9177: ** *pmTime is left unchanged), or non-zero otherwise.
! 9178: **
! 9179: ** The general format of an extra field is:
! 9180: **
! 9181: ** Header ID 2 bytes
! 9182: ** Data Size 2 bytes
! 9183: ** Data N bytes
! 9184: */
! 9185: static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){
! 9186: int ret = 0;
! 9187: u8 *p = aExtra;
! 9188: u8 *pEnd = &aExtra[nExtra];
! 9189:
! 9190: while( p<pEnd ){
! 9191: u16 id = zipfileRead16(p);
! 9192: u16 nByte = zipfileRead16(p);
! 9193:
! 9194: switch( id ){
! 9195: case ZIPFILE_EXTRA_TIMESTAMP: {
! 9196: u8 b = p[0];
! 9197: if( b & 0x01 ){ /* 0x01 -> modtime is present */
! 9198: *pmTime = zipfileGetU32(&p[1]);
! 9199: ret = 1;
! 9200: }
! 9201: break;
! 9202: }
! 9203: }
! 9204:
! 9205: p += nByte;
! 9206: }
! 9207: return ret;
! 9208: }
! 9209:
! 9210: /*
! 9211: ** Convert the standard MS-DOS timestamp stored in the mTime and mDate
! 9212: ** fields of the CDS structure passed as the only argument to a 32-bit
! 9213: ** UNIX seconds-since-the-epoch timestamp. Return the result.
! 9214: **
! 9215: ** "Standard" MS-DOS time format:
! 9216: **
! 9217: ** File modification time:
! 9218: ** Bits 00-04: seconds divided by 2
! 9219: ** Bits 05-10: minute
! 9220: ** Bits 11-15: hour
! 9221: ** File modification date:
! 9222: ** Bits 00-04: day
! 9223: ** Bits 05-08: month (1-12)
! 9224: ** Bits 09-15: years from 1980
! 9225: **
! 9226: ** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
! 9227: */
! 9228: static u32 zipfileMtime(ZipfileCDS *pCDS){
! 9229: int Y,M,D,X1,X2,A,B,sec,min,hr;
! 9230: i64 JDsec;
! 9231: Y = (1980 + ((pCDS->mDate >> 9) & 0x7F));
! 9232: M = ((pCDS->mDate >> 5) & 0x0F);
! 9233: D = (pCDS->mDate & 0x1F);
! 9234: sec = (pCDS->mTime & 0x1F)*2;
! 9235: min = (pCDS->mTime >> 5) & 0x3F;
! 9236: hr = (pCDS->mTime >> 11) & 0x1F;
! 9237: if( M<=2 ){
! 9238: Y--;
! 9239: M += 12;
! 9240: }
! 9241: X1 = 36525*(Y+4716)/100;
! 9242: X2 = 306001*(M+1)/10000;
! 9243: A = Y/100;
! 9244: B = 2 - A + (A/4);
! 9245: JDsec = (i64)((X1 + X2 + D + B - 1524.5)*86400) + hr*3600 + min*60 + sec;
! 9246: return (u32)(JDsec - (i64)24405875*(i64)8640);
! 9247: }
! 9248:
! 9249: /*
! 9250: ** The opposite of zipfileMtime(). This function populates the mTime and
! 9251: ** mDate fields of the CDS structure passed as the first argument according
! 9252: ** to the UNIX timestamp value passed as the second.
! 9253: */
! 9254: static void zipfileMtimeToDos(ZipfileCDS *pCds, u32 mUnixTime){
! 9255: /* Convert unix timestamp to JD (2440588 is noon on 1/1/1970) */
! 9256: i64 JD = (i64)2440588 + mUnixTime / (24*60*60);
! 9257:
! 9258: int A, B, C, D, E;
! 9259: int yr, mon, day;
! 9260: int hr, min, sec;
! 9261:
! 9262: A = (int)((JD - 1867216.25)/36524.25);
! 9263: A = (int)(JD + 1 + A - (A/4));
! 9264: B = A + 1524;
! 9265: C = (int)((B - 122.1)/365.25);
! 9266: D = (36525*(C&32767))/100;
! 9267: E = (int)((B-D)/30.6001);
! 9268:
! 9269: day = B - D - (int)(30.6001*E);
! 9270: mon = (E<14 ? E-1 : E-13);
! 9271: yr = mon>2 ? C-4716 : C-4715;
! 9272:
! 9273: hr = (mUnixTime % (24*60*60)) / (60*60);
! 9274: min = (mUnixTime % (60*60)) / 60;
! 9275: sec = (mUnixTime % 60);
! 9276:
! 9277: if( yr>=1980 ){
! 9278: pCds->mDate = (u16)(day + (mon << 5) + ((yr-1980) << 9));
! 9279: pCds->mTime = (u16)(sec/2 + (min<<5) + (hr<<11));
! 9280: }else{
! 9281: pCds->mDate = pCds->mTime = 0;
! 9282: }
! 9283:
! 9284: assert( mUnixTime<315507600
! 9285: || mUnixTime==zipfileMtime(pCds)
! 9286: || ((mUnixTime % 2) && mUnixTime-1==zipfileMtime(pCds))
! 9287: /* || (mUnixTime % 2) */
! 9288: );
! 9289: }
! 9290:
! 9291: /*
! 9292: ** If aBlob is not NULL, then it is a pointer to a buffer (nBlob bytes in
! 9293: ** size) containing an entire zip archive image. Or, if aBlob is NULL,
! 9294: ** then pFile is a file-handle open on a zip file. In either case, this
! 9295: ** function creates a ZipfileEntry object based on the zip archive entry
! 9296: ** for which the CDS record is at offset iOff.
! 9297: **
! 9298: ** If successful, SQLITE_OK is returned and (*ppEntry) set to point to
! 9299: ** the new object. Otherwise, an SQLite error code is returned and the
! 9300: ** final value of (*ppEntry) undefined.
! 9301: */
! 9302: static int zipfileGetEntry(
! 9303: ZipfileTab *pTab, /* Store any error message here */
! 9304: const u8 *aBlob, /* Pointer to in-memory file image */
! 9305: int nBlob, /* Size of aBlob[] in bytes */
! 9306: FILE *pFile, /* If aBlob==0, read from this file */
! 9307: i64 iOff, /* Offset of CDS record */
! 9308: ZipfileEntry **ppEntry /* OUT: Pointer to new object */
! 9309: ){
! 9310: u8 *aRead;
! 9311: char **pzErr = &pTab->base.zErrMsg;
! 9312: int rc = SQLITE_OK;
! 9313: (void)nBlob;
! 9314:
! 9315: if( aBlob==0 ){
! 9316: aRead = pTab->aBuffer;
! 9317: rc = zipfileReadData(pFile, aRead, ZIPFILE_CDS_FIXED_SZ, iOff, pzErr);
! 9318: }else{
! 9319: aRead = (u8*)&aBlob[iOff];
! 9320: }
! 9321:
! 9322: if( rc==SQLITE_OK ){
! 9323: sqlite3_int64 nAlloc;
! 9324: ZipfileEntry *pNew;
! 9325:
! 9326: int nFile = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF]);
! 9327: int nExtra = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+2]);
! 9328: nExtra += zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+4]);
! 9329:
! 9330: nAlloc = sizeof(ZipfileEntry) + nExtra;
! 9331: if( aBlob ){
! 9332: nAlloc += zipfileGetU32(&aRead[ZIPFILE_CDS_SZCOMPRESSED_OFF]);
! 9333: }
! 9334:
! 9335: pNew = (ZipfileEntry*)sqlite3_malloc64(nAlloc);
! 9336: if( pNew==0 ){
! 9337: rc = SQLITE_NOMEM;
! 9338: }else{
! 9339: memset(pNew, 0, sizeof(ZipfileEntry));
! 9340: rc = zipfileReadCDS(aRead, &pNew->cds);
! 9341: if( rc!=SQLITE_OK ){
! 9342: *pzErr = sqlite3_mprintf("failed to read CDS at offset %lld", iOff);
! 9343: }else if( aBlob==0 ){
! 9344: rc = zipfileReadData(
! 9345: pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr
! 9346: );
! 9347: }else{
! 9348: aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ];
! 9349: }
! 9350: }
! 9351:
! 9352: if( rc==SQLITE_OK ){
! 9353: u32 *pt = &pNew->mUnixTime;
! 9354: pNew->cds.zFile = sqlite3_mprintf("%.*s", nFile, aRead);
! 9355: pNew->aExtra = (u8*)&pNew[1];
! 9356: memcpy(pNew->aExtra, &aRead[nFile], nExtra);
! 9357: if( pNew->cds.zFile==0 ){
! 9358: rc = SQLITE_NOMEM;
! 9359: }else if( 0==zipfileScanExtra(&aRead[nFile], pNew->cds.nExtra, pt) ){
! 9360: pNew->mUnixTime = zipfileMtime(&pNew->cds);
! 9361: }
! 9362: }
! 9363:
! 9364: if( rc==SQLITE_OK ){
! 9365: static const int szFix = ZIPFILE_LFH_FIXED_SZ;
! 9366: ZipfileLFH lfh;
! 9367: if( pFile ){
! 9368: rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr);
! 9369: }else{
! 9370: aRead = (u8*)&aBlob[pNew->cds.iOffset];
! 9371: }
! 9372:
! 9373: if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh);
! 9374: if( rc==SQLITE_OK ){
! 9375: pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
! 9376: pNew->iDataOff += lfh.nFile + lfh.nExtra;
! 9377: if( aBlob && pNew->cds.szCompressed ){
! 9378: pNew->aData = &pNew->aExtra[nExtra];
! 9379: memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed);
! 9380: }
! 9381: }else{
! 9382: *pzErr = sqlite3_mprintf("failed to read LFH at offset %d",
! 9383: (int)pNew->cds.iOffset
! 9384: );
! 9385: }
! 9386: }
! 9387:
! 9388: if( rc!=SQLITE_OK ){
! 9389: zipfileEntryFree(pNew);
! 9390: }else{
! 9391: *ppEntry = pNew;
! 9392: }
! 9393: }
! 9394:
! 9395: return rc;
! 9396: }
! 9397:
! 9398: /*
! 9399: ** Advance an ZipfileCsr to its next row of output.
! 9400: */
! 9401: static int zipfileNext(sqlite3_vtab_cursor *cur){
! 9402: ZipfileCsr *pCsr = (ZipfileCsr*)cur;
! 9403: int rc = SQLITE_OK;
! 9404:
! 9405: if( pCsr->pFile ){
! 9406: i64 iEof = pCsr->eocd.iOffset + pCsr->eocd.nSize;
! 9407: zipfileEntryFree(pCsr->pCurrent);
! 9408: pCsr->pCurrent = 0;
! 9409: if( pCsr->iNextOff>=iEof ){
! 9410: pCsr->bEof = 1;
! 9411: }else{
! 9412: ZipfileEntry *p = 0;
! 9413: ZipfileTab *pTab = (ZipfileTab*)(cur->pVtab);
! 9414: rc = zipfileGetEntry(pTab, 0, 0, pCsr->pFile, pCsr->iNextOff, &p);
! 9415: if( rc==SQLITE_OK ){
! 9416: pCsr->iNextOff += ZIPFILE_CDS_FIXED_SZ;
! 9417: pCsr->iNextOff += (int)p->cds.nExtra + p->cds.nFile + p->cds.nComment;
! 9418: }
! 9419: pCsr->pCurrent = p;
! 9420: }
! 9421: }else{
! 9422: if( !pCsr->bNoop ){
! 9423: pCsr->pCurrent = pCsr->pCurrent->pNext;
! 9424: }
! 9425: if( pCsr->pCurrent==0 ){
! 9426: pCsr->bEof = 1;
! 9427: }
! 9428: }
! 9429:
! 9430: pCsr->bNoop = 0;
! 9431: return rc;
! 9432: }
! 9433:
! 9434: static void zipfileFree(void *p) {
! 9435: sqlite3_free(p);
! 9436: }
! 9437:
! 9438: /*
! 9439: ** Buffer aIn (size nIn bytes) contains compressed data. Uncompressed, the
! 9440: ** size is nOut bytes. This function uncompresses the data and sets the
! 9441: ** return value in context pCtx to the result (a blob).
! 9442: **
! 9443: ** If an error occurs, an error code is left in pCtx instead.
! 9444: */
! 9445: static void zipfileInflate(
! 9446: sqlite3_context *pCtx, /* Store result here */
! 9447: const u8 *aIn, /* Compressed data */
! 9448: int nIn, /* Size of buffer aIn[] in bytes */
! 9449: int nOut /* Expected output size */
! 9450: ){
! 9451: u8 *aRes = sqlite3_malloc(nOut);
! 9452: if( aRes==0 ){
! 9453: sqlite3_result_error_nomem(pCtx);
! 9454: }else{
! 9455: int err;
! 9456: z_stream str;
! 9457: memset(&str, 0, sizeof(str));
! 9458:
! 9459: str.next_in = (Byte*)aIn;
! 9460: str.avail_in = nIn;
! 9461: str.next_out = (Byte*)aRes;
! 9462: str.avail_out = nOut;
! 9463:
! 9464: err = inflateInit2(&str, -15);
! 9465: if( err!=Z_OK ){
! 9466: zipfileCtxErrorMsg(pCtx, "inflateInit2() failed (%d)", err);
! 9467: }else{
! 9468: err = inflate(&str, Z_NO_FLUSH);
! 9469: if( err!=Z_STREAM_END ){
! 9470: zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err);
! 9471: }else{
! 9472: sqlite3_result_blob(pCtx, aRes, nOut, zipfileFree);
! 9473: aRes = 0;
! 9474: }
! 9475: }
! 9476: sqlite3_free(aRes);
! 9477: inflateEnd(&str);
! 9478: }
! 9479: }
! 9480:
! 9481: /*
! 9482: ** Buffer aIn (size nIn bytes) contains uncompressed data. This function
! 9483: ** compresses it and sets (*ppOut) to point to a buffer containing the
! 9484: ** compressed data. The caller is responsible for eventually calling
! 9485: ** sqlite3_free() to release buffer (*ppOut). Before returning, (*pnOut)
! 9486: ** is set to the size of buffer (*ppOut) in bytes.
! 9487: **
! 9488: ** If no error occurs, SQLITE_OK is returned. Otherwise, an SQLite error
! 9489: ** code is returned and an error message left in virtual-table handle
! 9490: ** pTab. The values of (*ppOut) and (*pnOut) are left unchanged in this
! 9491: ** case.
! 9492: */
! 9493: static int zipfileDeflate(
! 9494: const u8 *aIn, int nIn, /* Input */
! 9495: u8 **ppOut, int *pnOut, /* Output */
! 9496: char **pzErr /* OUT: Error message */
! 9497: ){
! 9498: int rc = SQLITE_OK;
! 9499: sqlite3_int64 nAlloc;
! 9500: z_stream str;
! 9501: u8 *aOut;
! 9502:
! 9503: memset(&str, 0, sizeof(str));
! 9504: str.next_in = (Bytef*)aIn;
! 9505: str.avail_in = nIn;
! 9506: deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
! 9507:
! 9508: nAlloc = deflateBound(&str, nIn);
! 9509: aOut = (u8*)sqlite3_malloc64(nAlloc);
! 9510: if( aOut==0 ){
! 9511: rc = SQLITE_NOMEM;
! 9512: }else{
! 9513: int res;
! 9514: str.next_out = aOut;
! 9515: str.avail_out = nAlloc;
! 9516: res = deflate(&str, Z_FINISH);
! 9517: if( res==Z_STREAM_END ){
! 9518: *ppOut = aOut;
! 9519: *pnOut = (int)str.total_out;
! 9520: }else{
! 9521: sqlite3_free(aOut);
! 9522: *pzErr = sqlite3_mprintf("zipfile: deflate() error");
! 9523: rc = SQLITE_ERROR;
! 9524: }
! 9525: deflateEnd(&str);
! 9526: }
! 9527:
! 9528: return rc;
! 9529: }
! 9530:
! 9531:
! 9532: /*
! 9533: ** Return values of columns for the row at which the series_cursor
! 9534: ** is currently pointing.
! 9535: */
! 9536: static int zipfileColumn(
! 9537: sqlite3_vtab_cursor *cur, /* The cursor */
! 9538: sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
! 9539: int i /* Which column to return */
! 9540: ){
! 9541: ZipfileCsr *pCsr = (ZipfileCsr*)cur;
! 9542: ZipfileCDS *pCDS = &pCsr->pCurrent->cds;
! 9543: int rc = SQLITE_OK;
! 9544: switch( i ){
! 9545: case 0: /* name */
! 9546: sqlite3_result_text(ctx, pCDS->zFile, -1, SQLITE_TRANSIENT);
! 9547: break;
! 9548: case 1: /* mode */
! 9549: /* TODO: Whether or not the following is correct surely depends on
! 9550: ** the platform on which the archive was created. */
! 9551: sqlite3_result_int(ctx, pCDS->iExternalAttr >> 16);
! 9552: break;
! 9553: case 2: { /* mtime */
! 9554: sqlite3_result_int64(ctx, pCsr->pCurrent->mUnixTime);
! 9555: break;
! 9556: }
! 9557: case 3: { /* sz */
! 9558: if( sqlite3_vtab_nochange(ctx)==0 ){
! 9559: sqlite3_result_int64(ctx, pCDS->szUncompressed);
! 9560: }
! 9561: break;
! 9562: }
! 9563: case 4: /* rawdata */
! 9564: if( sqlite3_vtab_nochange(ctx) ) break;
! 9565: case 5: { /* data */
! 9566: if( i==4 || pCDS->iCompression==0 || pCDS->iCompression==8 ){
! 9567: int sz = pCDS->szCompressed;
! 9568: int szFinal = pCDS->szUncompressed;
! 9569: if( szFinal>0 ){
! 9570: u8 *aBuf;
! 9571: u8 *aFree = 0;
! 9572: if( pCsr->pCurrent->aData ){
! 9573: aBuf = pCsr->pCurrent->aData;
! 9574: }else{
! 9575: aBuf = aFree = sqlite3_malloc64(sz);
! 9576: if( aBuf==0 ){
! 9577: rc = SQLITE_NOMEM;
! 9578: }else{
! 9579: FILE *pFile = pCsr->pFile;
! 9580: if( pFile==0 ){
! 9581: pFile = ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd;
! 9582: }
! 9583: rc = zipfileReadData(pFile, aBuf, sz, pCsr->pCurrent->iDataOff,
! 9584: &pCsr->base.pVtab->zErrMsg
! 9585: );
! 9586: }
! 9587: }
! 9588: if( rc==SQLITE_OK ){
! 9589: if( i==5 && pCDS->iCompression ){
! 9590: zipfileInflate(ctx, aBuf, sz, szFinal);
! 9591: }else{
! 9592: sqlite3_result_blob(ctx, aBuf, sz, SQLITE_TRANSIENT);
! 9593: }
! 9594: }
! 9595: sqlite3_free(aFree);
! 9596: }else{
! 9597: /* Figure out if this is a directory or a zero-sized file. Consider
! 9598: ** it to be a directory either if the mode suggests so, or if
! 9599: ** the final character in the name is '/'. */
! 9600: u32 mode = pCDS->iExternalAttr >> 16;
! 9601: if( !(mode & S_IFDIR)
! 9602: && pCDS->nFile>=1
! 9603: && pCDS->zFile[pCDS->nFile-1]!='/'
! 9604: ){
! 9605: sqlite3_result_blob(ctx, "", 0, SQLITE_STATIC);
! 9606: }
! 9607: }
! 9608: }
! 9609: break;
! 9610: }
! 9611: case 6: /* method */
! 9612: sqlite3_result_int(ctx, pCDS->iCompression);
! 9613: break;
! 9614: default: /* z */
! 9615: assert( i==7 );
! 9616: sqlite3_result_int64(ctx, pCsr->iId);
! 9617: break;
! 9618: }
! 9619:
! 9620: return rc;
! 9621: }
! 9622:
! 9623: /*
! 9624: ** Return TRUE if the cursor is at EOF.
! 9625: */
! 9626: static int zipfileEof(sqlite3_vtab_cursor *cur){
! 9627: ZipfileCsr *pCsr = (ZipfileCsr*)cur;
! 9628: return pCsr->bEof;
! 9629: }
! 9630:
! 9631: /*
! 9632: ** If aBlob is not NULL, then it points to a buffer nBlob bytes in size
! 9633: ** containing an entire zip archive image. Or, if aBlob is NULL, then pFile
! 9634: ** is guaranteed to be a file-handle open on a zip file.
! 9635: **
! 9636: ** This function attempts to locate the EOCD record within the zip archive
! 9637: ** and populate *pEOCD with the results of decoding it. SQLITE_OK is
! 9638: ** returned if successful. Otherwise, an SQLite error code is returned and
! 9639: ** an English language error message may be left in virtual-table pTab.
! 9640: */
! 9641: static int zipfileReadEOCD(
! 9642: ZipfileTab *pTab, /* Return errors here */
! 9643: const u8 *aBlob, /* Pointer to in-memory file image */
! 9644: int nBlob, /* Size of aBlob[] in bytes */
! 9645: FILE *pFile, /* Read from this file if aBlob==0 */
! 9646: ZipfileEOCD *pEOCD /* Object to populate */
! 9647: ){
! 9648: u8 *aRead = pTab->aBuffer; /* Temporary buffer */
! 9649: int nRead; /* Bytes to read from file */
! 9650: int rc = SQLITE_OK;
! 9651:
! 9652: memset(pEOCD, 0, sizeof(ZipfileEOCD));
! 9653: if( aBlob==0 ){
! 9654: i64 iOff; /* Offset to read from */
! 9655: i64 szFile; /* Total size of file in bytes */
! 9656: fseek(pFile, 0, SEEK_END);
! 9657: szFile = (i64)ftell(pFile);
! 9658: if( szFile==0 ){
! 9659: return SQLITE_OK;
! 9660: }
! 9661: nRead = (int)(MIN(szFile, ZIPFILE_BUFFER_SIZE));
! 9662: iOff = szFile - nRead;
! 9663: rc = zipfileReadData(pFile, aRead, nRead, iOff, &pTab->base.zErrMsg);
! 9664: }else{
! 9665: nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE));
! 9666: aRead = (u8*)&aBlob[nBlob-nRead];
! 9667: }
! 9668:
! 9669: if( rc==SQLITE_OK ){
! 9670: int i;
! 9671:
! 9672: /* Scan backwards looking for the signature bytes */
! 9673: for(i=nRead-20; i>=0; i--){
! 9674: if( aRead[i]==0x50 && aRead[i+1]==0x4b
! 9675: && aRead[i+2]==0x05 && aRead[i+3]==0x06
! 9676: ){
! 9677: break;
! 9678: }
! 9679: }
! 9680: if( i<0 ){
! 9681: pTab->base.zErrMsg = sqlite3_mprintf(
! 9682: "cannot find end of central directory record"
! 9683: );
! 9684: return SQLITE_ERROR;
! 9685: }
! 9686:
! 9687: aRead += i+4;
! 9688: pEOCD->iDisk = zipfileRead16(aRead);
! 9689: pEOCD->iFirstDisk = zipfileRead16(aRead);
! 9690: pEOCD->nEntry = zipfileRead16(aRead);
! 9691: pEOCD->nEntryTotal = zipfileRead16(aRead);
! 9692: pEOCD->nSize = zipfileRead32(aRead);
! 9693: pEOCD->iOffset = zipfileRead32(aRead);
! 9694: }
! 9695:
! 9696: return rc;
! 9697: }
! 9698:
! 9699: /*
! 9700: ** Add object pNew to the linked list that begins at ZipfileTab.pFirstEntry
! 9701: ** and ends with pLastEntry. If argument pBefore is NULL, then pNew is added
! 9702: ** to the end of the list. Otherwise, it is added to the list immediately
! 9703: ** before pBefore (which is guaranteed to be a part of said list).
! 9704: */
! 9705: static void zipfileAddEntry(
! 9706: ZipfileTab *pTab,
! 9707: ZipfileEntry *pBefore,
! 9708: ZipfileEntry *pNew
! 9709: ){
! 9710: assert( (pTab->pFirstEntry==0)==(pTab->pLastEntry==0) );
! 9711: assert( pNew->pNext==0 );
! 9712: if( pBefore==0 ){
! 9713: if( pTab->pFirstEntry==0 ){
! 9714: pTab->pFirstEntry = pTab->pLastEntry = pNew;
! 9715: }else{
! 9716: assert( pTab->pLastEntry->pNext==0 );
! 9717: pTab->pLastEntry->pNext = pNew;
! 9718: pTab->pLastEntry = pNew;
! 9719: }
! 9720: }else{
! 9721: ZipfileEntry **pp;
! 9722: for(pp=&pTab->pFirstEntry; *pp!=pBefore; pp=&((*pp)->pNext));
! 9723: pNew->pNext = pBefore;
! 9724: *pp = pNew;
! 9725: }
! 9726: }
! 9727:
! 9728: static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, int nBlob){
! 9729: ZipfileEOCD eocd;
! 9730: int rc;
! 9731: int i;
! 9732: i64 iOff;
! 9733:
! 9734: rc = zipfileReadEOCD(pTab, aBlob, nBlob, pTab->pWriteFd, &eocd);
! 9735: iOff = eocd.iOffset;
! 9736: for(i=0; rc==SQLITE_OK && i<eocd.nEntry; i++){
! 9737: ZipfileEntry *pNew = 0;
! 9738: rc = zipfileGetEntry(pTab, aBlob, nBlob, pTab->pWriteFd, iOff, &pNew);
! 9739:
! 9740: if( rc==SQLITE_OK ){
! 9741: zipfileAddEntry(pTab, 0, pNew);
! 9742: iOff += ZIPFILE_CDS_FIXED_SZ;
! 9743: iOff += (int)pNew->cds.nExtra + pNew->cds.nFile + pNew->cds.nComment;
! 9744: }
! 9745: }
! 9746: return rc;
! 9747: }
! 9748:
! 9749: /*
! 9750: ** xFilter callback.
! 9751: */
! 9752: static int zipfileFilter(
! 9753: sqlite3_vtab_cursor *cur,
! 9754: int idxNum, const char *idxStr,
! 9755: int argc, sqlite3_value **argv
! 9756: ){
! 9757: ZipfileTab *pTab = (ZipfileTab*)cur->pVtab;
! 9758: ZipfileCsr *pCsr = (ZipfileCsr*)cur;
! 9759: const char *zFile = 0; /* Zip file to scan */
! 9760: int rc = SQLITE_OK; /* Return Code */
! 9761: int bInMemory = 0; /* True for an in-memory zipfile */
! 9762:
! 9763: (void)idxStr;
! 9764: (void)argc;
! 9765:
! 9766: zipfileResetCursor(pCsr);
! 9767:
! 9768: if( pTab->zFile ){
! 9769: zFile = pTab->zFile;
! 9770: }else if( idxNum==0 ){
! 9771: zipfileCursorErr(pCsr, "zipfile() function requires an argument");
! 9772: return SQLITE_ERROR;
! 9773: }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
! 9774: static const u8 aEmptyBlob = 0;
! 9775: const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
! 9776: int nBlob = sqlite3_value_bytes(argv[0]);
! 9777: assert( pTab->pFirstEntry==0 );
! 9778: if( aBlob==0 ){
! 9779: aBlob = &aEmptyBlob;
! 9780: nBlob = 0;
! 9781: }
! 9782: rc = zipfileLoadDirectory(pTab, aBlob, nBlob);
! 9783: pCsr->pFreeEntry = pTab->pFirstEntry;
! 9784: pTab->pFirstEntry = pTab->pLastEntry = 0;
! 9785: if( rc!=SQLITE_OK ) return rc;
! 9786: bInMemory = 1;
! 9787: }else{
! 9788: zFile = (const char*)sqlite3_value_text(argv[0]);
! 9789: }
! 9790:
! 9791: if( 0==pTab->pWriteFd && 0==bInMemory ){
! 9792: pCsr->pFile = zFile ? fopen(zFile, "rb") : 0;
! 9793: if( pCsr->pFile==0 ){
! 9794: zipfileCursorErr(pCsr, "cannot open file: %s", zFile);
! 9795: rc = SQLITE_ERROR;
! 9796: }else{
! 9797: rc = zipfileReadEOCD(pTab, 0, 0, pCsr->pFile, &pCsr->eocd);
! 9798: if( rc==SQLITE_OK ){
! 9799: if( pCsr->eocd.nEntry==0 ){
! 9800: pCsr->bEof = 1;
! 9801: }else{
! 9802: pCsr->iNextOff = pCsr->eocd.iOffset;
! 9803: rc = zipfileNext(cur);
! 9804: }
! 9805: }
! 9806: }
! 9807: }else{
! 9808: pCsr->bNoop = 1;
! 9809: pCsr->pCurrent = pCsr->pFreeEntry ? pCsr->pFreeEntry : pTab->pFirstEntry;
! 9810: rc = zipfileNext(cur);
! 9811: }
! 9812:
! 9813: return rc;
! 9814: }
! 9815:
! 9816: /*
! 9817: ** xBestIndex callback.
! 9818: */
! 9819: static int zipfileBestIndex(
! 9820: sqlite3_vtab *tab,
! 9821: sqlite3_index_info *pIdxInfo
! 9822: ){
! 9823: int i;
! 9824: int idx = -1;
! 9825: int unusable = 0;
! 9826: (void)tab;
! 9827:
! 9828: for(i=0; i<pIdxInfo->nConstraint; i++){
! 9829: const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
! 9830: if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue;
! 9831: if( pCons->usable==0 ){
! 9832: unusable = 1;
! 9833: }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
! 9834: idx = i;
! 9835: }
! 9836: }
! 9837: pIdxInfo->estimatedCost = 1000.0;
! 9838: if( idx>=0 ){
! 9839: pIdxInfo->aConstraintUsage[idx].argvIndex = 1;
! 9840: pIdxInfo->aConstraintUsage[idx].omit = 1;
! 9841: pIdxInfo->idxNum = 1;
! 9842: }else if( unusable ){
! 9843: return SQLITE_CONSTRAINT;
! 9844: }
! 9845: return SQLITE_OK;
! 9846: }
! 9847:
! 9848: static ZipfileEntry *zipfileNewEntry(const char *zPath){
! 9849: ZipfileEntry *pNew;
! 9850: pNew = sqlite3_malloc(sizeof(ZipfileEntry));
! 9851: if( pNew ){
! 9852: memset(pNew, 0, sizeof(ZipfileEntry));
! 9853: pNew->cds.zFile = sqlite3_mprintf("%s", zPath);
! 9854: if( pNew->cds.zFile==0 ){
! 9855: sqlite3_free(pNew);
! 9856: pNew = 0;
! 9857: }
! 9858: }
! 9859: return pNew;
! 9860: }
! 9861:
! 9862: static int zipfileSerializeLFH(ZipfileEntry *pEntry, u8 *aBuf){
! 9863: ZipfileCDS *pCds = &pEntry->cds;
! 9864: u8 *a = aBuf;
! 9865:
! 9866: pCds->nExtra = 9;
! 9867:
! 9868: /* Write the LFH itself */
! 9869: zipfileWrite32(a, ZIPFILE_SIGNATURE_LFH);
! 9870: zipfileWrite16(a, pCds->iVersionExtract);
! 9871: zipfileWrite16(a, pCds->flags);
! 9872: zipfileWrite16(a, pCds->iCompression);
! 9873: zipfileWrite16(a, pCds->mTime);
! 9874: zipfileWrite16(a, pCds->mDate);
! 9875: zipfileWrite32(a, pCds->crc32);
! 9876: zipfileWrite32(a, pCds->szCompressed);
! 9877: zipfileWrite32(a, pCds->szUncompressed);
! 9878: zipfileWrite16(a, (u16)pCds->nFile);
! 9879: zipfileWrite16(a, pCds->nExtra);
! 9880: assert( a==&aBuf[ZIPFILE_LFH_FIXED_SZ] );
! 9881:
! 9882: /* Add the file name */
! 9883: memcpy(a, pCds->zFile, (int)pCds->nFile);
! 9884: a += (int)pCds->nFile;
! 9885:
! 9886: /* The "extra" data */
! 9887: zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP);
! 9888: zipfileWrite16(a, 5);
! 9889: *a++ = 0x01;
! 9890: zipfileWrite32(a, pEntry->mUnixTime);
! 9891:
! 9892: return a-aBuf;
! 9893: }
! 9894:
! 9895: static int zipfileAppendEntry(
! 9896: ZipfileTab *pTab,
! 9897: ZipfileEntry *pEntry,
! 9898: const u8 *pData,
! 9899: int nData
! 9900: ){
! 9901: u8 *aBuf = pTab->aBuffer;
! 9902: int nBuf;
! 9903: int rc;
! 9904:
! 9905: nBuf = zipfileSerializeLFH(pEntry, aBuf);
! 9906: rc = zipfileAppendData(pTab, aBuf, nBuf);
! 9907: if( rc==SQLITE_OK ){
! 9908: pEntry->iDataOff = pTab->szCurrent;
! 9909: rc = zipfileAppendData(pTab, pData, nData);
! 9910: }
! 9911:
! 9912: return rc;
! 9913: }
! 9914:
! 9915: static int zipfileGetMode(
! 9916: sqlite3_value *pVal,
! 9917: int bIsDir, /* If true, default to directory */
! 9918: u32 *pMode, /* OUT: Mode value */
! 9919: char **pzErr /* OUT: Error message */
! 9920: ){
! 9921: const char *z = (const char*)sqlite3_value_text(pVal);
! 9922: u32 mode = 0;
! 9923: if( z==0 ){
! 9924: mode = (bIsDir ? (S_IFDIR + 0755) : (S_IFREG + 0644));
! 9925: }else if( z[0]>='0' && z[0]<='9' ){
! 9926: mode = (unsigned int)sqlite3_value_int(pVal);
! 9927: }else{
! 9928: const char zTemplate[11] = "-rwxrwxrwx";
! 9929: int i;
! 9930: if( strlen(z)!=10 ) goto parse_error;
! 9931: switch( z[0] ){
! 9932: case '-': mode |= S_IFREG; break;
! 9933: case 'd': mode |= S_IFDIR; break;
! 9934: case 'l': mode |= S_IFLNK; break;
! 9935: default: goto parse_error;
! 9936: }
! 9937: for(i=1; i<10; i++){
! 9938: if( z[i]==zTemplate[i] ) mode |= 1 << (9-i);
! 9939: else if( z[i]!='-' ) goto parse_error;
! 9940: }
! 9941: }
! 9942: if( ((mode & S_IFDIR)==0)==bIsDir ){
! 9943: /* The "mode" attribute is a directory, but data has been specified.
! 9944: ** Or vice-versa - no data but "mode" is a file or symlink. */
! 9945: *pzErr = sqlite3_mprintf("zipfile: mode does not match data");
! 9946: return SQLITE_CONSTRAINT;
! 9947: }
! 9948: *pMode = mode;
! 9949: return SQLITE_OK;
! 9950:
! 9951: parse_error:
! 9952: *pzErr = sqlite3_mprintf("zipfile: parse error in mode: %s", z);
! 9953: return SQLITE_ERROR;
! 9954: }
! 9955:
! 9956: /*
! 9957: ** Both (const char*) arguments point to nul-terminated strings. Argument
! 9958: ** nB is the value of strlen(zB). This function returns 0 if the strings are
! 9959: ** identical, ignoring any trailing '/' character in either path. */
! 9960: static int zipfileComparePath(const char *zA, const char *zB, int nB){
! 9961: int nA = (int)strlen(zA);
! 9962: if( nA>0 && zA[nA-1]=='/' ) nA--;
! 9963: if( nB>0 && zB[nB-1]=='/' ) nB--;
! 9964: if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
! 9965: return 1;
! 9966: }
! 9967:
! 9968: static int zipfileBegin(sqlite3_vtab *pVtab){
! 9969: ZipfileTab *pTab = (ZipfileTab*)pVtab;
! 9970: int rc = SQLITE_OK;
! 9971:
! 9972: assert( pTab->pWriteFd==0 );
! 9973: if( pTab->zFile==0 || pTab->zFile[0]==0 ){
! 9974: pTab->base.zErrMsg = sqlite3_mprintf("zipfile: missing filename");
! 9975: return SQLITE_ERROR;
! 9976: }
! 9977:
! 9978: /* Open a write fd on the file. Also load the entire central directory
! 9979: ** structure into memory. During the transaction any new file data is
! 9980: ** appended to the archive file, but the central directory is accumulated
! 9981: ** in main-memory until the transaction is committed. */
! 9982: pTab->pWriteFd = fopen(pTab->zFile, "ab+");
! 9983: if( pTab->pWriteFd==0 ){
! 9984: pTab->base.zErrMsg = sqlite3_mprintf(
! 9985: "zipfile: failed to open file %s for writing", pTab->zFile
! 9986: );
! 9987: rc = SQLITE_ERROR;
! 9988: }else{
! 9989: fseek(pTab->pWriteFd, 0, SEEK_END);
! 9990: pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd);
! 9991: rc = zipfileLoadDirectory(pTab, 0, 0);
! 9992: }
! 9993:
! 9994: if( rc!=SQLITE_OK ){
! 9995: zipfileCleanupTransaction(pTab);
! 9996: }
! 9997:
! 9998: return rc;
! 9999: }
! 10000:
! 10001: /*
! 10002: ** Return the current time as a 32-bit timestamp in UNIX epoch format (like
! 10003: ** time(2)).
! 10004: */
! 10005: static u32 zipfileTime(void){
! 10006: sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
! 10007: u32 ret;
! 10008: if( pVfs==0 ) return 0;
! 10009: if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
! 10010: i64 ms;
! 10011: pVfs->xCurrentTimeInt64(pVfs, &ms);
! 10012: ret = (u32)((ms/1000) - ((i64)24405875 * 8640));
! 10013: }else{
! 10014: double day;
! 10015: pVfs->xCurrentTime(pVfs, &day);
! 10016: ret = (u32)((day - 2440587.5) * 86400);
! 10017: }
! 10018: return ret;
! 10019: }
! 10020:
! 10021: /*
! 10022: ** Return a 32-bit timestamp in UNIX epoch format.
! 10023: **
! 10024: ** If the value passed as the only argument is either NULL or an SQL NULL,
! 10025: ** return the current time. Otherwise, return the value stored in (*pVal)
! 10026: ** cast to a 32-bit unsigned integer.
! 10027: */
! 10028: static u32 zipfileGetTime(sqlite3_value *pVal){
! 10029: if( pVal==0 || sqlite3_value_type(pVal)==SQLITE_NULL ){
! 10030: return zipfileTime();
! 10031: }
! 10032: return (u32)sqlite3_value_int64(pVal);
! 10033: }
! 10034:
! 10035: /*
! 10036: ** Unless it is NULL, entry pOld is currently part of the pTab->pFirstEntry
! 10037: ** linked list. Remove it from the list and free the object.
! 10038: */
! 10039: static void zipfileRemoveEntryFromList(ZipfileTab *pTab, ZipfileEntry *pOld){
! 10040: if( pOld ){
! 10041: if( pTab->pFirstEntry==pOld ){
! 10042: pTab->pFirstEntry = pOld->pNext;
! 10043: if( pTab->pLastEntry==pOld ) pTab->pLastEntry = 0;
! 10044: }else{
! 10045: ZipfileEntry *p;
! 10046: for(p=pTab->pFirstEntry; p; p=p->pNext){
! 10047: if( p->pNext==pOld ){
! 10048: p->pNext = pOld->pNext;
! 10049: if( pTab->pLastEntry==pOld ) pTab->pLastEntry = p;
! 10050: break;
! 10051: }
! 10052: }
! 10053: }
! 10054: zipfileEntryFree(pOld);
! 10055: }
! 10056: }
! 10057:
! 10058: /*
! 10059: ** xUpdate method.
! 10060: */
! 10061: static int zipfileUpdate(
! 10062: sqlite3_vtab *pVtab,
! 10063: int nVal,
! 10064: sqlite3_value **apVal,
! 10065: sqlite_int64 *pRowid
! 10066: ){
! 10067: ZipfileTab *pTab = (ZipfileTab*)pVtab;
! 10068: int rc = SQLITE_OK; /* Return Code */
! 10069: ZipfileEntry *pNew = 0; /* New in-memory CDS entry */
! 10070:
! 10071: u32 mode = 0; /* Mode for new entry */
! 10072: u32 mTime = 0; /* Modification time for new entry */
! 10073: i64 sz = 0; /* Uncompressed size */
! 10074: const char *zPath = 0; /* Path for new entry */
! 10075: int nPath = 0; /* strlen(zPath) */
! 10076: const u8 *pData = 0; /* Pointer to buffer containing content */
! 10077: int nData = 0; /* Size of pData buffer in bytes */
! 10078: int iMethod = 0; /* Compression method for new entry */
! 10079: u8 *pFree = 0; /* Free this */
! 10080: char *zFree = 0; /* Also free this */
! 10081: ZipfileEntry *pOld = 0;
! 10082: ZipfileEntry *pOld2 = 0;
! 10083: int bUpdate = 0; /* True for an update that modifies "name" */
! 10084: int bIsDir = 0;
! 10085: u32 iCrc32 = 0;
! 10086:
! 10087: (void)pRowid;
! 10088:
! 10089: if( pTab->pWriteFd==0 ){
! 10090: rc = zipfileBegin(pVtab);
! 10091: if( rc!=SQLITE_OK ) return rc;
! 10092: }
! 10093:
! 10094: /* If this is a DELETE or UPDATE, find the archive entry to delete. */
! 10095: if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
! 10096: const char *zDelete = (const char*)sqlite3_value_text(apVal[0]);
! 10097: int nDelete = (int)strlen(zDelete);
! 10098: if( nVal>1 ){
! 10099: const char *zUpdate = (const char*)sqlite3_value_text(apVal[1]);
! 10100: if( zUpdate && zipfileComparePath(zUpdate, zDelete, nDelete)!=0 ){
! 10101: bUpdate = 1;
! 10102: }
! 10103: }
! 10104: for(pOld=pTab->pFirstEntry; 1; pOld=pOld->pNext){
! 10105: if( zipfileComparePath(pOld->cds.zFile, zDelete, nDelete)==0 ){
! 10106: break;
! 10107: }
! 10108: assert( pOld->pNext );
! 10109: }
! 10110: }
! 10111:
! 10112: if( nVal>1 ){
! 10113: /* Check that "sz" and "rawdata" are both NULL: */
! 10114: if( sqlite3_value_type(apVal[5])!=SQLITE_NULL ){
! 10115: zipfileTableErr(pTab, "sz must be NULL");
! 10116: rc = SQLITE_CONSTRAINT;
! 10117: }
! 10118: if( sqlite3_value_type(apVal[6])!=SQLITE_NULL ){
! 10119: zipfileTableErr(pTab, "rawdata must be NULL");
! 10120: rc = SQLITE_CONSTRAINT;
! 10121: }
! 10122:
! 10123: if( rc==SQLITE_OK ){
! 10124: if( sqlite3_value_type(apVal[7])==SQLITE_NULL ){
! 10125: /* data=NULL. A directory */
! 10126: bIsDir = 1;
! 10127: }else{
! 10128: /* Value specified for "data", and possibly "method". This must be
! 10129: ** a regular file or a symlink. */
! 10130: const u8 *aIn = sqlite3_value_blob(apVal[7]);
! 10131: int nIn = sqlite3_value_bytes(apVal[7]);
! 10132: int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL;
! 10133:
! 10134: iMethod = sqlite3_value_int(apVal[8]);
! 10135: sz = nIn;
! 10136: pData = aIn;
! 10137: nData = nIn;
! 10138: if( iMethod!=0 && iMethod!=8 ){
! 10139: zipfileTableErr(pTab, "unknown compression method: %d", iMethod);
! 10140: rc = SQLITE_CONSTRAINT;
! 10141: }else{
! 10142: if( bAuto || iMethod ){
! 10143: int nCmp;
! 10144: rc = zipfileDeflate(aIn, nIn, &pFree, &nCmp, &pTab->base.zErrMsg);
! 10145: if( rc==SQLITE_OK ){
! 10146: if( iMethod || nCmp<nIn ){
! 10147: iMethod = 8;
! 10148: pData = pFree;
! 10149: nData = nCmp;
! 10150: }
! 10151: }
! 10152: }
! 10153: iCrc32 = crc32(0, aIn, nIn);
! 10154: }
! 10155: }
! 10156: }
! 10157:
! 10158: if( rc==SQLITE_OK ){
! 10159: rc = zipfileGetMode(apVal[3], bIsDir, &mode, &pTab->base.zErrMsg);
! 10160: }
! 10161:
! 10162: if( rc==SQLITE_OK ){
! 10163: zPath = (const char*)sqlite3_value_text(apVal[2]);
! 10164: if( zPath==0 ) zPath = "";
! 10165: nPath = (int)strlen(zPath);
! 10166: mTime = zipfileGetTime(apVal[4]);
! 10167: }
! 10168:
! 10169: if( rc==SQLITE_OK && bIsDir ){
! 10170: /* For a directory, check that the last character in the path is a
! 10171: ** '/'. This appears to be required for compatibility with info-zip
! 10172: ** (the unzip command on unix). It does not create directories
! 10173: ** otherwise. */
! 10174: if( nPath<=0 || zPath[nPath-1]!='/' ){
! 10175: zFree = sqlite3_mprintf("%s/", zPath);
! 10176: zPath = (const char*)zFree;
! 10177: if( zFree==0 ){
! 10178: rc = SQLITE_NOMEM;
! 10179: nPath = 0;
! 10180: }else{
! 10181: nPath = (int)strlen(zPath);
! 10182: }
! 10183: }
! 10184: }
! 10185:
! 10186: /* Check that we're not inserting a duplicate entry -OR- updating an
! 10187: ** entry with a path, thereby making it into a duplicate. */
! 10188: if( (pOld==0 || bUpdate) && rc==SQLITE_OK ){
! 10189: ZipfileEntry *p;
! 10190: for(p=pTab->pFirstEntry; p; p=p->pNext){
! 10191: if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){
! 10192: switch( sqlite3_vtab_on_conflict(pTab->db) ){
! 10193: case SQLITE_IGNORE: {
! 10194: goto zipfile_update_done;
! 10195: }
! 10196: case SQLITE_REPLACE: {
! 10197: pOld2 = p;
! 10198: break;
! 10199: }
! 10200: default: {
! 10201: zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath);
! 10202: rc = SQLITE_CONSTRAINT;
! 10203: break;
! 10204: }
! 10205: }
! 10206: break;
! 10207: }
! 10208: }
! 10209: }
! 10210:
! 10211: if( rc==SQLITE_OK ){
! 10212: /* Create the new CDS record. */
! 10213: pNew = zipfileNewEntry(zPath);
! 10214: if( pNew==0 ){
! 10215: rc = SQLITE_NOMEM;
! 10216: }else{
! 10217: pNew->cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
! 10218: pNew->cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
! 10219: pNew->cds.flags = ZIPFILE_NEWENTRY_FLAGS;
! 10220: pNew->cds.iCompression = (u16)iMethod;
! 10221: zipfileMtimeToDos(&pNew->cds, mTime);
! 10222: pNew->cds.crc32 = iCrc32;
! 10223: pNew->cds.szCompressed = nData;
! 10224: pNew->cds.szUncompressed = (u32)sz;
! 10225: pNew->cds.iExternalAttr = (mode<<16);
! 10226: pNew->cds.iOffset = (u32)pTab->szCurrent;
! 10227: pNew->cds.nFile = (u16)nPath;
! 10228: pNew->mUnixTime = (u32)mTime;
! 10229: rc = zipfileAppendEntry(pTab, pNew, pData, nData);
! 10230: zipfileAddEntry(pTab, pOld, pNew);
! 10231: }
! 10232: }
! 10233: }
! 10234:
! 10235: if( rc==SQLITE_OK && (pOld || pOld2) ){
! 10236: ZipfileCsr *pCsr;
! 10237: for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
! 10238: if( pCsr->pCurrent && (pCsr->pCurrent==pOld || pCsr->pCurrent==pOld2) ){
! 10239: pCsr->pCurrent = pCsr->pCurrent->pNext;
! 10240: pCsr->bNoop = 1;
! 10241: }
! 10242: }
! 10243:
! 10244: zipfileRemoveEntryFromList(pTab, pOld);
! 10245: zipfileRemoveEntryFromList(pTab, pOld2);
! 10246: }
! 10247:
! 10248: zipfile_update_done:
! 10249: sqlite3_free(pFree);
! 10250: sqlite3_free(zFree);
! 10251: return rc;
! 10252: }
! 10253:
! 10254: static int zipfileSerializeEOCD(ZipfileEOCD *p, u8 *aBuf){
! 10255: u8 *a = aBuf;
! 10256: zipfileWrite32(a, ZIPFILE_SIGNATURE_EOCD);
! 10257: zipfileWrite16(a, p->iDisk);
! 10258: zipfileWrite16(a, p->iFirstDisk);
! 10259: zipfileWrite16(a, p->nEntry);
! 10260: zipfileWrite16(a, p->nEntryTotal);
! 10261: zipfileWrite32(a, p->nSize);
! 10262: zipfileWrite32(a, p->iOffset);
! 10263: zipfileWrite16(a, 0); /* Size of trailing comment in bytes*/
! 10264:
! 10265: return a-aBuf;
! 10266: }
! 10267:
! 10268: static int zipfileAppendEOCD(ZipfileTab *pTab, ZipfileEOCD *p){
! 10269: int nBuf = zipfileSerializeEOCD(p, pTab->aBuffer);
! 10270: assert( nBuf==ZIPFILE_EOCD_FIXED_SZ );
! 10271: return zipfileAppendData(pTab, pTab->aBuffer, nBuf);
! 10272: }
1.5 misho 10273:
10274: /*
1.6.2.1 ! misho 10275: ** Serialize the CDS structure into buffer aBuf[]. Return the number
! 10276: ** of bytes written.
1.5 misho 10277: */
1.6.2.1 ! misho 10278: static int zipfileSerializeCDS(ZipfileEntry *pEntry, u8 *aBuf){
! 10279: u8 *a = aBuf;
! 10280: ZipfileCDS *pCDS = &pEntry->cds;
1.5 misho 10281:
1.6.2.1 ! misho 10282: if( pEntry->aExtra==0 ){
! 10283: pCDS->nExtra = 9;
! 10284: }
1.5 misho 10285:
1.6.2.1 ! misho 10286: zipfileWrite32(a, ZIPFILE_SIGNATURE_CDS);
! 10287: zipfileWrite16(a, pCDS->iVersionMadeBy);
! 10288: zipfileWrite16(a, pCDS->iVersionExtract);
! 10289: zipfileWrite16(a, pCDS->flags);
! 10290: zipfileWrite16(a, pCDS->iCompression);
! 10291: zipfileWrite16(a, pCDS->mTime);
! 10292: zipfileWrite16(a, pCDS->mDate);
! 10293: zipfileWrite32(a, pCDS->crc32);
! 10294: zipfileWrite32(a, pCDS->szCompressed);
! 10295: zipfileWrite32(a, pCDS->szUncompressed);
! 10296: assert( a==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
! 10297: zipfileWrite16(a, pCDS->nFile);
! 10298: zipfileWrite16(a, pCDS->nExtra);
! 10299: zipfileWrite16(a, pCDS->nComment);
! 10300: zipfileWrite16(a, pCDS->iDiskStart);
! 10301: zipfileWrite16(a, pCDS->iInternalAttr);
! 10302: zipfileWrite32(a, pCDS->iExternalAttr);
! 10303: zipfileWrite32(a, pCDS->iOffset);
1.5 misho 10304:
1.6.2.1 ! misho 10305: memcpy(a, pCDS->zFile, pCDS->nFile);
! 10306: a += pCDS->nFile;
1.5 misho 10307:
1.6.2.1 ! misho 10308: if( pEntry->aExtra ){
! 10309: int n = (int)pCDS->nExtra + (int)pCDS->nComment;
! 10310: memcpy(a, pEntry->aExtra, n);
! 10311: a += n;
! 10312: }else{
! 10313: assert( pCDS->nExtra==9 );
! 10314: zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP);
! 10315: zipfileWrite16(a, 5);
! 10316: *a++ = 0x01;
! 10317: zipfileWrite32(a, pEntry->mUnixTime);
! 10318: }
1.5 misho 10319:
1.6.2.1 ! misho 10320: return a-aBuf;
! 10321: }
1.5 misho 10322:
1.6.2.1 ! misho 10323: static int zipfileCommit(sqlite3_vtab *pVtab){
! 10324: ZipfileTab *pTab = (ZipfileTab*)pVtab;
! 10325: int rc = SQLITE_OK;
! 10326: if( pTab->pWriteFd ){
! 10327: i64 iOffset = pTab->szCurrent;
! 10328: ZipfileEntry *p;
! 10329: ZipfileEOCD eocd;
! 10330: int nEntry = 0;
1.5 misho 10331:
1.6.2.1 ! misho 10332: /* Write out all entries */
! 10333: for(p=pTab->pFirstEntry; rc==SQLITE_OK && p; p=p->pNext){
! 10334: int n = zipfileSerializeCDS(p, pTab->aBuffer);
! 10335: rc = zipfileAppendData(pTab, pTab->aBuffer, n);
! 10336: nEntry++;
! 10337: }
! 10338:
! 10339: /* Write out the EOCD record */
! 10340: eocd.iDisk = 0;
! 10341: eocd.iFirstDisk = 0;
! 10342: eocd.nEntry = (u16)nEntry;
! 10343: eocd.nEntryTotal = (u16)nEntry;
! 10344: eocd.nSize = (u32)(pTab->szCurrent - iOffset);
! 10345: eocd.iOffset = (u32)iOffset;
! 10346: rc = zipfileAppendEOCD(pTab, &eocd);
! 10347:
! 10348: zipfileCleanupTransaction(pTab);
! 10349: }
! 10350: return rc;
! 10351: }
! 10352:
! 10353: static int zipfileRollback(sqlite3_vtab *pVtab){
! 10354: return zipfileCommit(pVtab);
! 10355: }
! 10356:
! 10357: static ZipfileCsr *zipfileFindCursor(ZipfileTab *pTab, i64 iId){
! 10358: ZipfileCsr *pCsr;
! 10359: for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
! 10360: if( iId==pCsr->iId ) break;
! 10361: }
! 10362: return pCsr;
! 10363: }
! 10364:
! 10365: static void zipfileFunctionCds(
! 10366: sqlite3_context *context,
! 10367: int argc,
! 10368: sqlite3_value **argv
! 10369: ){
! 10370: ZipfileCsr *pCsr;
! 10371: ZipfileTab *pTab = (ZipfileTab*)sqlite3_user_data(context);
! 10372: assert( argc>0 );
! 10373:
! 10374: pCsr = zipfileFindCursor(pTab, sqlite3_value_int64(argv[0]));
! 10375: if( pCsr ){
! 10376: ZipfileCDS *p = &pCsr->pCurrent->cds;
! 10377: char *zRes = sqlite3_mprintf("{"
! 10378: "\"version-made-by\" : %u, "
! 10379: "\"version-to-extract\" : %u, "
! 10380: "\"flags\" : %u, "
! 10381: "\"compression\" : %u, "
! 10382: "\"time\" : %u, "
! 10383: "\"date\" : %u, "
! 10384: "\"crc32\" : %u, "
! 10385: "\"compressed-size\" : %u, "
! 10386: "\"uncompressed-size\" : %u, "
! 10387: "\"file-name-length\" : %u, "
! 10388: "\"extra-field-length\" : %u, "
! 10389: "\"file-comment-length\" : %u, "
! 10390: "\"disk-number-start\" : %u, "
! 10391: "\"internal-attr\" : %u, "
! 10392: "\"external-attr\" : %u, "
! 10393: "\"offset\" : %u }",
! 10394: (u32)p->iVersionMadeBy, (u32)p->iVersionExtract,
! 10395: (u32)p->flags, (u32)p->iCompression,
! 10396: (u32)p->mTime, (u32)p->mDate,
! 10397: (u32)p->crc32, (u32)p->szCompressed,
! 10398: (u32)p->szUncompressed, (u32)p->nFile,
! 10399: (u32)p->nExtra, (u32)p->nComment,
! 10400: (u32)p->iDiskStart, (u32)p->iInternalAttr,
! 10401: (u32)p->iExternalAttr, (u32)p->iOffset
! 10402: );
! 10403:
! 10404: if( zRes==0 ){
! 10405: sqlite3_result_error_nomem(context);
! 10406: }else{
! 10407: sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
! 10408: sqlite3_free(zRes);
! 10409: }
! 10410: }
! 10411: }
1.5 misho 10412:
10413: /*
1.6.2.1 ! misho 10414: ** xFindFunction method.
1.5 misho 10415: */
1.6.2.1 ! misho 10416: static int zipfileFindFunction(
! 10417: sqlite3_vtab *pVtab, /* Virtual table handle */
! 10418: int nArg, /* Number of SQL function arguments */
! 10419: const char *zName, /* Name of SQL function */
! 10420: void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
! 10421: void **ppArg /* OUT: User data for *pxFunc */
! 10422: ){
! 10423: (void)nArg;
! 10424: if( sqlite3_stricmp("zipfile_cds", zName)==0 ){
! 10425: *pxFunc = zipfileFunctionCds;
! 10426: *ppArg = (void*)pVtab;
! 10427: return 1;
! 10428: }
! 10429: return 0;
1.5 misho 10430: }
10431:
1.6.2.1 ! misho 10432: typedef struct ZipfileBuffer ZipfileBuffer;
! 10433: struct ZipfileBuffer {
! 10434: u8 *a; /* Pointer to buffer */
! 10435: int n; /* Size of buffer in bytes */
! 10436: int nAlloc; /* Byte allocated at a[] */
! 10437: };
! 10438:
! 10439: typedef struct ZipfileCtx ZipfileCtx;
! 10440: struct ZipfileCtx {
! 10441: int nEntry;
! 10442: ZipfileBuffer body;
! 10443: ZipfileBuffer cds;
! 10444: };
! 10445:
! 10446: static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){
! 10447: if( pBuf->n+nByte>pBuf->nAlloc ){
! 10448: u8 *aNew;
! 10449: sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512;
! 10450: int nReq = pBuf->n + nByte;
! 10451:
! 10452: while( nNew<nReq ) nNew = nNew*2;
! 10453: aNew = sqlite3_realloc64(pBuf->a, nNew);
! 10454: if( aNew==0 ) return SQLITE_NOMEM;
! 10455: pBuf->a = aNew;
! 10456: pBuf->nAlloc = (int)nNew;
1.5 misho 10457: }
1.6.2.1 ! misho 10458: return SQLITE_OK;
1.5 misho 10459: }
10460:
10461: /*
1.6.2.1 ! misho 10462: ** xStep() callback for the zipfile() aggregate. This can be called in
! 10463: ** any of the following ways:
! 10464: **
! 10465: ** SELECT zipfile(name,data) ...
! 10466: ** SELECT zipfile(name,mode,mtime,data) ...
! 10467: ** SELECT zipfile(name,mode,mtime,data,method) ...
1.5 misho 10468: */
1.6.2.1 ! misho 10469: static void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
! 10470: ZipfileCtx *p; /* Aggregate function context */
! 10471: ZipfileEntry e; /* New entry to add to zip archive */
1.5 misho 10472:
1.6.2.1 ! misho 10473: sqlite3_value *pName = 0;
! 10474: sqlite3_value *pMode = 0;
! 10475: sqlite3_value *pMtime = 0;
! 10476: sqlite3_value *pData = 0;
! 10477: sqlite3_value *pMethod = 0;
1.5 misho 10478:
1.6.2.1 ! misho 10479: int bIsDir = 0;
! 10480: u32 mode;
! 10481: int rc = SQLITE_OK;
! 10482: char *zErr = 0;
1.5 misho 10483:
1.6.2.1 ! misho 10484: int iMethod = -1; /* Compression method to use (0 or 8) */
! 10485:
! 10486: const u8 *aData = 0; /* Possibly compressed data for new entry */
! 10487: int nData = 0; /* Size of aData[] in bytes */
! 10488: int szUncompressed = 0; /* Size of data before compression */
! 10489: u8 *aFree = 0; /* Free this before returning */
! 10490: u32 iCrc32 = 0; /* crc32 of uncompressed data */
! 10491:
! 10492: char *zName = 0; /* Path (name) of new entry */
! 10493: int nName = 0; /* Size of zName in bytes */
! 10494: char *zFree = 0; /* Free this before returning */
! 10495: int nByte;
! 10496:
! 10497: memset(&e, 0, sizeof(e));
! 10498: p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
! 10499: if( p==0 ) return;
! 10500:
! 10501: /* Martial the arguments into stack variables */
! 10502: if( nVal!=2 && nVal!=4 && nVal!=5 ){
! 10503: zErr = sqlite3_mprintf("wrong number of arguments to function zipfile()");
! 10504: rc = SQLITE_ERROR;
! 10505: goto zipfile_step_out;
! 10506: }
! 10507: pName = apVal[0];
! 10508: if( nVal==2 ){
! 10509: pData = apVal[1];
! 10510: }else{
! 10511: pMode = apVal[1];
! 10512: pMtime = apVal[2];
! 10513: pData = apVal[3];
! 10514: if( nVal==5 ){
! 10515: pMethod = apVal[4];
1.5 misho 10516: }
10517: }
10518:
1.6.2.1 ! misho 10519: /* Check that the 'name' parameter looks ok. */
! 10520: zName = (char*)sqlite3_value_text(pName);
! 10521: nName = sqlite3_value_bytes(pName);
! 10522: if( zName==0 ){
! 10523: zErr = sqlite3_mprintf("first argument to zipfile() must be non-NULL");
! 10524: rc = SQLITE_ERROR;
! 10525: goto zipfile_step_out;
1.5 misho 10526: }
10527:
1.6.2.1 ! misho 10528: /* Inspect the 'method' parameter. This must be either 0 (store), 8 (use
! 10529: ** deflate compression) or NULL (choose automatically). */
! 10530: if( pMethod && SQLITE_NULL!=sqlite3_value_type(pMethod) ){
! 10531: iMethod = (int)sqlite3_value_int64(pMethod);
! 10532: if( iMethod!=0 && iMethod!=8 ){
! 10533: zErr = sqlite3_mprintf("illegal method value: %d", iMethod);
! 10534: rc = SQLITE_ERROR;
! 10535: goto zipfile_step_out;
! 10536: }
1.5 misho 10537: }
1.6.2.1 ! misho 10538:
! 10539: /* Now inspect the data. If this is NULL, then the new entry must be a
! 10540: ** directory. Otherwise, figure out whether or not the data should
! 10541: ** be deflated or simply stored in the zip archive. */
! 10542: if( sqlite3_value_type(pData)==SQLITE_NULL ){
! 10543: bIsDir = 1;
! 10544: iMethod = 0;
! 10545: }else{
! 10546: aData = sqlite3_value_blob(pData);
! 10547: szUncompressed = nData = sqlite3_value_bytes(pData);
! 10548: iCrc32 = crc32(0, aData, nData);
! 10549: if( iMethod<0 || iMethod==8 ){
! 10550: int nOut = 0;
! 10551: rc = zipfileDeflate(aData, nData, &aFree, &nOut, &zErr);
! 10552: if( rc!=SQLITE_OK ){
! 10553: goto zipfile_step_out;
! 10554: }
! 10555: if( iMethod==8 || nOut<nData ){
! 10556: aData = aFree;
! 10557: nData = nOut;
! 10558: iMethod = 8;
! 10559: }else{
! 10560: iMethod = 0;
! 10561: }
! 10562: }
1.5 misho 10563: }
10564:
1.6.2.1 ! misho 10565: /* Decode the "mode" argument. */
! 10566: rc = zipfileGetMode(pMode, bIsDir, &mode, &zErr);
! 10567: if( rc ) goto zipfile_step_out;
1.5 misho 10568:
1.6.2.1 ! misho 10569: /* Decode the "mtime" argument. */
! 10570: e.mUnixTime = zipfileGetTime(pMtime);
! 10571:
! 10572: /* If this is a directory entry, ensure that there is exactly one '/'
! 10573: ** at the end of the path. Or, if this is not a directory and the path
! 10574: ** ends in '/' it is an error. */
! 10575: if( bIsDir==0 ){
! 10576: if( nName>0 && zName[nName-1]=='/' ){
! 10577: zErr = sqlite3_mprintf("non-directory name must not end with /");
! 10578: rc = SQLITE_ERROR;
! 10579: goto zipfile_step_out;
! 10580: }
! 10581: }else{
! 10582: if( nName==0 || zName[nName-1]!='/' ){
! 10583: zName = zFree = sqlite3_mprintf("%s/", zName);
! 10584: if( zName==0 ){
! 10585: rc = SQLITE_NOMEM;
! 10586: goto zipfile_step_out;
! 10587: }
! 10588: nName = (int)strlen(zName);
! 10589: }else{
! 10590: while( nName>1 && zName[nName-2]=='/' ) nName--;
! 10591: }
1.5 misho 10592: }
10593:
1.6.2.1 ! misho 10594: /* Assemble the ZipfileEntry object for the new zip archive entry */
! 10595: e.cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
! 10596: e.cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
! 10597: e.cds.flags = ZIPFILE_NEWENTRY_FLAGS;
! 10598: e.cds.iCompression = (u16)iMethod;
! 10599: zipfileMtimeToDos(&e.cds, (u32)e.mUnixTime);
! 10600: e.cds.crc32 = iCrc32;
! 10601: e.cds.szCompressed = nData;
! 10602: e.cds.szUncompressed = szUncompressed;
! 10603: e.cds.iExternalAttr = (mode<<16);
! 10604: e.cds.iOffset = p->body.n;
! 10605: e.cds.nFile = (u16)nName;
! 10606: e.cds.zFile = zName;
! 10607:
! 10608: /* Append the LFH to the body of the new archive */
! 10609: nByte = ZIPFILE_LFH_FIXED_SZ + e.cds.nFile + 9;
! 10610: if( (rc = zipfileBufferGrow(&p->body, nByte)) ) goto zipfile_step_out;
! 10611: p->body.n += zipfileSerializeLFH(&e, &p->body.a[p->body.n]);
1.5 misho 10612:
1.6.2.1 ! misho 10613: /* Append the data to the body of the new archive */
! 10614: if( nData>0 ){
! 10615: if( (rc = zipfileBufferGrow(&p->body, nData)) ) goto zipfile_step_out;
! 10616: memcpy(&p->body.a[p->body.n], aData, nData);
! 10617: p->body.n += nData;
1.5 misho 10618: }
10619:
1.6.2.1 ! misho 10620: /* Append the CDS record to the directory of the new archive */
! 10621: nByte = ZIPFILE_CDS_FIXED_SZ + e.cds.nFile + 9;
! 10622: if( (rc = zipfileBufferGrow(&p->cds, nByte)) ) goto zipfile_step_out;
! 10623: p->cds.n += zipfileSerializeCDS(&e, &p->cds.a[p->cds.n]);
! 10624:
! 10625: /* Increment the count of entries in the archive */
! 10626: p->nEntry++;
! 10627:
! 10628: zipfile_step_out:
! 10629: sqlite3_free(aFree);
! 10630: sqlite3_free(zFree);
! 10631: if( rc ){
! 10632: if( zErr ){
! 10633: sqlite3_result_error(pCtx, zErr, -1);
! 10634: }else{
! 10635: sqlite3_result_error_code(pCtx, rc);
! 10636: }
1.5 misho 10637: }
1.6.2.1 ! misho 10638: sqlite3_free(zErr);
1.5 misho 10639: }
10640:
10641: /*
1.6.2.1 ! misho 10642: ** xFinalize() callback for zipfile aggregate function.
1.5 misho 10643: */
1.6.2.1 ! misho 10644: static void zipfileFinal(sqlite3_context *pCtx){
! 10645: ZipfileCtx *p;
! 10646: ZipfileEOCD eocd;
! 10647: sqlite3_int64 nZip;
! 10648: u8 *aZip;
1.5 misho 10649:
1.6.2.1 ! misho 10650: p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
! 10651: if( p==0 ) return;
! 10652: if( p->nEntry>0 ){
! 10653: memset(&eocd, 0, sizeof(eocd));
! 10654: eocd.nEntry = (u16)p->nEntry;
! 10655: eocd.nEntryTotal = (u16)p->nEntry;
! 10656: eocd.nSize = p->cds.n;
! 10657: eocd.iOffset = p->body.n;
1.5 misho 10658:
1.6.2.1 ! misho 10659: nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ;
! 10660: aZip = (u8*)sqlite3_malloc64(nZip);
! 10661: if( aZip==0 ){
! 10662: sqlite3_result_error_nomem(pCtx);
! 10663: }else{
! 10664: memcpy(aZip, p->body.a, p->body.n);
! 10665: memcpy(&aZip[p->body.n], p->cds.a, p->cds.n);
! 10666: zipfileSerializeEOCD(&eocd, &aZip[p->body.n + p->cds.n]);
! 10667: sqlite3_result_blob(pCtx, aZip, (int)nZip, zipfileFree);
! 10668: }
! 10669: }
1.5 misho 10670:
1.6.2.1 ! misho 10671: sqlite3_free(p->body.a);
! 10672: sqlite3_free(p->cds.a);
1.5 misho 10673: }
10674:
1.6.2.1 ! misho 10675:
1.5 misho 10676: /*
1.6.2.1 ! misho 10677: ** Register the "zipfile" virtual table.
1.5 misho 10678: */
1.6.2.1 ! misho 10679: static int zipfileRegister(sqlite3 *db){
! 10680: static sqlite3_module zipfileModule = {
! 10681: 1, /* iVersion */
! 10682: zipfileConnect, /* xCreate */
! 10683: zipfileConnect, /* xConnect */
! 10684: zipfileBestIndex, /* xBestIndex */
! 10685: zipfileDisconnect, /* xDisconnect */
! 10686: zipfileDisconnect, /* xDestroy */
! 10687: zipfileOpen, /* xOpen - open a cursor */
! 10688: zipfileClose, /* xClose - close a cursor */
! 10689: zipfileFilter, /* xFilter - configure scan constraints */
! 10690: zipfileNext, /* xNext - advance a cursor */
! 10691: zipfileEof, /* xEof - check for end of scan */
! 10692: zipfileColumn, /* xColumn - read data */
! 10693: 0, /* xRowid - read data */
! 10694: zipfileUpdate, /* xUpdate */
! 10695: zipfileBegin, /* xBegin */
! 10696: 0, /* xSync */
! 10697: zipfileCommit, /* xCommit */
! 10698: zipfileRollback, /* xRollback */
! 10699: zipfileFindFunction, /* xFindMethod */
! 10700: 0, /* xRename */
! 10701: 0, /* xSavepoint */
! 10702: 0, /* xRelease */
! 10703: 0, /* xRollback */
! 10704: 0 /* xShadowName */
! 10705: };
! 10706:
! 10707: int rc = sqlite3_create_module(db, "zipfile" , &zipfileModule, 0);
! 10708: if( rc==SQLITE_OK ) rc = sqlite3_overload_function(db, "zipfile_cds", -1);
! 10709: if( rc==SQLITE_OK ){
! 10710: rc = sqlite3_create_function(db, "zipfile", -1, SQLITE_UTF8, 0, 0,
! 10711: zipfileStep, zipfileFinal
! 10712: );
1.5 misho 10713: }
1.6.2.1 ! misho 10714: assert( sizeof(i64)==8 );
! 10715: assert( sizeof(u32)==4 );
! 10716: assert( sizeof(u16)==2 );
! 10717: assert( sizeof(u8)==1 );
! 10718: return rc;
1.5 misho 10719: }
1.6.2.1 ! misho 10720: #else /* SQLITE_OMIT_VIRTUALTABLE */
! 10721: # define zipfileRegister(x) SQLITE_OK
! 10722: #endif
1.5 misho 10723:
1.6.2.1 ! misho 10724: #ifdef _WIN32
! 10725:
! 10726: #endif
! 10727: int sqlite3_zipfile_init(
! 10728: sqlite3 *db,
! 10729: char **pzErrMsg,
! 10730: const sqlite3_api_routines *pApi
1.5 misho 10731: ){
1.6.2.1 ! misho 10732: SQLITE_EXTENSION_INIT2(pApi);
! 10733: (void)pzErrMsg; /* Unused parameter */
! 10734: return zipfileRegister(db);
1.5 misho 10735: }
10736:
1.6.2.1 ! misho 10737: /************************* End ../ext/misc/zipfile.c ********************/
! 10738: /************************* Begin ../ext/misc/sqlar.c ******************/
1.5 misho 10739: /*
1.6.2.1 ! misho 10740: ** 2017-12-17
! 10741: **
! 10742: ** The author disclaims copyright to this source code. In place of
! 10743: ** a legal notice, here is a blessing:
! 10744: **
! 10745: ** May you do good and not evil.
! 10746: ** May you find forgiveness for yourself and forgive others.
! 10747: ** May you share freely, never taking more than you give.
! 10748: **
! 10749: ******************************************************************************
! 10750: **
! 10751: ** Utility functions sqlar_compress() and sqlar_uncompress(). Useful
! 10752: ** for working with sqlar archives and used by the shell tool's built-in
! 10753: ** sqlar support.
1.5 misho 10754: */
1.6.2.1 ! misho 10755: /* #include "sqlite3ext.h" */
! 10756: SQLITE_EXTENSION_INIT1
! 10757: #include <zlib.h>
! 10758: #include <assert.h>
1.5 misho 10759:
10760: /*
1.6.2.1 ! misho 10761: ** Implementation of the "sqlar_compress(X)" SQL function.
! 10762: **
! 10763: ** If the type of X is SQLITE_BLOB, and compressing that blob using
! 10764: ** zlib utility function compress() yields a smaller blob, return the
! 10765: ** compressed blob. Otherwise, return a copy of X.
! 10766: **
! 10767: ** SQLar uses the "zlib format" for compressed content. The zlib format
! 10768: ** contains a two-byte identification header and a four-byte checksum at
! 10769: ** the end. This is different from ZIP which uses the raw deflate format.
! 10770: **
! 10771: ** Future enhancements to SQLar might add support for new compression formats.
! 10772: ** If so, those new formats will be identified by alternative headers in the
! 10773: ** compressed data.
1.5 misho 10774: */
1.6.2.1 ! misho 10775: static void sqlarCompressFunc(
! 10776: sqlite3_context *context,
! 10777: int argc,
! 10778: sqlite3_value **argv
! 10779: ){
! 10780: assert( argc==1 );
! 10781: if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
! 10782: const Bytef *pData = sqlite3_value_blob(argv[0]);
! 10783: uLong nData = sqlite3_value_bytes(argv[0]);
! 10784: uLongf nOut = compressBound(nData);
! 10785: Bytef *pOut;
! 10786:
! 10787: pOut = (Bytef*)sqlite3_malloc(nOut);
! 10788: if( pOut==0 ){
! 10789: sqlite3_result_error_nomem(context);
! 10790: return;
! 10791: }else{
! 10792: if( Z_OK!=compress(pOut, &nOut, pData, nData) ){
! 10793: sqlite3_result_error(context, "error in compress()", -1);
! 10794: }else if( nOut<nData ){
! 10795: sqlite3_result_blob(context, pOut, nOut, SQLITE_TRANSIENT);
! 10796: }else{
! 10797: sqlite3_result_value(context, argv[0]);
! 10798: }
! 10799: sqlite3_free(pOut);
! 10800: }
! 10801: }else{
! 10802: sqlite3_result_value(context, argv[0]);
! 10803: }
1.5 misho 10804: }
10805:
10806: /*
1.6.2.1 ! misho 10807: ** Implementation of the "sqlar_uncompress(X,SZ)" SQL function
! 10808: **
! 10809: ** Parameter SZ is interpreted as an integer. If it is less than or
! 10810: ** equal to zero, then this function returns a copy of X. Or, if
! 10811: ** SZ is equal to the size of X when interpreted as a blob, also
! 10812: ** return a copy of X. Otherwise, decompress blob X using zlib
! 10813: ** utility function uncompress() and return the results (another
! 10814: ** blob).
1.5 misho 10815: */
1.6.2.1 ! misho 10816: static void sqlarUncompressFunc(
! 10817: sqlite3_context *context,
! 10818: int argc,
! 10819: sqlite3_value **argv
! 10820: ){
! 10821: uLong nData;
! 10822: uLongf sz;
1.5 misho 10823:
1.6.2.1 ! misho 10824: assert( argc==2 );
! 10825: sz = sqlite3_value_int(argv[1]);
! 10826:
! 10827: if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){
! 10828: sqlite3_result_value(context, argv[0]);
! 10829: }else{
! 10830: const Bytef *pData= sqlite3_value_blob(argv[0]);
! 10831: Bytef *pOut = sqlite3_malloc(sz);
! 10832: if( pOut==0 ){
! 10833: sqlite3_result_error_nomem(context);
! 10834: }else if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){
! 10835: sqlite3_result_error(context, "error in uncompress()", -1);
! 10836: }else{
! 10837: sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT);
! 10838: }
! 10839: sqlite3_free(pOut);
! 10840: }
1.5 misho 10841: }
10842:
1.6.2.1 ! misho 10843: #ifdef _WIN32
1.5 misho 10844:
1.6.2.1 ! misho 10845: #endif
! 10846: int sqlite3_sqlar_init(
! 10847: sqlite3 *db,
! 10848: char **pzErrMsg,
! 10849: const sqlite3_api_routines *pApi
! 10850: ){
! 10851: int rc = SQLITE_OK;
! 10852: SQLITE_EXTENSION_INIT2(pApi);
! 10853: (void)pzErrMsg; /* Unused parameter */
! 10854: rc = sqlite3_create_function(db, "sqlar_compress", 1,
! 10855: SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
! 10856: sqlarCompressFunc, 0, 0);
! 10857: if( rc==SQLITE_OK ){
! 10858: rc = sqlite3_create_function(db, "sqlar_uncompress", 2,
! 10859: SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
! 10860: sqlarUncompressFunc, 0, 0);
! 10861: }
! 10862: return rc;
! 10863: }
1.5 misho 10864:
1.6.2.1 ! misho 10865: /************************* End ../ext/misc/sqlar.c ********************/
! 10866: #endif
! 10867: /************************* Begin ../ext/expert/sqlite3expert.h ******************/
1.5 misho 10868: /*
1.6.2.1 ! misho 10869: ** 2017 April 07
! 10870: **
! 10871: ** The author disclaims copyright to this source code. In place of
! 10872: ** a legal notice, here is a blessing:
! 10873: **
! 10874: ** May you do good and not evil.
! 10875: ** May you find forgiveness for yourself and forgive others.
! 10876: ** May you share freely, never taking more than you give.
! 10877: **
! 10878: *************************************************************************
1.5 misho 10879: */
1.6.2.1 ! misho 10880: #if !defined(SQLITEEXPERT_H)
! 10881: #define SQLITEEXPERT_H 1
! 10882: /* #include "sqlite3.h" */
! 10883:
! 10884: typedef struct sqlite3expert sqlite3expert;
1.5 misho 10885:
10886: /*
1.6.2.1 ! misho 10887: ** Create a new sqlite3expert object.
! 10888: **
! 10889: ** If successful, a pointer to the new object is returned and (*pzErr) set
! 10890: ** to NULL. Or, if an error occurs, NULL is returned and (*pzErr) set to
! 10891: ** an English-language error message. In this case it is the responsibility
! 10892: ** of the caller to eventually free the error message buffer using
! 10893: ** sqlite3_free().
1.5 misho 10894: */
1.6.2.1 ! misho 10895: sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErr);
1.5 misho 10896:
10897: /*
1.6.2.1 ! misho 10898: ** Configure an sqlite3expert object.
! 10899: **
! 10900: ** EXPERT_CONFIG_SAMPLE:
! 10901: ** By default, sqlite3_expert_analyze() generates sqlite_stat1 data for
! 10902: ** each candidate index. This involves scanning and sorting the entire
! 10903: ** contents of each user database table once for each candidate index
! 10904: ** associated with the table. For large databases, this can be
! 10905: ** prohibitively slow. This option allows the sqlite3expert object to
! 10906: ** be configured so that sqlite_stat1 data is instead generated based on a
! 10907: ** subset of each table, or so that no sqlite_stat1 data is used at all.
! 10908: **
! 10909: ** A single integer argument is passed to this option. If the value is less
! 10910: ** than or equal to zero, then no sqlite_stat1 data is generated or used by
! 10911: ** the analysis - indexes are recommended based on the database schema only.
! 10912: ** Or, if the value is 100 or greater, complete sqlite_stat1 data is
! 10913: ** generated for each candidate index (this is the default). Finally, if the
! 10914: ** value falls between 0 and 100, then it represents the percentage of user
! 10915: ** table rows that should be considered when generating sqlite_stat1 data.
! 10916: **
! 10917: ** Examples:
! 10918: **
! 10919: ** // Do not generate any sqlite_stat1 data
! 10920: ** sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 0);
! 10921: **
! 10922: ** // Generate sqlite_stat1 data based on 10% of the rows in each table.
! 10923: ** sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 10);
1.5 misho 10924: */
1.6.2.1 ! misho 10925: int sqlite3_expert_config(sqlite3expert *p, int op, ...);
1.5 misho 10926:
1.6.2.1 ! misho 10927: #define EXPERT_CONFIG_SAMPLE 1 /* int */
1.5 misho 10928:
10929: /*
1.6.2.1 ! misho 10930: ** Specify zero or more SQL statements to be included in the analysis.
1.5 misho 10931: **
1.6.2.1 ! misho 10932: ** Buffer zSql must contain zero or more complete SQL statements. This
! 10933: ** function parses all statements contained in the buffer and adds them
! 10934: ** to the internal list of statements to analyze. If successful, SQLITE_OK
! 10935: ** is returned and (*pzErr) set to NULL. Or, if an error occurs - for example
! 10936: ** due to a error in the SQL - an SQLite error code is returned and (*pzErr)
! 10937: ** may be set to point to an English language error message. In this case
! 10938: ** the caller is responsible for eventually freeing the error message buffer
! 10939: ** using sqlite3_free().
1.5 misho 10940: **
1.6.2.1 ! misho 10941: ** If an error does occur while processing one of the statements in the
! 10942: ** buffer passed as the second argument, none of the statements in the
! 10943: ** buffer are added to the analysis.
1.5 misho 10944: **
1.6.2.1 ! misho 10945: ** This function must be called before sqlite3_expert_analyze(). If a call
! 10946: ** to this function is made on an sqlite3expert object that has already
! 10947: ** been passed to sqlite3_expert_analyze() SQLITE_MISUSE is returned
! 10948: ** immediately and no statements are added to the analysis.
1.5 misho 10949: */
1.6.2.1 ! misho 10950: int sqlite3_expert_sql(
! 10951: sqlite3expert *p, /* From a successful sqlite3_expert_new() */
! 10952: const char *zSql, /* SQL statement(s) to add */
! 10953: char **pzErr /* OUT: Error message (if any) */
! 10954: );
1.5 misho 10955:
10956:
1.6.2.1 ! misho 10957: /*
! 10958: ** This function is called after the sqlite3expert object has been configured
! 10959: ** with all SQL statements using sqlite3_expert_sql() to actually perform
! 10960: ** the analysis. Once this function has been called, it is not possible to
! 10961: ** add further SQL statements to the analysis.
! 10962: **
! 10963: ** If successful, SQLITE_OK is returned and (*pzErr) is set to NULL. Or, if
! 10964: ** an error occurs, an SQLite error code is returned and (*pzErr) set to
! 10965: ** point to a buffer containing an English language error message. In this
! 10966: ** case it is the responsibility of the caller to eventually free the buffer
! 10967: ** using sqlite3_free().
! 10968: **
! 10969: ** If an error does occur within this function, the sqlite3expert object
! 10970: ** is no longer useful for any purpose. At that point it is no longer
! 10971: ** possible to add further SQL statements to the object or to re-attempt
! 10972: ** the analysis. The sqlite3expert object must still be freed using a call
! 10973: ** sqlite3_expert_destroy().
! 10974: */
! 10975: int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr);
1.5 misho 10976:
1.6.2.1 ! misho 10977: /*
! 10978: ** Return the total number of statements loaded using sqlite3_expert_sql().
! 10979: ** The total number of SQL statements may be different from the total number
! 10980: ** to calls to sqlite3_expert_sql().
! 10981: */
! 10982: int sqlite3_expert_count(sqlite3expert*);
1.5 misho 10983:
10984: /*
1.6.2.1 ! misho 10985: ** Return a component of the report.
1.5 misho 10986: **
1.6.2.1 ! misho 10987: ** This function is called after sqlite3_expert_analyze() to extract the
! 10988: ** results of the analysis. Each call to this function returns either a
! 10989: ** NULL pointer or a pointer to a buffer containing a nul-terminated string.
! 10990: ** The value passed as the third argument must be one of the EXPERT_REPORT_*
! 10991: ** #define constants defined below.
1.5 misho 10992: **
1.6.2.1 ! misho 10993: ** For some EXPERT_REPORT_* parameters, the buffer returned contains
! 10994: ** information relating to a specific SQL statement. In these cases that
! 10995: ** SQL statement is identified by the value passed as the second argument.
! 10996: ** SQL statements are numbered from 0 in the order in which they are parsed.
! 10997: ** If an out-of-range value (less than zero or equal to or greater than the
! 10998: ** value returned by sqlite3_expert_count()) is passed as the second argument
! 10999: ** along with such an EXPERT_REPORT_* parameter, NULL is always returned.
1.5 misho 11000: **
1.6.2.1 ! misho 11001: ** EXPERT_REPORT_SQL:
! 11002: ** Return the text of SQL statement iStmt.
! 11003: **
! 11004: ** EXPERT_REPORT_INDEXES:
! 11005: ** Return a buffer containing the CREATE INDEX statements for all recommended
! 11006: ** indexes for statement iStmt. If there are no new recommeded indexes, NULL
! 11007: ** is returned.
! 11008: **
! 11009: ** EXPERT_REPORT_PLAN:
! 11010: ** Return a buffer containing the EXPLAIN QUERY PLAN output for SQL query
! 11011: ** iStmt after the proposed indexes have been added to the database schema.
! 11012: **
! 11013: ** EXPERT_REPORT_CANDIDATES:
! 11014: ** Return a pointer to a buffer containing the CREATE INDEX statements
! 11015: ** for all indexes that were tested (for all SQL statements). The iStmt
! 11016: ** parameter is ignored for EXPERT_REPORT_CANDIDATES calls.
1.5 misho 11017: */
1.6.2.1 ! misho 11018: const char *sqlite3_expert_report(sqlite3expert*, int iStmt, int eReport);
1.5 misho 11019:
11020: /*
1.6.2.1 ! misho 11021: ** Values for the third argument passed to sqlite3_expert_report().
1.5 misho 11022: */
1.6.2.1 ! misho 11023: #define EXPERT_REPORT_SQL 1
! 11024: #define EXPERT_REPORT_INDEXES 2
! 11025: #define EXPERT_REPORT_PLAN 3
! 11026: #define EXPERT_REPORT_CANDIDATES 4
1.5 misho 11027:
1.6.2.1 ! misho 11028: /*
! 11029: ** Free an (sqlite3expert*) handle and all associated resources. There
! 11030: ** should be one call to this function for each successful call to
! 11031: ** sqlite3-expert_new().
! 11032: */
! 11033: void sqlite3_expert_destroy(sqlite3expert*);
1.5 misho 11034:
1.6.2.1 ! misho 11035: #endif /* !defined(SQLITEEXPERT_H) */
1.5 misho 11036:
1.6.2.1 ! misho 11037: /************************* End ../ext/expert/sqlite3expert.h ********************/
! 11038: /************************* Begin ../ext/expert/sqlite3expert.c ******************/
1.5 misho 11039: /*
1.6.2.1 ! misho 11040: ** 2017 April 09
1.5 misho 11041: **
1.6.2.1 ! misho 11042: ** The author disclaims copyright to this source code. In place of
! 11043: ** a legal notice, here is a blessing:
! 11044: **
! 11045: ** May you do good and not evil.
! 11046: ** May you find forgiveness for yourself and forgive others.
! 11047: ** May you share freely, never taking more than you give.
! 11048: **
! 11049: *************************************************************************
1.5 misho 11050: */
1.6.2.1 ! misho 11051: /* #include "sqlite3expert.h" */
! 11052: #include <assert.h>
! 11053: #include <string.h>
! 11054: #include <stdio.h>
1.5 misho 11055:
1.6.2.1 ! misho 11056: #if !defined(SQLITE_AMALGAMATION)
! 11057: #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
! 11058: # define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
! 11059: #endif
! 11060: #if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
! 11061: # define ALWAYS(X) (1)
! 11062: # define NEVER(X) (0)
! 11063: #elif !defined(NDEBUG)
! 11064: # define ALWAYS(X) ((X)?1:(assert(0),0))
! 11065: # define NEVER(X) ((X)?(assert(0),1):0)
! 11066: #else
! 11067: # define ALWAYS(X) (X)
! 11068: # define NEVER(X) (X)
! 11069: #endif
! 11070: #endif /* !defined(SQLITE_AMALGAMATION) */
1.5 misho 11071:
11072:
1.6.2.1 ! misho 11073: #ifndef SQLITE_OMIT_VIRTUALTABLE
1.5 misho 11074:
1.6.2.1 ! misho 11075: /* typedef sqlite3_int64 i64; */
! 11076: /* typedef sqlite3_uint64 u64; */
1.5 misho 11077:
1.6.2.1 ! misho 11078: typedef struct IdxColumn IdxColumn;
! 11079: typedef struct IdxConstraint IdxConstraint;
! 11080: typedef struct IdxScan IdxScan;
! 11081: typedef struct IdxStatement IdxStatement;
! 11082: typedef struct IdxTable IdxTable;
! 11083: typedef struct IdxWrite IdxWrite;
1.5 misho 11084:
1.6.2.1 ! misho 11085: #define STRLEN (int)strlen
1.5 misho 11086:
11087: /*
1.6.2.1 ! misho 11088: ** A temp table name that we assume no user database will actually use.
! 11089: ** If this assumption proves incorrect triggers on the table with the
! 11090: ** conflicting name will be ignored.
1.5 misho 11091: */
1.6.2.1 ! misho 11092: #define UNIQUE_TABLE_NAME "t592690916721053953805701627921227776"
1.5 misho 11093:
11094: /*
1.6.2.1 ! misho 11095: ** A single constraint. Equivalent to either "col = ?" or "col < ?" (or
! 11096: ** any other type of single-ended range constraint on a column).
1.5 misho 11097: **
1.6.2.1 ! misho 11098: ** pLink:
! 11099: ** Used to temporarily link IdxConstraint objects into lists while
! 11100: ** creating candidate indexes.
1.5 misho 11101: */
1.6.2.1 ! misho 11102: struct IdxConstraint {
! 11103: char *zColl; /* Collation sequence */
! 11104: int bRange; /* True for range, false for eq */
! 11105: int iCol; /* Constrained table column */
! 11106: int bFlag; /* Used by idxFindCompatible() */
! 11107: int bDesc; /* True if ORDER BY <expr> DESC */
! 11108: IdxConstraint *pNext; /* Next constraint in pEq or pRange list */
! 11109: IdxConstraint *pLink; /* See above */
! 11110: };
1.5 misho 11111:
1.6.2.1 ! misho 11112: /*
! 11113: ** A single scan of a single table.
! 11114: */
! 11115: struct IdxScan {
! 11116: IdxTable *pTab; /* Associated table object */
! 11117: int iDb; /* Database containing table zTable */
! 11118: i64 covering; /* Mask of columns required for cov. index */
! 11119: IdxConstraint *pOrder; /* ORDER BY columns */
! 11120: IdxConstraint *pEq; /* List of == constraints */
! 11121: IdxConstraint *pRange; /* List of < constraints */
! 11122: IdxScan *pNextScan; /* Next IdxScan object for same analysis */
! 11123: };
1.5 misho 11124:
1.6.2.1 ! misho 11125: /*
! 11126: ** Information regarding a single database table. Extracted from
! 11127: ** "PRAGMA table_info" by function idxGetTableInfo().
! 11128: */
! 11129: struct IdxColumn {
! 11130: char *zName;
! 11131: char *zColl;
! 11132: int iPk;
! 11133: };
! 11134: struct IdxTable {
! 11135: int nCol;
! 11136: char *zName; /* Table name */
! 11137: IdxColumn *aCol;
! 11138: IdxTable *pNext; /* Next table in linked list of all tables */
! 11139: };
1.5 misho 11140:
1.6.2.1 ! misho 11141: /*
! 11142: ** An object of the following type is created for each unique table/write-op
! 11143: ** seen. The objects are stored in a singly-linked list beginning at
! 11144: ** sqlite3expert.pWrite.
! 11145: */
! 11146: struct IdxWrite {
! 11147: IdxTable *pTab;
! 11148: int eOp; /* SQLITE_UPDATE, DELETE or INSERT */
! 11149: IdxWrite *pNext;
! 11150: };
! 11151:
! 11152: /*
! 11153: ** Each statement being analyzed is represented by an instance of this
! 11154: ** structure.
! 11155: */
! 11156: struct IdxStatement {
! 11157: int iId; /* Statement number */
! 11158: char *zSql; /* SQL statement */
! 11159: char *zIdx; /* Indexes */
! 11160: char *zEQP; /* Plan */
! 11161: IdxStatement *pNext;
! 11162: };
1.5 misho 11163:
11164:
11165: /*
1.6.2.1 ! misho 11166: ** A hash table for storing strings. With space for a payload string
! 11167: ** with each entry. Methods are:
! 11168: **
! 11169: ** idxHashInit()
! 11170: ** idxHashClear()
! 11171: ** idxHashAdd()
! 11172: ** idxHashSearch()
1.5 misho 11173: */
1.6.2.1 ! misho 11174: #define IDX_HASH_SIZE 1023
! 11175: typedef struct IdxHashEntry IdxHashEntry;
! 11176: typedef struct IdxHash IdxHash;
! 11177: struct IdxHashEntry {
! 11178: char *zKey; /* nul-terminated key */
! 11179: char *zVal; /* nul-terminated value string */
! 11180: char *zVal2; /* nul-terminated value string 2 */
! 11181: IdxHashEntry *pHashNext; /* Next entry in same hash bucket */
! 11182: IdxHashEntry *pNext; /* Next entry in hash */
! 11183: };
! 11184: struct IdxHash {
! 11185: IdxHashEntry *pFirst;
! 11186: IdxHashEntry *aHash[IDX_HASH_SIZE];
! 11187: };
! 11188:
! 11189: /*
! 11190: ** sqlite3expert object.
! 11191: */
! 11192: struct sqlite3expert {
! 11193: int iSample; /* Percentage of tables to sample for stat1 */
! 11194: sqlite3 *db; /* User database */
! 11195: sqlite3 *dbm; /* In-memory db for this analysis */
! 11196: sqlite3 *dbv; /* Vtab schema for this analysis */
! 11197: IdxTable *pTable; /* List of all IdxTable objects */
! 11198: IdxScan *pScan; /* List of scan objects */
! 11199: IdxWrite *pWrite; /* List of write objects */
! 11200: IdxStatement *pStatement; /* List of IdxStatement objects */
! 11201: int bRun; /* True once analysis has run */
! 11202: char **pzErrmsg;
! 11203: int rc; /* Error code from whereinfo hook */
! 11204: IdxHash hIdx; /* Hash containing all candidate indexes */
! 11205: char *zCandidates; /* For EXPERT_REPORT_CANDIDATES */
! 11206: };
1.5 misho 11207:
11208:
11209: /*
1.6.2.1 ! misho 11210: ** Allocate and return nByte bytes of zeroed memory using sqlite3_malloc().
! 11211: ** If the allocation fails, set *pRc to SQLITE_NOMEM and return NULL.
1.5 misho 11212: */
1.6.2.1 ! misho 11213: static void *idxMalloc(int *pRc, int nByte){
! 11214: void *pRet;
! 11215: assert( *pRc==SQLITE_OK );
! 11216: assert( nByte>0 );
! 11217: pRet = sqlite3_malloc(nByte);
! 11218: if( pRet ){
! 11219: memset(pRet, 0, nByte);
! 11220: }else{
! 11221: *pRc = SQLITE_NOMEM;
! 11222: }
! 11223: return pRet;
1.5 misho 11224: }
11225:
11226: /*
1.6.2.1 ! misho 11227: ** Initialize an IdxHash hash table.
1.5 misho 11228: */
1.6.2.1 ! misho 11229: static void idxHashInit(IdxHash *pHash){
! 11230: memset(pHash, 0, sizeof(IdxHash));
! 11231: }
1.5 misho 11232:
1.6.2.1 ! misho 11233: /*
! 11234: ** Reset an IdxHash hash table.
! 11235: */
! 11236: static void idxHashClear(IdxHash *pHash){
! 11237: int i;
! 11238: for(i=0; i<IDX_HASH_SIZE; i++){
! 11239: IdxHashEntry *pEntry;
! 11240: IdxHashEntry *pNext;
! 11241: for(pEntry=pHash->aHash[i]; pEntry; pEntry=pNext){
! 11242: pNext = pEntry->pHashNext;
! 11243: sqlite3_free(pEntry->zVal2);
! 11244: sqlite3_free(pEntry);
1.5 misho 11245: }
11246: }
1.6.2.1 ! misho 11247: memset(pHash, 0, sizeof(IdxHash));
! 11248: }
1.5 misho 11249:
1.6.2.1 ! misho 11250: /*
! 11251: ** Return the index of the hash bucket that the string specified by the
! 11252: ** arguments to this function belongs.
! 11253: */
! 11254: static int idxHashString(const char *z, int n){
! 11255: unsigned int ret = 0;
! 11256: int i;
! 11257: for(i=0; i<n; i++){
! 11258: ret += (ret<<3) + (unsigned char)(z[i]);
! 11259: }
! 11260: return (int)(ret % IDX_HASH_SIZE);
! 11261: }
1.5 misho 11262:
1.6.2.1 ! misho 11263: /*
! 11264: ** If zKey is already present in the hash table, return non-zero and do
! 11265: ** nothing. Otherwise, add an entry with key zKey and payload string zVal to
! 11266: ** the hash table passed as the second argument.
! 11267: */
! 11268: static int idxHashAdd(
! 11269: int *pRc,
! 11270: IdxHash *pHash,
! 11271: const char *zKey,
! 11272: const char *zVal
! 11273: ){
! 11274: int nKey = STRLEN(zKey);
! 11275: int iHash = idxHashString(zKey, nKey);
! 11276: int nVal = (zVal ? STRLEN(zVal) : 0);
! 11277: IdxHashEntry *pEntry;
! 11278: assert( iHash>=0 );
! 11279: for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){
! 11280: if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){
! 11281: return 1;
1.5 misho 11282: }
1.6.2.1 ! misho 11283: }
! 11284: pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + nKey+1 + nVal+1);
! 11285: if( pEntry ){
! 11286: pEntry->zKey = (char*)&pEntry[1];
! 11287: memcpy(pEntry->zKey, zKey, nKey);
! 11288: if( zVal ){
! 11289: pEntry->zVal = &pEntry->zKey[nKey+1];
! 11290: memcpy(pEntry->zVal, zVal, nVal);
1.5 misho 11291: }
1.6.2.1 ! misho 11292: pEntry->pHashNext = pHash->aHash[iHash];
! 11293: pHash->aHash[iHash] = pEntry;
1.5 misho 11294:
1.6.2.1 ! misho 11295: pEntry->pNext = pHash->pFirst;
! 11296: pHash->pFirst = pEntry;
1.5 misho 11297: }
1.6.2.1 ! misho 11298: return 0;
1.5 misho 11299: }
11300:
11301: /*
1.6.2.1 ! misho 11302: ** If zKey/nKey is present in the hash table, return a pointer to the
! 11303: ** hash-entry object.
1.5 misho 11304: */
1.6.2.1 ! misho 11305: static IdxHashEntry *idxHashFind(IdxHash *pHash, const char *zKey, int nKey){
! 11306: int iHash;
! 11307: IdxHashEntry *pEntry;
! 11308: if( nKey<0 ) nKey = STRLEN(zKey);
! 11309: iHash = idxHashString(zKey, nKey);
! 11310: assert( iHash>=0 );
! 11311: for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){
! 11312: if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){
! 11313: return pEntry;
1.5 misho 11314: }
11315: }
1.6.2.1 ! misho 11316: return 0;
1.5 misho 11317: }
11318:
1.6.2.1 ! misho 11319: /*
! 11320: ** If the hash table contains an entry with a key equal to the string
! 11321: ** passed as the final two arguments to this function, return a pointer
! 11322: ** to the payload string. Otherwise, if zKey/nKey is not present in the
! 11323: ** hash table, return NULL.
! 11324: */
! 11325: static const char *idxHashSearch(IdxHash *pHash, const char *zKey, int nKey){
! 11326: IdxHashEntry *pEntry = idxHashFind(pHash, zKey, nKey);
! 11327: if( pEntry ) return pEntry->zVal;
! 11328: return 0;
! 11329: }
1.5 misho 11330:
1.6.2.1 ! misho 11331: /*
! 11332: ** Allocate and return a new IdxConstraint object. Set the IdxConstraint.zColl
! 11333: ** variable to point to a copy of nul-terminated string zColl.
! 11334: */
! 11335: static IdxConstraint *idxNewConstraint(int *pRc, const char *zColl){
! 11336: IdxConstraint *pNew;
! 11337: int nColl = STRLEN(zColl);
1.5 misho 11338:
1.6.2.1 ! misho 11339: assert( *pRc==SQLITE_OK );
! 11340: pNew = (IdxConstraint*)idxMalloc(pRc, sizeof(IdxConstraint) * nColl + 1);
! 11341: if( pNew ){
! 11342: pNew->zColl = (char*)&pNew[1];
! 11343: memcpy(pNew->zColl, zColl, nColl+1);
! 11344: }
! 11345: return pNew;
! 11346: }
! 11347:
! 11348: /*
! 11349: ** An error associated with database handle db has just occurred. Pass
! 11350: ** the error message to callback function xOut.
! 11351: */
! 11352: static void idxDatabaseError(
! 11353: sqlite3 *db, /* Database handle */
! 11354: char **pzErrmsg /* Write error here */
! 11355: ){
! 11356: *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db));
! 11357: }
! 11358:
! 11359: /*
! 11360: ** Prepare an SQL statement.
! 11361: */
! 11362: static int idxPrepareStmt(
! 11363: sqlite3 *db, /* Database handle to compile against */
! 11364: sqlite3_stmt **ppStmt, /* OUT: Compiled SQL statement */
! 11365: char **pzErrmsg, /* OUT: sqlite3_malloc()ed error message */
! 11366: const char *zSql /* SQL statement to compile */
! 11367: ){
! 11368: int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
! 11369: if( rc!=SQLITE_OK ){
! 11370: *ppStmt = 0;
! 11371: idxDatabaseError(db, pzErrmsg);
1.5 misho 11372: }
11373: return rc;
11374: }
11375:
11376: /*
1.6.2.1 ! misho 11377: ** Prepare an SQL statement using the results of a printf() formatting.
1.5 misho 11378: */
1.6.2.1 ! misho 11379: static int idxPrintfPrepareStmt(
! 11380: sqlite3 *db, /* Database handle to compile against */
! 11381: sqlite3_stmt **ppStmt, /* OUT: Compiled SQL statement */
! 11382: char **pzErrmsg, /* OUT: sqlite3_malloc()ed error message */
! 11383: const char *zFmt, /* printf() format of SQL statement */
! 11384: ... /* Trailing printf() arguments */
1.5 misho 11385: ){
1.6.2.1 ! misho 11386: va_list ap;
! 11387: int rc;
! 11388: char *zSql;
! 11389: va_start(ap, zFmt);
! 11390: zSql = sqlite3_vmprintf(zFmt, ap);
! 11391: if( zSql==0 ){
! 11392: rc = SQLITE_NOMEM;
1.5 misho 11393: }else{
1.6.2.1 ! misho 11394: rc = idxPrepareStmt(db, ppStmt, pzErrmsg, zSql);
! 11395: sqlite3_free(zSql);
1.5 misho 11396: }
1.6.2.1 ! misho 11397: va_end(ap);
! 11398: return rc;
! 11399: }
1.5 misho 11400:
1.6.2.1 ! misho 11401:
! 11402: /*************************************************************************
! 11403: ** Beginning of virtual table implementation.
! 11404: */
! 11405: typedef struct ExpertVtab ExpertVtab;
! 11406: struct ExpertVtab {
! 11407: sqlite3_vtab base;
! 11408: IdxTable *pTab;
! 11409: sqlite3expert *pExpert;
! 11410: };
! 11411:
! 11412: typedef struct ExpertCsr ExpertCsr;
! 11413: struct ExpertCsr {
! 11414: sqlite3_vtab_cursor base;
! 11415: sqlite3_stmt *pData;
! 11416: };
! 11417:
! 11418: static char *expertDequote(const char *zIn){
! 11419: int n = STRLEN(zIn);
! 11420: char *zRet = sqlite3_malloc(n);
! 11421:
! 11422: assert( zIn[0]=='\'' );
! 11423: assert( zIn[n-1]=='\'' );
! 11424:
! 11425: if( zRet ){
! 11426: int iOut = 0;
! 11427: int iIn = 0;
! 11428: for(iIn=1; iIn<(n-1); iIn++){
! 11429: if( zIn[iIn]=='\'' ){
! 11430: assert( zIn[iIn+1]=='\'' );
! 11431: iIn++;
1.5 misho 11432: }
1.6.2.1 ! misho 11433: zRet[iOut++] = zIn[iIn];
1.5 misho 11434: }
1.6.2.1 ! misho 11435: zRet[iOut] = '\0';
1.5 misho 11436: }
11437:
1.6.2.1 ! misho 11438: return zRet;
1.5 misho 11439: }
11440:
1.6.2.1 ! misho 11441: /*
! 11442: ** This function is the implementation of both the xConnect and xCreate
! 11443: ** methods of the r-tree virtual table.
! 11444: **
! 11445: ** argv[0] -> module name
! 11446: ** argv[1] -> database name
! 11447: ** argv[2] -> table name
! 11448: ** argv[...] -> column names...
1.5 misho 11449: */
1.6.2.1 ! misho 11450: static int expertConnect(
! 11451: sqlite3 *db,
! 11452: void *pAux,
! 11453: int argc, const char *const*argv,
! 11454: sqlite3_vtab **ppVtab,
! 11455: char **pzErr
1.5 misho 11456: ){
1.6.2.1 ! misho 11457: sqlite3expert *pExpert = (sqlite3expert*)pAux;
! 11458: ExpertVtab *p = 0;
! 11459: int rc;
1.5 misho 11460:
1.6.2.1 ! misho 11461: if( argc!=4 ){
! 11462: *pzErr = sqlite3_mprintf("internal error!");
! 11463: rc = SQLITE_ERROR;
! 11464: }else{
! 11465: char *zCreateTable = expertDequote(argv[3]);
! 11466: if( zCreateTable ){
! 11467: rc = sqlite3_declare_vtab(db, zCreateTable);
! 11468: if( rc==SQLITE_OK ){
! 11469: p = idxMalloc(&rc, sizeof(ExpertVtab));
! 11470: }
! 11471: if( rc==SQLITE_OK ){
! 11472: p->pExpert = pExpert;
! 11473: p->pTab = pExpert->pTable;
! 11474: assert( sqlite3_stricmp(p->pTab->zName, argv[2])==0 );
! 11475: }
! 11476: sqlite3_free(zCreateTable);
! 11477: }else{
! 11478: rc = SQLITE_NOMEM;
1.5 misho 11479: }
11480: }
11481:
1.6.2.1 ! misho 11482: *ppVtab = (sqlite3_vtab*)p;
! 11483: return rc;
1.5 misho 11484: }
11485:
1.6.2.1 ! misho 11486: static int expertDisconnect(sqlite3_vtab *pVtab){
! 11487: ExpertVtab *p = (ExpertVtab*)pVtab;
! 11488: sqlite3_free(p);
! 11489: return SQLITE_OK;
! 11490: }
1.5 misho 11491:
1.6.2.1 ! misho 11492: static int expertBestIndex(sqlite3_vtab *pVtab, sqlite3_index_info *pIdxInfo){
! 11493: ExpertVtab *p = (ExpertVtab*)pVtab;
! 11494: int rc = SQLITE_OK;
! 11495: int n = 0;
! 11496: IdxScan *pScan;
! 11497: const int opmask =
! 11498: SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_GT |
! 11499: SQLITE_INDEX_CONSTRAINT_LT | SQLITE_INDEX_CONSTRAINT_GE |
! 11500: SQLITE_INDEX_CONSTRAINT_LE;
1.5 misho 11501:
1.6.2.1 ! misho 11502: pScan = idxMalloc(&rc, sizeof(IdxScan));
! 11503: if( pScan ){
! 11504: int i;
1.5 misho 11505:
1.6.2.1 ! misho 11506: /* Link the new scan object into the list */
! 11507: pScan->pTab = p->pTab;
! 11508: pScan->pNextScan = p->pExpert->pScan;
! 11509: p->pExpert->pScan = pScan;
1.5 misho 11510:
1.6.2.1 ! misho 11511: /* Add the constraints to the IdxScan object */
! 11512: for(i=0; i<pIdxInfo->nConstraint; i++){
! 11513: struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
! 11514: if( pCons->usable
! 11515: && pCons->iColumn>=0
! 11516: && p->pTab->aCol[pCons->iColumn].iPk==0
! 11517: && (pCons->op & opmask)
! 11518: ){
! 11519: IdxConstraint *pNew;
! 11520: const char *zColl = sqlite3_vtab_collation(pIdxInfo, i);
! 11521: pNew = idxNewConstraint(&rc, zColl);
! 11522: if( pNew ){
! 11523: pNew->iCol = pCons->iColumn;
! 11524: if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
! 11525: pNew->pNext = pScan->pEq;
! 11526: pScan->pEq = pNew;
! 11527: }else{
! 11528: pNew->bRange = 1;
! 11529: pNew->pNext = pScan->pRange;
! 11530: pScan->pRange = pNew;
! 11531: }
! 11532: }
! 11533: n++;
! 11534: pIdxInfo->aConstraintUsage[i].argvIndex = n;
! 11535: }
! 11536: }
1.5 misho 11537:
1.6.2.1 ! misho 11538: /* Add the ORDER BY to the IdxScan object */
! 11539: for(i=pIdxInfo->nOrderBy-1; i>=0; i--){
! 11540: int iCol = pIdxInfo->aOrderBy[i].iColumn;
! 11541: if( iCol>=0 ){
! 11542: IdxConstraint *pNew = idxNewConstraint(&rc, p->pTab->aCol[iCol].zColl);
! 11543: if( pNew ){
! 11544: pNew->iCol = iCol;
! 11545: pNew->bDesc = pIdxInfo->aOrderBy[i].desc;
! 11546: pNew->pNext = pScan->pOrder;
! 11547: pNew->pLink = pScan->pOrder;
! 11548: pScan->pOrder = pNew;
! 11549: n++;
! 11550: }
! 11551: }
! 11552: }
1.5 misho 11553: }
11554:
1.6.2.1 ! misho 11555: pIdxInfo->estimatedCost = 1000000.0 / (n+1);
1.5 misho 11556: return rc;
11557: }
11558:
1.6.2.1 ! misho 11559: static int expertUpdate(
! 11560: sqlite3_vtab *pVtab,
! 11561: int nData,
! 11562: sqlite3_value **azData,
! 11563: sqlite_int64 *pRowid
1.5 misho 11564: ){
1.6.2.1 ! misho 11565: (void)pVtab;
! 11566: (void)nData;
! 11567: (void)azData;
! 11568: (void)pRowid;
1.5 misho 11569: return SQLITE_OK;
1.6.2.1 ! misho 11570: }
1.5 misho 11571:
1.6.2.1 ! misho 11572: /*
! 11573: ** Virtual table module xOpen method.
! 11574: */
! 11575: static int expertOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
! 11576: int rc = SQLITE_OK;
! 11577: ExpertCsr *pCsr;
! 11578: (void)pVTab;
! 11579: pCsr = idxMalloc(&rc, sizeof(ExpertCsr));
! 11580: *ppCursor = (sqlite3_vtab_cursor*)pCsr;
! 11581: return rc;
! 11582: }
! 11583:
! 11584: /*
! 11585: ** Virtual table module xClose method.
! 11586: */
! 11587: static int expertClose(sqlite3_vtab_cursor *cur){
! 11588: ExpertCsr *pCsr = (ExpertCsr*)cur;
! 11589: sqlite3_finalize(pCsr->pData);
! 11590: sqlite3_free(pCsr);
! 11591: return SQLITE_OK;
1.5 misho 11592: }
11593:
11594: /*
1.6.2.1 ! misho 11595: ** Virtual table module xEof method.
! 11596: **
! 11597: ** Return non-zero if the cursor does not currently point to a valid
! 11598: ** record (i.e if the scan has finished), or zero otherwise.
! 11599: */
! 11600: static int expertEof(sqlite3_vtab_cursor *cur){
! 11601: ExpertCsr *pCsr = (ExpertCsr*)cur;
! 11602: return pCsr->pData==0;
1.5 misho 11603: }
11604:
1.6.2.1 ! misho 11605: /*
! 11606: ** Virtual table module xNext method.
! 11607: */
! 11608: static int expertNext(sqlite3_vtab_cursor *cur){
! 11609: ExpertCsr *pCsr = (ExpertCsr*)cur;
1.5 misho 11610: int rc = SQLITE_OK;
11611:
1.6.2.1 ! misho 11612: assert( pCsr->pData );
! 11613: rc = sqlite3_step(pCsr->pData);
! 11614: if( rc!=SQLITE_ROW ){
! 11615: rc = sqlite3_finalize(pCsr->pData);
! 11616: pCsr->pData = 0;
1.5 misho 11617: }else{
1.6.2.1 ! misho 11618: rc = SQLITE_OK;
1.5 misho 11619: }
11620:
11621: return rc;
11622: }
11623:
1.6.2.1 ! misho 11624: /*
! 11625: ** Virtual table module xRowid method.
1.5 misho 11626: */
1.6.2.1 ! misho 11627: static int expertRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
! 11628: (void)cur;
! 11629: *pRowid = 0;
! 11630: return SQLITE_OK;
! 11631: }
! 11632:
! 11633: /*
! 11634: ** Virtual table module xColumn method.
! 11635: */
! 11636: static int expertColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
! 11637: ExpertCsr *pCsr = (ExpertCsr*)cur;
! 11638: sqlite3_value *pVal;
! 11639: pVal = sqlite3_column_value(pCsr->pData, i);
! 11640: if( pVal ){
! 11641: sqlite3_result_value(ctx, pVal);
1.5 misho 11642: }
1.6.2.1 ! misho 11643: return SQLITE_OK;
1.5 misho 11644: }
11645:
1.6.2.1 ! misho 11646: /*
! 11647: ** Virtual table module xFilter method.
1.5 misho 11648: */
1.6.2.1 ! misho 11649: static int expertFilter(
! 11650: sqlite3_vtab_cursor *cur,
! 11651: int idxNum, const char *idxStr,
! 11652: int argc, sqlite3_value **argv
! 11653: ){
! 11654: ExpertCsr *pCsr = (ExpertCsr*)cur;
! 11655: ExpertVtab *pVtab = (ExpertVtab*)(cur->pVtab);
! 11656: sqlite3expert *pExpert = pVtab->pExpert;
! 11657: int rc;
! 11658:
! 11659: (void)idxNum;
! 11660: (void)idxStr;
! 11661: (void)argc;
! 11662: (void)argv;
! 11663: rc = sqlite3_finalize(pCsr->pData);
! 11664: pCsr->pData = 0;
! 11665: if( rc==SQLITE_OK ){
! 11666: rc = idxPrintfPrepareStmt(pExpert->db, &pCsr->pData, &pVtab->base.zErrMsg,
! 11667: "SELECT * FROM main.%Q WHERE sample()", pVtab->pTab->zName
! 11668: );
1.5 misho 11669: }
1.6.2.1 ! misho 11670:
! 11671: if( rc==SQLITE_OK ){
! 11672: rc = expertNext(cur);
! 11673: }
! 11674: return rc;
1.5 misho 11675: }
11676:
1.6.2.1 ! misho 11677: static int idxRegisterVtab(sqlite3expert *p){
! 11678: static sqlite3_module expertModule = {
! 11679: 2, /* iVersion */
! 11680: expertConnect, /* xCreate - create a table */
! 11681: expertConnect, /* xConnect - connect to an existing table */
! 11682: expertBestIndex, /* xBestIndex - Determine search strategy */
! 11683: expertDisconnect, /* xDisconnect - Disconnect from a table */
! 11684: expertDisconnect, /* xDestroy - Drop a table */
! 11685: expertOpen, /* xOpen - open a cursor */
! 11686: expertClose, /* xClose - close a cursor */
! 11687: expertFilter, /* xFilter - configure scan constraints */
! 11688: expertNext, /* xNext - advance a cursor */
! 11689: expertEof, /* xEof */
! 11690: expertColumn, /* xColumn - read data */
! 11691: expertRowid, /* xRowid - read data */
! 11692: expertUpdate, /* xUpdate - write data */
! 11693: 0, /* xBegin - begin transaction */
! 11694: 0, /* xSync - sync transaction */
! 11695: 0, /* xCommit - commit transaction */
! 11696: 0, /* xRollback - rollback transaction */
! 11697: 0, /* xFindFunction - function overloading */
! 11698: 0, /* xRename - rename the table */
! 11699: 0, /* xSavepoint */
! 11700: 0, /* xRelease */
! 11701: 0, /* xRollbackTo */
! 11702: 0, /* xShadowName */
! 11703: };
! 11704:
! 11705: return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p);
! 11706: }
1.5 misho 11707: /*
1.6.2.1 ! misho 11708: ** End of virtual table implementation.
! 11709: *************************************************************************/
! 11710: /*
! 11711: ** Finalize SQL statement pStmt. If (*pRc) is SQLITE_OK when this function
! 11712: ** is called, set it to the return value of sqlite3_finalize() before
! 11713: ** returning. Otherwise, discard the sqlite3_finalize() return value.
1.5 misho 11714: */
1.6.2.1 ! misho 11715: static void idxFinalize(int *pRc, sqlite3_stmt *pStmt){
! 11716: int rc = sqlite3_finalize(pStmt);
! 11717: if( *pRc==SQLITE_OK ) *pRc = rc;
1.5 misho 11718: }
11719:
11720: /*
1.6.2.1 ! misho 11721: ** Attempt to allocate an IdxTable structure corresponding to table zTab
! 11722: ** in the main database of connection db. If successful, set (*ppOut) to
! 11723: ** point to the new object and return SQLITE_OK. Otherwise, return an
! 11724: ** SQLite error code and set (*ppOut) to NULL. In this case *pzErrmsg may be
! 11725: ** set to point to an error string.
! 11726: **
! 11727: ** It is the responsibility of the caller to eventually free either the
! 11728: ** IdxTable object or error message using sqlite3_free().
1.5 misho 11729: */
1.6.2.1 ! misho 11730: static int idxGetTableInfo(
! 11731: sqlite3 *db, /* Database connection to read details from */
! 11732: const char *zTab, /* Table name */
! 11733: IdxTable **ppOut, /* OUT: New object (if successful) */
! 11734: char **pzErrmsg /* OUT: Error message (if not) */
1.5 misho 11735: ){
1.6.2.1 ! misho 11736: sqlite3_stmt *p1 = 0;
! 11737: int nCol = 0;
! 11738: int nTab;
! 11739: int nByte;
! 11740: IdxTable *pNew = 0;
! 11741: int rc, rc2;
! 11742: char *pCsr = 0;
! 11743: int nPk = 0;
1.5 misho 11744:
1.6.2.1 ! misho 11745: *ppOut = 0;
! 11746: if( zTab==0 ) return SQLITE_ERROR;
! 11747: nTab = STRLEN(zTab);
! 11748: nByte = sizeof(IdxTable) + nTab + 1;
! 11749: rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_xinfo=%Q", zTab);
! 11750: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
! 11751: const char *zCol = (const char*)sqlite3_column_text(p1, 1);
! 11752: const char *zColSeq = 0;
! 11753: if( zCol==0 ){
! 11754: rc = SQLITE_ERROR;
! 11755: break;
! 11756: }
! 11757: nByte += 1 + STRLEN(zCol);
! 11758: rc = sqlite3_table_column_metadata(
! 11759: db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0
! 11760: );
! 11761: if( zColSeq==0 ) zColSeq = "binary";
! 11762: nByte += 1 + STRLEN(zColSeq);
! 11763: nCol++;
! 11764: nPk += (sqlite3_column_int(p1, 5)>0);
1.5 misho 11765: }
1.6.2.1 ! misho 11766: rc2 = sqlite3_reset(p1);
! 11767: if( rc==SQLITE_OK ) rc = rc2;
1.5 misho 11768:
1.6.2.1 ! misho 11769: nByte += sizeof(IdxColumn) * nCol;
! 11770: if( rc==SQLITE_OK ){
! 11771: pNew = idxMalloc(&rc, nByte);
! 11772: }
! 11773: if( rc==SQLITE_OK ){
! 11774: pNew->aCol = (IdxColumn*)&pNew[1];
! 11775: pNew->nCol = nCol;
! 11776: pCsr = (char*)&pNew->aCol[nCol];
1.5 misho 11777: }
11778:
1.6.2.1 ! misho 11779: nCol = 0;
! 11780: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
! 11781: const char *zCol = (const char*)sqlite3_column_text(p1, 1);
! 11782: const char *zColSeq = 0;
! 11783: int nCopy;
! 11784: if( zCol==0 ) continue;
! 11785: nCopy = STRLEN(zCol) + 1;
! 11786: pNew->aCol[nCol].zName = pCsr;
! 11787: pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1);
! 11788: memcpy(pCsr, zCol, nCopy);
! 11789: pCsr += nCopy;
1.5 misho 11790:
1.6.2.1 ! misho 11791: rc = sqlite3_table_column_metadata(
! 11792: db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0
! 11793: );
1.5 misho 11794: if( rc==SQLITE_OK ){
1.6.2.1 ! misho 11795: if( zColSeq==0 ) zColSeq = "binary";
! 11796: nCopy = STRLEN(zColSeq) + 1;
! 11797: pNew->aCol[nCol].zColl = pCsr;
! 11798: memcpy(pCsr, zColSeq, nCopy);
! 11799: pCsr += nCopy;
1.5 misho 11800: }
11801:
1.6.2.1 ! misho 11802: nCol++;
! 11803: }
! 11804: idxFinalize(&rc, p1);
1.5 misho 11805:
1.6.2.1 ! misho 11806: if( rc!=SQLITE_OK ){
! 11807: sqlite3_free(pNew);
! 11808: pNew = 0;
! 11809: }else if( ALWAYS(pNew!=0) ){
! 11810: pNew->zName = pCsr;
! 11811: if( ALWAYS(pNew->zName!=0) ) memcpy(pNew->zName, zTab, nTab+1);
! 11812: }
1.5 misho 11813:
1.6.2.1 ! misho 11814: *ppOut = pNew;
! 11815: return rc;
! 11816: }
1.5 misho 11817:
1.6.2.1 ! misho 11818: /*
! 11819: ** This function is a no-op if *pRc is set to anything other than
! 11820: ** SQLITE_OK when it is called.
! 11821: **
! 11822: ** If *pRc is initially set to SQLITE_OK, then the text specified by
! 11823: ** the printf() style arguments is appended to zIn and the result returned
! 11824: ** in a buffer allocated by sqlite3_malloc(). sqlite3_free() is called on
! 11825: ** zIn before returning.
! 11826: */
! 11827: static char *idxAppendText(int *pRc, char *zIn, const char *zFmt, ...){
! 11828: va_list ap;
! 11829: char *zAppend = 0;
! 11830: char *zRet = 0;
! 11831: int nIn = zIn ? STRLEN(zIn) : 0;
! 11832: int nAppend = 0;
! 11833: va_start(ap, zFmt);
! 11834: if( *pRc==SQLITE_OK ){
! 11835: zAppend = sqlite3_vmprintf(zFmt, ap);
! 11836: if( zAppend ){
! 11837: nAppend = STRLEN(zAppend);
! 11838: zRet = (char*)sqlite3_malloc(nIn + nAppend + 1);
1.5 misho 11839: }
1.6.2.1 ! misho 11840: if( zAppend && zRet ){
! 11841: if( nIn ) memcpy(zRet, zIn, nIn);
! 11842: memcpy(&zRet[nIn], zAppend, nAppend+1);
! 11843: }else{
! 11844: sqlite3_free(zRet);
! 11845: zRet = 0;
! 11846: *pRc = SQLITE_NOMEM;
1.5 misho 11847: }
1.6.2.1 ! misho 11848: sqlite3_free(zAppend);
! 11849: sqlite3_free(zIn);
1.5 misho 11850: }
1.6.2.1 ! misho 11851: va_end(ap);
! 11852: return zRet;
! 11853: }
1.5 misho 11854:
1.6.2.1 ! misho 11855: /*
! 11856: ** Return true if zId must be quoted in order to use it as an SQL
! 11857: ** identifier, or false otherwise.
! 11858: */
! 11859: static int idxIdentifierRequiresQuotes(const char *zId){
! 11860: int i;
! 11861: int nId = STRLEN(zId);
! 11862:
! 11863: if( sqlite3_keyword_check(zId, nId) ) return 1;
1.5 misho 11864:
1.6.2.1 ! misho 11865: for(i=0; zId[i]; i++){
! 11866: if( !(zId[i]=='_')
! 11867: && !(zId[i]>='0' && zId[i]<='9')
! 11868: && !(zId[i]>='a' && zId[i]<='z')
! 11869: && !(zId[i]>='A' && zId[i]<='Z')
! 11870: ){
! 11871: return 1;
! 11872: }
1.5 misho 11873: }
1.6.2.1 ! misho 11874: return 0;
1.5 misho 11875: }
11876:
1.6.2.1 ! misho 11877: /*
! 11878: ** This function appends an index column definition suitable for constraint
! 11879: ** pCons to the string passed as zIn and returns the result.
! 11880: */
! 11881: static char *idxAppendColDefn(
! 11882: int *pRc, /* IN/OUT: Error code */
! 11883: char *zIn, /* Column defn accumulated so far */
! 11884: IdxTable *pTab, /* Table index will be created on */
! 11885: IdxConstraint *pCons
! 11886: ){
! 11887: char *zRet = zIn;
! 11888: IdxColumn *p = &pTab->aCol[pCons->iCol];
! 11889: if( zRet ) zRet = idxAppendText(pRc, zRet, ", ");
1.5 misho 11890:
1.6.2.1 ! misho 11891: if( idxIdentifierRequiresQuotes(p->zName) ){
! 11892: zRet = idxAppendText(pRc, zRet, "%Q", p->zName);
! 11893: }else{
! 11894: zRet = idxAppendText(pRc, zRet, "%s", p->zName);
! 11895: }
1.5 misho 11896:
1.6.2.1 ! misho 11897: if( sqlite3_stricmp(p->zColl, pCons->zColl) ){
! 11898: if( idxIdentifierRequiresQuotes(pCons->zColl) ){
! 11899: zRet = idxAppendText(pRc, zRet, " COLLATE %Q", pCons->zColl);
! 11900: }else{
! 11901: zRet = idxAppendText(pRc, zRet, " COLLATE %s", pCons->zColl);
! 11902: }
! 11903: }
! 11904:
! 11905: if( pCons->bDesc ){
! 11906: zRet = idxAppendText(pRc, zRet, " DESC");
! 11907: }
! 11908: return zRet;
1.5 misho 11909: }
11910:
11911: /*
1.6.2.1 ! misho 11912: ** Search database dbm for an index compatible with the one idxCreateFromCons()
! 11913: ** would create from arguments pScan, pEq and pTail. If no error occurs and
! 11914: ** such an index is found, return non-zero. Or, if no such index is found,
! 11915: ** return zero.
! 11916: **
! 11917: ** If an error occurs, set *pRc to an SQLite error code and return zero.
1.5 misho 11918: */
1.6.2.1 ! misho 11919: static int idxFindCompatible(
! 11920: int *pRc, /* OUT: Error code */
! 11921: sqlite3* dbm, /* Database to search */
! 11922: IdxScan *pScan, /* Scan for table to search for index on */
! 11923: IdxConstraint *pEq, /* List of == constraints */
! 11924: IdxConstraint *pTail /* List of range constraints */
! 11925: ){
! 11926: const char *zTbl = pScan->pTab->zName;
! 11927: sqlite3_stmt *pIdxList = 0;
! 11928: IdxConstraint *pIter;
! 11929: int nEq = 0; /* Number of elements in pEq */
! 11930: int rc;
1.5 misho 11931:
1.6.2.1 ! misho 11932: /* Count the elements in list pEq */
! 11933: for(pIter=pEq; pIter; pIter=pIter->pLink) nEq++;
1.5 misho 11934:
1.6.2.1 ! misho 11935: rc = idxPrintfPrepareStmt(dbm, &pIdxList, 0, "PRAGMA index_list=%Q", zTbl);
! 11936: while( rc==SQLITE_OK && sqlite3_step(pIdxList)==SQLITE_ROW ){
! 11937: int bMatch = 1;
! 11938: IdxConstraint *pT = pTail;
! 11939: sqlite3_stmt *pInfo = 0;
! 11940: const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1);
! 11941: if( zIdx==0 ) continue;
1.5 misho 11942:
1.6.2.1 ! misho 11943: /* Zero the IdxConstraint.bFlag values in the pEq list */
! 11944: for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0;
1.5 misho 11945:
1.6.2.1 ! misho 11946: rc = idxPrintfPrepareStmt(dbm, &pInfo, 0, "PRAGMA index_xInfo=%Q", zIdx);
! 11947: while( rc==SQLITE_OK && sqlite3_step(pInfo)==SQLITE_ROW ){
! 11948: int iIdx = sqlite3_column_int(pInfo, 0);
! 11949: int iCol = sqlite3_column_int(pInfo, 1);
! 11950: const char *zColl = (const char*)sqlite3_column_text(pInfo, 4);
! 11951:
! 11952: if( iIdx<nEq ){
! 11953: for(pIter=pEq; pIter; pIter=pIter->pLink){
! 11954: if( pIter->bFlag ) continue;
! 11955: if( pIter->iCol!=iCol ) continue;
! 11956: if( sqlite3_stricmp(pIter->zColl, zColl) ) continue;
! 11957: pIter->bFlag = 1;
! 11958: break;
! 11959: }
! 11960: if( pIter==0 ){
! 11961: bMatch = 0;
! 11962: break;
! 11963: }
! 11964: }else{
! 11965: if( pT ){
! 11966: if( pT->iCol!=iCol || sqlite3_stricmp(pT->zColl, zColl) ){
! 11967: bMatch = 0;
! 11968: break;
! 11969: }
! 11970: pT = pT->pLink;
! 11971: }
! 11972: }
! 11973: }
! 11974: idxFinalize(&rc, pInfo);
! 11975:
! 11976: if( rc==SQLITE_OK && bMatch ){
! 11977: sqlite3_finalize(pIdxList);
! 11978: return 1;
! 11979: }
1.5 misho 11980: }
1.6.2.1 ! misho 11981: idxFinalize(&rc, pIdxList);
1.5 misho 11982:
1.6.2.1 ! misho 11983: *pRc = rc;
! 11984: return 0;
1.5 misho 11985: }
11986:
1.6.2.1 ! misho 11987: /* Callback for sqlite3_exec() with query with leading count(*) column.
! 11988: * The first argument is expected to be an int*, referent to be incremented
! 11989: * if that leading column is not exactly '0'.
! 11990: */
! 11991: static int countNonzeros(void* pCount, int nc,
! 11992: char* azResults[], char* azColumns[]){
! 11993: (void)azColumns; /* Suppress unused parameter warning */
! 11994: if( nc>0 && (azResults[0][0]!='0' || azResults[0][1]!=0) ){
! 11995: *((int *)pCount) += 1;
! 11996: }
! 11997: return 0;
! 11998: }
! 11999:
! 12000: static int idxCreateFromCons(
! 12001: sqlite3expert *p,
! 12002: IdxScan *pScan,
! 12003: IdxConstraint *pEq,
! 12004: IdxConstraint *pTail
! 12005: ){
! 12006: sqlite3 *dbm = p->dbm;
1.5 misho 12007: int rc = SQLITE_OK;
1.6.2.1 ! misho 12008: if( (pEq || pTail) && 0==idxFindCompatible(&rc, dbm, pScan, pEq, pTail) ){
! 12009: IdxTable *pTab = pScan->pTab;
! 12010: char *zCols = 0;
! 12011: char *zIdx = 0;
! 12012: IdxConstraint *pCons;
! 12013: unsigned int h = 0;
! 12014: const char *zFmt;
1.5 misho 12015:
1.6.2.1 ! misho 12016: for(pCons=pEq; pCons; pCons=pCons->pLink){
! 12017: zCols = idxAppendColDefn(&rc, zCols, pTab, pCons);
! 12018: }
! 12019: for(pCons=pTail; pCons; pCons=pCons->pLink){
! 12020: zCols = idxAppendColDefn(&rc, zCols, pTab, pCons);
1.5 misho 12021: }
12022:
1.6.2.1 ! misho 12023: if( rc==SQLITE_OK ){
! 12024: /* Hash the list of columns to come up with a name for the index */
! 12025: const char *zTable = pScan->pTab->zName;
! 12026: int quoteTable = idxIdentifierRequiresQuotes(zTable);
! 12027: char *zName = 0; /* Index name */
! 12028: int collisions = 0;
! 12029: do{
! 12030: int i;
! 12031: char *zFind;
! 12032: for(i=0; zCols[i]; i++){
! 12033: h += ((h<<3) + zCols[i]);
! 12034: }
! 12035: sqlite3_free(zName);
! 12036: zName = sqlite3_mprintf("%s_idx_%08x", zTable, h);
! 12037: if( zName==0 ) break;
! 12038: /* Is is unique among table, view and index names? */
! 12039: zFmt = "SELECT count(*) FROM sqlite_schema WHERE name=%Q"
! 12040: " AND type in ('index','table','view')";
! 12041: zFind = sqlite3_mprintf(zFmt, zName);
! 12042: i = 0;
! 12043: rc = sqlite3_exec(dbm, zFind, countNonzeros, &i, 0);
! 12044: assert(rc==SQLITE_OK);
! 12045: sqlite3_free(zFind);
! 12046: if( i==0 ){
! 12047: collisions = 0;
! 12048: break;
! 12049: }
! 12050: ++collisions;
! 12051: }while( collisions<50 && zName!=0 );
! 12052: if( collisions ){
! 12053: /* This return means "Gave up trying to find a unique index name." */
! 12054: rc = SQLITE_BUSY_TIMEOUT;
! 12055: }else if( zName==0 ){
! 12056: rc = SQLITE_NOMEM;
! 12057: }else{
! 12058: if( quoteTable ){
! 12059: zFmt = "CREATE INDEX \"%w\" ON \"%w\"(%s)";
! 12060: }else{
! 12061: zFmt = "CREATE INDEX %s ON %s(%s)";
! 12062: }
! 12063: zIdx = sqlite3_mprintf(zFmt, zName, zTable, zCols);
! 12064: if( !zIdx ){
! 12065: rc = SQLITE_NOMEM;
! 12066: }else{
! 12067: rc = sqlite3_exec(dbm, zIdx, 0, 0, p->pzErrmsg);
! 12068: if( rc!=SQLITE_OK ){
! 12069: rc = SQLITE_BUSY_TIMEOUT;
! 12070: }else{
! 12071: idxHashAdd(&rc, &p->hIdx, zName, zIdx);
! 12072: }
! 12073: }
! 12074: sqlite3_free(zName);
! 12075: sqlite3_free(zIdx);
! 12076: }
! 12077: }
1.5 misho 12078:
1.6.2.1 ! misho 12079: sqlite3_free(zCols);
1.5 misho 12080: }
12081: return rc;
12082: }
12083:
1.6.2.1 ! misho 12084: /*
! 12085: ** Return true if list pList (linked by IdxConstraint.pLink) contains
! 12086: ** a constraint compatible with *p. Otherwise return false.
! 12087: */
! 12088: static int idxFindConstraint(IdxConstraint *pList, IdxConstraint *p){
! 12089: IdxConstraint *pCmp;
! 12090: for(pCmp=pList; pCmp; pCmp=pCmp->pLink){
! 12091: if( p->iCol==pCmp->iCol ) return 1;
1.5 misho 12092: }
1.6.2.1 ! misho 12093: return 0;
1.5 misho 12094: }
12095:
1.6.2.1 ! misho 12096: static int idxCreateFromWhere(
! 12097: sqlite3expert *p,
! 12098: IdxScan *pScan, /* Create indexes for this scan */
! 12099: IdxConstraint *pTail /* range/ORDER BY constraints for inclusion */
1.5 misho 12100: ){
1.6.2.1 ! misho 12101: IdxConstraint *p1 = 0;
! 12102: IdxConstraint *pCon;
! 12103: int rc;
1.5 misho 12104:
1.6.2.1 ! misho 12105: /* Gather up all the == constraints. */
! 12106: for(pCon=pScan->pEq; pCon; pCon=pCon->pNext){
! 12107: if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
! 12108: pCon->pLink = p1;
! 12109: p1 = pCon;
! 12110: }
! 12111: }
1.5 misho 12112:
1.6.2.1 ! misho 12113: /* Create an index using the == constraints collected above. And the
! 12114: ** range constraint/ORDER BY terms passed in by the caller, if any. */
! 12115: rc = idxCreateFromCons(p, pScan, p1, pTail);
! 12116:
! 12117: /* If no range/ORDER BY passed by the caller, create a version of the
! 12118: ** index for each range constraint. */
! 12119: if( pTail==0 ){
! 12120: for(pCon=pScan->pRange; rc==SQLITE_OK && pCon; pCon=pCon->pNext){
! 12121: assert( pCon->pLink==0 );
! 12122: if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
! 12123: rc = idxCreateFromCons(p, pScan, p1, pCon);
! 12124: }
1.5 misho 12125: }
12126: }
1.6.2.1 ! misho 12127:
! 12128: return rc;
1.5 misho 12129: }
12130:
12131: /*
1.6.2.1 ! misho 12132: ** Create candidate indexes in database [dbm] based on the data in
! 12133: ** linked-list pScan.
1.5 misho 12134: */
1.6.2.1 ! misho 12135: static int idxCreateCandidates(sqlite3expert *p){
! 12136: int rc = SQLITE_OK;
! 12137: IdxScan *pIter;
1.5 misho 12138:
1.6.2.1 ! misho 12139: for(pIter=p->pScan; pIter && rc==SQLITE_OK; pIter=pIter->pNextScan){
! 12140: rc = idxCreateFromWhere(p, pIter, 0);
! 12141: if( rc==SQLITE_OK && pIter->pOrder ){
! 12142: rc = idxCreateFromWhere(p, pIter, pIter->pOrder);
! 12143: }
! 12144: }
1.5 misho 12145:
1.6.2.1 ! misho 12146: return rc;
! 12147: }
1.5 misho 12148:
1.6.2.1 ! misho 12149: /*
! 12150: ** Free all elements of the linked list starting at pConstraint.
! 12151: */
! 12152: static void idxConstraintFree(IdxConstraint *pConstraint){
! 12153: IdxConstraint *pNext;
! 12154: IdxConstraint *p;
1.5 misho 12155:
1.6.2.1 ! misho 12156: for(p=pConstraint; p; p=pNext){
! 12157: pNext = p->pNext;
! 12158: sqlite3_free(p);
1.5 misho 12159: }
12160: }
12161:
12162: /*
1.6.2.1 ! misho 12163: ** Free all elements of the linked list starting from pScan up until pLast
! 12164: ** (pLast is not freed).
1.5 misho 12165: */
1.6.2.1 ! misho 12166: static void idxScanFree(IdxScan *pScan, IdxScan *pLast){
! 12167: IdxScan *p;
! 12168: IdxScan *pNext;
! 12169: for(p=pScan; p!=pLast; p=pNext){
! 12170: pNext = p->pNextScan;
! 12171: idxConstraintFree(p->pOrder);
! 12172: idxConstraintFree(p->pEq);
! 12173: idxConstraintFree(p->pRange);
! 12174: sqlite3_free(p);
! 12175: }
! 12176: }
1.5 misho 12177:
1.6.2.1 ! misho 12178: /*
! 12179: ** Free all elements of the linked list starting from pStatement up
! 12180: ** until pLast (pLast is not freed).
! 12181: */
! 12182: static void idxStatementFree(IdxStatement *pStatement, IdxStatement *pLast){
! 12183: IdxStatement *p;
! 12184: IdxStatement *pNext;
! 12185: for(p=pStatement; p!=pLast; p=pNext){
! 12186: pNext = p->pNext;
! 12187: sqlite3_free(p->zEQP);
! 12188: sqlite3_free(p->zIdx);
! 12189: sqlite3_free(p);
! 12190: }
! 12191: }
1.5 misho 12192:
1.6.2.1 ! misho 12193: /*
! 12194: ** Free the linked list of IdxTable objects starting at pTab.
! 12195: */
! 12196: static void idxTableFree(IdxTable *pTab){
! 12197: IdxTable *pIter;
! 12198: IdxTable *pNext;
! 12199: for(pIter=pTab; pIter; pIter=pNext){
! 12200: pNext = pIter->pNext;
! 12201: sqlite3_free(pIter);
! 12202: }
! 12203: }
1.5 misho 12204:
1.6.2.1 ! misho 12205: /*
! 12206: ** Free the linked list of IdxWrite objects starting at pTab.
! 12207: */
! 12208: static void idxWriteFree(IdxWrite *pTab){
! 12209: IdxWrite *pIter;
! 12210: IdxWrite *pNext;
! 12211: for(pIter=pTab; pIter; pIter=pNext){
! 12212: pNext = pIter->pNext;
! 12213: sqlite3_free(pIter);
! 12214: }
! 12215: }
1.5 misho 12216:
12217:
12218:
1.6.2.1 ! misho 12219: /*
! 12220: ** This function is called after candidate indexes have been created. It
! 12221: ** runs all the queries to see which indexes they prefer, and populates
! 12222: ** IdxStatement.zIdx and IdxStatement.zEQP with the results.
! 12223: */
! 12224: static int idxFindIndexes(
! 12225: sqlite3expert *p,
! 12226: char **pzErr /* OUT: Error message (sqlite3_malloc) */
! 12227: ){
! 12228: IdxStatement *pStmt;
! 12229: sqlite3 *dbm = p->dbm;
! 12230: int rc = SQLITE_OK;
1.5 misho 12231:
1.6.2.1 ! misho 12232: IdxHash hIdx;
! 12233: idxHashInit(&hIdx);
1.5 misho 12234:
1.6.2.1 ! misho 12235: for(pStmt=p->pStatement; rc==SQLITE_OK && pStmt; pStmt=pStmt->pNext){
! 12236: IdxHashEntry *pEntry;
! 12237: sqlite3_stmt *pExplain = 0;
! 12238: idxHashClear(&hIdx);
! 12239: rc = idxPrintfPrepareStmt(dbm, &pExplain, pzErr,
! 12240: "EXPLAIN QUERY PLAN %s", pStmt->zSql
! 12241: );
! 12242: while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){
! 12243: /* int iId = sqlite3_column_int(pExplain, 0); */
! 12244: /* int iParent = sqlite3_column_int(pExplain, 1); */
! 12245: /* int iNotUsed = sqlite3_column_int(pExplain, 2); */
! 12246: const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
! 12247: int nDetail;
! 12248: int i;
1.5 misho 12249:
1.6.2.1 ! misho 12250: if( !zDetail ) continue;
! 12251: nDetail = STRLEN(zDetail);
! 12252:
! 12253: for(i=0; i<nDetail; i++){
! 12254: const char *zIdx = 0;
! 12255: if( i+13<nDetail && memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
! 12256: zIdx = &zDetail[i+13];
! 12257: }else if( i+22<nDetail
! 12258: && memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0
! 12259: ){
! 12260: zIdx = &zDetail[i+22];
! 12261: }
! 12262: if( zIdx ){
! 12263: const char *zSql;
! 12264: int nIdx = 0;
! 12265: while( zIdx[nIdx]!='\0' && (zIdx[nIdx]!=' ' || zIdx[nIdx+1]!='(') ){
! 12266: nIdx++;
! 12267: }
! 12268: zSql = idxHashSearch(&p->hIdx, zIdx, nIdx);
! 12269: if( zSql ){
! 12270: idxHashAdd(&rc, &hIdx, zSql, 0);
! 12271: if( rc ) goto find_indexes_out;
! 12272: }
! 12273: break;
! 12274: }
1.5 misho 12275: }
1.6.2.1 ! misho 12276:
! 12277: if( zDetail[0]!='-' ){
! 12278: pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%s\n", zDetail);
1.5 misho 12279: }
12280: }
12281:
1.6.2.1 ! misho 12282: for(pEntry=hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
! 12283: pStmt->zIdx = idxAppendText(&rc, pStmt->zIdx, "%s;\n", pEntry->zKey);
! 12284: }
1.5 misho 12285:
1.6.2.1 ! misho 12286: idxFinalize(&rc, pExplain);
! 12287: }
1.5 misho 12288:
1.6.2.1 ! misho 12289: find_indexes_out:
! 12290: idxHashClear(&hIdx);
! 12291: return rc;
! 12292: }
! 12293:
! 12294: static int idxAuthCallback(
! 12295: void *pCtx,
! 12296: int eOp,
! 12297: const char *z3,
! 12298: const char *z4,
! 12299: const char *zDb,
! 12300: const char *zTrigger
! 12301: ){
! 12302: int rc = SQLITE_OK;
! 12303: (void)z4;
! 12304: (void)zTrigger;
! 12305: if( eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE || eOp==SQLITE_DELETE ){
! 12306: if( sqlite3_stricmp(zDb, "main")==0 ){
! 12307: sqlite3expert *p = (sqlite3expert*)pCtx;
! 12308: IdxTable *pTab;
! 12309: for(pTab=p->pTable; pTab; pTab=pTab->pNext){
! 12310: if( 0==sqlite3_stricmp(z3, pTab->zName) ) break;
! 12311: }
! 12312: if( pTab ){
! 12313: IdxWrite *pWrite;
! 12314: for(pWrite=p->pWrite; pWrite; pWrite=pWrite->pNext){
! 12315: if( pWrite->pTab==pTab && pWrite->eOp==eOp ) break;
! 12316: }
! 12317: if( pWrite==0 ){
! 12318: pWrite = idxMalloc(&rc, sizeof(IdxWrite));
! 12319: if( rc==SQLITE_OK ){
! 12320: pWrite->pTab = pTab;
! 12321: pWrite->eOp = eOp;
! 12322: pWrite->pNext = p->pWrite;
! 12323: p->pWrite = pWrite;
! 12324: }
! 12325: }
1.5 misho 12326: }
12327: }
12328: }
1.6.2.1 ! misho 12329: return rc;
! 12330: }
1.5 misho 12331:
1.6.2.1 ! misho 12332: static int idxProcessOneTrigger(
! 12333: sqlite3expert *p,
! 12334: IdxWrite *pWrite,
! 12335: char **pzErr
! 12336: ){
! 12337: static const char *zInt = UNIQUE_TABLE_NAME;
! 12338: static const char *zDrop = "DROP TABLE " UNIQUE_TABLE_NAME;
! 12339: IdxTable *pTab = pWrite->pTab;
! 12340: const char *zTab = pTab->zName;
! 12341: const char *zSql =
! 12342: "SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_schema "
! 12343: "WHERE tbl_name = %Q AND type IN ('table', 'trigger') "
! 12344: "ORDER BY type;";
! 12345: sqlite3_stmt *pSelect = 0;
! 12346: int rc = SQLITE_OK;
! 12347: char *zWrite = 0;
1.5 misho 12348:
1.6.2.1 ! misho 12349: /* Create the table and its triggers in the temp schema */
! 12350: rc = idxPrintfPrepareStmt(p->db, &pSelect, pzErr, zSql, zTab, zTab);
! 12351: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSelect) ){
! 12352: const char *zCreate = (const char*)sqlite3_column_text(pSelect, 0);
! 12353: if( zCreate==0 ) continue;
! 12354: rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr);
1.5 misho 12355: }
1.6.2.1 ! misho 12356: idxFinalize(&rc, pSelect);
1.5 misho 12357:
1.6.2.1 ! misho 12358: /* Rename the table in the temp schema to zInt */
! 12359: if( rc==SQLITE_OK ){
! 12360: char *z = sqlite3_mprintf("ALTER TABLE temp.%Q RENAME TO %Q", zTab, zInt);
! 12361: if( z==0 ){
! 12362: rc = SQLITE_NOMEM;
1.5 misho 12363: }else{
1.6.2.1 ! misho 12364: rc = sqlite3_exec(p->dbv, z, 0, 0, pzErr);
! 12365: sqlite3_free(z);
1.5 misho 12366: }
12367: }
12368:
1.6.2.1 ! misho 12369: switch( pWrite->eOp ){
! 12370: case SQLITE_INSERT: {
! 12371: int i;
! 12372: zWrite = idxAppendText(&rc, zWrite, "INSERT INTO %Q VALUES(", zInt);
! 12373: for(i=0; i<pTab->nCol; i++){
! 12374: zWrite = idxAppendText(&rc, zWrite, "%s?", i==0 ? "" : ", ");
! 12375: }
! 12376: zWrite = idxAppendText(&rc, zWrite, ")");
! 12377: break;
! 12378: }
! 12379: case SQLITE_UPDATE: {
! 12380: int i;
! 12381: zWrite = idxAppendText(&rc, zWrite, "UPDATE %Q SET ", zInt);
! 12382: for(i=0; i<pTab->nCol; i++){
! 12383: zWrite = idxAppendText(&rc, zWrite, "%s%Q=?", i==0 ? "" : ", ",
! 12384: pTab->aCol[i].zName
! 12385: );
! 12386: }
! 12387: break;
! 12388: }
! 12389: default: {
! 12390: assert( pWrite->eOp==SQLITE_DELETE );
! 12391: if( rc==SQLITE_OK ){
! 12392: zWrite = sqlite3_mprintf("DELETE FROM %Q", zInt);
! 12393: if( zWrite==0 ) rc = SQLITE_NOMEM;
! 12394: }
1.5 misho 12395: }
12396: }
12397:
12398: if( rc==SQLITE_OK ){
1.6.2.1 ! misho 12399: sqlite3_stmt *pX = 0;
! 12400: rc = sqlite3_prepare_v2(p->dbv, zWrite, -1, &pX, 0);
! 12401: idxFinalize(&rc, pX);
! 12402: if( rc!=SQLITE_OK ){
! 12403: idxDatabaseError(p->dbv, pzErr);
! 12404: }
1.5 misho 12405: }
1.6.2.1 ! misho 12406: sqlite3_free(zWrite);
1.5 misho 12407:
1.6.2.1 ! misho 12408: if( rc==SQLITE_OK ){
! 12409: rc = sqlite3_exec(p->dbv, zDrop, 0, 0, pzErr);
! 12410: }
1.5 misho 12411:
1.6.2.1 ! misho 12412: return rc;
1.5 misho 12413: }
12414:
1.6.2.1 ! misho 12415: static int idxProcessTriggers(sqlite3expert *p, char **pzErr){
! 12416: int rc = SQLITE_OK;
! 12417: IdxWrite *pEnd = 0;
! 12418: IdxWrite *pFirst = p->pWrite;
1.5 misho 12419:
1.6.2.1 ! misho 12420: while( rc==SQLITE_OK && pFirst!=pEnd ){
! 12421: IdxWrite *pIter;
! 12422: for(pIter=pFirst; rc==SQLITE_OK && pIter!=pEnd; pIter=pIter->pNext){
! 12423: rc = idxProcessOneTrigger(p, pIter, pzErr);
1.5 misho 12424: }
1.6.2.1 ! misho 12425: pEnd = pFirst;
! 12426: pFirst = p->pWrite;
1.5 misho 12427: }
1.6.2.1 ! misho 12428:
! 12429: return rc;
1.5 misho 12430: }
12431:
12432:
1.6.2.1 ! misho 12433: static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
! 12434: int rc = idxRegisterVtab(p);
! 12435: sqlite3_stmt *pSchema = 0;
1.5 misho 12436:
1.6.2.1 ! misho 12437: /* For each table in the main db schema:
! 12438: **
! 12439: ** 1) Add an entry to the p->pTable list, and
! 12440: ** 2) Create the equivalent virtual table in dbv.
! 12441: */
! 12442: rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg,
! 12443: "SELECT type, name, sql, 1 FROM sqlite_schema "
! 12444: "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' "
! 12445: " UNION ALL "
! 12446: "SELECT type, name, sql, 2 FROM sqlite_schema "
! 12447: "WHERE type = 'trigger'"
! 12448: " AND tbl_name IN(SELECT name FROM sqlite_schema WHERE type = 'view') "
! 12449: "ORDER BY 4, 1"
! 12450: );
! 12451: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){
! 12452: const char *zType = (const char*)sqlite3_column_text(pSchema, 0);
! 12453: const char *zName = (const char*)sqlite3_column_text(pSchema, 1);
! 12454: const char *zSql = (const char*)sqlite3_column_text(pSchema, 2);
1.5 misho 12455:
1.6.2.1 ! misho 12456: if( zType==0 || zName==0 ) continue;
! 12457: if( zType[0]=='v' || zType[1]=='r' ){
! 12458: if( zSql ) rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
! 12459: }else{
! 12460: IdxTable *pTab;
! 12461: rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
! 12462: if( rc==SQLITE_OK ){
! 12463: int i;
! 12464: char *zInner = 0;
! 12465: char *zOuter = 0;
! 12466: pTab->pNext = p->pTable;
! 12467: p->pTable = pTab;
1.5 misho 12468:
1.6.2.1 ! misho 12469: /* The statement the vtab will pass to sqlite3_declare_vtab() */
! 12470: zInner = idxAppendText(&rc, 0, "CREATE TABLE x(");
! 12471: for(i=0; i<pTab->nCol; i++){
! 12472: zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %s",
! 12473: (i==0 ? "" : ", "), pTab->aCol[i].zName, pTab->aCol[i].zColl
! 12474: );
! 12475: }
! 12476: zInner = idxAppendText(&rc, zInner, ")");
1.5 misho 12477:
1.6.2.1 ! misho 12478: /* The CVT statement to create the vtab */
! 12479: zOuter = idxAppendText(&rc, 0,
! 12480: "CREATE VIRTUAL TABLE %Q USING expert(%Q)", zName, zInner
! 12481: );
! 12482: if( rc==SQLITE_OK ){
! 12483: rc = sqlite3_exec(p->dbv, zOuter, 0, 0, pzErrmsg);
! 12484: }
! 12485: sqlite3_free(zInner);
! 12486: sqlite3_free(zOuter);
! 12487: }
! 12488: }
1.5 misho 12489: }
1.6.2.1 ! misho 12490: idxFinalize(&rc, pSchema);
1.5 misho 12491: return rc;
12492: }
12493:
1.6.2.1 ! misho 12494: struct IdxSampleCtx {
! 12495: int iTarget;
! 12496: double target; /* Target nRet/nRow value */
! 12497: double nRow; /* Number of rows seen */
! 12498: double nRet; /* Number of rows returned */
! 12499: };
1.5 misho 12500:
1.6.2.1 ! misho 12501: static void idxSampleFunc(
! 12502: sqlite3_context *pCtx,
! 12503: int argc,
! 12504: sqlite3_value **argv
! 12505: ){
! 12506: struct IdxSampleCtx *p = (struct IdxSampleCtx*)sqlite3_user_data(pCtx);
! 12507: int bRet;
1.5 misho 12508:
1.6.2.1 ! misho 12509: (void)argv;
! 12510: assert( argc==0 );
! 12511: if( p->nRow==0.0 ){
! 12512: bRet = 1;
! 12513: }else{
! 12514: bRet = (p->nRet / p->nRow) <= p->target;
! 12515: if( bRet==0 ){
! 12516: unsigned short rnd;
! 12517: sqlite3_randomness(2, (void*)&rnd);
! 12518: bRet = ((int)rnd % 100) <= p->iTarget;
! 12519: }
! 12520: }
1.5 misho 12521:
1.6.2.1 ! misho 12522: sqlite3_result_int(pCtx, bRet);
! 12523: p->nRow += 1.0;
! 12524: p->nRet += (double)bRet;
! 12525: }
1.5 misho 12526:
1.6.2.1 ! misho 12527: struct IdxRemCtx {
! 12528: int nSlot;
! 12529: struct IdxRemSlot {
! 12530: int eType; /* SQLITE_NULL, INTEGER, REAL, TEXT, BLOB */
! 12531: i64 iVal; /* SQLITE_INTEGER value */
! 12532: double rVal; /* SQLITE_FLOAT value */
! 12533: int nByte; /* Bytes of space allocated at z */
! 12534: int n; /* Size of buffer z */
! 12535: char *z; /* SQLITE_TEXT/BLOB value */
! 12536: } aSlot[1];
! 12537: };
1.5 misho 12538:
12539: /*
1.6.2.1 ! misho 12540: ** Implementation of scalar function rem().
1.5 misho 12541: */
1.6.2.1 ! misho 12542: static void idxRemFunc(
! 12543: sqlite3_context *pCtx,
! 12544: int argc,
! 12545: sqlite3_value **argv
! 12546: ){
! 12547: struct IdxRemCtx *p = (struct IdxRemCtx*)sqlite3_user_data(pCtx);
! 12548: struct IdxRemSlot *pSlot;
! 12549: int iSlot;
! 12550: assert( argc==2 );
1.5 misho 12551:
1.6.2.1 ! misho 12552: iSlot = sqlite3_value_int(argv[0]);
! 12553: assert( iSlot<=p->nSlot );
! 12554: pSlot = &p->aSlot[iSlot];
1.5 misho 12555:
1.6.2.1 ! misho 12556: switch( pSlot->eType ){
! 12557: case SQLITE_NULL:
! 12558: /* no-op */
! 12559: break;
1.5 misho 12560:
1.6.2.1 ! misho 12561: case SQLITE_INTEGER:
! 12562: sqlite3_result_int64(pCtx, pSlot->iVal);
! 12563: break;
1.5 misho 12564:
1.6.2.1 ! misho 12565: case SQLITE_FLOAT:
! 12566: sqlite3_result_double(pCtx, pSlot->rVal);
! 12567: break;
1.5 misho 12568:
1.6.2.1 ! misho 12569: case SQLITE_BLOB:
! 12570: sqlite3_result_blob(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT);
! 12571: break;
1.5 misho 12572:
1.6.2.1 ! misho 12573: case SQLITE_TEXT:
! 12574: sqlite3_result_text(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT);
! 12575: break;
! 12576: }
1.5 misho 12577:
1.6.2.1 ! misho 12578: pSlot->eType = sqlite3_value_type(argv[1]);
! 12579: switch( pSlot->eType ){
! 12580: case SQLITE_NULL:
! 12581: /* no-op */
! 12582: break;
1.5 misho 12583:
1.6.2.1 ! misho 12584: case SQLITE_INTEGER:
! 12585: pSlot->iVal = sqlite3_value_int64(argv[1]);
! 12586: break;
1.5 misho 12587:
1.6.2.1 ! misho 12588: case SQLITE_FLOAT:
! 12589: pSlot->rVal = sqlite3_value_double(argv[1]);
! 12590: break;
1.5 misho 12591:
1.6.2.1 ! misho 12592: case SQLITE_BLOB:
! 12593: case SQLITE_TEXT: {
! 12594: int nByte = sqlite3_value_bytes(argv[1]);
! 12595: const void *pData = 0;
! 12596: if( nByte>pSlot->nByte ){
! 12597: char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2);
! 12598: if( zNew==0 ){
! 12599: sqlite3_result_error_nomem(pCtx);
! 12600: return;
! 12601: }
! 12602: pSlot->nByte = nByte*2;
! 12603: pSlot->z = zNew;
! 12604: }
! 12605: pSlot->n = nByte;
! 12606: if( pSlot->eType==SQLITE_BLOB ){
! 12607: pData = sqlite3_value_blob(argv[1]);
! 12608: if( pData ) memcpy(pSlot->z, pData, nByte);
! 12609: }else{
! 12610: pData = sqlite3_value_text(argv[1]);
! 12611: memcpy(pSlot->z, pData, nByte);
! 12612: }
! 12613: break;
! 12614: }
! 12615: }
! 12616: }
1.5 misho 12617:
1.6.2.1 ! misho 12618: static int idxLargestIndex(sqlite3 *db, int *pnMax, char **pzErr){
! 12619: int rc = SQLITE_OK;
! 12620: const char *zMax =
! 12621: "SELECT max(i.seqno) FROM "
! 12622: " sqlite_schema AS s, "
! 12623: " pragma_index_list(s.name) AS l, "
! 12624: " pragma_index_info(l.name) AS i "
! 12625: "WHERE s.type = 'table'";
! 12626: sqlite3_stmt *pMax = 0;
1.5 misho 12627:
1.6.2.1 ! misho 12628: *pnMax = 0;
! 12629: rc = idxPrepareStmt(db, &pMax, pzErr, zMax);
! 12630: if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){
! 12631: *pnMax = sqlite3_column_int(pMax, 0) + 1;
! 12632: }
! 12633: idxFinalize(&rc, pMax);
1.5 misho 12634:
1.6.2.1 ! misho 12635: return rc;
! 12636: }
1.5 misho 12637:
1.6.2.1 ! misho 12638: static int idxPopulateOneStat1(
! 12639: sqlite3expert *p,
! 12640: sqlite3_stmt *pIndexXInfo,
! 12641: sqlite3_stmt *pWriteStat,
! 12642: const char *zTab,
! 12643: const char *zIdx,
! 12644: char **pzErr
! 12645: ){
! 12646: char *zCols = 0;
! 12647: char *zOrder = 0;
! 12648: char *zQuery = 0;
! 12649: int nCol = 0;
! 12650: int i;
! 12651: sqlite3_stmt *pQuery = 0;
! 12652: int *aStat = 0;
! 12653: int rc = SQLITE_OK;
1.5 misho 12654:
1.6.2.1 ! misho 12655: assert( p->iSample>0 );
1.5 misho 12656:
1.6.2.1 ! misho 12657: /* Formulate the query text */
! 12658: sqlite3_bind_text(pIndexXInfo, 1, zIdx, -1, SQLITE_STATIC);
! 12659: while( SQLITE_OK==rc && SQLITE_ROW==sqlite3_step(pIndexXInfo) ){
! 12660: const char *zComma = zCols==0 ? "" : ", ";
! 12661: const char *zName = (const char*)sqlite3_column_text(pIndexXInfo, 0);
! 12662: const char *zColl = (const char*)sqlite3_column_text(pIndexXInfo, 1);
! 12663: zCols = idxAppendText(&rc, zCols,
! 12664: "%sx.%Q IS rem(%d, x.%Q) COLLATE %s", zComma, zName, nCol, zName, zColl
! 12665: );
! 12666: zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol);
! 12667: }
! 12668: sqlite3_reset(pIndexXInfo);
! 12669: if( rc==SQLITE_OK ){
! 12670: if( p->iSample==100 ){
! 12671: zQuery = sqlite3_mprintf(
! 12672: "SELECT %s FROM %Q x ORDER BY %s", zCols, zTab, zOrder
! 12673: );
! 12674: }else{
! 12675: zQuery = sqlite3_mprintf(
! 12676: "SELECT %s FROM temp."UNIQUE_TABLE_NAME" x ORDER BY %s", zCols, zOrder
! 12677: );
! 12678: }
! 12679: }
! 12680: sqlite3_free(zCols);
! 12681: sqlite3_free(zOrder);
1.5 misho 12682:
1.6.2.1 ! misho 12683: /* Formulate the query text */
! 12684: if( rc==SQLITE_OK ){
! 12685: sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv);
! 12686: rc = idxPrepareStmt(dbrem, &pQuery, pzErr, zQuery);
! 12687: }
! 12688: sqlite3_free(zQuery);
! 12689:
! 12690: if( rc==SQLITE_OK ){
! 12691: aStat = (int*)idxMalloc(&rc, sizeof(int)*(nCol+1));
! 12692: }
! 12693: if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){
! 12694: IdxHashEntry *pEntry;
! 12695: char *zStat = 0;
! 12696: for(i=0; i<=nCol; i++) aStat[i] = 1;
! 12697: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){
! 12698: aStat[0]++;
! 12699: for(i=0; i<nCol; i++){
! 12700: if( sqlite3_column_int(pQuery, i)==0 ) break;
! 12701: }
! 12702: for(/*no-op*/; i<nCol; i++){
! 12703: aStat[i+1]++;
! 12704: }
! 12705: }
1.5 misho 12706:
1.6.2.1 ! misho 12707: if( rc==SQLITE_OK ){
! 12708: int s0 = aStat[0];
! 12709: zStat = sqlite3_mprintf("%d", s0);
! 12710: if( zStat==0 ) rc = SQLITE_NOMEM;
! 12711: for(i=1; rc==SQLITE_OK && i<=nCol; i++){
! 12712: zStat = idxAppendText(&rc, zStat, " %d", (s0+aStat[i]/2) / aStat[i]);
! 12713: }
! 12714: }
1.5 misho 12715:
1.6.2.1 ! misho 12716: if( rc==SQLITE_OK ){
! 12717: sqlite3_bind_text(pWriteStat, 1, zTab, -1, SQLITE_STATIC);
! 12718: sqlite3_bind_text(pWriteStat, 2, zIdx, -1, SQLITE_STATIC);
! 12719: sqlite3_bind_text(pWriteStat, 3, zStat, -1, SQLITE_STATIC);
! 12720: sqlite3_step(pWriteStat);
! 12721: rc = sqlite3_reset(pWriteStat);
! 12722: }
! 12723:
! 12724: pEntry = idxHashFind(&p->hIdx, zIdx, STRLEN(zIdx));
! 12725: if( pEntry ){
! 12726: assert( pEntry->zVal2==0 );
! 12727: pEntry->zVal2 = zStat;
! 12728: }else{
! 12729: sqlite3_free(zStat);
! 12730: }
1.5 misho 12731: }
1.6.2.1 ! misho 12732: sqlite3_free(aStat);
! 12733: idxFinalize(&rc, pQuery);
! 12734:
! 12735: return rc;
1.5 misho 12736: }
12737:
1.6.2.1 ! misho 12738: static int idxBuildSampleTable(sqlite3expert *p, const char *zTab){
! 12739: int rc;
! 12740: char *zSql;
! 12741:
! 12742: rc = sqlite3_exec(p->dbv,"DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
! 12743: if( rc!=SQLITE_OK ) return rc;
! 12744:
! 12745: zSql = sqlite3_mprintf(
! 12746: "CREATE TABLE temp." UNIQUE_TABLE_NAME " AS SELECT * FROM %Q", zTab
! 12747: );
! 12748: if( zSql==0 ) return SQLITE_NOMEM;
! 12749: rc = sqlite3_exec(p->dbv, zSql, 0, 0, 0);
! 12750: sqlite3_free(zSql);
! 12751:
! 12752: return rc;
1.5 misho 12753: }
12754:
12755: /*
1.6.2.1 ! misho 12756: ** This function is called as part of sqlite3_expert_analyze(). Candidate
! 12757: ** indexes have already been created in database sqlite3expert.dbm, this
! 12758: ** function populates sqlite_stat1 table in the same database.
! 12759: **
! 12760: ** The stat1 data is generated by querying the
1.5 misho 12761: */
1.6.2.1 ! misho 12762: static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
! 12763: int rc = SQLITE_OK;
! 12764: int nMax =0;
! 12765: struct IdxRemCtx *pCtx = 0;
! 12766: struct IdxSampleCtx samplectx;
1.5 misho 12767: int i;
1.6.2.1 ! misho 12768: i64 iPrev = -100000;
! 12769: sqlite3_stmt *pAllIndex = 0;
! 12770: sqlite3_stmt *pIndexXInfo = 0;
! 12771: sqlite3_stmt *pWrite = 0;
! 12772:
! 12773: const char *zAllIndex =
! 12774: "SELECT s.rowid, s.name, l.name FROM "
! 12775: " sqlite_schema AS s, "
! 12776: " pragma_index_list(s.name) AS l "
! 12777: "WHERE s.type = 'table'";
! 12778: const char *zIndexXInfo =
! 12779: "SELECT name, coll FROM pragma_index_xinfo(?) WHERE key";
! 12780: const char *zWrite = "INSERT INTO sqlite_stat1 VALUES(?, ?, ?)";
! 12781:
! 12782: /* If iSample==0, no sqlite_stat1 data is required. */
! 12783: if( p->iSample==0 ) return SQLITE_OK;
! 12784:
! 12785: rc = idxLargestIndex(p->dbm, &nMax, pzErr);
! 12786: if( nMax<=0 || rc!=SQLITE_OK ) return rc;
! 12787:
! 12788: rc = sqlite3_exec(p->dbm, "ANALYZE; PRAGMA writable_schema=1", 0, 0, 0);
! 12789:
! 12790: if( rc==SQLITE_OK ){
! 12791: int nByte = sizeof(struct IdxRemCtx) + (sizeof(struct IdxRemSlot) * nMax);
! 12792: pCtx = (struct IdxRemCtx*)idxMalloc(&rc, nByte);
1.5 misho 12793: }
12794:
1.6.2.1 ! misho 12795: if( rc==SQLITE_OK ){
! 12796: sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv);
! 12797: rc = sqlite3_create_function(
! 12798: dbrem, "rem", 2, SQLITE_UTF8, (void*)pCtx, idxRemFunc, 0, 0
! 12799: );
! 12800: }
! 12801: if( rc==SQLITE_OK ){
! 12802: rc = sqlite3_create_function(
! 12803: p->db, "sample", 0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0
! 12804: );
1.5 misho 12805: }
12806:
1.6.2.1 ! misho 12807: if( rc==SQLITE_OK ){
! 12808: pCtx->nSlot = nMax+1;
! 12809: rc = idxPrepareStmt(p->dbm, &pAllIndex, pzErr, zAllIndex);
! 12810: }
! 12811: if( rc==SQLITE_OK ){
! 12812: rc = idxPrepareStmt(p->dbm, &pIndexXInfo, pzErr, zIndexXInfo);
! 12813: }
! 12814: if( rc==SQLITE_OK ){
! 12815: rc = idxPrepareStmt(p->dbm, &pWrite, pzErr, zWrite);
! 12816: }
! 12817:
! 12818: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pAllIndex) ){
! 12819: i64 iRowid = sqlite3_column_int64(pAllIndex, 0);
! 12820: const char *zTab = (const char*)sqlite3_column_text(pAllIndex, 1);
! 12821: const char *zIdx = (const char*)sqlite3_column_text(pAllIndex, 2);
! 12822: if( zTab==0 || zIdx==0 ) continue;
! 12823: if( p->iSample<100 && iPrev!=iRowid ){
! 12824: samplectx.target = (double)p->iSample / 100.0;
! 12825: samplectx.iTarget = p->iSample;
! 12826: samplectx.nRow = 0.0;
! 12827: samplectx.nRet = 0.0;
! 12828: rc = idxBuildSampleTable(p, zTab);
! 12829: if( rc!=SQLITE_OK ) break;
1.5 misho 12830: }
1.6.2.1 ! misho 12831: rc = idxPopulateOneStat1(p, pIndexXInfo, pWrite, zTab, zIdx, pzErr);
! 12832: iPrev = iRowid;
1.5 misho 12833: }
1.6.2.1 ! misho 12834: if( rc==SQLITE_OK && p->iSample<100 ){
! 12835: rc = sqlite3_exec(p->dbv,
! 12836: "DROP TABLE IF EXISTS temp." UNIQUE_TABLE_NAME, 0,0,0
! 12837: );
! 12838: }
! 12839:
! 12840: idxFinalize(&rc, pAllIndex);
! 12841: idxFinalize(&rc, pIndexXInfo);
! 12842: idxFinalize(&rc, pWrite);
! 12843:
! 12844: if( pCtx ){
! 12845: for(i=0; i<pCtx->nSlot; i++){
! 12846: sqlite3_free(pCtx->aSlot[i].z);
1.5 misho 12847: }
1.6.2.1 ! misho 12848: sqlite3_free(pCtx);
! 12849: }
1.5 misho 12850:
1.6.2.1 ! misho 12851: if( rc==SQLITE_OK ){
! 12852: rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_schema", 0, 0, 0);
1.5 misho 12853: }
1.6.2.1 ! misho 12854:
! 12855: sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
! 12856: return rc;
1.5 misho 12857: }
12858:
12859: /*
1.6.2.1 ! misho 12860: ** Allocate a new sqlite3expert object.
1.5 misho 12861: */
1.6.2.1 ! misho 12862: sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
! 12863: int rc = SQLITE_OK;
! 12864: sqlite3expert *pNew;
! 12865:
! 12866: pNew = (sqlite3expert*)idxMalloc(&rc, sizeof(sqlite3expert));
! 12867:
! 12868: /* Open two in-memory databases to work with. The "vtab database" (dbv)
! 12869: ** will contain a virtual table corresponding to each real table in
! 12870: ** the user database schema, and a copy of each view. It is used to
! 12871: ** collect information regarding the WHERE, ORDER BY and other clauses
! 12872: ** of the user's query.
! 12873: */
! 12874: if( rc==SQLITE_OK ){
! 12875: pNew->db = db;
! 12876: pNew->iSample = 100;
! 12877: rc = sqlite3_open(":memory:", &pNew->dbv);
! 12878: }
! 12879: if( rc==SQLITE_OK ){
! 12880: rc = sqlite3_open(":memory:", &pNew->dbm);
! 12881: if( rc==SQLITE_OK ){
! 12882: sqlite3_db_config(pNew->dbm, SQLITE_DBCONFIG_TRIGGER_EQP, 1, (int*)0);
1.5 misho 12883: }
12884: }
1.6.2.1 ! misho 12885:
1.5 misho 12886:
1.6.2.1 ! misho 12887: /* Copy the entire schema of database [db] into [dbm]. */
! 12888: if( rc==SQLITE_OK ){
! 12889: sqlite3_stmt *pSql = 0;
! 12890: rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg,
! 12891: "SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
! 12892: " AND sql NOT LIKE 'CREATE VIRTUAL %%'"
! 12893: );
! 12894: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
! 12895: const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
! 12896: if( zSql ) rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
! 12897: }
! 12898: idxFinalize(&rc, pSql);
! 12899: }
1.5 misho 12900:
1.6.2.1 ! misho 12901: /* Create the vtab schema */
! 12902: if( rc==SQLITE_OK ){
! 12903: rc = idxCreateVtabSchema(pNew, pzErrmsg);
! 12904: }
1.5 misho 12905:
1.6.2.1 ! misho 12906: /* Register the auth callback with dbv */
! 12907: if( rc==SQLITE_OK ){
! 12908: sqlite3_set_authorizer(pNew->dbv, idxAuthCallback, (void*)pNew);
! 12909: }
! 12910:
! 12911: /* If an error has occurred, free the new object and reutrn NULL. Otherwise,
! 12912: ** return the new sqlite3expert handle. */
! 12913: if( rc!=SQLITE_OK ){
! 12914: sqlite3_expert_destroy(pNew);
! 12915: pNew = 0;
1.5 misho 12916: }
12917: return pNew;
12918: }
12919:
12920: /*
1.6.2.1 ! misho 12921: ** Configure an sqlite3expert object.
1.5 misho 12922: */
1.6.2.1 ! misho 12923: int sqlite3_expert_config(sqlite3expert *p, int op, ...){
! 12924: int rc = SQLITE_OK;
! 12925: va_list ap;
! 12926: va_start(ap, op);
! 12927: switch( op ){
! 12928: case EXPERT_CONFIG_SAMPLE: {
! 12929: int iVal = va_arg(ap, int);
! 12930: if( iVal<0 ) iVal = 0;
! 12931: if( iVal>100 ) iVal = 100;
! 12932: p->iSample = iVal;
! 12933: break;
! 12934: }
! 12935: default:
! 12936: rc = SQLITE_NOTFOUND;
! 12937: break;
! 12938: }
! 12939:
! 12940: va_end(ap);
! 12941: return rc;
1.5 misho 12942: }
12943:
12944: /*
1.6.2.1 ! misho 12945: ** Add an SQL statement to the analysis.
1.5 misho 12946: */
1.6.2.1 ! misho 12947: int sqlite3_expert_sql(
! 12948: sqlite3expert *p, /* From sqlite3_expert_new() */
! 12949: const char *zSql, /* SQL statement to add */
! 12950: char **pzErr /* OUT: Error message (if any) */
1.5 misho 12951: ){
1.6.2.1 ! misho 12952: IdxScan *pScanOrig = p->pScan;
! 12953: IdxStatement *pStmtOrig = p->pStatement;
! 12954: int rc = SQLITE_OK;
! 12955: const char *zStmt = zSql;
! 12956:
! 12957: if( p->bRun ) return SQLITE_MISUSE;
! 12958:
! 12959: while( rc==SQLITE_OK && zStmt && zStmt[0] ){
! 12960: sqlite3_stmt *pStmt = 0;
! 12961: rc = sqlite3_prepare_v2(p->dbv, zStmt, -1, &pStmt, &zStmt);
! 12962: if( rc==SQLITE_OK ){
! 12963: if( pStmt ){
! 12964: IdxStatement *pNew;
! 12965: const char *z = sqlite3_sql(pStmt);
! 12966: int n = STRLEN(z);
! 12967: pNew = (IdxStatement*)idxMalloc(&rc, sizeof(IdxStatement) + n+1);
! 12968: if( rc==SQLITE_OK ){
! 12969: pNew->zSql = (char*)&pNew[1];
! 12970: memcpy(pNew->zSql, z, n+1);
! 12971: pNew->pNext = p->pStatement;
! 12972: if( p->pStatement ) pNew->iId = p->pStatement->iId+1;
! 12973: p->pStatement = pNew;
! 12974: }
! 12975: sqlite3_finalize(pStmt);
! 12976: }
! 12977: }else{
! 12978: idxDatabaseError(p->dbv, pzErr);
! 12979: }
! 12980: }
! 12981:
1.5 misho 12982: if( rc!=SQLITE_OK ){
1.6.2.1 ! misho 12983: idxScanFree(p->pScan, pScanOrig);
! 12984: idxStatementFree(p->pStatement, pStmtOrig);
! 12985: p->pScan = pScanOrig;
! 12986: p->pStatement = pStmtOrig;
1.5 misho 12987: }
1.6.2.1 ! misho 12988:
1.5 misho 12989: return rc;
12990: }
12991:
1.6.2.1 ! misho 12992: int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr){
1.5 misho 12993: int rc;
1.6.2.1 ! misho 12994: IdxHashEntry *pEntry;
1.5 misho 12995:
1.6.2.1 ! misho 12996: /* Do trigger processing to collect any extra IdxScan structures */
! 12997: rc = idxProcessTriggers(p, pzErr);
1.5 misho 12998:
1.6.2.1 ! misho 12999: /* Create candidate indexes within the in-memory database file */
! 13000: if( rc==SQLITE_OK ){
! 13001: rc = idxCreateCandidates(p);
! 13002: }else if ( rc==SQLITE_BUSY_TIMEOUT ){
! 13003: if( pzErr )
! 13004: *pzErr = sqlite3_mprintf("Cannot find a unique index name to propose.");
! 13005: return rc;
! 13006: }
1.5 misho 13007:
1.6.2.1 ! misho 13008: /* Generate the stat1 data */
! 13009: if( rc==SQLITE_OK ){
! 13010: rc = idxPopulateStat1(p, pzErr);
! 13011: }
1.5 misho 13012:
1.6.2.1 ! misho 13013: /* Formulate the EXPERT_REPORT_CANDIDATES text */
! 13014: for(pEntry=p->hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
! 13015: p->zCandidates = idxAppendText(&rc, p->zCandidates,
! 13016: "%s;%s%s\n", pEntry->zVal,
! 13017: pEntry->zVal2 ? " -- stat1: " : "", pEntry->zVal2
! 13018: );
! 13019: }
1.5 misho 13020:
1.6.2.1 ! misho 13021: /* Figure out which of the candidate indexes are preferred by the query
! 13022: ** planner and report the results to the user. */
! 13023: if( rc==SQLITE_OK ){
! 13024: rc = idxFindIndexes(p, pzErr);
! 13025: }
1.5 misho 13026:
1.6.2.1 ! misho 13027: if( rc==SQLITE_OK ){
! 13028: p->bRun = 1;
1.5 misho 13029: }
1.6.2.1 ! misho 13030: return rc;
! 13031: }
1.5 misho 13032:
1.6.2.1 ! misho 13033: /*
! 13034: ** Return the total number of statements that have been added to this
! 13035: ** sqlite3expert using sqlite3_expert_sql().
! 13036: */
! 13037: int sqlite3_expert_count(sqlite3expert *p){
! 13038: int nRet = 0;
! 13039: if( p->pStatement ) nRet = p->pStatement->iId+1;
! 13040: return nRet;
1.5 misho 13041: }
13042:
1.6.2.1 ! misho 13043: /*
! 13044: ** Return a component of the report.
1.5 misho 13045: */
1.6.2.1 ! misho 13046: const char *sqlite3_expert_report(sqlite3expert *p, int iStmt, int eReport){
! 13047: const char *zRet = 0;
! 13048: IdxStatement *pStmt;
1.5 misho 13049:
1.6.2.1 ! misho 13050: if( p->bRun==0 ) return 0;
! 13051: for(pStmt=p->pStatement; pStmt && pStmt->iId!=iStmt; pStmt=pStmt->pNext);
! 13052: switch( eReport ){
! 13053: case EXPERT_REPORT_SQL:
! 13054: if( pStmt ) zRet = pStmt->zSql;
! 13055: break;
! 13056: case EXPERT_REPORT_INDEXES:
! 13057: if( pStmt ) zRet = pStmt->zIdx;
! 13058: break;
! 13059: case EXPERT_REPORT_PLAN:
! 13060: if( pStmt ) zRet = pStmt->zEQP;
! 13061: break;
! 13062: case EXPERT_REPORT_CANDIDATES:
! 13063: zRet = p->zCandidates;
! 13064: break;
1.5 misho 13065: }
1.6.2.1 ! misho 13066: return zRet;
1.5 misho 13067: }
13068:
1.6.2.1 ! misho 13069: /*
! 13070: ** Free an sqlite3expert object.
! 13071: */
! 13072: void sqlite3_expert_destroy(sqlite3expert *p){
! 13073: if( p ){
! 13074: sqlite3_close(p->dbm);
! 13075: sqlite3_close(p->dbv);
! 13076: idxScanFree(p->pScan, 0);
! 13077: idxStatementFree(p->pStatement, 0);
! 13078: idxTableFree(p->pTable);
! 13079: idxWriteFree(p->pWrite);
! 13080: idxHashClear(&p->hIdx);
! 13081: sqlite3_free(p->zCandidates);
! 13082: sqlite3_free(p);
! 13083: }
1.5 misho 13084: }
13085:
1.6.2.1 ! misho 13086: #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
! 13087:
! 13088: /************************* End ../ext/expert/sqlite3expert.c ********************/
1.5 misho 13089:
1.6.2.1 ! misho 13090: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
! 13091: #define SQLITE_SHELL_HAVE_RECOVER 1
! 13092: #else
! 13093: #define SQLITE_SHELL_HAVE_RECOVER 0
! 13094: #endif
! 13095: #if SQLITE_SHELL_HAVE_RECOVER
! 13096: /************************* Begin ../ext/recover/sqlite3recover.h ******************/
! 13097: /*
! 13098: ** 2022-08-27
! 13099: **
! 13100: ** The author disclaims copyright to this source code. In place of
! 13101: ** a legal notice, here is a blessing:
! 13102: **
! 13103: ** May you do good and not evil.
! 13104: ** May you find forgiveness for yourself and forgive others.
! 13105: ** May you share freely, never taking more than you give.
! 13106: **
! 13107: *************************************************************************
! 13108: **
! 13109: ** This file contains the public interface to the "recover" extension -
! 13110: ** an SQLite extension designed to recover data from corrupted database
! 13111: ** files.
! 13112: */
1.5 misho 13113:
1.6.2.1 ! misho 13114: /*
! 13115: ** OVERVIEW:
! 13116: **
! 13117: ** To use the API to recover data from a corrupted database, an
! 13118: ** application:
! 13119: **
! 13120: ** 1) Creates an sqlite3_recover handle by calling either
! 13121: ** sqlite3_recover_init() or sqlite3_recover_init_sql().
! 13122: **
! 13123: ** 2) Configures the new handle using one or more calls to
! 13124: ** sqlite3_recover_config().
! 13125: **
! 13126: ** 3) Executes the recovery by repeatedly calling sqlite3_recover_step() on
! 13127: ** the handle until it returns something other than SQLITE_OK. If it
! 13128: ** returns SQLITE_DONE, then the recovery operation completed without
! 13129: ** error. If it returns some other non-SQLITE_OK value, then an error
! 13130: ** has occurred.
! 13131: **
! 13132: ** 4) Retrieves any error code and English language error message using the
! 13133: ** sqlite3_recover_errcode() and sqlite3_recover_errmsg() APIs,
! 13134: ** respectively.
! 13135: **
! 13136: ** 5) Destroys the sqlite3_recover handle and frees all resources
! 13137: ** using sqlite3_recover_finish().
! 13138: **
! 13139: ** The application may abandon the recovery operation at any point
! 13140: ** before it is finished by passing the sqlite3_recover handle to
! 13141: ** sqlite3_recover_finish(). This is not an error, but the final state
! 13142: ** of the output database, or the results of running the partial script
! 13143: ** delivered to the SQL callback, are undefined.
! 13144: */
1.5 misho 13145:
1.6.2.1 ! misho 13146: #ifndef _SQLITE_RECOVER_H
! 13147: #define _SQLITE_RECOVER_H
1.5 misho 13148:
1.6.2.1 ! misho 13149: /* #include "sqlite3.h" */
1.5 misho 13150:
1.6.2.1 ! misho 13151: #ifdef __cplusplus
! 13152: extern "C" {
! 13153: #endif
1.5 misho 13154:
1.6.2.1 ! misho 13155: /*
! 13156: ** An instance of the sqlite3_recover object represents a recovery
! 13157: ** operation in progress.
! 13158: **
! 13159: ** Constructors:
! 13160: **
! 13161: ** sqlite3_recover_init()
! 13162: ** sqlite3_recover_init_sql()
! 13163: **
! 13164: ** Destructor:
! 13165: **
! 13166: ** sqlite3_recover_finish()
! 13167: **
! 13168: ** Methods:
! 13169: **
! 13170: ** sqlite3_recover_config()
! 13171: ** sqlite3_recover_errcode()
! 13172: ** sqlite3_recover_errmsg()
! 13173: ** sqlite3_recover_run()
! 13174: ** sqlite3_recover_step()
! 13175: */
! 13176: typedef struct sqlite3_recover sqlite3_recover;
1.5 misho 13177:
13178: /*
1.6.2.1 ! misho 13179: ** These two APIs attempt to create and return a new sqlite3_recover object.
! 13180: ** In both cases the first two arguments identify the (possibly
! 13181: ** corrupt) database to recover data from. The first argument is an open
! 13182: ** database handle and the second the name of a database attached to that
! 13183: ** handle (i.e. "main", "temp" or the name of an attached database).
! 13184: **
! 13185: ** If sqlite3_recover_init() is used to create the new sqlite3_recover
! 13186: ** handle, then data is recovered into a new database, identified by
! 13187: ** string parameter zUri. zUri may be an absolute or relative file path,
! 13188: ** or may be an SQLite URI. If the identified database file already exists,
! 13189: ** it is overwritten.
! 13190: **
! 13191: ** If sqlite3_recover_init_sql() is invoked, then any recovered data will
! 13192: ** be returned to the user as a series of SQL statements. Executing these
! 13193: ** SQL statements results in the same database as would have been created
! 13194: ** had sqlite3_recover_init() been used. For each SQL statement in the
! 13195: ** output, the callback function passed as the third argument (xSql) is
! 13196: ** invoked once. The first parameter is a passed a copy of the fourth argument
! 13197: ** to this function (pCtx) as its first parameter, and a pointer to a
! 13198: ** nul-terminated buffer containing the SQL statement formated as UTF-8 as
! 13199: ** the second. If the xSql callback returns any value other than SQLITE_OK,
! 13200: ** then processing is immediately abandoned and the value returned used as
! 13201: ** the recover handle error code (see below).
! 13202: **
! 13203: ** If an out-of-memory error occurs, NULL may be returned instead of
! 13204: ** a valid handle. In all other cases, it is the responsibility of the
! 13205: ** application to avoid resource leaks by ensuring that
! 13206: ** sqlite3_recover_finish() is called on all allocated handles.
! 13207: */
! 13208: sqlite3_recover *sqlite3_recover_init(
! 13209: sqlite3* db,
! 13210: const char *zDb,
! 13211: const char *zUri
! 13212: );
! 13213: sqlite3_recover *sqlite3_recover_init_sql(
! 13214: sqlite3* db,
! 13215: const char *zDb,
! 13216: int (*xSql)(void*, const char*),
! 13217: void *pCtx
! 13218: );
! 13219:
! 13220: /*
! 13221: ** Configure an sqlite3_recover object that has just been created using
! 13222: ** sqlite3_recover_init() or sqlite3_recover_init_sql(). This function
! 13223: ** may only be called before the first call to sqlite3_recover_step()
! 13224: ** or sqlite3_recover_run() on the object.
! 13225: **
! 13226: ** The second argument passed to this function must be one of the
! 13227: ** SQLITE_RECOVER_* symbols defined below. Valid values for the third argument
! 13228: ** depend on the specific SQLITE_RECOVER_* symbol in use.
! 13229: **
! 13230: ** SQLITE_OK is returned if the configuration operation was successful,
! 13231: ** or an SQLite error code otherwise.
! 13232: */
! 13233: int sqlite3_recover_config(sqlite3_recover*, int op, void *pArg);
! 13234:
! 13235: /*
! 13236: ** SQLITE_RECOVER_LOST_AND_FOUND:
! 13237: ** The pArg argument points to a string buffer containing the name
! 13238: ** of a "lost-and-found" table in the output database, or NULL. If
! 13239: ** the argument is non-NULL and the database contains seemingly
! 13240: ** valid pages that cannot be associated with any table in the
! 13241: ** recovered part of the schema, data is extracted from these
! 13242: ** pages to add to the lost-and-found table.
! 13243: **
! 13244: ** SQLITE_RECOVER_FREELIST_CORRUPT:
! 13245: ** The pArg value must actually be a pointer to a value of type
! 13246: ** int containing value 0 or 1 cast as a (void*). If this option is set
! 13247: ** (argument is 1) and a lost-and-found table has been configured using
! 13248: ** SQLITE_RECOVER_LOST_AND_FOUND, then is assumed that the freelist is
! 13249: ** corrupt and an attempt is made to recover records from pages that
! 13250: ** appear to be linked into the freelist. Otherwise, pages on the freelist
! 13251: ** are ignored. Setting this option can recover more data from the
! 13252: ** database, but often ends up "recovering" deleted records. The default
! 13253: ** value is 0 (clear).
! 13254: **
! 13255: ** SQLITE_RECOVER_ROWIDS:
! 13256: ** The pArg value must actually be a pointer to a value of type
! 13257: ** int containing value 0 or 1 cast as a (void*). If this option is set
! 13258: ** (argument is 1), then an attempt is made to recover rowid values
! 13259: ** that are not also INTEGER PRIMARY KEY values. If this option is
! 13260: ** clear, then new rowids are assigned to all recovered rows. The
! 13261: ** default value is 1 (set).
! 13262: **
! 13263: ** SQLITE_RECOVER_SLOWINDEXES:
! 13264: ** The pArg value must actually be a pointer to a value of type
! 13265: ** int containing value 0 or 1 cast as a (void*). If this option is clear
! 13266: ** (argument is 0), then when creating an output database, the recover
! 13267: ** module creates and populates non-UNIQUE indexes right at the end of the
! 13268: ** recovery operation - after all recoverable data has been inserted
! 13269: ** into the new database. This is faster overall, but means that the
! 13270: ** final call to sqlite3_recover_step() for a recovery operation may
! 13271: ** be need to create a large number of indexes, which may be very slow.
! 13272: **
! 13273: ** Or, if this option is set (argument is 1), then non-UNIQUE indexes
! 13274: ** are created in the output database before it is populated with
! 13275: ** recovered data. This is slower overall, but avoids the slow call
! 13276: ** to sqlite3_recover_step() at the end of the recovery operation.
! 13277: **
! 13278: ** The default option value is 0.
! 13279: */
! 13280: #define SQLITE_RECOVER_LOST_AND_FOUND 1
! 13281: #define SQLITE_RECOVER_FREELIST_CORRUPT 2
! 13282: #define SQLITE_RECOVER_ROWIDS 3
! 13283: #define SQLITE_RECOVER_SLOWINDEXES 4
! 13284:
! 13285: /*
! 13286: ** Perform a unit of work towards the recovery operation. This function
! 13287: ** must normally be called multiple times to complete database recovery.
! 13288: **
! 13289: ** If no error occurs but the recovery operation is not completed, this
! 13290: ** function returns SQLITE_OK. If recovery has been completed successfully
! 13291: ** then SQLITE_DONE is returned. If an error has occurred, then an SQLite
! 13292: ** error code (e.g. SQLITE_IOERR or SQLITE_NOMEM) is returned. It is not
! 13293: ** considered an error if some or all of the data cannot be recovered
! 13294: ** due to database corruption.
! 13295: **
! 13296: ** Once sqlite3_recover_step() has returned a value other than SQLITE_OK,
! 13297: ** all further such calls on the same recover handle are no-ops that return
! 13298: ** the same non-SQLITE_OK value.
1.5 misho 13299: */
1.6.2.1 ! misho 13300: int sqlite3_recover_step(sqlite3_recover*);
1.5 misho 13301:
13302: /*
1.6.2.1 ! misho 13303: ** Run the recovery operation to completion. Return SQLITE_OK if successful,
! 13304: ** or an SQLite error code otherwise. Calling this function is the same
! 13305: ** as executing:
! 13306: **
! 13307: ** while( SQLITE_OK==sqlite3_recover_step(p) );
! 13308: ** return sqlite3_recover_errcode(p);
1.5 misho 13309: */
1.6.2.1 ! misho 13310: int sqlite3_recover_run(sqlite3_recover*);
1.5 misho 13311:
13312: /*
1.6.2.1 ! misho 13313: ** If an error has been encountered during a prior call to
! 13314: ** sqlite3_recover_step(), then this function attempts to return a
! 13315: ** pointer to a buffer containing an English language explanation of
! 13316: ** the error. If no error message is available, or if an out-of memory
! 13317: ** error occurs while attempting to allocate a buffer in which to format
! 13318: ** the error message, NULL is returned.
1.5 misho 13319: **
1.6.2.1 ! misho 13320: ** The returned buffer remains valid until the sqlite3_recover handle is
! 13321: ** destroyed using sqlite3_recover_finish().
1.5 misho 13322: */
1.6.2.1 ! misho 13323: const char *sqlite3_recover_errmsg(sqlite3_recover*);
! 13324:
! 13325: /*
! 13326: ** If this function is called on an sqlite3_recover handle after
! 13327: ** an error occurs, an SQLite error code is returned. Otherwise, SQLITE_OK.
! 13328: */
! 13329: int sqlite3_recover_errcode(sqlite3_recover*);
1.5 misho 13330:
13331: /*
1.6.2.1 ! misho 13332: ** Clean up a recovery object created by a call to sqlite3_recover_init().
! 13333: ** The results of using a recovery object with any API after it has been
! 13334: ** passed to this function are undefined.
! 13335: **
! 13336: ** This function returns the same value as sqlite3_recover_errcode().
1.5 misho 13337: */
1.6.2.1 ! misho 13338: int sqlite3_recover_finish(sqlite3_recover*);
1.5 misho 13339:
13340:
1.6.2.1 ! misho 13341: #ifdef __cplusplus
! 13342: } /* end of the 'extern "C"' block */
! 13343: #endif
! 13344:
! 13345: #endif /* ifndef _SQLITE_RECOVER_H */
! 13346:
! 13347: /************************* End ../ext/recover/sqlite3recover.h ********************/
! 13348: # ifndef SQLITE_HAVE_SQLITE3R
! 13349: /************************* Begin ../ext/recover/dbdata.c ******************/
! 13350: /*
! 13351: ** 2019-04-17
! 13352: **
! 13353: ** The author disclaims copyright to this source code. In place of
! 13354: ** a legal notice, here is a blessing:
! 13355: **
! 13356: ** May you do good and not evil.
! 13357: ** May you find forgiveness for yourself and forgive others.
! 13358: ** May you share freely, never taking more than you give.
! 13359: **
! 13360: ******************************************************************************
! 13361: **
! 13362: ** This file contains an implementation of two eponymous virtual tables,
! 13363: ** "sqlite_dbdata" and "sqlite_dbptr". Both modules require that the
! 13364: ** "sqlite_dbpage" eponymous virtual table be available.
! 13365: **
! 13366: ** SQLITE_DBDATA:
! 13367: ** sqlite_dbdata is used to extract data directly from a database b-tree
! 13368: ** page and its associated overflow pages, bypassing the b-tree layer.
! 13369: ** The table schema is equivalent to:
! 13370: **
! 13371: ** CREATE TABLE sqlite_dbdata(
! 13372: ** pgno INTEGER,
! 13373: ** cell INTEGER,
! 13374: ** field INTEGER,
! 13375: ** value ANY,
! 13376: ** schema TEXT HIDDEN
! 13377: ** );
! 13378: **
! 13379: ** IMPORTANT: THE VIRTUAL TABLE SCHEMA ABOVE IS SUBJECT TO CHANGE. IN THE
! 13380: ** FUTURE NEW NON-HIDDEN COLUMNS MAY BE ADDED BETWEEN "value" AND
! 13381: ** "schema".
! 13382: **
! 13383: ** Each page of the database is inspected. If it cannot be interpreted as
! 13384: ** a b-tree page, or if it is a b-tree page containing 0 entries, the
! 13385: ** sqlite_dbdata table contains no rows for that page. Otherwise, the
! 13386: ** table contains one row for each field in the record associated with
! 13387: ** each cell on the page. For intkey b-trees, the key value is stored in
! 13388: ** field -1.
! 13389: **
! 13390: ** For example, for the database:
! 13391: **
! 13392: ** CREATE TABLE t1(a, b); -- root page is page 2
! 13393: ** INSERT INTO t1(rowid, a, b) VALUES(5, 'v', 'five');
! 13394: ** INSERT INTO t1(rowid, a, b) VALUES(10, 'x', 'ten');
! 13395: **
! 13396: ** the sqlite_dbdata table contains, as well as from entries related to
! 13397: ** page 1, content equivalent to:
! 13398: **
! 13399: ** INSERT INTO sqlite_dbdata(pgno, cell, field, value) VALUES
! 13400: ** (2, 0, -1, 5 ),
! 13401: ** (2, 0, 0, 'v' ),
! 13402: ** (2, 0, 1, 'five'),
! 13403: ** (2, 1, -1, 10 ),
! 13404: ** (2, 1, 0, 'x' ),
! 13405: ** (2, 1, 1, 'ten' );
! 13406: **
! 13407: ** If database corruption is encountered, this module does not report an
! 13408: ** error. Instead, it attempts to extract as much data as possible and
! 13409: ** ignores the corruption.
! 13410: **
! 13411: ** SQLITE_DBPTR:
! 13412: ** The sqlite_dbptr table has the following schema:
! 13413: **
! 13414: ** CREATE TABLE sqlite_dbptr(
! 13415: ** pgno INTEGER,
! 13416: ** child INTEGER,
! 13417: ** schema TEXT HIDDEN
! 13418: ** );
! 13419: **
! 13420: ** It contains one entry for each b-tree pointer between a parent and
! 13421: ** child page in the database.
! 13422: */
! 13423:
! 13424: #if !defined(SQLITEINT_H)
! 13425: /* #include "sqlite3.h" */
! 13426:
! 13427: /* typedef unsigned char u8; */
! 13428: /* typedef unsigned int u32; */
! 13429:
! 13430: #endif
! 13431: #include <string.h>
! 13432: #include <assert.h>
! 13433:
! 13434: #ifndef SQLITE_OMIT_VIRTUALTABLE
! 13435:
! 13436: #define DBDATA_PADDING_BYTES 100
! 13437:
! 13438: typedef struct DbdataTable DbdataTable;
! 13439: typedef struct DbdataCursor DbdataCursor;
! 13440:
! 13441: /* Cursor object */
! 13442: struct DbdataCursor {
! 13443: sqlite3_vtab_cursor base; /* Base class. Must be first */
! 13444: sqlite3_stmt *pStmt; /* For fetching database pages */
! 13445:
! 13446: int iPgno; /* Current page number */
! 13447: u8 *aPage; /* Buffer containing page */
! 13448: int nPage; /* Size of aPage[] in bytes */
! 13449: int nCell; /* Number of cells on aPage[] */
! 13450: int iCell; /* Current cell number */
! 13451: int bOnePage; /* True to stop after one page */
! 13452: int szDb;
! 13453: sqlite3_int64 iRowid;
! 13454:
! 13455: /* Only for the sqlite_dbdata table */
! 13456: u8 *pRec; /* Buffer containing current record */
! 13457: sqlite3_int64 nRec; /* Size of pRec[] in bytes */
! 13458: sqlite3_int64 nHdr; /* Size of header in bytes */
! 13459: int iField; /* Current field number */
! 13460: u8 *pHdrPtr;
! 13461: u8 *pPtr;
! 13462: u32 enc; /* Text encoding */
! 13463:
! 13464: sqlite3_int64 iIntkey; /* Integer key value */
! 13465: };
1.5 misho 13466:
1.6.2.1 ! misho 13467: /* Table object */
! 13468: struct DbdataTable {
! 13469: sqlite3_vtab base; /* Base class. Must be first */
! 13470: sqlite3 *db; /* The database connection */
! 13471: sqlite3_stmt *pStmt; /* For fetching database pages */
! 13472: int bPtr; /* True for sqlite3_dbptr table */
! 13473: };
1.5 misho 13474:
1.6.2.1 ! misho 13475: /* Column and schema definitions for sqlite_dbdata */
! 13476: #define DBDATA_COLUMN_PGNO 0
! 13477: #define DBDATA_COLUMN_CELL 1
! 13478: #define DBDATA_COLUMN_FIELD 2
! 13479: #define DBDATA_COLUMN_VALUE 3
! 13480: #define DBDATA_COLUMN_SCHEMA 4
! 13481: #define DBDATA_SCHEMA \
! 13482: "CREATE TABLE x(" \
! 13483: " pgno INTEGER," \
! 13484: " cell INTEGER," \
! 13485: " field INTEGER," \
! 13486: " value ANY," \
! 13487: " schema TEXT HIDDEN" \
! 13488: ")"
1.5 misho 13489:
1.6.2.1 ! misho 13490: /* Column and schema definitions for sqlite_dbptr */
! 13491: #define DBPTR_COLUMN_PGNO 0
! 13492: #define DBPTR_COLUMN_CHILD 1
! 13493: #define DBPTR_COLUMN_SCHEMA 2
! 13494: #define DBPTR_SCHEMA \
! 13495: "CREATE TABLE x(" \
! 13496: " pgno INTEGER," \
! 13497: " child INTEGER," \
! 13498: " schema TEXT HIDDEN" \
! 13499: ")"
! 13500:
! 13501: /*
! 13502: ** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual
! 13503: ** table.
1.5 misho 13504: */
1.6.2.1 ! misho 13505: static int dbdataConnect(
! 13506: sqlite3 *db,
! 13507: void *pAux,
! 13508: int argc, const char *const*argv,
! 13509: sqlite3_vtab **ppVtab,
! 13510: char **pzErr
1.5 misho 13511: ){
1.6.2.1 ! misho 13512: DbdataTable *pTab = 0;
! 13513: int rc = sqlite3_declare_vtab(db, pAux ? DBPTR_SCHEMA : DBDATA_SCHEMA);
1.5 misho 13514:
13515: (void)argc;
13516: (void)argv;
1.6.2.1 ! misho 13517: (void)pzErr;
! 13518: sqlite3_vtab_config(db, SQLITE_VTAB_USES_ALL_SCHEMAS);
1.5 misho 13519: if( rc==SQLITE_OK ){
1.6.2.1 ! misho 13520: pTab = (DbdataTable*)sqlite3_malloc64(sizeof(DbdataTable));
! 13521: if( pTab==0 ){
! 13522: rc = SQLITE_NOMEM;
! 13523: }else{
! 13524: memset(pTab, 0, sizeof(DbdataTable));
! 13525: pTab->db = db;
! 13526: pTab->bPtr = (pAux!=0);
! 13527: }
1.5 misho 13528: }
13529:
1.6.2.1 ! misho 13530: *ppVtab = (sqlite3_vtab*)pTab;
1.5 misho 13531: return rc;
13532: }
13533:
13534: /*
1.6.2.1 ! misho 13535: ** Disconnect from or destroy a sqlite_dbdata or sqlite_dbptr virtual table.
1.5 misho 13536: */
1.6.2.1 ! misho 13537: static int dbdataDisconnect(sqlite3_vtab *pVtab){
! 13538: DbdataTable *pTab = (DbdataTable*)pVtab;
! 13539: if( pTab ){
! 13540: sqlite3_finalize(pTab->pStmt);
! 13541: sqlite3_free(pVtab);
! 13542: }
! 13543: return SQLITE_OK;
1.5 misho 13544: }
13545:
13546: /*
1.6.2.1 ! misho 13547: ** This function interprets two types of constraints:
1.5 misho 13548: **
1.6.2.1 ! misho 13549: ** schema=?
! 13550: ** pgno=?
! 13551: **
! 13552: ** If neither are present, idxNum is set to 0. If schema=? is present,
! 13553: ** the 0x01 bit in idxNum is set. If pgno=? is present, the 0x02 bit
! 13554: ** in idxNum is set.
! 13555: **
! 13556: ** If both parameters are present, schema is in position 0 and pgno in
! 13557: ** position 1.
1.5 misho 13558: */
1.6.2.1 ! misho 13559: static int dbdataBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdx){
! 13560: DbdataTable *pTab = (DbdataTable*)tab;
! 13561: int i;
! 13562: int iSchema = -1;
! 13563: int iPgno = -1;
! 13564: int colSchema = (pTab->bPtr ? DBPTR_COLUMN_SCHEMA : DBDATA_COLUMN_SCHEMA);
1.5 misho 13565:
1.6.2.1 ! misho 13566: for(i=0; i<pIdx->nConstraint; i++){
! 13567: struct sqlite3_index_constraint *p = &pIdx->aConstraint[i];
! 13568: if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
! 13569: if( p->iColumn==colSchema ){
! 13570: if( p->usable==0 ) return SQLITE_CONSTRAINT;
! 13571: iSchema = i;
! 13572: }
! 13573: if( p->iColumn==DBDATA_COLUMN_PGNO && p->usable ){
! 13574: iPgno = i;
! 13575: }
! 13576: }
1.5 misho 13577: }
13578:
1.6.2.1 ! misho 13579: if( iSchema>=0 ){
! 13580: pIdx->aConstraintUsage[iSchema].argvIndex = 1;
! 13581: pIdx->aConstraintUsage[iSchema].omit = 1;
1.5 misho 13582: }
1.6.2.1 ! misho 13583: if( iPgno>=0 ){
! 13584: pIdx->aConstraintUsage[iPgno].argvIndex = 1 + (iSchema>=0);
! 13585: pIdx->aConstraintUsage[iPgno].omit = 1;
! 13586: pIdx->estimatedCost = 100;
! 13587: pIdx->estimatedRows = 50;
1.5 misho 13588:
1.6.2.1 ! misho 13589: if( pTab->bPtr==0 && pIdx->nOrderBy && pIdx->aOrderBy[0].desc==0 ){
! 13590: int iCol = pIdx->aOrderBy[0].iColumn;
! 13591: if( pIdx->nOrderBy==1 ){
! 13592: pIdx->orderByConsumed = (iCol==0 || iCol==1);
! 13593: }else if( pIdx->nOrderBy==2 && pIdx->aOrderBy[1].desc==0 && iCol==0 ){
! 13594: pIdx->orderByConsumed = (pIdx->aOrderBy[1].iColumn==1);
! 13595: }
1.5 misho 13596: }
13597:
1.6.2.1 ! misho 13598: }else{
! 13599: pIdx->estimatedCost = 100000000;
! 13600: pIdx->estimatedRows = 1000000000;
! 13601: }
! 13602: pIdx->idxNum = (iSchema>=0 ? 0x01 : 0x00) | (iPgno>=0 ? 0x02 : 0x00);
! 13603: return SQLITE_OK;
! 13604: }
! 13605:
! 13606: /*
! 13607: ** Open a new sqlite_dbdata or sqlite_dbptr cursor.
! 13608: */
! 13609: static int dbdataOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
! 13610: DbdataCursor *pCsr;
1.5 misho 13611:
1.6.2.1 ! misho 13612: pCsr = (DbdataCursor*)sqlite3_malloc64(sizeof(DbdataCursor));
! 13613: if( pCsr==0 ){
! 13614: return SQLITE_NOMEM;
1.5 misho 13615: }else{
1.6.2.1 ! misho 13616: memset(pCsr, 0, sizeof(DbdataCursor));
! 13617: pCsr->base.pVtab = pVTab;
1.5 misho 13618: }
13619:
1.6.2.1 ! misho 13620: *ppCursor = (sqlite3_vtab_cursor *)pCsr;
! 13621: return SQLITE_OK;
1.5 misho 13622: }
13623:
13624: /*
1.6.2.1 ! misho 13625: ** Restore a cursor object to the state it was in when first allocated
! 13626: ** by dbdataOpen().
1.5 misho 13627: */
1.6.2.1 ! misho 13628: static void dbdataResetCursor(DbdataCursor *pCsr){
! 13629: DbdataTable *pTab = (DbdataTable*)(pCsr->base.pVtab);
! 13630: if( pTab->pStmt==0 ){
! 13631: pTab->pStmt = pCsr->pStmt;
! 13632: }else{
! 13633: sqlite3_finalize(pCsr->pStmt);
1.5 misho 13634: }
1.6.2.1 ! misho 13635: pCsr->pStmt = 0;
! 13636: pCsr->iPgno = 1;
! 13637: pCsr->iCell = 0;
! 13638: pCsr->iField = 0;
! 13639: pCsr->bOnePage = 0;
! 13640: sqlite3_free(pCsr->aPage);
! 13641: sqlite3_free(pCsr->pRec);
! 13642: pCsr->pRec = 0;
! 13643: pCsr->aPage = 0;
1.5 misho 13644: }
13645:
13646: /*
1.6.2.1 ! misho 13647: ** Close an sqlite_dbdata or sqlite_dbptr cursor.
1.5 misho 13648: */
1.6.2.1 ! misho 13649: static int dbdataClose(sqlite3_vtab_cursor *pCursor){
! 13650: DbdataCursor *pCsr = (DbdataCursor*)pCursor;
! 13651: dbdataResetCursor(pCsr);
! 13652: sqlite3_free(pCsr);
! 13653: return SQLITE_OK;
! 13654: }
! 13655:
! 13656: /*
! 13657: ** Utility methods to decode 16 and 32-bit big-endian unsigned integers.
! 13658: */
! 13659: static u32 get_uint16(unsigned char *a){
! 13660: return (a[0]<<8)|a[1];
! 13661: }
! 13662: static u32 get_uint32(unsigned char *a){
! 13663: return ((u32)a[0]<<24)
! 13664: | ((u32)a[1]<<16)
! 13665: | ((u32)a[2]<<8)
! 13666: | ((u32)a[3]);
1.5 misho 13667: }
13668:
13669: /*
1.6.2.1 ! misho 13670: ** Load page pgno from the database via the sqlite_dbpage virtual table.
! 13671: ** If successful, set (*ppPage) to point to a buffer containing the page
! 13672: ** data, (*pnPage) to the size of that buffer in bytes and return
! 13673: ** SQLITE_OK. In this case it is the responsibility of the caller to
! 13674: ** eventually free the buffer using sqlite3_free().
! 13675: **
! 13676: ** Or, if an error occurs, set both (*ppPage) and (*pnPage) to 0 and
! 13677: ** return an SQLite error code.
1.5 misho 13678: */
1.6.2.1 ! misho 13679: static int dbdataLoadPage(
! 13680: DbdataCursor *pCsr, /* Cursor object */
! 13681: u32 pgno, /* Page number of page to load */
! 13682: u8 **ppPage, /* OUT: pointer to page buffer */
! 13683: int *pnPage /* OUT: Size of (*ppPage) in bytes */
1.5 misho 13684: ){
1.6.2.1 ! misho 13685: int rc2;
! 13686: int rc = SQLITE_OK;
! 13687: sqlite3_stmt *pStmt = pCsr->pStmt;
1.5 misho 13688:
1.6.2.1 ! misho 13689: *ppPage = 0;
! 13690: *pnPage = 0;
! 13691: if( pgno>0 ){
! 13692: sqlite3_bind_int64(pStmt, 2, pgno);
! 13693: if( SQLITE_ROW==sqlite3_step(pStmt) ){
! 13694: int nCopy = sqlite3_column_bytes(pStmt, 0);
! 13695: if( nCopy>0 ){
! 13696: u8 *pPage;
! 13697: pPage = (u8*)sqlite3_malloc64(nCopy + DBDATA_PADDING_BYTES);
! 13698: if( pPage==0 ){
! 13699: rc = SQLITE_NOMEM;
! 13700: }else{
! 13701: const u8 *pCopy = sqlite3_column_blob(pStmt, 0);
! 13702: memcpy(pPage, pCopy, nCopy);
! 13703: memset(&pPage[nCopy], 0, DBDATA_PADDING_BYTES);
! 13704: }
! 13705: *ppPage = pPage;
! 13706: *pnPage = nCopy;
! 13707: }
1.5 misho 13708: }
1.6.2.1 ! misho 13709: rc2 = sqlite3_reset(pStmt);
! 13710: if( rc==SQLITE_OK ) rc = rc2;
1.5 misho 13711: }
13712:
1.6.2.1 ! misho 13713: return rc;
1.5 misho 13714: }
13715:
13716: /*
1.6.2.1 ! misho 13717: ** Read a varint. Put the value in *pVal and return the number of bytes.
1.5 misho 13718: */
1.6.2.1 ! misho 13719: static int dbdataGetVarint(const u8 *z, sqlite3_int64 *pVal){
! 13720: sqlite3_uint64 u = 0;
! 13721: int i;
! 13722: for(i=0; i<8; i++){
! 13723: u = (u<<7) + (z[i]&0x7f);
! 13724: if( (z[i]&0x80)==0 ){ *pVal = (sqlite3_int64)u; return i+1; }
! 13725: }
! 13726: u = (u<<8) + (z[i]&0xff);
! 13727: *pVal = (sqlite3_int64)u;
! 13728: return 9;
! 13729: }
1.5 misho 13730:
1.6.2.1 ! misho 13731: /*
! 13732: ** Like dbdataGetVarint(), but set the output to 0 if it is less than 0
! 13733: ** or greater than 0xFFFFFFFF. This can be used for all varints in an
! 13734: ** SQLite database except for key values in intkey tables.
! 13735: */
! 13736: static int dbdataGetVarintU32(const u8 *z, sqlite3_int64 *pVal){
! 13737: sqlite3_int64 val;
! 13738: int nRet = dbdataGetVarint(z, &val);
! 13739: if( val<0 || val>0xFFFFFFFF ) val = 0;
! 13740: *pVal = val;
! 13741: return nRet;
! 13742: }
1.5 misho 13743:
1.6.2.1 ! misho 13744: /*
! 13745: ** Return the number of bytes of space used by an SQLite value of type
! 13746: ** eType.
! 13747: */
! 13748: static int dbdataValueBytes(int eType){
! 13749: switch( eType ){
! 13750: case 0: case 8: case 9:
! 13751: case 10: case 11:
! 13752: return 0;
! 13753: case 1:
! 13754: return 1;
! 13755: case 2:
! 13756: return 2;
! 13757: case 3:
! 13758: return 3;
! 13759: case 4:
! 13760: return 4;
! 13761: case 5:
! 13762: return 6;
! 13763: case 6:
! 13764: case 7:
! 13765: return 8;
! 13766: default:
! 13767: if( eType>0 ){
! 13768: return ((eType-12) / 2);
! 13769: }
! 13770: return 0;
! 13771: }
! 13772: }
1.5 misho 13773:
1.6.2.1 ! misho 13774: /*
! 13775: ** Load a value of type eType from buffer pData and use it to set the
! 13776: ** result of context object pCtx.
! 13777: */
! 13778: static void dbdataValue(
! 13779: sqlite3_context *pCtx,
! 13780: u32 enc,
! 13781: int eType,
! 13782: u8 *pData,
! 13783: sqlite3_int64 nData
! 13784: ){
! 13785: if( eType>=0 && dbdataValueBytes(eType)<=nData ){
! 13786: switch( eType ){
! 13787: case 0:
! 13788: case 10:
! 13789: case 11:
! 13790: sqlite3_result_null(pCtx);
! 13791: break;
! 13792:
! 13793: case 8:
! 13794: sqlite3_result_int(pCtx, 0);
! 13795: break;
! 13796: case 9:
! 13797: sqlite3_result_int(pCtx, 1);
! 13798: break;
! 13799:
! 13800: case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
! 13801: sqlite3_uint64 v = (signed char)pData[0];
! 13802: pData++;
! 13803: switch( eType ){
! 13804: case 7:
! 13805: case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
! 13806: case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
! 13807: case 4: v = (v<<8) + pData[0]; pData++;
! 13808: case 3: v = (v<<8) + pData[0]; pData++;
! 13809: case 2: v = (v<<8) + pData[0]; pData++;
1.5 misho 13810: }
1.6.2.1 ! misho 13811:
! 13812: if( eType==7 ){
! 13813: double r;
! 13814: memcpy(&r, &v, sizeof(r));
! 13815: sqlite3_result_double(pCtx, r);
! 13816: }else{
! 13817: sqlite3_result_int64(pCtx, (sqlite3_int64)v);
1.5 misho 13818: }
1.6.2.1 ! misho 13819: break;
! 13820: }
! 13821:
! 13822: default: {
! 13823: int n = ((eType-12) / 2);
! 13824: if( eType % 2 ){
! 13825: switch( enc ){
! 13826: #ifndef SQLITE_OMIT_UTF16
! 13827: case SQLITE_UTF16BE:
! 13828: sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
! 13829: break;
! 13830: case SQLITE_UTF16LE:
! 13831: sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
! 13832: break;
! 13833: #endif
! 13834: default:
! 13835: sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT);
! 13836: break;
1.5 misho 13837: }
1.6.2.1 ! misho 13838: }else{
! 13839: sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
1.5 misho 13840: }
13841: }
13842: }
13843: }
13844: }
13845:
1.6.2.1 ! misho 13846: /*
! 13847: ** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry.
! 13848: */
! 13849: static int dbdataNext(sqlite3_vtab_cursor *pCursor){
! 13850: DbdataCursor *pCsr = (DbdataCursor*)pCursor;
! 13851: DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
1.5 misho 13852:
1.6.2.1 ! misho 13853: pCsr->iRowid++;
! 13854: while( 1 ){
! 13855: int rc;
! 13856: int iOff = (pCsr->iPgno==1 ? 100 : 0);
! 13857: int bNextPage = 0;
! 13858:
! 13859: if( pCsr->aPage==0 ){
! 13860: while( 1 ){
! 13861: if( pCsr->bOnePage==0 && pCsr->iPgno>pCsr->szDb ) return SQLITE_OK;
! 13862: rc = dbdataLoadPage(pCsr, pCsr->iPgno, &pCsr->aPage, &pCsr->nPage);
! 13863: if( rc!=SQLITE_OK ) return rc;
! 13864: if( pCsr->aPage && pCsr->nPage>=256 ) break;
! 13865: sqlite3_free(pCsr->aPage);
! 13866: pCsr->aPage = 0;
! 13867: if( pCsr->bOnePage ) return SQLITE_OK;
! 13868: pCsr->iPgno++;
! 13869: }
! 13870:
! 13871: assert( iOff+3+2<=pCsr->nPage );
! 13872: pCsr->iCell = pTab->bPtr ? -2 : 0;
! 13873: pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]);
1.5 misho 13874: }
13875:
1.6.2.1 ! misho 13876: if( pTab->bPtr ){
! 13877: if( pCsr->aPage[iOff]!=0x02 && pCsr->aPage[iOff]!=0x05 ){
! 13878: pCsr->iCell = pCsr->nCell;
1.5 misho 13879: }
1.6.2.1 ! misho 13880: pCsr->iCell++;
! 13881: if( pCsr->iCell>=pCsr->nCell ){
! 13882: sqlite3_free(pCsr->aPage);
! 13883: pCsr->aPage = 0;
! 13884: if( pCsr->bOnePage ) return SQLITE_OK;
! 13885: pCsr->iPgno++;
1.5 misho 13886: }else{
1.6.2.1 ! misho 13887: return SQLITE_OK;
! 13888: }
! 13889: }else{
! 13890: /* If there is no record loaded, load it now. */
! 13891: if( pCsr->pRec==0 ){
! 13892: int bHasRowid = 0;
! 13893: int nPointer = 0;
! 13894: sqlite3_int64 nPayload = 0;
! 13895: sqlite3_int64 nHdr = 0;
! 13896: int iHdr;
! 13897: int U, X;
! 13898: int nLocal;
! 13899:
! 13900: switch( pCsr->aPage[iOff] ){
! 13901: case 0x02:
! 13902: nPointer = 4;
! 13903: break;
! 13904: case 0x0a:
! 13905: break;
! 13906: case 0x0d:
! 13907: bHasRowid = 1;
! 13908: break;
! 13909: default:
! 13910: /* This is not a b-tree page with records on it. Continue. */
! 13911: pCsr->iCell = pCsr->nCell;
! 13912: break;
1.5 misho 13913: }
1.6.2.1 ! misho 13914:
! 13915: if( pCsr->iCell>=pCsr->nCell ){
! 13916: bNextPage = 1;
1.5 misho 13917: }else{
1.6.2.1 ! misho 13918:
! 13919: iOff += 8 + nPointer + pCsr->iCell*2;
! 13920: if( iOff>pCsr->nPage ){
! 13921: bNextPage = 1;
! 13922: }else{
! 13923: iOff = get_uint16(&pCsr->aPage[iOff]);
! 13924: }
! 13925:
! 13926: /* For an interior node cell, skip past the child-page number */
! 13927: iOff += nPointer;
! 13928:
! 13929: /* Load the "byte of payload including overflow" field */
! 13930: if( bNextPage || iOff>pCsr->nPage ){
! 13931: bNextPage = 1;
! 13932: }else{
! 13933: iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
! 13934: }
! 13935:
! 13936: /* If this is a leaf intkey cell, load the rowid */
! 13937: if( bHasRowid && !bNextPage && iOff<pCsr->nPage ){
! 13938: iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey);
! 13939: }
! 13940:
! 13941: /* Figure out how much data to read from the local page */
! 13942: U = pCsr->nPage;
! 13943: if( bHasRowid ){
! 13944: X = U-35;
! 13945: }else{
! 13946: X = ((U-12)*64/255)-23;
! 13947: }
! 13948: if( nPayload<=X ){
! 13949: nLocal = nPayload;
! 13950: }else{
! 13951: int M, K;
! 13952: M = ((U-12)*32/255)-23;
! 13953: K = M+((nPayload-M)%(U-4));
! 13954: if( K<=X ){
! 13955: nLocal = K;
! 13956: }else{
! 13957: nLocal = M;
! 13958: }
! 13959: }
1.5 misho 13960:
1.6.2.1 ! misho 13961: if( bNextPage || nLocal+iOff>pCsr->nPage ){
! 13962: bNextPage = 1;
! 13963: }else{
1.5 misho 13964:
1.6.2.1 ! misho 13965: /* Allocate space for payload. And a bit more to catch small buffer
! 13966: ** overruns caused by attempting to read a varint or similar from
! 13967: ** near the end of a corrupt record. */
! 13968: pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES);
! 13969: if( pCsr->pRec==0 ) return SQLITE_NOMEM;
! 13970: memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES);
! 13971: pCsr->nRec = nPayload;
1.5 misho 13972:
1.6.2.1 ! misho 13973: /* Load the nLocal bytes of payload */
! 13974: memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal);
! 13975: iOff += nLocal;
1.5 misho 13976:
1.6.2.1 ! misho 13977: /* Load content from overflow pages */
! 13978: if( nPayload>nLocal ){
! 13979: sqlite3_int64 nRem = nPayload - nLocal;
! 13980: u32 pgnoOvfl = get_uint32(&pCsr->aPage[iOff]);
! 13981: while( nRem>0 ){
! 13982: u8 *aOvfl = 0;
! 13983: int nOvfl = 0;
! 13984: int nCopy;
! 13985: rc = dbdataLoadPage(pCsr, pgnoOvfl, &aOvfl, &nOvfl);
! 13986: assert( rc!=SQLITE_OK || aOvfl==0 || nOvfl==pCsr->nPage );
! 13987: if( rc!=SQLITE_OK ) return rc;
! 13988: if( aOvfl==0 ) break;
! 13989:
! 13990: nCopy = U-4;
! 13991: if( nCopy>nRem ) nCopy = nRem;
! 13992: memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy);
! 13993: nRem -= nCopy;
! 13994:
! 13995: pgnoOvfl = get_uint32(aOvfl);
! 13996: sqlite3_free(aOvfl);
! 13997: }
! 13998: }
! 13999:
! 14000: iHdr = dbdataGetVarintU32(pCsr->pRec, &nHdr);
! 14001: if( nHdr>nPayload ) nHdr = 0;
! 14002: pCsr->nHdr = nHdr;
! 14003: pCsr->pHdrPtr = &pCsr->pRec[iHdr];
! 14004: pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
! 14005: pCsr->iField = (bHasRowid ? -1 : 0);
! 14006: }
! 14007: }
! 14008: }else{
! 14009: pCsr->iField++;
! 14010: if( pCsr->iField>0 ){
! 14011: sqlite3_int64 iType;
! 14012: if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){
! 14013: bNextPage = 1;
! 14014: }else{
! 14015: int szField = 0;
! 14016: pCsr->pHdrPtr += dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
! 14017: szField = dbdataValueBytes(iType);
! 14018: if( (pCsr->nRec - (pCsr->pPtr - pCsr->pRec))<szField ){
! 14019: pCsr->pPtr = &pCsr->pRec[pCsr->nRec];
! 14020: }else{
! 14021: pCsr->pPtr += szField;
! 14022: }
! 14023: }
! 14024: }
! 14025: }
1.5 misho 14026:
1.6.2.1 ! misho 14027: if( bNextPage ){
! 14028: sqlite3_free(pCsr->aPage);
! 14029: sqlite3_free(pCsr->pRec);
! 14030: pCsr->aPage = 0;
! 14031: pCsr->pRec = 0;
! 14032: if( pCsr->bOnePage ) return SQLITE_OK;
! 14033: pCsr->iPgno++;
! 14034: }else{
! 14035: if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){
! 14036: return SQLITE_OK;
! 14037: }
1.5 misho 14038:
1.6.2.1 ! misho 14039: /* Advance to the next cell. The next iteration of the loop will load
! 14040: ** the record and so on. */
! 14041: sqlite3_free(pCsr->pRec);
! 14042: pCsr->pRec = 0;
! 14043: pCsr->iCell++;
1.5 misho 14044: }
14045: }
14046: }
14047:
1.6.2.1 ! misho 14048: assert( !"can't get here" );
! 14049: return SQLITE_OK;
1.5 misho 14050: }
14051:
1.6.2.1 ! misho 14052: /*
! 14053: ** Return true if the cursor is at EOF.
1.5 misho 14054: */
1.6.2.1 ! misho 14055: static int dbdataEof(sqlite3_vtab_cursor *pCursor){
! 14056: DbdataCursor *pCsr = (DbdataCursor*)pCursor;
! 14057: return pCsr->aPage==0;
1.5 misho 14058: }
14059:
14060: /*
1.6.2.1 ! misho 14061: ** Return true if nul-terminated string zSchema ends in "()". Or false
! 14062: ** otherwise.
1.5 misho 14063: */
1.6.2.1 ! misho 14064: static int dbdataIsFunction(const char *zSchema){
! 14065: size_t n = strlen(zSchema);
! 14066: if( n>2 && zSchema[n-2]=='(' && zSchema[n-1]==')' ){
! 14067: return (int)n-2;
1.5 misho 14068: }
1.6.2.1 ! misho 14069: return 0;
1.5 misho 14070: }
14071:
1.6.2.1 ! misho 14072: /*
! 14073: ** Determine the size in pages of database zSchema (where zSchema is
! 14074: ** "main", "temp" or the name of an attached database) and set
! 14075: ** pCsr->szDb accordingly. If successful, return SQLITE_OK. Otherwise,
! 14076: ** an SQLite error code.
1.5 misho 14077: */
1.6.2.1 ! misho 14078: static int dbdataDbsize(DbdataCursor *pCsr, const char *zSchema){
! 14079: DbdataTable *pTab = (DbdataTable*)pCsr->base.pVtab;
! 14080: char *zSql = 0;
! 14081: int rc, rc2;
! 14082: int nFunc = 0;
! 14083: sqlite3_stmt *pStmt = 0;
1.5 misho 14084:
1.6.2.1 ! misho 14085: if( (nFunc = dbdataIsFunction(zSchema))>0 ){
! 14086: zSql = sqlite3_mprintf("SELECT %.*s(0)", nFunc, zSchema);
! 14087: }else{
! 14088: zSql = sqlite3_mprintf("PRAGMA %Q.page_count", zSchema);
1.5 misho 14089: }
1.6.2.1 ! misho 14090: if( zSql==0 ) return SQLITE_NOMEM;
1.5 misho 14091:
1.6.2.1 ! misho 14092: rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pStmt, 0);
! 14093: sqlite3_free(zSql);
! 14094: if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
! 14095: pCsr->szDb = sqlite3_column_int(pStmt, 0);
1.5 misho 14096: }
1.6.2.1 ! misho 14097: rc2 = sqlite3_finalize(pStmt);
! 14098: if( rc==SQLITE_OK ) rc = rc2;
! 14099: return rc;
1.5 misho 14100: }
14101:
14102: /*
1.6.2.1 ! misho 14103: ** Attempt to figure out the encoding of the database by retrieving page 1
! 14104: ** and inspecting the header field. If successful, set the pCsr->enc variable
! 14105: ** and return SQLITE_OK. Otherwise, return an SQLite error code.
1.5 misho 14106: */
1.6.2.1 ! misho 14107: static int dbdataGetEncoding(DbdataCursor *pCsr){
! 14108: int rc = SQLITE_OK;
! 14109: int nPg1 = 0;
! 14110: u8 *aPg1 = 0;
! 14111: rc = dbdataLoadPage(pCsr, 1, &aPg1, &nPg1);
! 14112: if( rc==SQLITE_OK && nPg1>=(56+4) ){
! 14113: pCsr->enc = get_uint32(&aPg1[56]);
1.5 misho 14114: }
1.6.2.1 ! misho 14115: sqlite3_free(aPg1);
! 14116: return rc;
1.5 misho 14117: }
14118:
14119:
1.6.2.1 ! misho 14120: /*
! 14121: ** xFilter method for sqlite_dbdata and sqlite_dbptr.
1.5 misho 14122: */
1.6.2.1 ! misho 14123: static int dbdataFilter(
! 14124: sqlite3_vtab_cursor *pCursor,
! 14125: int idxNum, const char *idxStr,
! 14126: int argc, sqlite3_value **argv
1.5 misho 14127: ){
1.6.2.1 ! misho 14128: DbdataCursor *pCsr = (DbdataCursor*)pCursor;
! 14129: DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
1.5 misho 14130: int rc = SQLITE_OK;
1.6.2.1 ! misho 14131: const char *zSchema = "main";
! 14132: (void)idxStr;
! 14133: (void)argc;
1.5 misho 14134:
1.6.2.1 ! misho 14135: dbdataResetCursor(pCsr);
! 14136: assert( pCsr->iPgno==1 );
! 14137: if( idxNum & 0x01 ){
! 14138: zSchema = (const char*)sqlite3_value_text(argv[0]);
! 14139: if( zSchema==0 ) zSchema = "";
! 14140: }
! 14141: if( idxNum & 0x02 ){
! 14142: pCsr->iPgno = sqlite3_value_int(argv[(idxNum & 0x01)]);
! 14143: pCsr->bOnePage = 1;
! 14144: }else{
! 14145: rc = dbdataDbsize(pCsr, zSchema);
1.5 misho 14146: }
14147:
1.6.2.1 ! misho 14148: if( rc==SQLITE_OK ){
! 14149: int nFunc = 0;
! 14150: if( pTab->pStmt ){
! 14151: pCsr->pStmt = pTab->pStmt;
! 14152: pTab->pStmt = 0;
! 14153: }else if( (nFunc = dbdataIsFunction(zSchema))>0 ){
! 14154: char *zSql = sqlite3_mprintf("SELECT %.*s(?2)", nFunc, zSchema);
! 14155: if( zSql==0 ){
! 14156: rc = SQLITE_NOMEM;
! 14157: }else{
! 14158: rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0);
! 14159: sqlite3_free(zSql);
1.5 misho 14160: }
1.6.2.1 ! misho 14161: }else{
! 14162: rc = sqlite3_prepare_v2(pTab->db,
! 14163: "SELECT data FROM sqlite_dbpage(?) WHERE pgno=?", -1,
! 14164: &pCsr->pStmt, 0
! 14165: );
1.5 misho 14166: }
14167: }
1.6.2.1 ! misho 14168: if( rc==SQLITE_OK ){
! 14169: rc = sqlite3_bind_text(pCsr->pStmt, 1, zSchema, -1, SQLITE_TRANSIENT);
! 14170: }
1.5 misho 14171:
1.6.2.1 ! misho 14172: /* Try to determine the encoding of the db by inspecting the header
! 14173: ** field on page 1. */
! 14174: if( rc==SQLITE_OK ){
! 14175: rc = dbdataGetEncoding(pCsr);
! 14176: }
1.5 misho 14177:
1.6.2.1 ! misho 14178: if( rc!=SQLITE_OK ){
! 14179: pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
1.5 misho 14180: }
14181:
14182: if( rc==SQLITE_OK ){
1.6.2.1 ! misho 14183: rc = dbdataNext(pCursor);
1.5 misho 14184: }
1.6.2.1 ! misho 14185: return rc;
! 14186: }
1.5 misho 14187:
1.6.2.1 ! misho 14188: /*
! 14189: ** Return a column for the sqlite_dbdata or sqlite_dbptr table.
! 14190: */
! 14191: static int dbdataColumn(
! 14192: sqlite3_vtab_cursor *pCursor,
! 14193: sqlite3_context *ctx,
! 14194: int i
! 14195: ){
! 14196: DbdataCursor *pCsr = (DbdataCursor*)pCursor;
! 14197: DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
! 14198: if( pTab->bPtr ){
! 14199: switch( i ){
! 14200: case DBPTR_COLUMN_PGNO:
! 14201: sqlite3_result_int64(ctx, pCsr->iPgno);
! 14202: break;
! 14203: case DBPTR_COLUMN_CHILD: {
! 14204: int iOff = pCsr->iPgno==1 ? 100 : 0;
! 14205: if( pCsr->iCell<0 ){
! 14206: iOff += 8;
! 14207: }else{
! 14208: iOff += 12 + pCsr->iCell*2;
! 14209: if( iOff>pCsr->nPage ) return SQLITE_OK;
! 14210: iOff = get_uint16(&pCsr->aPage[iOff]);
! 14211: }
! 14212: if( iOff<=pCsr->nPage ){
! 14213: sqlite3_result_int64(ctx, get_uint32(&pCsr->aPage[iOff]));
! 14214: }
! 14215: break;
1.5 misho 14216: }
14217: }
1.6.2.1 ! misho 14218: }else{
! 14219: switch( i ){
! 14220: case DBDATA_COLUMN_PGNO:
! 14221: sqlite3_result_int64(ctx, pCsr->iPgno);
! 14222: break;
! 14223: case DBDATA_COLUMN_CELL:
! 14224: sqlite3_result_int(ctx, pCsr->iCell);
! 14225: break;
! 14226: case DBDATA_COLUMN_FIELD:
! 14227: sqlite3_result_int(ctx, pCsr->iField);
! 14228: break;
! 14229: case DBDATA_COLUMN_VALUE: {
! 14230: if( pCsr->iField<0 ){
! 14231: sqlite3_result_int64(ctx, pCsr->iIntkey);
! 14232: }else if( &pCsr->pRec[pCsr->nRec] >= pCsr->pPtr ){
! 14233: sqlite3_int64 iType;
! 14234: dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
! 14235: dbdataValue(
! 14236: ctx, pCsr->enc, iType, pCsr->pPtr,
! 14237: &pCsr->pRec[pCsr->nRec] - pCsr->pPtr
! 14238: );
! 14239: }
! 14240: break;
1.5 misho 14241: }
14242: }
14243: }
1.6.2.1 ! misho 14244: return SQLITE_OK;
! 14245: }
1.5 misho 14246:
1.6.2.1 ! misho 14247: /*
! 14248: ** Return the rowid for an sqlite_dbdata or sqlite_dptr table.
! 14249: */
! 14250: static int dbdataRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
! 14251: DbdataCursor *pCsr = (DbdataCursor*)pCursor;
! 14252: *pRowid = pCsr->iRowid;
! 14253: return SQLITE_OK;
! 14254: }
! 14255:
! 14256:
! 14257: /*
! 14258: ** Invoke this routine to register the "sqlite_dbdata" virtual table module
! 14259: */
! 14260: static int sqlite3DbdataRegister(sqlite3 *db){
! 14261: static sqlite3_module dbdata_module = {
! 14262: 0, /* iVersion */
! 14263: 0, /* xCreate */
! 14264: dbdataConnect, /* xConnect */
! 14265: dbdataBestIndex, /* xBestIndex */
! 14266: dbdataDisconnect, /* xDisconnect */
! 14267: 0, /* xDestroy */
! 14268: dbdataOpen, /* xOpen - open a cursor */
! 14269: dbdataClose, /* xClose - close a cursor */
! 14270: dbdataFilter, /* xFilter - configure scan constraints */
! 14271: dbdataNext, /* xNext - advance a cursor */
! 14272: dbdataEof, /* xEof - check for end of scan */
! 14273: dbdataColumn, /* xColumn - read data */
! 14274: dbdataRowid, /* xRowid - read data */
! 14275: 0, /* xUpdate */
! 14276: 0, /* xBegin */
! 14277: 0, /* xSync */
! 14278: 0, /* xCommit */
! 14279: 0, /* xRollback */
! 14280: 0, /* xFindMethod */
! 14281: 0, /* xRename */
! 14282: 0, /* xSavepoint */
! 14283: 0, /* xRelease */
! 14284: 0, /* xRollbackTo */
! 14285: 0 /* xShadowName */
! 14286: };
1.5 misho 14287:
1.6.2.1 ! misho 14288: int rc = sqlite3_create_module(db, "sqlite_dbdata", &dbdata_module, 0);
1.5 misho 14289: if( rc==SQLITE_OK ){
1.6.2.1 ! misho 14290: rc = sqlite3_create_module(db, "sqlite_dbptr", &dbdata_module, (void*)1);
1.5 misho 14291: }
14292: return rc;
14293: }
14294:
1.6.2.1 ! misho 14295: int sqlite3_dbdata_init(
! 14296: sqlite3 *db,
! 14297: char **pzErrMsg,
! 14298: const sqlite3_api_routines *pApi
! 14299: ){
! 14300: (void)pzErrMsg;
! 14301: return sqlite3DbdataRegister(db);
! 14302: }
1.5 misho 14303:
1.6.2.1 ! misho 14304: #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
1.5 misho 14305:
1.6.2.1 ! misho 14306: /************************* End ../ext/recover/dbdata.c ********************/
! 14307: /************************* Begin ../ext/recover/sqlite3recover.c ******************/
! 14308: /*
! 14309: ** 2022-08-27
! 14310: **
! 14311: ** The author disclaims copyright to this source code. In place of
! 14312: ** a legal notice, here is a blessing:
! 14313: **
! 14314: ** May you do good and not evil.
! 14315: ** May you find forgiveness for yourself and forgive others.
! 14316: ** May you share freely, never taking more than you give.
! 14317: **
! 14318: *************************************************************************
! 14319: **
! 14320: */
1.5 misho 14321:
14322:
1.6.2.1 ! misho 14323: /* #include "sqlite3recover.h" */
! 14324: #include <assert.h>
! 14325: #include <string.h>
1.5 misho 14326:
1.6.2.1 ! misho 14327: #ifndef SQLITE_OMIT_VIRTUALTABLE
1.5 misho 14328:
1.6.2.1 ! misho 14329: /*
! 14330: ** Declaration for public API function in file dbdata.c. This may be called
! 14331: ** with NULL as the final two arguments to register the sqlite_dbptr and
! 14332: ** sqlite_dbdata virtual tables with a database handle.
! 14333: */
! 14334: #ifdef _WIN32
1.5 misho 14335:
1.6.2.1 ! misho 14336: #endif
! 14337: int sqlite3_dbdata_init(sqlite3*, char**, const sqlite3_api_routines*);
1.5 misho 14338:
1.6.2.1 ! misho 14339: /* typedef unsigned int u32; */
! 14340: /* typedef unsigned char u8; */
! 14341: /* typedef sqlite3_int64 i64; */
1.5 misho 14342:
1.6.2.1 ! misho 14343: typedef struct RecoverTable RecoverTable;
! 14344: typedef struct RecoverColumn RecoverColumn;
! 14345:
! 14346: /*
! 14347: ** When recovering rows of data that can be associated with table
! 14348: ** definitions recovered from the sqlite_schema table, each table is
! 14349: ** represented by an instance of the following object.
! 14350: **
! 14351: ** iRoot:
! 14352: ** The root page in the original database. Not necessarily (and usually
! 14353: ** not) the same in the recovered database.
! 14354: **
! 14355: ** zTab:
! 14356: ** Name of the table.
! 14357: **
! 14358: ** nCol/aCol[]:
! 14359: ** aCol[] is an array of nCol columns. In the order in which they appear
! 14360: ** in the table.
! 14361: **
! 14362: ** bIntkey:
! 14363: ** Set to true for intkey tables, false for WITHOUT ROWID.
! 14364: **
! 14365: ** iRowidBind:
! 14366: ** Each column in the aCol[] array has associated with it the index of
! 14367: ** the bind parameter its values will be bound to in the INSERT statement
! 14368: ** used to construct the output database. If the table does has a rowid
! 14369: ** but not an INTEGER PRIMARY KEY column, then iRowidBind contains the
! 14370: ** index of the bind paramater to which the rowid value should be bound.
! 14371: ** Otherwise, it contains -1. If the table does contain an INTEGER PRIMARY
! 14372: ** KEY column, then the rowid value should be bound to the index associated
! 14373: ** with the column.
! 14374: **
! 14375: ** pNext:
! 14376: ** All RecoverTable objects used by the recovery operation are allocated
! 14377: ** and populated as part of creating the recovered database schema in
! 14378: ** the output database, before any non-schema data are recovered. They
! 14379: ** are then stored in a singly-linked list linked by this variable beginning
! 14380: ** at sqlite3_recover.pTblList.
! 14381: */
! 14382: struct RecoverTable {
! 14383: u32 iRoot; /* Root page in original database */
! 14384: char *zTab; /* Name of table */
! 14385: int nCol; /* Number of columns in table */
! 14386: RecoverColumn *aCol; /* Array of columns */
! 14387: int bIntkey; /* True for intkey, false for without rowid */
! 14388: int iRowidBind; /* If >0, bind rowid to INSERT here */
! 14389: RecoverTable *pNext;
1.5 misho 14390: };
14391:
1.6.2.1 ! misho 14392: /*
! 14393: ** Each database column is represented by an instance of the following object
! 14394: ** stored in the RecoverTable.aCol[] array of the associated table.
! 14395: **
! 14396: ** iField:
! 14397: ** The index of the associated field within database records. Or -1 if
! 14398: ** there is no associated field (e.g. for virtual generated columns).
! 14399: **
! 14400: ** iBind:
! 14401: ** The bind index of the INSERT statement to bind this columns values
! 14402: ** to. Or 0 if there is no such index (iff (iField<0)).
! 14403: **
! 14404: ** bIPK:
! 14405: ** True if this is the INTEGER PRIMARY KEY column.
! 14406: **
! 14407: ** zCol:
! 14408: ** Name of column.
! 14409: **
! 14410: ** eHidden:
! 14411: ** A RECOVER_EHIDDEN_* constant value (see below for interpretation of each).
! 14412: */
! 14413: struct RecoverColumn {
! 14414: int iField; /* Field in record on disk */
! 14415: int iBind; /* Binding to use in INSERT */
! 14416: int bIPK; /* True for IPK column */
! 14417: char *zCol;
! 14418: int eHidden;
! 14419: };
1.5 misho 14420:
1.6.2.1 ! misho 14421: #define RECOVER_EHIDDEN_NONE 0 /* Normal database column */
! 14422: #define RECOVER_EHIDDEN_HIDDEN 1 /* Column is __HIDDEN__ */
! 14423: #define RECOVER_EHIDDEN_VIRTUAL 2 /* Virtual generated column */
! 14424: #define RECOVER_EHIDDEN_STORED 3 /* Stored generated column */
! 14425:
! 14426: /*
! 14427: ** Bitmap object used to track pages in the input database. Allocated
! 14428: ** and manipulated only by the following functions:
! 14429: **
! 14430: ** recoverBitmapAlloc()
! 14431: ** recoverBitmapFree()
! 14432: ** recoverBitmapSet()
! 14433: ** recoverBitmapQuery()
! 14434: **
! 14435: ** nPg:
! 14436: ** Largest page number that may be stored in the bitmap. The range
! 14437: ** of valid keys is 1 to nPg, inclusive.
! 14438: **
! 14439: ** aElem[]:
! 14440: ** Array large enough to contain a bit for each key. For key value
! 14441: ** iKey, the associated bit is the bit (iKey%32) of aElem[iKey/32].
! 14442: ** In other words, the following is true if bit iKey is set, or
! 14443: ** false if it is clear:
! 14444: **
! 14445: ** (aElem[iKey/32] & (1 << (iKey%32))) ? 1 : 0
! 14446: */
! 14447: typedef struct RecoverBitmap RecoverBitmap;
! 14448: struct RecoverBitmap {
! 14449: i64 nPg; /* Size of bitmap */
! 14450: u32 aElem[1]; /* Array of 32-bit bitmasks */
! 14451: };
1.5 misho 14452:
1.6.2.1 ! misho 14453: /*
! 14454: ** State variables (part of the sqlite3_recover structure) used while
! 14455: ** recovering data for tables identified in the recovered schema (state
! 14456: ** RECOVER_STATE_WRITING).
! 14457: */
! 14458: typedef struct RecoverStateW1 RecoverStateW1;
! 14459: struct RecoverStateW1 {
! 14460: sqlite3_stmt *pTbls;
! 14461: sqlite3_stmt *pSel;
! 14462: sqlite3_stmt *pInsert;
! 14463: int nInsert;
! 14464:
! 14465: RecoverTable *pTab; /* Table currently being written */
! 14466: int nMax; /* Max column count in any schema table */
! 14467: sqlite3_value **apVal; /* Array of nMax values */
! 14468: int nVal; /* Number of valid entries in apVal[] */
! 14469: int bHaveRowid;
! 14470: i64 iRowid;
! 14471: i64 iPrevPage;
! 14472: int iPrevCell;
! 14473: };
1.5 misho 14474:
1.6.2.1 ! misho 14475: /*
! 14476: ** State variables (part of the sqlite3_recover structure) used while
! 14477: ** recovering data destined for the lost and found table (states
! 14478: ** RECOVER_STATE_LOSTANDFOUND[123]).
! 14479: */
! 14480: typedef struct RecoverStateLAF RecoverStateLAF;
! 14481: struct RecoverStateLAF {
! 14482: RecoverBitmap *pUsed;
! 14483: i64 nPg; /* Size of db in pages */
! 14484: sqlite3_stmt *pAllAndParent;
! 14485: sqlite3_stmt *pMapInsert;
! 14486: sqlite3_stmt *pMaxField;
! 14487: sqlite3_stmt *pUsedPages;
! 14488: sqlite3_stmt *pFindRoot;
! 14489: sqlite3_stmt *pInsert; /* INSERT INTO lost_and_found ... */
! 14490: sqlite3_stmt *pAllPage;
! 14491: sqlite3_stmt *pPageData;
! 14492: sqlite3_value **apVal;
! 14493: int nMaxField;
1.5 misho 14494: };
14495:
14496: /*
1.6.2.1 ! misho 14497: ** Main recover handle structure.
1.5 misho 14498: */
1.6.2.1 ! misho 14499: struct sqlite3_recover {
! 14500: /* Copies of sqlite3_recover_init[_sql]() parameters */
! 14501: sqlite3 *dbIn; /* Input database */
! 14502: char *zDb; /* Name of input db ("main" etc.) */
! 14503: char *zUri; /* URI for output database */
! 14504: void *pSqlCtx; /* SQL callback context */
! 14505: int (*xSql)(void*,const char*); /* Pointer to SQL callback function */
! 14506:
! 14507: /* Values configured by sqlite3_recover_config() */
! 14508: char *zStateDb; /* State database to use (or NULL) */
! 14509: char *zLostAndFound; /* Name of lost-and-found table (or NULL) */
! 14510: int bFreelistCorrupt; /* SQLITE_RECOVER_FREELIST_CORRUPT setting */
! 14511: int bRecoverRowid; /* SQLITE_RECOVER_ROWIDS setting */
! 14512: int bSlowIndexes; /* SQLITE_RECOVER_SLOWINDEXES setting */
! 14513:
! 14514: int pgsz;
! 14515: int detected_pgsz;
! 14516: int nReserve;
! 14517: u8 *pPage1Disk;
! 14518: u8 *pPage1Cache;
! 14519:
! 14520: /* Error code and error message */
! 14521: int errCode; /* For sqlite3_recover_errcode() */
! 14522: char *zErrMsg; /* For sqlite3_recover_errmsg() */
! 14523:
! 14524: int eState;
! 14525: int bCloseTransaction;
! 14526:
! 14527: /* Variables used with eState==RECOVER_STATE_WRITING */
! 14528: RecoverStateW1 w1;
! 14529:
! 14530: /* Variables used with states RECOVER_STATE_LOSTANDFOUND[123] */
! 14531: RecoverStateLAF laf;
! 14532:
! 14533: /* Fields used within sqlite3_recover_run() */
! 14534: sqlite3 *dbOut; /* Output database */
! 14535: sqlite3_stmt *pGetPage; /* SELECT against input db sqlite_dbdata */
! 14536: RecoverTable *pTblList; /* List of tables recovered from schema */
! 14537: };
1.5 misho 14538:
1.6.2.1 ! misho 14539: /*
! 14540: ** The various states in which an sqlite3_recover object may exist:
! 14541: **
! 14542: ** RECOVER_STATE_INIT:
! 14543: ** The object is initially created in this state. sqlite3_recover_step()
! 14544: ** has yet to be called. This is the only state in which it is permitted
! 14545: ** to call sqlite3_recover_config().
! 14546: **
! 14547: ** RECOVER_STATE_WRITING:
! 14548: **
! 14549: ** RECOVER_STATE_LOSTANDFOUND1:
! 14550: ** State to populate the bitmap of pages used by other tables or the
! 14551: ** database freelist.
! 14552: **
! 14553: ** RECOVER_STATE_LOSTANDFOUND2:
! 14554: ** Populate the recovery.map table - used to figure out a "root" page
! 14555: ** for each lost page from in the database from which records are
! 14556: ** extracted.
! 14557: **
! 14558: ** RECOVER_STATE_LOSTANDFOUND3:
! 14559: ** Populate the lost-and-found table itself.
! 14560: */
! 14561: #define RECOVER_STATE_INIT 0
! 14562: #define RECOVER_STATE_WRITING 1
! 14563: #define RECOVER_STATE_LOSTANDFOUND1 2
! 14564: #define RECOVER_STATE_LOSTANDFOUND2 3
! 14565: #define RECOVER_STATE_LOSTANDFOUND3 4
! 14566: #define RECOVER_STATE_SCHEMA2 5
! 14567: #define RECOVER_STATE_DONE 6
1.5 misho 14568:
14569:
1.6.2.1 ! misho 14570: /*
! 14571: ** Global variables used by this extension.
! 14572: */
! 14573: typedef struct RecoverGlobal RecoverGlobal;
! 14574: struct RecoverGlobal {
! 14575: const sqlite3_io_methods *pMethods;
! 14576: sqlite3_recover *p;
! 14577: };
! 14578: static RecoverGlobal recover_g;
1.5 misho 14579:
1.6.2.1 ! misho 14580: /*
! 14581: ** Use this static SQLite mutex to protect the globals during the
! 14582: ** first call to sqlite3_recover_step().
! 14583: */
! 14584: #define RECOVER_MUTEX_ID SQLITE_MUTEX_STATIC_APP2
1.5 misho 14585:
14586:
1.6.2.1 ! misho 14587: /*
! 14588: ** Default value for SQLITE_RECOVER_ROWIDS (sqlite3_recover.bRecoverRowid).
! 14589: */
! 14590: #define RECOVER_ROWID_DEFAULT 1
1.5 misho 14591:
1.6.2.1 ! misho 14592: /*
! 14593: ** Mutex handling:
! 14594: **
! 14595: ** recoverEnterMutex() - Enter the recovery mutex
! 14596: ** recoverLeaveMutex() - Leave the recovery mutex
! 14597: ** recoverAssertMutexHeld() - Assert that the recovery mutex is held
! 14598: */
! 14599: #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
! 14600: # define recoverEnterMutex()
! 14601: # define recoverLeaveMutex()
! 14602: #else
! 14603: static void recoverEnterMutex(void){
! 14604: sqlite3_mutex_enter(sqlite3_mutex_alloc(RECOVER_MUTEX_ID));
! 14605: }
! 14606: static void recoverLeaveMutex(void){
! 14607: sqlite3_mutex_leave(sqlite3_mutex_alloc(RECOVER_MUTEX_ID));
! 14608: }
! 14609: #endif
! 14610: #if SQLITE_THREADSAFE+0>=1 && defined(SQLITE_DEBUG)
! 14611: static void recoverAssertMutexHeld(void){
! 14612: assert( sqlite3_mutex_held(sqlite3_mutex_alloc(RECOVER_MUTEX_ID)) );
! 14613: }
! 14614: #else
! 14615: # define recoverAssertMutexHeld()
! 14616: #endif
1.5 misho 14617:
14618:
1.6.2.1 ! misho 14619: /*
! 14620: ** Like strlen(). But handles NULL pointer arguments.
! 14621: */
! 14622: static int recoverStrlen(const char *zStr){
! 14623: if( zStr==0 ) return 0;
! 14624: return (int)(strlen(zStr)&0x7fffffff);
! 14625: }
1.5 misho 14626:
1.6.2.1 ! misho 14627: /*
! 14628: ** This function is a no-op if the recover handle passed as the first
! 14629: ** argument already contains an error (if p->errCode!=SQLITE_OK).
! 14630: **
! 14631: ** Otherwise, an attempt is made to allocate, zero and return a buffer nByte
! 14632: ** bytes in size. If successful, a pointer to the new buffer is returned. Or,
! 14633: ** if an OOM error occurs, NULL is returned and the handle error code
! 14634: ** (p->errCode) set to SQLITE_NOMEM.
! 14635: */
! 14636: static void *recoverMalloc(sqlite3_recover *p, i64 nByte){
! 14637: void *pRet = 0;
! 14638: assert( nByte>0 );
! 14639: if( p->errCode==SQLITE_OK ){
! 14640: pRet = sqlite3_malloc64(nByte);
! 14641: if( pRet ){
! 14642: memset(pRet, 0, nByte);
! 14643: }else{
! 14644: p->errCode = SQLITE_NOMEM;
1.5 misho 14645: }
14646: }
1.6.2.1 ! misho 14647: return pRet;
1.5 misho 14648: }
14649:
1.6.2.1 ! misho 14650: /*
! 14651: ** Set the error code and error message for the recover handle passed as
! 14652: ** the first argument. The error code is set to the value of parameter
! 14653: ** errCode.
! 14654: **
! 14655: ** Parameter zFmt must be a printf() style formatting string. The handle
! 14656: ** error message is set to the result of using any trailing arguments for
! 14657: ** parameter substitutions in the formatting string.
! 14658: **
! 14659: ** For example:
! 14660: **
! 14661: ** recoverError(p, SQLITE_ERROR, "no such table: %s", zTablename);
! 14662: */
! 14663: static int recoverError(
! 14664: sqlite3_recover *p,
! 14665: int errCode,
! 14666: const char *zFmt, ...
! 14667: ){
! 14668: char *z = 0;
! 14669: va_list ap;
! 14670: va_start(ap, zFmt);
! 14671: if( zFmt ){
! 14672: z = sqlite3_vmprintf(zFmt, ap);
! 14673: va_end(ap);
! 14674: }
! 14675: sqlite3_free(p->zErrMsg);
! 14676: p->zErrMsg = z;
! 14677: p->errCode = errCode;
! 14678: return errCode;
! 14679: }
1.5 misho 14680:
1.6.2.1 ! misho 14681:
! 14682: /*
! 14683: ** This function is a no-op if p->errCode is initially other than SQLITE_OK.
! 14684: ** In this case it returns NULL.
! 14685: **
! 14686: ** Otherwise, an attempt is made to allocate and return a bitmap object
! 14687: ** large enough to store a bit for all page numbers between 1 and nPg,
! 14688: ** inclusive. The bitmap is initially zeroed.
! 14689: */
! 14690: static RecoverBitmap *recoverBitmapAlloc(sqlite3_recover *p, i64 nPg){
! 14691: int nElem = (nPg+1+31) / 32;
! 14692: int nByte = sizeof(RecoverBitmap) + nElem*sizeof(u32);
! 14693: RecoverBitmap *pRet = (RecoverBitmap*)recoverMalloc(p, nByte);
! 14694:
! 14695: if( pRet ){
! 14696: pRet->nPg = nPg;
1.5 misho 14697: }
1.6.2.1 ! misho 14698: return pRet;
! 14699: }
1.5 misho 14700:
1.6.2.1 ! misho 14701: /*
! 14702: ** Free a bitmap object allocated by recoverBitmapAlloc().
! 14703: */
! 14704: static void recoverBitmapFree(RecoverBitmap *pMap){
! 14705: sqlite3_free(pMap);
1.5 misho 14706: }
14707:
1.6.2.1 ! misho 14708: /*
! 14709: ** Set the bit associated with page iPg in bitvec pMap.
! 14710: */
! 14711: static void recoverBitmapSet(RecoverBitmap *pMap, i64 iPg){
! 14712: if( iPg<=pMap->nPg ){
! 14713: int iElem = (iPg / 32);
! 14714: int iBit = (iPg % 32);
! 14715: pMap->aElem[iElem] |= (((u32)1) << iBit);
! 14716: }
! 14717: }
1.5 misho 14718:
1.6.2.1 ! misho 14719: /*
! 14720: ** Query bitmap object pMap for the state of the bit associated with page
! 14721: ** iPg. Return 1 if it is set, or 0 otherwise.
! 14722: */
! 14723: static int recoverBitmapQuery(RecoverBitmap *pMap, i64 iPg){
! 14724: int ret = 1;
! 14725: if( iPg<=pMap->nPg && iPg>0 ){
! 14726: int iElem = (iPg / 32);
! 14727: int iBit = (iPg % 32);
! 14728: ret = (pMap->aElem[iElem] & (((u32)1) << iBit)) ? 1 : 0;
! 14729: }
! 14730: return ret;
! 14731: }
1.5 misho 14732:
1.6.2.1 ! misho 14733: /*
! 14734: ** Set the recover handle error to the error code and message returned by
! 14735: ** calling sqlite3_errcode() and sqlite3_errmsg(), respectively, on database
! 14736: ** handle db.
! 14737: */
! 14738: static int recoverDbError(sqlite3_recover *p, sqlite3 *db){
! 14739: return recoverError(p, sqlite3_errcode(db), "%s", sqlite3_errmsg(db));
! 14740: }
! 14741:
! 14742: /*
! 14743: ** This function is a no-op if recover handle p already contains an error
! 14744: ** (if p->errCode!=SQLITE_OK).
! 14745: **
! 14746: ** Otherwise, it attempts to prepare the SQL statement in zSql against
! 14747: ** database handle db. If successful, the statement handle is returned.
! 14748: ** Or, if an error occurs, NULL is returned and an error left in the
! 14749: ** recover handle.
! 14750: */
! 14751: static sqlite3_stmt *recoverPrepare(
! 14752: sqlite3_recover *p,
! 14753: sqlite3 *db,
! 14754: const char *zSql
! 14755: ){
! 14756: sqlite3_stmt *pStmt = 0;
! 14757: if( p->errCode==SQLITE_OK ){
! 14758: if( sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) ){
! 14759: recoverDbError(p, db);
! 14760: }
1.5 misho 14761: }
1.6.2.1 ! misho 14762: return pStmt;
! 14763: }
! 14764:
! 14765: /*
! 14766: ** This function is a no-op if recover handle p already contains an error
! 14767: ** (if p->errCode!=SQLITE_OK).
! 14768: **
! 14769: ** Otherwise, argument zFmt is used as a printf() style format string,
! 14770: ** along with any trailing arguments, to create an SQL statement. This
! 14771: ** SQL statement is prepared against database handle db and, if successful,
! 14772: ** the statment handle returned. Or, if an error occurs - either during
! 14773: ** the printf() formatting or when preparing the resulting SQL - an
! 14774: ** error code and message are left in the recover handle.
! 14775: */
! 14776: static sqlite3_stmt *recoverPreparePrintf(
! 14777: sqlite3_recover *p,
! 14778: sqlite3 *db,
! 14779: const char *zFmt, ...
! 14780: ){
! 14781: sqlite3_stmt *pStmt = 0;
! 14782: if( p->errCode==SQLITE_OK ){
! 14783: va_list ap;
! 14784: char *z;
! 14785: va_start(ap, zFmt);
! 14786: z = sqlite3_vmprintf(zFmt, ap);
! 14787: va_end(ap);
! 14788: if( z==0 ){
! 14789: p->errCode = SQLITE_NOMEM;
1.5 misho 14790: }else{
1.6.2.1 ! misho 14791: pStmt = recoverPrepare(p, db, z);
! 14792: sqlite3_free(z);
1.5 misho 14793: }
14794: }
1.6.2.1 ! misho 14795: return pStmt;
! 14796: }
1.5 misho 14797:
1.6.2.1 ! misho 14798: /*
! 14799: ** Reset SQLite statement handle pStmt. If the call to sqlite3_reset()
! 14800: ** indicates that an error occurred, and there is not already an error
! 14801: ** in the recover handle passed as the first argument, set the error
! 14802: ** code and error message appropriately.
! 14803: **
! 14804: ** This function returns a copy of the statement handle pointer passed
! 14805: ** as the second argument.
! 14806: */
! 14807: static sqlite3_stmt *recoverReset(sqlite3_recover *p, sqlite3_stmt *pStmt){
! 14808: int rc = sqlite3_reset(pStmt);
! 14809: if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT && p->errCode==SQLITE_OK ){
! 14810: recoverDbError(p, sqlite3_db_handle(pStmt));
1.5 misho 14811: }
1.6.2.1 ! misho 14812: return pStmt;
! 14813: }
1.5 misho 14814:
1.6.2.1 ! misho 14815: /*
! 14816: ** Finalize SQLite statement handle pStmt. If the call to sqlite3_reset()
! 14817: ** indicates that an error occurred, and there is not already an error
! 14818: ** in the recover handle passed as the first argument, set the error
! 14819: ** code and error message appropriately.
! 14820: */
! 14821: static void recoverFinalize(sqlite3_recover *p, sqlite3_stmt *pStmt){
! 14822: sqlite3 *db = sqlite3_db_handle(pStmt);
! 14823: int rc = sqlite3_finalize(pStmt);
! 14824: if( rc!=SQLITE_OK && p->errCode==SQLITE_OK ){
! 14825: recoverDbError(p, db);
1.5 misho 14826: }
1.6.2.1 ! misho 14827: }
1.5 misho 14828:
1.6.2.1 ! misho 14829: /*
! 14830: ** This function is a no-op if recover handle p already contains an error
! 14831: ** (if p->errCode!=SQLITE_OK). A copy of p->errCode is returned in this
! 14832: ** case.
! 14833: **
! 14834: ** Otherwise, execute SQL script zSql. If successful, return SQLITE_OK.
! 14835: ** Or, if an error occurs, leave an error code and message in the recover
! 14836: ** handle and return a copy of the error code.
! 14837: */
! 14838: static int recoverExec(sqlite3_recover *p, sqlite3 *db, const char *zSql){
! 14839: if( p->errCode==SQLITE_OK ){
! 14840: int rc = sqlite3_exec(db, zSql, 0, 0, 0);
! 14841: if( rc ){
! 14842: recoverDbError(p, db);
1.5 misho 14843: }
1.6.2.1 ! misho 14844: }
! 14845: return p->errCode;
! 14846: }
1.5 misho 14847:
1.6.2.1 ! misho 14848: /*
! 14849: ** Bind the value pVal to parameter iBind of statement pStmt. Leave an
! 14850: ** error in the recover handle passed as the first argument if an error
! 14851: ** (e.g. an OOM) occurs.
! 14852: */
! 14853: static void recoverBindValue(
! 14854: sqlite3_recover *p,
! 14855: sqlite3_stmt *pStmt,
! 14856: int iBind,
! 14857: sqlite3_value *pVal
! 14858: ){
! 14859: if( p->errCode==SQLITE_OK ){
! 14860: int rc = sqlite3_bind_value(pStmt, iBind, pVal);
! 14861: if( rc ) recoverError(p, rc, 0);
1.5 misho 14862: }
1.6.2.1 ! misho 14863: }
1.5 misho 14864:
1.6.2.1 ! misho 14865: /*
! 14866: ** This function is a no-op if recover handle p already contains an error
! 14867: ** (if p->errCode!=SQLITE_OK). NULL is returned in this case.
! 14868: **
! 14869: ** Otherwise, an attempt is made to interpret zFmt as a printf() style
! 14870: ** formatting string and the result of using the trailing arguments for
! 14871: ** parameter substitution with it written into a buffer obtained from
! 14872: ** sqlite3_malloc(). If successful, a pointer to the buffer is returned.
! 14873: ** It is the responsibility of the caller to eventually free the buffer
! 14874: ** using sqlite3_free().
! 14875: **
! 14876: ** Or, if an error occurs, an error code and message is left in the recover
! 14877: ** handle and NULL returned.
! 14878: */
! 14879: static char *recoverMPrintf(sqlite3_recover *p, const char *zFmt, ...){
! 14880: va_list ap;
! 14881: char *z;
! 14882: va_start(ap, zFmt);
! 14883: z = sqlite3_vmprintf(zFmt, ap);
! 14884: va_end(ap);
! 14885: if( p->errCode==SQLITE_OK ){
! 14886: if( z==0 ) p->errCode = SQLITE_NOMEM;
! 14887: }else{
! 14888: sqlite3_free(z);
! 14889: z = 0;
! 14890: }
! 14891: return z;
1.5 misho 14892: }
14893:
1.6.2.1 ! misho 14894: /*
! 14895: ** This function is a no-op if recover handle p already contains an error
! 14896: ** (if p->errCode!=SQLITE_OK). Zero is returned in this case.
! 14897: **
! 14898: ** Otherwise, execute "PRAGMA page_count" against the input database. If
! 14899: ** successful, return the integer result. Or, if an error occurs, leave an
! 14900: ** error code and error message in the sqlite3_recover handle and return
! 14901: ** zero.
! 14902: */
! 14903: static i64 recoverPageCount(sqlite3_recover *p){
! 14904: i64 nPg = 0;
! 14905: if( p->errCode==SQLITE_OK ){
! 14906: sqlite3_stmt *pStmt = 0;
! 14907: pStmt = recoverPreparePrintf(p, p->dbIn, "PRAGMA %Q.page_count", p->zDb);
! 14908: if( pStmt ){
! 14909: sqlite3_step(pStmt);
! 14910: nPg = sqlite3_column_int64(pStmt, 0);
! 14911: }
! 14912: recoverFinalize(p, pStmt);
! 14913: }
! 14914: return nPg;
! 14915: }
1.5 misho 14916:
1.6.2.1 ! misho 14917: /*
! 14918: ** Implementation of SQL scalar function "read_i32". The first argument to
! 14919: ** this function must be a blob. The second a non-negative integer. This
! 14920: ** function reads and returns a 32-bit big-endian integer from byte
! 14921: ** offset (4*<arg2>) of the blob.
! 14922: **
! 14923: ** SELECT read_i32(<blob>, <idx>)
! 14924: */
! 14925: static void recoverReadI32(
! 14926: sqlite3_context *context,
! 14927: int argc,
! 14928: sqlite3_value **argv
! 14929: ){
! 14930: const unsigned char *pBlob;
! 14931: int nBlob;
! 14932: int iInt;
1.5 misho 14933:
1.6.2.1 ! misho 14934: assert( argc==2 );
! 14935: nBlob = sqlite3_value_bytes(argv[0]);
! 14936: pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
! 14937: iInt = sqlite3_value_int(argv[1]) & 0xFFFF;
1.5 misho 14938:
1.6.2.1 ! misho 14939: if( (iInt+1)*4<=nBlob ){
! 14940: const unsigned char *a = &pBlob[iInt*4];
! 14941: i64 iVal = ((i64)a[0]<<24)
! 14942: + ((i64)a[1]<<16)
! 14943: + ((i64)a[2]<< 8)
! 14944: + ((i64)a[3]<< 0);
! 14945: sqlite3_result_int64(context, iVal);
! 14946: }
1.5 misho 14947: }
14948:
14949: /*
1.6.2.1 ! misho 14950: ** Implementation of SQL scalar function "page_is_used". This function
! 14951: ** is used as part of the procedure for locating orphan rows for the
! 14952: ** lost-and-found table, and it depends on those routines having populated
! 14953: ** the sqlite3_recover.laf.pUsed variable.
! 14954: **
! 14955: ** The only argument to this function is a page-number. It returns true
! 14956: ** if the page has already been used somehow during data recovery, or false
! 14957: ** otherwise.
1.5 misho 14958: **
1.6.2.1 ! misho 14959: ** SELECT page_is_used(<pgno>);
1.5 misho 14960: */
1.6.2.1 ! misho 14961: static void recoverPageIsUsed(
! 14962: sqlite3_context *pCtx,
! 14963: int nArg,
! 14964: sqlite3_value **apArg
! 14965: ){
! 14966: sqlite3_recover *p = (sqlite3_recover*)sqlite3_user_data(pCtx);
! 14967: i64 pgno = sqlite3_value_int64(apArg[0]);
! 14968: assert( nArg==1 );
! 14969: sqlite3_result_int(pCtx, recoverBitmapQuery(p->laf.pUsed, pgno));
! 14970: }
1.5 misho 14971:
1.6.2.1 ! misho 14972: /*
! 14973: ** The implementation of a user-defined SQL function invoked by the
! 14974: ** sqlite_dbdata and sqlite_dbptr virtual table modules to access pages
! 14975: ** of the database being recovered.
! 14976: **
! 14977: ** This function always takes a single integer argument. If the argument
! 14978: ** is zero, then the value returned is the number of pages in the db being
! 14979: ** recovered. If the argument is greater than zero, it is a page number.
! 14980: ** The value returned in this case is an SQL blob containing the data for
! 14981: ** the identified page of the db being recovered. e.g.
! 14982: **
! 14983: ** SELECT getpage(0); -- return number of pages in db
! 14984: ** SELECT getpage(4); -- return page 4 of db as a blob of data
! 14985: */
! 14986: static void recoverGetPage(
! 14987: sqlite3_context *pCtx,
! 14988: int nArg,
! 14989: sqlite3_value **apArg
! 14990: ){
! 14991: sqlite3_recover *p = (sqlite3_recover*)sqlite3_user_data(pCtx);
! 14992: i64 pgno = sqlite3_value_int64(apArg[0]);
! 14993: sqlite3_stmt *pStmt = 0;
1.5 misho 14994:
1.6.2.1 ! misho 14995: assert( nArg==1 );
! 14996: if( pgno==0 ){
! 14997: i64 nPg = recoverPageCount(p);
! 14998: sqlite3_result_int64(pCtx, nPg);
! 14999: return;
! 15000: }else{
! 15001: if( p->pGetPage==0 ){
! 15002: pStmt = p->pGetPage = recoverPreparePrintf(
! 15003: p, p->dbIn, "SELECT data FROM sqlite_dbpage(%Q) WHERE pgno=?", p->zDb
! 15004: );
! 15005: }else if( p->errCode==SQLITE_OK ){
! 15006: pStmt = p->pGetPage;
! 15007: }
1.5 misho 15008:
1.6.2.1 ! misho 15009: if( pStmt ){
! 15010: sqlite3_bind_int64(pStmt, 1, pgno);
! 15011: if( SQLITE_ROW==sqlite3_step(pStmt) ){
! 15012: const u8 *aPg;
! 15013: int nPg;
! 15014: assert( p->errCode==SQLITE_OK );
! 15015: aPg = sqlite3_column_blob(pStmt, 0);
! 15016: nPg = sqlite3_column_bytes(pStmt, 0);
! 15017: if( pgno==1 && nPg==p->pgsz && 0==memcmp(p->pPage1Cache, aPg, nPg) ){
! 15018: aPg = p->pPage1Disk;
! 15019: }
! 15020: sqlite3_result_blob(pCtx, aPg, nPg-p->nReserve, SQLITE_TRANSIENT);
! 15021: }
! 15022: recoverReset(p, pStmt);
! 15023: }
1.5 misho 15024: }
15025:
1.6.2.1 ! misho 15026: if( p->errCode ){
! 15027: if( p->zErrMsg ) sqlite3_result_error(pCtx, p->zErrMsg, -1);
! 15028: sqlite3_result_error_code(pCtx, p->errCode);
1.5 misho 15029: }
1.6.2.1 ! misho 15030: }
1.5 misho 15031:
1.6.2.1 ! misho 15032: /*
! 15033: ** Find a string that is not found anywhere in z[]. Return a pointer
! 15034: ** to that string.
! 15035: **
! 15036: ** Try to use zA and zB first. If both of those are already found in z[]
! 15037: ** then make up some string and store it in the buffer zBuf.
! 15038: */
! 15039: static const char *recoverUnusedString(
! 15040: const char *z, /* Result must not appear anywhere in z */
! 15041: const char *zA, const char *zB, /* Try these first */
! 15042: char *zBuf /* Space to store a generated string */
! 15043: ){
! 15044: unsigned i = 0;
! 15045: if( strstr(z, zA)==0 ) return zA;
! 15046: if( strstr(z, zB)==0 ) return zB;
! 15047: do{
! 15048: sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
! 15049: }while( strstr(z,zBuf)!=0 );
! 15050: return zBuf;
! 15051: }
1.5 misho 15052:
1.6.2.1 ! misho 15053: /*
! 15054: ** Implementation of scalar SQL function "escape_crnl". The argument passed to
! 15055: ** this function is the output of built-in function quote(). If the first
! 15056: ** character of the input is "'", indicating that the value passed to quote()
! 15057: ** was a text value, then this function searches the input for "\n" and "\r"
! 15058: ** characters and adds a wrapper similar to the following:
! 15059: **
! 15060: ** replace(replace(<input>, '\n', char(10), '\r', char(13));
! 15061: **
! 15062: ** Or, if the first character of the input is not "'", then a copy of the input
! 15063: ** is returned.
! 15064: */
! 15065: static void recoverEscapeCrnl(
! 15066: sqlite3_context *context,
! 15067: int argc,
! 15068: sqlite3_value **argv
! 15069: ){
! 15070: const char *zText = (const char*)sqlite3_value_text(argv[0]);
! 15071: (void)argc;
! 15072: if( zText && zText[0]=='\'' ){
! 15073: int nText = sqlite3_value_bytes(argv[0]);
! 15074: int i;
! 15075: char zBuf1[20];
! 15076: char zBuf2[20];
! 15077: const char *zNL = 0;
! 15078: const char *zCR = 0;
! 15079: int nCR = 0;
! 15080: int nNL = 0;
! 15081:
! 15082: for(i=0; zText[i]; i++){
! 15083: if( zNL==0 && zText[i]=='\n' ){
! 15084: zNL = recoverUnusedString(zText, "\\n", "\\012", zBuf1);
! 15085: nNL = (int)strlen(zNL);
! 15086: }
! 15087: if( zCR==0 && zText[i]=='\r' ){
! 15088: zCR = recoverUnusedString(zText, "\\r", "\\015", zBuf2);
! 15089: nCR = (int)strlen(zCR);
! 15090: }
1.5 misho 15091: }
15092:
1.6.2.1 ! misho 15093: if( zNL || zCR ){
! 15094: int iOut = 0;
! 15095: i64 nMax = (nNL > nCR) ? nNL : nCR;
! 15096: i64 nAlloc = nMax * nText + (nMax+64)*2;
! 15097: char *zOut = (char*)sqlite3_malloc64(nAlloc);
! 15098: if( zOut==0 ){
! 15099: sqlite3_result_error_nomem(context);
! 15100: return;
! 15101: }
1.5 misho 15102:
1.6.2.1 ! misho 15103: if( zNL && zCR ){
! 15104: memcpy(&zOut[iOut], "replace(replace(", 16);
! 15105: iOut += 16;
! 15106: }else{
! 15107: memcpy(&zOut[iOut], "replace(", 8);
! 15108: iOut += 8;
! 15109: }
! 15110: for(i=0; zText[i]; i++){
! 15111: if( zText[i]=='\n' ){
! 15112: memcpy(&zOut[iOut], zNL, nNL);
! 15113: iOut += nNL;
! 15114: }else if( zText[i]=='\r' ){
! 15115: memcpy(&zOut[iOut], zCR, nCR);
! 15116: iOut += nCR;
! 15117: }else{
! 15118: zOut[iOut] = zText[i];
! 15119: iOut++;
! 15120: }
! 15121: }
! 15122:
! 15123: if( zNL ){
! 15124: memcpy(&zOut[iOut], ",'", 2); iOut += 2;
! 15125: memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
! 15126: memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
! 15127: }
! 15128: if( zCR ){
! 15129: memcpy(&zOut[iOut], ",'", 2); iOut += 2;
! 15130: memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
! 15131: memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
! 15132: }
! 15133:
! 15134: sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
! 15135: sqlite3_free(zOut);
! 15136: return;
1.6 misho 15137: }
1.5 misho 15138: }
15139:
1.6.2.1 ! misho 15140: sqlite3_result_value(context, argv[0]);
! 15141: }
1.5 misho 15142:
1.6.2.1 ! misho 15143: /*
! 15144: ** This function is a no-op if recover handle p already contains an error
! 15145: ** (if p->errCode!=SQLITE_OK). A copy of the error code is returned in
! 15146: ** this case.
! 15147: **
! 15148: ** Otherwise, attempt to populate temporary table "recovery.schema" with the
! 15149: ** parts of the database schema that can be extracted from the input database.
! 15150: **
! 15151: ** If no error occurs, SQLITE_OK is returned. Otherwise, an error code
! 15152: ** and error message are left in the recover handle and a copy of the
! 15153: ** error code returned. It is not considered an error if part of all of
! 15154: ** the database schema cannot be recovered due to corruption.
! 15155: */
! 15156: static int recoverCacheSchema(sqlite3_recover *p){
! 15157: return recoverExec(p, p->dbOut,
! 15158: "WITH RECURSIVE pages(p) AS ("
! 15159: " SELECT 1"
! 15160: " UNION"
! 15161: " SELECT child FROM sqlite_dbptr('getpage()'), pages WHERE pgno=p"
! 15162: ")"
! 15163: "INSERT INTO recovery.schema SELECT"
! 15164: " max(CASE WHEN field=0 THEN value ELSE NULL END),"
! 15165: " max(CASE WHEN field=1 THEN value ELSE NULL END),"
! 15166: " max(CASE WHEN field=2 THEN value ELSE NULL END),"
! 15167: " max(CASE WHEN field=3 THEN value ELSE NULL END),"
! 15168: " max(CASE WHEN field=4 THEN value ELSE NULL END)"
! 15169: "FROM sqlite_dbdata('getpage()') WHERE pgno IN ("
! 15170: " SELECT p FROM pages"
! 15171: ") GROUP BY pgno, cell"
! 15172: );
1.5 misho 15173: }
15174:
15175: /*
1.6.2.1 ! misho 15176: ** If this recover handle is not in SQL callback mode (i.e. was not created
! 15177: ** using sqlite3_recover_init_sql()) of if an error has already occurred,
! 15178: ** this function is a no-op. Otherwise, issue a callback with SQL statement
! 15179: ** zSql as the parameter.
! 15180: **
! 15181: ** If the callback returns non-zero, set the recover handle error code to
! 15182: ** the value returned (so that the caller will abandon processing).
1.5 misho 15183: */
1.6.2.1 ! misho 15184: static void recoverSqlCallback(sqlite3_recover *p, const char *zSql){
! 15185: if( p->errCode==SQLITE_OK && p->xSql ){
! 15186: int res = p->xSql(p->pSqlCtx, zSql);
! 15187: if( res ){
! 15188: recoverError(p, SQLITE_ERROR, "callback returned an error - %d", res);
1.5 misho 15189: }
15190: }
1.6.2.1 ! misho 15191: }
1.5 misho 15192:
1.6.2.1 ! misho 15193: /*
! 15194: ** Transfer the following settings from the input database to the output
! 15195: ** database:
! 15196: **
! 15197: ** + page-size,
! 15198: ** + auto-vacuum settings,
! 15199: ** + database encoding,
! 15200: ** + user-version (PRAGMA user_version), and
! 15201: ** + application-id (PRAGMA application_id), and
! 15202: */
! 15203: static void recoverTransferSettings(sqlite3_recover *p){
! 15204: const char *aPragma[] = {
! 15205: "encoding",
! 15206: "page_size",
! 15207: "auto_vacuum",
! 15208: "user_version",
! 15209: "application_id"
! 15210: };
! 15211: int ii;
1.5 misho 15212:
1.6.2.1 ! misho 15213: /* Truncate the output database to 0 pages in size. This is done by
! 15214: ** opening a new, empty, temp db, then using the backup API to clobber
! 15215: ** any existing output db with a copy of it. */
! 15216: if( p->errCode==SQLITE_OK ){
! 15217: sqlite3 *db2 = 0;
! 15218: int rc = sqlite3_open("", &db2);
! 15219: if( rc!=SQLITE_OK ){
! 15220: recoverDbError(p, db2);
! 15221: return;
! 15222: }
1.5 misho 15223:
1.6.2.1 ! misho 15224: for(ii=0; ii<(int)(sizeof(aPragma)/sizeof(aPragma[0])); ii++){
! 15225: const char *zPrag = aPragma[ii];
! 15226: sqlite3_stmt *p1 = 0;
! 15227: p1 = recoverPreparePrintf(p, p->dbIn, "PRAGMA %Q.%s", p->zDb, zPrag);
! 15228: if( p->errCode==SQLITE_OK && sqlite3_step(p1)==SQLITE_ROW ){
! 15229: const char *zArg = (const char*)sqlite3_column_text(p1, 0);
! 15230: char *z2 = recoverMPrintf(p, "PRAGMA %s = %Q", zPrag, zArg);
! 15231: recoverSqlCallback(p, z2);
! 15232: recoverExec(p, db2, z2);
! 15233: sqlite3_free(z2);
! 15234: if( zArg==0 ){
! 15235: recoverError(p, SQLITE_NOMEM, 0);
! 15236: }
! 15237: }
! 15238: recoverFinalize(p, p1);
! 15239: }
! 15240: recoverExec(p, db2, "CREATE TABLE t1(a); DROP TABLE t1;");
! 15241:
! 15242: if( p->errCode==SQLITE_OK ){
! 15243: sqlite3 *db = p->dbOut;
! 15244: sqlite3_backup *pBackup = sqlite3_backup_init(db, "main", db2, "main");
! 15245: if( pBackup ){
! 15246: sqlite3_backup_step(pBackup, -1);
! 15247: p->errCode = sqlite3_backup_finish(pBackup);
! 15248: }else{
! 15249: recoverDbError(p, db);
! 15250: }
! 15251: }
1.5 misho 15252:
1.6.2.1 ! misho 15253: sqlite3_close(db2);
1.5 misho 15254: }
15255: }
15256:
15257: /*
1.6.2.1 ! misho 15258: ** This function is a no-op if recover handle p already contains an error
! 15259: ** (if p->errCode!=SQLITE_OK). A copy of the error code is returned in
! 15260: ** this case.
! 15261: **
! 15262: ** Otherwise, an attempt is made to open the output database, attach
! 15263: ** and create the schema of the temporary database used to store
! 15264: ** intermediate data, and to register all required user functions and
! 15265: ** virtual table modules with the output handle.
! 15266: **
! 15267: ** If no error occurs, SQLITE_OK is returned. Otherwise, an error code
! 15268: ** and error message are left in the recover handle and a copy of the
! 15269: ** error code returned.
1.5 misho 15270: */
1.6.2.1 ! misho 15271: static int recoverOpenOutput(sqlite3_recover *p){
! 15272: struct Func {
! 15273: const char *zName;
! 15274: int nArg;
! 15275: void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
! 15276: } aFunc[] = {
! 15277: { "getpage", 1, recoverGetPage },
! 15278: { "page_is_used", 1, recoverPageIsUsed },
! 15279: { "read_i32", 2, recoverReadI32 },
! 15280: { "escape_crnl", 1, recoverEscapeCrnl },
! 15281: };
! 15282:
! 15283: const int flags = SQLITE_OPEN_URI|SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE;
! 15284: sqlite3 *db = 0; /* New database handle */
! 15285: int ii; /* For iterating through aFunc[] */
! 15286:
! 15287: assert( p->dbOut==0 );
! 15288:
! 15289: if( sqlite3_open_v2(p->zUri, &db, flags, 0) ){
! 15290: recoverDbError(p, db);
! 15291: }
! 15292:
! 15293: /* Register the sqlite_dbdata and sqlite_dbptr virtual table modules.
! 15294: ** These two are registered with the output database handle - this
! 15295: ** module depends on the input handle supporting the sqlite_dbpage
! 15296: ** virtual table only. */
! 15297: if( p->errCode==SQLITE_OK ){
! 15298: p->errCode = sqlite3_dbdata_init(db, 0, 0);
! 15299: }
! 15300:
! 15301: /* Register the custom user-functions with the output handle. */
! 15302: for(ii=0;
! 15303: p->errCode==SQLITE_OK && ii<(int)(sizeof(aFunc)/sizeof(aFunc[0]));
! 15304: ii++){
! 15305: p->errCode = sqlite3_create_function(db, aFunc[ii].zName,
! 15306: aFunc[ii].nArg, SQLITE_UTF8, (void*)p, aFunc[ii].xFunc, 0, 0
! 15307: );
1.5 misho 15308: }
15309:
1.6.2.1 ! misho 15310: p->dbOut = db;
! 15311: return p->errCode;
1.5 misho 15312: }
15313:
15314: /*
1.6.2.1 ! misho 15315: ** Attach the auxiliary database 'recovery' to the output database handle.
! 15316: ** This temporary database is used during the recovery process and then
! 15317: ** discarded.
! 15318: */
! 15319: static void recoverOpenRecovery(sqlite3_recover *p){
! 15320: char *zSql = recoverMPrintf(p, "ATTACH %Q AS recovery;", p->zStateDb);
! 15321: recoverExec(p, p->dbOut, zSql);
! 15322: recoverExec(p, p->dbOut,
! 15323: "PRAGMA writable_schema = 1;"
! 15324: "CREATE TABLE recovery.map(pgno INTEGER PRIMARY KEY, parent INT);"
! 15325: "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
! 15326: );
! 15327: sqlite3_free(zSql);
! 15328: }
! 15329:
! 15330:
! 15331: /*
! 15332: ** This function is a no-op if recover handle p already contains an error
! 15333: ** (if p->errCode!=SQLITE_OK).
! 15334: **
! 15335: ** Otherwise, argument zName must be the name of a table that has just been
! 15336: ** created in the output database. This function queries the output db
! 15337: ** for the schema of said table, and creates a RecoverTable object to
! 15338: ** store the schema in memory. The new RecoverTable object is linked into
! 15339: ** the list at sqlite3_recover.pTblList.
! 15340: **
! 15341: ** Parameter iRoot must be the root page of table zName in the INPUT
! 15342: ** database.
! 15343: */
! 15344: static void recoverAddTable(
! 15345: sqlite3_recover *p,
! 15346: const char *zName, /* Name of table created in output db */
! 15347: i64 iRoot /* Root page of same table in INPUT db */
1.5 misho 15348: ){
1.6.2.1 ! misho 15349: sqlite3_stmt *pStmt = recoverPreparePrintf(p, p->dbOut,
! 15350: "PRAGMA table_xinfo(%Q)", zName
! 15351: );
1.5 misho 15352:
1.6.2.1 ! misho 15353: if( pStmt ){
! 15354: int iPk = -1;
! 15355: int iBind = 1;
! 15356: RecoverTable *pNew = 0;
! 15357: int nCol = 0;
! 15358: int nName = recoverStrlen(zName);
! 15359: int nByte = 0;
! 15360: while( sqlite3_step(pStmt)==SQLITE_ROW ){
! 15361: nCol++;
! 15362: nByte += (sqlite3_column_bytes(pStmt, 1)+1);
! 15363: }
! 15364: nByte += sizeof(RecoverTable) + nCol*sizeof(RecoverColumn) + nName+1;
! 15365: recoverReset(p, pStmt);
1.5 misho 15366:
1.6.2.1 ! misho 15367: pNew = recoverMalloc(p, nByte);
! 15368: if( pNew ){
! 15369: int i = 0;
! 15370: int iField = 0;
! 15371: char *csr = 0;
! 15372: pNew->aCol = (RecoverColumn*)&pNew[1];
! 15373: pNew->zTab = csr = (char*)&pNew->aCol[nCol];
! 15374: pNew->nCol = nCol;
! 15375: pNew->iRoot = iRoot;
! 15376: memcpy(csr, zName, nName);
! 15377: csr += nName+1;
! 15378:
! 15379: for(i=0; sqlite3_step(pStmt)==SQLITE_ROW; i++){
! 15380: int iPKF = sqlite3_column_int(pStmt, 5);
! 15381: int n = sqlite3_column_bytes(pStmt, 1);
! 15382: const char *z = (const char*)sqlite3_column_text(pStmt, 1);
! 15383: const char *zType = (const char*)sqlite3_column_text(pStmt, 2);
! 15384: int eHidden = sqlite3_column_int(pStmt, 6);
! 15385:
! 15386: if( iPk==-1 && iPKF==1 && !sqlite3_stricmp("integer", zType) ) iPk = i;
! 15387: if( iPKF>1 ) iPk = -2;
! 15388: pNew->aCol[i].zCol = csr;
! 15389: pNew->aCol[i].eHidden = eHidden;
! 15390: if( eHidden==RECOVER_EHIDDEN_VIRTUAL ){
! 15391: pNew->aCol[i].iField = -1;
! 15392: }else{
! 15393: pNew->aCol[i].iField = iField++;
1.5 misho 15394: }
1.6.2.1 ! misho 15395: if( eHidden!=RECOVER_EHIDDEN_VIRTUAL
! 15396: && eHidden!=RECOVER_EHIDDEN_STORED
! 15397: ){
! 15398: pNew->aCol[i].iBind = iBind++;
! 15399: }
! 15400: memcpy(csr, z, n);
! 15401: csr += (n+1);
1.5 misho 15402: }
15403:
1.6.2.1 ! misho 15404: pNew->pNext = p->pTblList;
! 15405: p->pTblList = pNew;
! 15406: pNew->bIntkey = 1;
! 15407: }
1.5 misho 15408:
1.6.2.1 ! misho 15409: recoverFinalize(p, pStmt);
1.5 misho 15410:
1.6.2.1 ! misho 15411: pStmt = recoverPreparePrintf(p, p->dbOut, "PRAGMA index_xinfo(%Q)", zName);
! 15412: while( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
! 15413: int iField = sqlite3_column_int(pStmt, 0);
! 15414: int iCol = sqlite3_column_int(pStmt, 1);
1.5 misho 15415:
1.6.2.1 ! misho 15416: assert( iCol<pNew->nCol );
! 15417: pNew->aCol[iCol].iField = iField;
1.5 misho 15418:
1.6.2.1 ! misho 15419: pNew->bIntkey = 0;
! 15420: iPk = -2;
! 15421: }
! 15422: recoverFinalize(p, pStmt);
1.5 misho 15423:
1.6.2.1 ! misho 15424: if( p->errCode==SQLITE_OK ){
! 15425: if( iPk>=0 ){
! 15426: pNew->aCol[iPk].bIPK = 1;
! 15427: }else if( pNew->bIntkey ){
! 15428: pNew->iRowidBind = iBind++;
! 15429: }
! 15430: }
! 15431: }
1.5 misho 15432: }
15433:
15434: /*
1.6.2.1 ! misho 15435: ** This function is called after recoverCacheSchema() has cached those parts
! 15436: ** of the input database schema that could be recovered in temporary table
! 15437: ** "recovery.schema". This function creates in the output database copies
! 15438: ** of all parts of that schema that must be created before the tables can
! 15439: ** be populated. Specifically, this means:
! 15440: **
! 15441: ** * all tables that are not VIRTUAL, and
! 15442: ** * UNIQUE indexes.
! 15443: **
! 15444: ** If the recovery handle uses SQL callbacks, then callbacks containing
! 15445: ** the associated "CREATE TABLE" and "CREATE INDEX" statements are made.
! 15446: **
! 15447: ** Additionally, records are added to the sqlite_schema table of the
! 15448: ** output database for any VIRTUAL tables. The CREATE VIRTUAL TABLE
! 15449: ** records are written directly to sqlite_schema, not actually executed.
! 15450: ** If the handle is in SQL callback mode, then callbacks are invoked
! 15451: ** with equivalent SQL statements.
1.5 misho 15452: */
1.6.2.1 ! misho 15453: static int recoverWriteSchema1(sqlite3_recover *p){
! 15454: sqlite3_stmt *pSelect = 0;
! 15455: sqlite3_stmt *pTblname = 0;
1.5 misho 15456:
1.6.2.1 ! misho 15457: pSelect = recoverPrepare(p, p->dbOut,
! 15458: "WITH dbschema(rootpage, name, sql, tbl, isVirtual, isIndex) AS ("
! 15459: " SELECT rootpage, name, sql, "
! 15460: " type='table', "
! 15461: " sql LIKE 'create virtual%',"
! 15462: " (type='index' AND (sql LIKE '%unique%' OR ?1))"
! 15463: " FROM recovery.schema"
! 15464: ")"
! 15465: "SELECT rootpage, tbl, isVirtual, name, sql"
! 15466: " FROM dbschema "
! 15467: " WHERE tbl OR isIndex"
! 15468: " ORDER BY tbl DESC, name=='sqlite_sequence' DESC"
! 15469: );
! 15470:
! 15471: pTblname = recoverPrepare(p, p->dbOut,
! 15472: "SELECT name FROM sqlite_schema "
! 15473: "WHERE type='table' ORDER BY rowid DESC LIMIT 1"
! 15474: );
! 15475:
! 15476: if( pSelect ){
! 15477: sqlite3_bind_int(pSelect, 1, p->bSlowIndexes);
! 15478: while( sqlite3_step(pSelect)==SQLITE_ROW ){
! 15479: i64 iRoot = sqlite3_column_int64(pSelect, 0);
! 15480: int bTable = sqlite3_column_int(pSelect, 1);
! 15481: int bVirtual = sqlite3_column_int(pSelect, 2);
! 15482: const char *zName = (const char*)sqlite3_column_text(pSelect, 3);
! 15483: const char *zSql = (const char*)sqlite3_column_text(pSelect, 4);
! 15484: char *zFree = 0;
! 15485: int rc = SQLITE_OK;
! 15486:
! 15487: if( bVirtual ){
! 15488: zSql = (const char*)(zFree = recoverMPrintf(p,
! 15489: "INSERT INTO sqlite_schema VALUES('table', %Q, %Q, 0, %Q)",
! 15490: zName, zName, zSql
! 15491: ));
! 15492: }
! 15493: rc = sqlite3_exec(p->dbOut, zSql, 0, 0, 0);
! 15494: if( rc==SQLITE_OK ){
! 15495: recoverSqlCallback(p, zSql);
! 15496: if( bTable && !bVirtual ){
! 15497: if( SQLITE_ROW==sqlite3_step(pTblname) ){
! 15498: const char *zTbl = (const char*)sqlite3_column_text(pTblname, 0);
! 15499: recoverAddTable(p, zTbl, iRoot);
! 15500: }
! 15501: recoverReset(p, pTblname);
! 15502: }
! 15503: }else if( rc!=SQLITE_ERROR ){
! 15504: recoverDbError(p, p->dbOut);
! 15505: }
! 15506: sqlite3_free(zFree);
! 15507: }
1.5 misho 15508: }
1.6.2.1 ! misho 15509: recoverFinalize(p, pSelect);
! 15510: recoverFinalize(p, pTblname);
! 15511:
! 15512: return p->errCode;
1.5 misho 15513: }
15514:
15515: /*
1.6.2.1 ! misho 15516: ** This function is called after the output database has been populated. It
! 15517: ** adds all recovered schema elements that were not created in the output
! 15518: ** database by recoverWriteSchema1() - everything except for tables and
! 15519: ** UNIQUE indexes. Specifically:
! 15520: **
! 15521: ** * views,
! 15522: ** * triggers,
! 15523: ** * non-UNIQUE indexes.
! 15524: **
! 15525: ** If the recover handle is in SQL callback mode, then equivalent callbacks
! 15526: ** are issued to create the schema elements.
1.5 misho 15527: */
1.6.2.1 ! misho 15528: static int recoverWriteSchema2(sqlite3_recover *p){
! 15529: sqlite3_stmt *pSelect = 0;
1.5 misho 15530:
1.6.2.1 ! misho 15531: pSelect = recoverPrepare(p, p->dbOut,
! 15532: p->bSlowIndexes ?
! 15533: "SELECT rootpage, sql FROM recovery.schema "
! 15534: " WHERE type!='table' AND type!='index'"
! 15535: :
! 15536: "SELECT rootpage, sql FROM recovery.schema "
! 15537: " WHERE type!='table' AND (type!='index' OR sql NOT LIKE '%unique%')"
! 15538: );
1.5 misho 15539:
1.6.2.1 ! misho 15540: if( pSelect ){
! 15541: while( sqlite3_step(pSelect)==SQLITE_ROW ){
! 15542: const char *zSql = (const char*)sqlite3_column_text(pSelect, 1);
! 15543: int rc = sqlite3_exec(p->dbOut, zSql, 0, 0, 0);
! 15544: if( rc==SQLITE_OK ){
! 15545: recoverSqlCallback(p, zSql);
! 15546: }else if( rc!=SQLITE_ERROR ){
! 15547: recoverDbError(p, p->dbOut);
! 15548: }
! 15549: }
! 15550: }
! 15551: recoverFinalize(p, pSelect);
! 15552:
! 15553: return p->errCode;
! 15554: }
1.5 misho 15555:
15556: /*
1.6.2.1 ! misho 15557: ** This function is a no-op if recover handle p already contains an error
! 15558: ** (if p->errCode!=SQLITE_OK). In this case it returns NULL.
1.5 misho 15559: **
1.6.2.1 ! misho 15560: ** Otherwise, if the recover handle is configured to create an output
! 15561: ** database (was created by sqlite3_recover_init()), then this function
! 15562: ** prepares and returns an SQL statement to INSERT a new record into table
! 15563: ** pTab, assuming the first nField fields of a record extracted from disk
! 15564: ** are valid.
1.5 misho 15565: **
1.6.2.1 ! misho 15566: ** For example, if table pTab is:
1.5 misho 15567: **
1.6.2.1 ! misho 15568: ** CREATE TABLE name(a, b GENERATED ALWAYS AS (a+1) STORED, c, d, e);
1.5 misho 15569: **
1.6.2.1 ! misho 15570: ** And nField is 4, then the SQL statement prepared and returned is:
1.5 misho 15571: **
1.6.2.1 ! misho 15572: ** INSERT INTO (a, c, d) VALUES (?1, ?2, ?3);
1.5 misho 15573: **
1.6.2.1 ! misho 15574: ** In this case even though 4 values were extracted from the input db,
! 15575: ** only 3 are written to the output, as the generated STORED column
! 15576: ** cannot be written.
1.5 misho 15577: **
1.6.2.1 ! misho 15578: ** If the recover handle is in SQL callback mode, then the SQL statement
! 15579: ** prepared is such that evaluating it returns a single row containing
! 15580: ** a single text value - itself an SQL statement similar to the above,
! 15581: ** except with SQL literals in place of the variables. For example:
1.5 misho 15582: **
1.6.2.1 ! misho 15583: ** SELECT 'INSERT INTO (a, c, d) VALUES ('
! 15584: ** || quote(?1) || ', '
! 15585: ** || quote(?2) || ', '
! 15586: ** || quote(?3) || ')';
1.5 misho 15587: **
1.6.2.1 ! misho 15588: ** In either case, it is the responsibility of the caller to eventually
! 15589: ** free the statement handle using sqlite3_finalize().
1.5 misho 15590: */
1.6.2.1 ! misho 15591: static sqlite3_stmt *recoverInsertStmt(
! 15592: sqlite3_recover *p,
! 15593: RecoverTable *pTab,
! 15594: int nField
! 15595: ){
! 15596: sqlite3_stmt *pRet = 0;
! 15597: const char *zSep = "";
! 15598: const char *zSqlSep = "";
! 15599: char *zSql = 0;
! 15600: char *zFinal = 0;
! 15601: char *zBind = 0;
! 15602: int ii;
! 15603: int bSql = p->xSql ? 1 : 0;
1.5 misho 15604:
1.6.2.1 ! misho 15605: if( nField<=0 ) return 0;
1.5 misho 15606:
1.6.2.1 ! misho 15607: assert( nField<=pTab->nCol );
1.5 misho 15608:
1.6.2.1 ! misho 15609: zSql = recoverMPrintf(p, "INSERT OR IGNORE INTO %Q(", pTab->zTab);
1.5 misho 15610:
1.6.2.1 ! misho 15611: if( pTab->iRowidBind ){
! 15612: assert( pTab->bIntkey );
! 15613: zSql = recoverMPrintf(p, "%z_rowid_", zSql);
! 15614: if( bSql ){
! 15615: zBind = recoverMPrintf(p, "%zquote(?%d)", zBind, pTab->iRowidBind);
! 15616: }else{
! 15617: zBind = recoverMPrintf(p, "%z?%d", zBind, pTab->iRowidBind);
! 15618: }
! 15619: zSqlSep = "||', '||";
! 15620: zSep = ", ";
! 15621: }
1.5 misho 15622:
1.6.2.1 ! misho 15623: for(ii=0; ii<nField; ii++){
! 15624: int eHidden = pTab->aCol[ii].eHidden;
! 15625: if( eHidden!=RECOVER_EHIDDEN_VIRTUAL
! 15626: && eHidden!=RECOVER_EHIDDEN_STORED
! 15627: ){
! 15628: assert( pTab->aCol[ii].iField>=0 && pTab->aCol[ii].iBind>=1 );
! 15629: zSql = recoverMPrintf(p, "%z%s%Q", zSql, zSep, pTab->aCol[ii].zCol);
1.5 misho 15630:
1.6.2.1 ! misho 15631: if( bSql ){
! 15632: zBind = recoverMPrintf(p,
! 15633: "%z%sescape_crnl(quote(?%d))", zBind, zSqlSep, pTab->aCol[ii].iBind
! 15634: );
! 15635: zSqlSep = "||', '||";
! 15636: }else{
! 15637: zBind = recoverMPrintf(p, "%z%s?%d", zBind, zSep, pTab->aCol[ii].iBind);
! 15638: }
! 15639: zSep = ", ";
! 15640: }
! 15641: }
1.5 misho 15642:
1.6.2.1 ! misho 15643: if( bSql ){
! 15644: zFinal = recoverMPrintf(p, "SELECT %Q || ') VALUES (' || %s || ')'",
! 15645: zSql, zBind
! 15646: );
! 15647: }else{
! 15648: zFinal = recoverMPrintf(p, "%s) VALUES (%s)", zSql, zBind);
! 15649: }
! 15650:
! 15651: pRet = recoverPrepare(p, p->dbOut, zFinal);
! 15652: sqlite3_free(zSql);
! 15653: sqlite3_free(zBind);
! 15654: sqlite3_free(zFinal);
1.5 misho 15655:
1.6.2.1 ! misho 15656: return pRet;
! 15657: }
1.5 misho 15658:
15659:
1.6.2.1 ! misho 15660: /*
! 15661: ** Search the list of RecoverTable objects at p->pTblList for one that
! 15662: ** has root page iRoot in the input database. If such an object is found,
! 15663: ** return a pointer to it. Otherwise, return NULL.
! 15664: */
! 15665: static RecoverTable *recoverFindTable(sqlite3_recover *p, u32 iRoot){
! 15666: RecoverTable *pRet = 0;
! 15667: for(pRet=p->pTblList; pRet && pRet->iRoot!=iRoot; pRet=pRet->pNext);
! 15668: return pRet;
! 15669: }
1.5 misho 15670:
1.6.2.1 ! misho 15671: /*
! 15672: ** This function attempts to create a lost and found table within the
! 15673: ** output db. If successful, it returns a pointer to a buffer containing
! 15674: ** the name of the new table. It is the responsibility of the caller to
! 15675: ** eventually free this buffer using sqlite3_free().
! 15676: **
! 15677: ** If an error occurs, NULL is returned and an error code and error
! 15678: ** message left in the recover handle.
! 15679: */
! 15680: static char *recoverLostAndFoundCreate(
! 15681: sqlite3_recover *p, /* Recover object */
! 15682: int nField /* Number of column fields in new table */
! 15683: ){
! 15684: char *zTbl = 0;
! 15685: sqlite3_stmt *pProbe = 0;
! 15686: int ii = 0;
! 15687:
! 15688: pProbe = recoverPrepare(p, p->dbOut,
! 15689: "SELECT 1 FROM sqlite_schema WHERE name=?"
! 15690: );
! 15691: for(ii=-1; zTbl==0 && p->errCode==SQLITE_OK && ii<1000; ii++){
! 15692: int bFail = 0;
! 15693: if( ii<0 ){
! 15694: zTbl = recoverMPrintf(p, "%s", p->zLostAndFound);
! 15695: }else{
! 15696: zTbl = recoverMPrintf(p, "%s_%d", p->zLostAndFound, ii);
! 15697: }
! 15698:
! 15699: if( p->errCode==SQLITE_OK ){
! 15700: sqlite3_bind_text(pProbe, 1, zTbl, -1, SQLITE_STATIC);
! 15701: if( SQLITE_ROW==sqlite3_step(pProbe) ){
! 15702: bFail = 1;
! 15703: }
! 15704: recoverReset(p, pProbe);
! 15705: }
! 15706:
! 15707: if( bFail ){
! 15708: sqlite3_clear_bindings(pProbe);
! 15709: sqlite3_free(zTbl);
! 15710: zTbl = 0;
! 15711: }
! 15712: }
! 15713: recoverFinalize(p, pProbe);
! 15714:
! 15715: if( zTbl ){
! 15716: const char *zSep = 0;
! 15717: char *zField = 0;
! 15718: char *zSql = 0;
! 15719:
! 15720: zSep = "rootpgno INTEGER, pgno INTEGER, nfield INTEGER, id INTEGER, ";
! 15721: for(ii=0; p->errCode==SQLITE_OK && ii<nField; ii++){
! 15722: zField = recoverMPrintf(p, "%z%sc%d", zField, zSep, ii);
! 15723: zSep = ", ";
! 15724: }
! 15725:
! 15726: zSql = recoverMPrintf(p, "CREATE TABLE %s(%s)", zTbl, zField);
! 15727: sqlite3_free(zField);
! 15728:
! 15729: recoverExec(p, p->dbOut, zSql);
! 15730: recoverSqlCallback(p, zSql);
! 15731: sqlite3_free(zSql);
! 15732: }else if( p->errCode==SQLITE_OK ){
! 15733: recoverError(
! 15734: p, SQLITE_ERROR, "failed to create %s output table", p->zLostAndFound
! 15735: );
! 15736: }
! 15737:
! 15738: return zTbl;
! 15739: }
1.5 misho 15740:
15741: /*
1.6.2.1 ! misho 15742: ** Synthesize and prepare an INSERT statement to write to the lost_and_found
! 15743: ** table in the output database. The name of the table is zTab, and it has
! 15744: ** nField c* fields.
1.5 misho 15745: */
1.6.2.1 ! misho 15746: static sqlite3_stmt *recoverLostAndFoundInsert(
! 15747: sqlite3_recover *p,
! 15748: const char *zTab,
! 15749: int nField
1.5 misho 15750: ){
1.6.2.1 ! misho 15751: int nTotal = nField + 4;
! 15752: int ii;
! 15753: char *zBind = 0;
! 15754: sqlite3_stmt *pRet = 0;
! 15755:
! 15756: if( p->xSql==0 ){
! 15757: for(ii=0; ii<nTotal; ii++){
! 15758: zBind = recoverMPrintf(p, "%z%s?", zBind, zBind?", ":"", ii);
1.5 misho 15759: }
1.6.2.1 ! misho 15760: pRet = recoverPreparePrintf(
! 15761: p, p->dbOut, "INSERT INTO %s VALUES(%s)", zTab, zBind
! 15762: );
! 15763: }else{
! 15764: const char *zSep = "";
! 15765: for(ii=0; ii<nTotal; ii++){
! 15766: zBind = recoverMPrintf(p, "%z%squote(?)", zBind, zSep);
! 15767: zSep = "|| ', ' ||";
! 15768: }
! 15769: pRet = recoverPreparePrintf(
! 15770: p, p->dbOut, "SELECT 'INSERT INTO %s VALUES(' || %s || ')'", zTab, zBind
! 15771: );
1.5 misho 15772: }
15773:
1.6.2.1 ! misho 15774: sqlite3_free(zBind);
! 15775: return pRet;
1.5 misho 15776: }
15777:
15778: /*
1.6.2.1 ! misho 15779: ** Input database page iPg contains data that will be written to the
! 15780: ** lost-and-found table of the output database. This function attempts
! 15781: ** to identify the root page of the tree that page iPg belonged to.
! 15782: ** If successful, it sets output variable (*piRoot) to the page number
! 15783: ** of the root page and returns SQLITE_OK. Otherwise, if an error occurs,
! 15784: ** an SQLite error code is returned and the final value of *piRoot
! 15785: ** undefined.
! 15786: */
! 15787: static int recoverLostAndFoundFindRoot(
! 15788: sqlite3_recover *p,
! 15789: i64 iPg,
! 15790: i64 *piRoot
! 15791: ){
! 15792: RecoverStateLAF *pLaf = &p->laf;
! 15793:
! 15794: if( pLaf->pFindRoot==0 ){
! 15795: pLaf->pFindRoot = recoverPrepare(p, p->dbOut,
! 15796: "WITH RECURSIVE p(pgno) AS ("
! 15797: " SELECT ?"
! 15798: " UNION"
! 15799: " SELECT parent FROM recovery.map AS m, p WHERE m.pgno=p.pgno"
! 15800: ") "
! 15801: "SELECT p.pgno FROM p, recovery.map m WHERE m.pgno=p.pgno "
! 15802: " AND m.parent IS NULL"
! 15803: );
1.5 misho 15804: }
1.6.2.1 ! misho 15805: if( p->errCode==SQLITE_OK ){
! 15806: sqlite3_bind_int64(pLaf->pFindRoot, 1, iPg);
! 15807: if( sqlite3_step(pLaf->pFindRoot)==SQLITE_ROW ){
! 15808: *piRoot = sqlite3_column_int64(pLaf->pFindRoot, 0);
! 15809: }else{
! 15810: *piRoot = iPg;
! 15811: }
! 15812: recoverReset(p, pLaf->pFindRoot);
! 15813: }
! 15814: return p->errCode;
1.5 misho 15815: }
15816:
15817: /*
1.6.2.1 ! misho 15818: ** Recover data from page iPage of the input database and write it to
! 15819: ** the lost-and-found table in the output database.
1.5 misho 15820: */
1.6.2.1 ! misho 15821: static void recoverLostAndFoundOnePage(sqlite3_recover *p, i64 iPage){
! 15822: RecoverStateLAF *pLaf = &p->laf;
! 15823: sqlite3_value **apVal = pLaf->apVal;
! 15824: sqlite3_stmt *pPageData = pLaf->pPageData;
! 15825: sqlite3_stmt *pInsert = pLaf->pInsert;
1.5 misho 15826:
1.6.2.1 ! misho 15827: int nVal = -1;
! 15828: int iPrevCell = 0;
! 15829: i64 iRoot = 0;
! 15830: int bHaveRowid = 0;
! 15831: i64 iRowid = 0;
! 15832: int ii = 0;
! 15833:
! 15834: if( recoverLostAndFoundFindRoot(p, iPage, &iRoot) ) return;
! 15835: sqlite3_bind_int64(pPageData, 1, iPage);
! 15836: while( p->errCode==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPageData) ){
! 15837: int iCell = sqlite3_column_int64(pPageData, 0);
! 15838: int iField = sqlite3_column_int64(pPageData, 1);
! 15839:
! 15840: if( iPrevCell!=iCell && nVal>=0 ){
! 15841: /* Insert the new row */
! 15842: sqlite3_bind_int64(pInsert, 1, iRoot); /* rootpgno */
! 15843: sqlite3_bind_int64(pInsert, 2, iPage); /* pgno */
! 15844: sqlite3_bind_int(pInsert, 3, nVal); /* nfield */
! 15845: if( bHaveRowid ){
! 15846: sqlite3_bind_int64(pInsert, 4, iRowid); /* id */
1.5 misho 15847: }
1.6.2.1 ! misho 15848: for(ii=0; ii<nVal; ii++){
! 15849: recoverBindValue(p, pInsert, 5+ii, apVal[ii]);
! 15850: }
! 15851: if( sqlite3_step(pInsert)==SQLITE_ROW ){
! 15852: recoverSqlCallback(p, (const char*)sqlite3_column_text(pInsert, 0));
! 15853: }
! 15854: recoverReset(p, pInsert);
! 15855:
! 15856: /* Discard the accumulated row data */
! 15857: for(ii=0; ii<nVal; ii++){
! 15858: sqlite3_value_free(apVal[ii]);
! 15859: apVal[ii] = 0;
! 15860: }
! 15861: sqlite3_clear_bindings(pInsert);
! 15862: bHaveRowid = 0;
! 15863: nVal = -1;
! 15864: }
! 15865:
! 15866: if( iCell<0 ) break;
! 15867:
! 15868: if( iField<0 ){
! 15869: assert( nVal==-1 );
! 15870: iRowid = sqlite3_column_int64(pPageData, 2);
! 15871: bHaveRowid = 1;
! 15872: nVal = 0;
! 15873: }else if( iField<pLaf->nMaxField ){
! 15874: sqlite3_value *pVal = sqlite3_column_value(pPageData, 2);
! 15875: apVal[iField] = sqlite3_value_dup(pVal);
! 15876: assert( iField==nVal || (nVal==-1 && iField==0) );
! 15877: nVal = iField+1;
! 15878: if( apVal[iField]==0 ){
! 15879: recoverError(p, SQLITE_NOMEM, 0);
1.5 misho 15880: }
15881: }
1.6.2.1 ! misho 15882:
! 15883: iPrevCell = iCell;
1.5 misho 15884: }
1.6.2.1 ! misho 15885: recoverReset(p, pPageData);
1.5 misho 15886:
1.6.2.1 ! misho 15887: for(ii=0; ii<nVal; ii++){
! 15888: sqlite3_value_free(apVal[ii]);
! 15889: apVal[ii] = 0;
1.5 misho 15890: }
1.6.2.1 ! misho 15891: }
1.5 misho 15892:
1.6.2.1 ! misho 15893: /*
! 15894: ** Perform one step (sqlite3_recover_step()) of work for the connection
! 15895: ** passed as the only argument, which is guaranteed to be in
! 15896: ** RECOVER_STATE_LOSTANDFOUND3 state - during which the lost-and-found
! 15897: ** table of the output database is populated with recovered data that can
! 15898: ** not be assigned to any recovered schema object.
! 15899: */
! 15900: static int recoverLostAndFound3Step(sqlite3_recover *p){
! 15901: RecoverStateLAF *pLaf = &p->laf;
! 15902: if( p->errCode==SQLITE_OK ){
! 15903: if( pLaf->pInsert==0 ){
! 15904: return SQLITE_DONE;
! 15905: }else{
! 15906: if( p->errCode==SQLITE_OK ){
! 15907: int res = sqlite3_step(pLaf->pAllPage);
! 15908: if( res==SQLITE_ROW ){
! 15909: i64 iPage = sqlite3_column_int64(pLaf->pAllPage, 0);
! 15910: if( recoverBitmapQuery(pLaf->pUsed, iPage)==0 ){
! 15911: recoverLostAndFoundOnePage(p, iPage);
! 15912: }
! 15913: }else{
! 15914: recoverReset(p, pLaf->pAllPage);
! 15915: return SQLITE_DONE;
! 15916: }
1.5 misho 15917: }
15918: }
15919: }
15920: return SQLITE_OK;
15921: }
15922:
15923: /*
1.6.2.1 ! misho 15924: ** Initialize resources required in RECOVER_STATE_LOSTANDFOUND3
! 15925: ** state - during which the lost-and-found table of the output database
! 15926: ** is populated with recovered data that can not be assigned to any
! 15927: ** recovered schema object.
! 15928: */
! 15929: static void recoverLostAndFound3Init(sqlite3_recover *p){
! 15930: RecoverStateLAF *pLaf = &p->laf;
1.5 misho 15931:
1.6.2.1 ! misho 15932: if( pLaf->nMaxField>0 ){
! 15933: char *zTab = 0; /* Name of lost_and_found table */
! 15934:
! 15935: zTab = recoverLostAndFoundCreate(p, pLaf->nMaxField);
! 15936: pLaf->pInsert = recoverLostAndFoundInsert(p, zTab, pLaf->nMaxField);
! 15937: sqlite3_free(zTab);
! 15938:
! 15939: pLaf->pAllPage = recoverPreparePrintf(p, p->dbOut,
! 15940: "WITH RECURSIVE seq(ii) AS ("
! 15941: " SELECT 1 UNION ALL SELECT ii+1 FROM seq WHERE ii<%lld"
! 15942: ")"
! 15943: "SELECT ii FROM seq" , p->laf.nPg
! 15944: );
! 15945: pLaf->pPageData = recoverPrepare(p, p->dbOut,
! 15946: "SELECT cell, field, value "
! 15947: "FROM sqlite_dbdata('getpage()') d WHERE d.pgno=? "
! 15948: "UNION ALL "
! 15949: "SELECT -1, -1, -1"
! 15950: );
! 15951:
! 15952: pLaf->apVal = (sqlite3_value**)recoverMalloc(p,
! 15953: pLaf->nMaxField*sizeof(sqlite3_value*)
! 15954: );
1.5 misho 15955: }
1.6.2.1 ! misho 15956: }
1.5 misho 15957:
1.6.2.1 ! misho 15958: /*
! 15959: ** Initialize resources required in RECOVER_STATE_WRITING state - during which
! 15960: ** tables recovered from the schema of the input database are populated with
! 15961: ** recovered data.
! 15962: */
! 15963: static int recoverWriteDataInit(sqlite3_recover *p){
! 15964: RecoverStateW1 *p1 = &p->w1;
! 15965: RecoverTable *pTbl = 0;
! 15966: int nByte = 0;
! 15967:
! 15968: /* Figure out the maximum number of columns for any table in the schema */
! 15969: assert( p1->nMax==0 );
! 15970: for(pTbl=p->pTblList; pTbl; pTbl=pTbl->pNext){
! 15971: if( pTbl->nCol>p1->nMax ) p1->nMax = pTbl->nCol;
! 15972: }
! 15973:
! 15974: /* Allocate an array of (sqlite3_value*) in which to accumulate the values
! 15975: ** that will be written to the output database in a single row. */
! 15976: nByte = sizeof(sqlite3_value*) * (p1->nMax+1);
! 15977: p1->apVal = (sqlite3_value**)recoverMalloc(p, nByte);
! 15978: if( p1->apVal==0 ) return p->errCode;
! 15979:
! 15980: /* Prepare the SELECT to loop through schema tables (pTbls) and the SELECT
! 15981: ** to loop through cells that appear to belong to a single table (pSel). */
! 15982: p1->pTbls = recoverPrepare(p, p->dbOut,
! 15983: "SELECT rootpage FROM recovery.schema "
! 15984: " WHERE type='table' AND (sql NOT LIKE 'create virtual%')"
! 15985: " ORDER BY (tbl_name='sqlite_sequence') ASC"
! 15986: );
! 15987: p1->pSel = recoverPrepare(p, p->dbOut,
! 15988: "WITH RECURSIVE pages(page) AS ("
! 15989: " SELECT ?1"
! 15990: " UNION"
! 15991: " SELECT child FROM sqlite_dbptr('getpage()'), pages "
! 15992: " WHERE pgno=page"
! 15993: ") "
! 15994: "SELECT page, cell, field, value "
! 15995: "FROM sqlite_dbdata('getpage()') d, pages p WHERE p.page=d.pgno "
! 15996: "UNION ALL "
! 15997: "SELECT 0, 0, 0, 0"
! 15998: );
! 15999:
! 16000: return p->errCode;
1.5 misho 16001: }
16002:
16003: /*
1.6.2.1 ! misho 16004: ** Clean up resources allocated by recoverWriteDataInit() (stuff in
! 16005: ** sqlite3_recover.w1).
1.5 misho 16006: */
1.6.2.1 ! misho 16007: static void recoverWriteDataCleanup(sqlite3_recover *p){
! 16008: RecoverStateW1 *p1 = &p->w1;
! 16009: int ii;
! 16010: for(ii=0; ii<p1->nVal; ii++){
! 16011: sqlite3_value_free(p1->apVal[ii]);
! 16012: }
! 16013: sqlite3_free(p1->apVal);
! 16014: recoverFinalize(p, p1->pInsert);
! 16015: recoverFinalize(p, p1->pTbls);
! 16016: recoverFinalize(p, p1->pSel);
! 16017: memset(p1, 0, sizeof(*p1));
! 16018: }
! 16019:
! 16020: /*
! 16021: ** Perform one step (sqlite3_recover_step()) of work for the connection
! 16022: ** passed as the only argument, which is guaranteed to be in
! 16023: ** RECOVER_STATE_WRITING state - during which tables recovered from the
! 16024: ** schema of the input database are populated with recovered data.
! 16025: */
! 16026: static int recoverWriteDataStep(sqlite3_recover *p){
! 16027: RecoverStateW1 *p1 = &p->w1;
! 16028: sqlite3_stmt *pSel = p1->pSel;
! 16029: sqlite3_value **apVal = p1->apVal;
! 16030:
! 16031: if( p->errCode==SQLITE_OK && p1->pTab==0 ){
! 16032: if( sqlite3_step(p1->pTbls)==SQLITE_ROW ){
! 16033: i64 iRoot = sqlite3_column_int64(p1->pTbls, 0);
! 16034: p1->pTab = recoverFindTable(p, iRoot);
! 16035:
! 16036: recoverFinalize(p, p1->pInsert);
! 16037: p1->pInsert = 0;
! 16038:
! 16039: /* If this table is unknown, return early. The caller will invoke this
! 16040: ** function again and it will move on to the next table. */
! 16041: if( p1->pTab==0 ) return p->errCode;
! 16042:
! 16043: /* If this is the sqlite_sequence table, delete any rows added by
! 16044: ** earlier INSERT statements on tables with AUTOINCREMENT primary
! 16045: ** keys before recovering its contents. The p1->pTbls SELECT statement
! 16046: ** is rigged to deliver "sqlite_sequence" last of all, so we don't
! 16047: ** worry about it being modified after it is recovered. */
! 16048: if( sqlite3_stricmp("sqlite_sequence", p1->pTab->zTab)==0 ){
! 16049: recoverExec(p, p->dbOut, "DELETE FROM sqlite_sequence");
! 16050: recoverSqlCallback(p, "DELETE FROM sqlite_sequence");
! 16051: }
! 16052:
! 16053: /* Bind the root page of this table within the original database to
! 16054: ** SELECT statement p1->pSel. The SELECT statement will then iterate
! 16055: ** through cells that look like they belong to table pTab. */
! 16056: sqlite3_bind_int64(pSel, 1, iRoot);
! 16057:
! 16058: p1->nVal = 0;
! 16059: p1->bHaveRowid = 0;
! 16060: p1->iPrevPage = -1;
! 16061: p1->iPrevCell = -1;
! 16062: }else{
! 16063: return SQLITE_DONE;
! 16064: }
! 16065: }
! 16066: assert( p->errCode!=SQLITE_OK || p1->pTab );
! 16067:
! 16068: if( p->errCode==SQLITE_OK && sqlite3_step(pSel)==SQLITE_ROW ){
! 16069: RecoverTable *pTab = p1->pTab;
! 16070:
! 16071: i64 iPage = sqlite3_column_int64(pSel, 0);
! 16072: int iCell = sqlite3_column_int(pSel, 1);
! 16073: int iField = sqlite3_column_int(pSel, 2);
! 16074: sqlite3_value *pVal = sqlite3_column_value(pSel, 3);
! 16075: int bNewCell = (p1->iPrevPage!=iPage || p1->iPrevCell!=iCell);
! 16076:
! 16077: assert( bNewCell==0 || (iField==-1 || iField==0) );
! 16078: assert( bNewCell || iField==p1->nVal || p1->nVal==pTab->nCol );
! 16079:
! 16080: if( bNewCell ){
! 16081: int ii = 0;
! 16082: if( p1->nVal>=0 ){
! 16083: if( p1->pInsert==0 || p1->nVal!=p1->nInsert ){
! 16084: recoverFinalize(p, p1->pInsert);
! 16085: p1->pInsert = recoverInsertStmt(p, pTab, p1->nVal);
! 16086: p1->nInsert = p1->nVal;
! 16087: }
! 16088: if( p1->nVal>0 ){
! 16089: sqlite3_stmt *pInsert = p1->pInsert;
! 16090: for(ii=0; ii<pTab->nCol; ii++){
! 16091: RecoverColumn *pCol = &pTab->aCol[ii];
! 16092: int iBind = pCol->iBind;
! 16093: if( iBind>0 ){
! 16094: if( pCol->bIPK ){
! 16095: sqlite3_bind_int64(pInsert, iBind, p1->iRowid);
! 16096: }else if( pCol->iField<p1->nVal ){
! 16097: recoverBindValue(p, pInsert, iBind, apVal[pCol->iField]);
! 16098: }
! 16099: }
! 16100: }
! 16101: if( p->bRecoverRowid && pTab->iRowidBind>0 && p1->bHaveRowid ){
! 16102: sqlite3_bind_int64(pInsert, pTab->iRowidBind, p1->iRowid);
! 16103: }
! 16104: if( SQLITE_ROW==sqlite3_step(pInsert) ){
! 16105: const char *z = (const char*)sqlite3_column_text(pInsert, 0);
! 16106: recoverSqlCallback(p, z);
! 16107: }
! 16108: recoverReset(p, pInsert);
! 16109: assert( p->errCode || pInsert );
! 16110: if( pInsert ) sqlite3_clear_bindings(pInsert);
! 16111: }
! 16112: }
! 16113:
! 16114: for(ii=0; ii<p1->nVal; ii++){
! 16115: sqlite3_value_free(apVal[ii]);
! 16116: apVal[ii] = 0;
! 16117: }
! 16118: p1->nVal = -1;
! 16119: p1->bHaveRowid = 0;
! 16120: }
! 16121:
! 16122: if( iPage!=0 ){
! 16123: if( iField<0 ){
! 16124: p1->iRowid = sqlite3_column_int64(pSel, 3);
! 16125: assert( p1->nVal==-1 );
! 16126: p1->nVal = 0;
! 16127: p1->bHaveRowid = 1;
! 16128: }else if( iField<pTab->nCol ){
! 16129: assert( apVal[iField]==0 );
! 16130: apVal[iField] = sqlite3_value_dup( pVal );
! 16131: if( apVal[iField]==0 ){
! 16132: recoverError(p, SQLITE_NOMEM, 0);
! 16133: }
! 16134: p1->nVal = iField+1;
! 16135: }
! 16136: p1->iPrevCell = iCell;
! 16137: p1->iPrevPage = iPage;
! 16138: }
1.5 misho 16139: }else{
1.6.2.1 ! misho 16140: recoverReset(p, pSel);
! 16141: p1->pTab = 0;
1.5 misho 16142: }
1.6.2.1 ! misho 16143:
! 16144: return p->errCode;
1.5 misho 16145: }
16146:
16147: /*
1.6.2.1 ! misho 16148: ** Initialize resources required by sqlite3_recover_step() in
! 16149: ** RECOVER_STATE_LOSTANDFOUND1 state - during which the set of pages not
! 16150: ** already allocated to a recovered schema element is determined.
! 16151: */
! 16152: static void recoverLostAndFound1Init(sqlite3_recover *p){
! 16153: RecoverStateLAF *pLaf = &p->laf;
! 16154: sqlite3_stmt *pStmt = 0;
1.5 misho 16155:
1.6.2.1 ! misho 16156: assert( p->laf.pUsed==0 );
! 16157: pLaf->nPg = recoverPageCount(p);
! 16158: pLaf->pUsed = recoverBitmapAlloc(p, pLaf->nPg);
! 16159:
! 16160: /* Prepare a statement to iterate through all pages that are part of any tree
! 16161: ** in the recoverable part of the input database schema to the bitmap. And,
! 16162: ** if !p->bFreelistCorrupt, add all pages that appear to be part of the
! 16163: ** freelist. */
! 16164: pStmt = recoverPrepare(
! 16165: p, p->dbOut,
! 16166: "WITH trunk(pgno) AS ("
! 16167: " SELECT read_i32(getpage(1), 8) AS x WHERE x>0"
! 16168: " UNION"
! 16169: " SELECT read_i32(getpage(trunk.pgno), 0) AS x FROM trunk WHERE x>0"
! 16170: "),"
! 16171: "trunkdata(pgno, data) AS ("
! 16172: " SELECT pgno, getpage(pgno) FROM trunk"
! 16173: "),"
! 16174: "freelist(data, n, freepgno) AS ("
! 16175: " SELECT data, min(16384, read_i32(data, 1)-1), pgno FROM trunkdata"
! 16176: " UNION ALL"
! 16177: " SELECT data, n-1, read_i32(data, 2+n) FROM freelist WHERE n>=0"
! 16178: "),"
! 16179: ""
! 16180: "roots(r) AS ("
! 16181: " SELECT 1 UNION ALL"
! 16182: " SELECT rootpage FROM recovery.schema WHERE rootpage>0"
! 16183: "),"
! 16184: "used(page) AS ("
! 16185: " SELECT r FROM roots"
! 16186: " UNION"
! 16187: " SELECT child FROM sqlite_dbptr('getpage()'), used "
! 16188: " WHERE pgno=page"
! 16189: ") "
! 16190: "SELECT page FROM used"
! 16191: " UNION ALL "
! 16192: "SELECT freepgno FROM freelist WHERE NOT ?"
! 16193: );
! 16194: if( pStmt ) sqlite3_bind_int(pStmt, 1, p->bFreelistCorrupt);
! 16195: pLaf->pUsedPages = pStmt;
1.5 misho 16196: }
1.6.2.1 ! misho 16197:
! 16198: /*
! 16199: ** Perform one step (sqlite3_recover_step()) of work for the connection
! 16200: ** passed as the only argument, which is guaranteed to be in
! 16201: ** RECOVER_STATE_LOSTANDFOUND1 state - during which the set of pages not
! 16202: ** already allocated to a recovered schema element is determined.
! 16203: */
! 16204: static int recoverLostAndFound1Step(sqlite3_recover *p){
! 16205: RecoverStateLAF *pLaf = &p->laf;
! 16206: int rc = p->errCode;
! 16207: if( rc==SQLITE_OK ){
! 16208: rc = sqlite3_step(pLaf->pUsedPages);
! 16209: if( rc==SQLITE_ROW ){
! 16210: i64 iPg = sqlite3_column_int64(pLaf->pUsedPages, 0);
! 16211: recoverBitmapSet(pLaf->pUsed, iPg);
! 16212: rc = SQLITE_OK;
! 16213: }else{
! 16214: recoverFinalize(p, pLaf->pUsedPages);
! 16215: pLaf->pUsedPages = 0;
! 16216: }
! 16217: }
! 16218: return rc;
1.5 misho 16219: }
16220:
16221: /*
1.6.2.1 ! misho 16222: ** Initialize resources required by RECOVER_STATE_LOSTANDFOUND2
! 16223: ** state - during which the pages identified in RECOVER_STATE_LOSTANDFOUND1
! 16224: ** are sorted into sets that likely belonged to the same database tree.
! 16225: */
! 16226: static void recoverLostAndFound2Init(sqlite3_recover *p){
! 16227: RecoverStateLAF *pLaf = &p->laf;
1.5 misho 16228:
1.6.2.1 ! misho 16229: assert( p->laf.pAllAndParent==0 );
! 16230: assert( p->laf.pMapInsert==0 );
! 16231: assert( p->laf.pMaxField==0 );
! 16232: assert( p->laf.nMaxField==0 );
! 16233:
! 16234: pLaf->pMapInsert = recoverPrepare(p, p->dbOut,
! 16235: "INSERT OR IGNORE INTO recovery.map(pgno, parent) VALUES(?, ?)"
! 16236: );
! 16237: pLaf->pAllAndParent = recoverPreparePrintf(p, p->dbOut,
! 16238: "WITH RECURSIVE seq(ii) AS ("
! 16239: " SELECT 1 UNION ALL SELECT ii+1 FROM seq WHERE ii<%lld"
! 16240: ")"
! 16241: "SELECT pgno, child FROM sqlite_dbptr('getpage()') "
! 16242: " UNION ALL "
! 16243: "SELECT NULL, ii FROM seq", p->laf.nPg
! 16244: );
! 16245: pLaf->pMaxField = recoverPreparePrintf(p, p->dbOut,
! 16246: "SELECT max(field)+1 FROM sqlite_dbdata('getpage') WHERE pgno = ?"
! 16247: );
! 16248: }
! 16249:
! 16250: /*
! 16251: ** Perform one step (sqlite3_recover_step()) of work for the connection
! 16252: ** passed as the only argument, which is guaranteed to be in
! 16253: ** RECOVER_STATE_LOSTANDFOUND2 state - during which the pages identified
! 16254: ** in RECOVER_STATE_LOSTANDFOUND1 are sorted into sets that likely belonged
! 16255: ** to the same database tree.
! 16256: */
! 16257: static int recoverLostAndFound2Step(sqlite3_recover *p){
! 16258: RecoverStateLAF *pLaf = &p->laf;
! 16259: if( p->errCode==SQLITE_OK ){
! 16260: int res = sqlite3_step(pLaf->pAllAndParent);
! 16261: if( res==SQLITE_ROW ){
! 16262: i64 iChild = sqlite3_column_int(pLaf->pAllAndParent, 1);
! 16263: if( recoverBitmapQuery(pLaf->pUsed, iChild)==0 ){
! 16264: sqlite3_bind_int64(pLaf->pMapInsert, 1, iChild);
! 16265: sqlite3_bind_value(pLaf->pMapInsert, 2,
! 16266: sqlite3_column_value(pLaf->pAllAndParent, 0)
! 16267: );
! 16268: sqlite3_step(pLaf->pMapInsert);
! 16269: recoverReset(p, pLaf->pMapInsert);
! 16270: sqlite3_bind_int64(pLaf->pMaxField, 1, iChild);
! 16271: if( SQLITE_ROW==sqlite3_step(pLaf->pMaxField) ){
! 16272: int nMax = sqlite3_column_int(pLaf->pMaxField, 0);
! 16273: if( nMax>pLaf->nMaxField ) pLaf->nMaxField = nMax;
! 16274: }
! 16275: recoverReset(p, pLaf->pMaxField);
1.5 misho 16276: }
1.6.2.1 ! misho 16277: }else{
! 16278: recoverFinalize(p, pLaf->pAllAndParent);
! 16279: pLaf->pAllAndParent =0;
! 16280: return SQLITE_DONE;
1.5 misho 16281: }
16282: }
1.6.2.1 ! misho 16283: return p->errCode;
! 16284: }
1.5 misho 16285:
1.6.2.1 ! misho 16286: /*
! 16287: ** Free all resources allocated as part of sqlite3_recover_step() calls
! 16288: ** in one of the RECOVER_STATE_LOSTANDFOUND[123] states.
! 16289: */
! 16290: static void recoverLostAndFoundCleanup(sqlite3_recover *p){
! 16291: recoverBitmapFree(p->laf.pUsed);
! 16292: p->laf.pUsed = 0;
! 16293: sqlite3_finalize(p->laf.pUsedPages);
! 16294: sqlite3_finalize(p->laf.pAllAndParent);
! 16295: sqlite3_finalize(p->laf.pMapInsert);
! 16296: sqlite3_finalize(p->laf.pMaxField);
! 16297: sqlite3_finalize(p->laf.pFindRoot);
! 16298: sqlite3_finalize(p->laf.pInsert);
! 16299: sqlite3_finalize(p->laf.pAllPage);
! 16300: sqlite3_finalize(p->laf.pPageData);
! 16301: p->laf.pUsedPages = 0;
! 16302: p->laf.pAllAndParent = 0;
! 16303: p->laf.pMapInsert = 0;
! 16304: p->laf.pMaxField = 0;
! 16305: p->laf.pFindRoot = 0;
! 16306: p->laf.pInsert = 0;
! 16307: p->laf.pAllPage = 0;
! 16308: p->laf.pPageData = 0;
! 16309: sqlite3_free(p->laf.apVal);
! 16310: p->laf.apVal = 0;
1.5 misho 16311: }
16312:
16313: /*
1.6.2.1 ! misho 16314: ** Free all resources allocated as part of sqlite3_recover_step() calls.
1.5 misho 16315: */
1.6.2.1 ! misho 16316: static void recoverFinalCleanup(sqlite3_recover *p){
! 16317: RecoverTable *pTab = 0;
! 16318: RecoverTable *pNext = 0;
! 16319:
! 16320: recoverWriteDataCleanup(p);
! 16321: recoverLostAndFoundCleanup(p);
! 16322:
! 16323: for(pTab=p->pTblList; pTab; pTab=pNext){
! 16324: pNext = pTab->pNext;
! 16325: sqlite3_free(pTab);
! 16326: }
! 16327: p->pTblList = 0;
! 16328: sqlite3_finalize(p->pGetPage);
! 16329: p->pGetPage = 0;
! 16330: sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_RESET_CACHE, 0);
! 16331:
! 16332: {
! 16333: #ifndef NDEBUG
! 16334: int res =
! 16335: #endif
! 16336: sqlite3_close(p->dbOut);
! 16337: assert( res==SQLITE_OK );
! 16338: }
! 16339: p->dbOut = 0;
! 16340: }
! 16341:
! 16342: /*
! 16343: ** Decode and return an unsigned 16-bit big-endian integer value from
! 16344: ** buffer a[].
! 16345: */
! 16346: static u32 recoverGetU16(const u8 *a){
! 16347: return (((u32)a[0])<<8) + ((u32)a[1]);
! 16348: }
! 16349:
! 16350: /*
! 16351: ** Decode and return an unsigned 32-bit big-endian integer value from
! 16352: ** buffer a[].
! 16353: */
! 16354: static u32 recoverGetU32(const u8 *a){
! 16355: return (((u32)a[0])<<24) + (((u32)a[1])<<16) + (((u32)a[2])<<8) + ((u32)a[3]);
! 16356: }
! 16357:
! 16358: /*
! 16359: ** Decode an SQLite varint from buffer a[]. Write the decoded value to (*pVal)
! 16360: ** and return the number of bytes consumed.
! 16361: */
! 16362: static int recoverGetVarint(const u8 *a, i64 *pVal){
! 16363: sqlite3_uint64 u = 0;
1.5 misho 16364: int i;
16365: for(i=0; i<8; i++){
1.6.2.1 ! misho 16366: u = (u<<7) + (a[i]&0x7f);
! 16367: if( (a[i]&0x80)==0 ){ *pVal = (sqlite3_int64)u; return i+1; }
1.5 misho 16368: }
1.6.2.1 ! misho 16369: u = (u<<8) + (a[i]&0xff);
! 16370: *pVal = (sqlite3_int64)u;
1.5 misho 16371: return 9;
16372: }
16373:
16374: /*
1.6.2.1 ! misho 16375: ** The second argument points to a buffer n bytes in size. If this buffer
! 16376: ** or a prefix thereof appears to contain a well-formed SQLite b-tree page,
! 16377: ** return the page-size in bytes. Otherwise, if the buffer does not
! 16378: ** appear to contain a well-formed b-tree page, return 0.
! 16379: */
! 16380: static int recoverIsValidPage(u8 *aTmp, const u8 *a, int n){
! 16381: u8 *aUsed = aTmp;
! 16382: int nFrag = 0;
! 16383: int nActual = 0;
! 16384: int iFree = 0;
! 16385: int nCell = 0; /* Number of cells on page */
! 16386: int iCellOff = 0; /* Offset of cell array in page */
! 16387: int iContent = 0;
! 16388: int eType = 0;
! 16389: int ii = 0;
! 16390:
! 16391: eType = (int)a[0];
! 16392: if( eType!=0x02 && eType!=0x05 && eType!=0x0A && eType!=0x0D ) return 0;
! 16393:
! 16394: iFree = (int)recoverGetU16(&a[1]);
! 16395: nCell = (int)recoverGetU16(&a[3]);
! 16396: iContent = (int)recoverGetU16(&a[5]);
! 16397: if( iContent==0 ) iContent = 65536;
! 16398: nFrag = (int)a[7];
! 16399:
! 16400: if( iContent>n ) return 0;
! 16401:
! 16402: memset(aUsed, 0, n);
! 16403: memset(aUsed, 0xFF, iContent);
! 16404:
! 16405: /* Follow the free-list. This is the same format for all b-tree pages. */
! 16406: if( iFree && iFree<=iContent ) return 0;
! 16407: while( iFree ){
! 16408: int iNext = 0;
! 16409: int nByte = 0;
! 16410: if( iFree>(n-4) ) return 0;
! 16411: iNext = recoverGetU16(&a[iFree]);
! 16412: nByte = recoverGetU16(&a[iFree+2]);
! 16413: if( iFree+nByte>n || nByte<4 ) return 0;
! 16414: if( iNext && iNext<iFree+nByte ) return 0;
! 16415: memset(&aUsed[iFree], 0xFF, nByte);
! 16416: iFree = iNext;
! 16417: }
! 16418:
! 16419: /* Run through the cells */
! 16420: if( eType==0x02 || eType==0x05 ){
! 16421: iCellOff = 12;
! 16422: }else{
! 16423: iCellOff = 8;
! 16424: }
! 16425: if( (iCellOff + 2*nCell)>iContent ) return 0;
! 16426: for(ii=0; ii<nCell; ii++){
! 16427: int iByte;
! 16428: i64 nPayload = 0;
! 16429: int nByte = 0;
! 16430: int iOff = recoverGetU16(&a[iCellOff + 2*ii]);
! 16431: if( iOff<iContent || iOff>n ){
1.5 misho 16432: return 0;
1.6.2.1 ! misho 16433: }
! 16434: if( eType==0x05 || eType==0x02 ) nByte += 4;
! 16435: nByte += recoverGetVarint(&a[iOff+nByte], &nPayload);
! 16436: if( eType==0x0D ){
! 16437: i64 dummy = 0;
! 16438: nByte += recoverGetVarint(&a[iOff+nByte], &dummy);
! 16439: }
! 16440: if( eType!=0x05 ){
! 16441: int X = (eType==0x0D) ? n-35 : (((n-12)*64/255)-23);
! 16442: int M = ((n-12)*32/255)-23;
! 16443: int K = M+((nPayload-M)%(n-4));
! 16444:
! 16445: if( nPayload<X ){
! 16446: nByte += nPayload;
! 16447: }else if( K<=X ){
! 16448: nByte += K+4;
! 16449: }else{
! 16450: nByte += M+4;
1.5 misho 16451: }
1.6.2.1 ! misho 16452: }
! 16453:
! 16454: if( iOff+nByte>n ){
1.5 misho 16455: return 0;
1.6.2.1 ! misho 16456: }
! 16457: for(iByte=iOff; iByte<(iOff+nByte); iByte++){
! 16458: if( aUsed[iByte]!=0 ){
! 16459: return 0;
! 16460: }
! 16461: aUsed[iByte] = 0xFF;
! 16462: }
1.5 misho 16463: }
1.6.2.1 ! misho 16464:
! 16465: nActual = 0;
! 16466: for(ii=0; ii<n; ii++){
! 16467: if( aUsed[ii]==0 ) nActual++;
! 16468: }
! 16469: return (nActual==nFrag);
! 16470: }
! 16471:
! 16472:
! 16473: static int recoverVfsClose(sqlite3_file*);
! 16474: static int recoverVfsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
! 16475: static int recoverVfsWrite(sqlite3_file*, const void*, int, sqlite3_int64);
! 16476: static int recoverVfsTruncate(sqlite3_file*, sqlite3_int64 size);
! 16477: static int recoverVfsSync(sqlite3_file*, int flags);
! 16478: static int recoverVfsFileSize(sqlite3_file*, sqlite3_int64 *pSize);
! 16479: static int recoverVfsLock(sqlite3_file*, int);
! 16480: static int recoverVfsUnlock(sqlite3_file*, int);
! 16481: static int recoverVfsCheckReservedLock(sqlite3_file*, int *pResOut);
! 16482: static int recoverVfsFileControl(sqlite3_file*, int op, void *pArg);
! 16483: static int recoverVfsSectorSize(sqlite3_file*);
! 16484: static int recoverVfsDeviceCharacteristics(sqlite3_file*);
! 16485: static int recoverVfsShmMap(sqlite3_file*, int, int, int, void volatile**);
! 16486: static int recoverVfsShmLock(sqlite3_file*, int offset, int n, int flags);
! 16487: static void recoverVfsShmBarrier(sqlite3_file*);
! 16488: static int recoverVfsShmUnmap(sqlite3_file*, int deleteFlag);
! 16489: static int recoverVfsFetch(sqlite3_file*, sqlite3_int64, int, void**);
! 16490: static int recoverVfsUnfetch(sqlite3_file *pFd, sqlite3_int64 iOff, void *p);
! 16491:
! 16492: static sqlite3_io_methods recover_methods = {
! 16493: 2, /* iVersion */
! 16494: recoverVfsClose,
! 16495: recoverVfsRead,
! 16496: recoverVfsWrite,
! 16497: recoverVfsTruncate,
! 16498: recoverVfsSync,
! 16499: recoverVfsFileSize,
! 16500: recoverVfsLock,
! 16501: recoverVfsUnlock,
! 16502: recoverVfsCheckReservedLock,
! 16503: recoverVfsFileControl,
! 16504: recoverVfsSectorSize,
! 16505: recoverVfsDeviceCharacteristics,
! 16506: recoverVfsShmMap,
! 16507: recoverVfsShmLock,
! 16508: recoverVfsShmBarrier,
! 16509: recoverVfsShmUnmap,
! 16510: recoverVfsFetch,
! 16511: recoverVfsUnfetch
! 16512: };
! 16513:
! 16514: static int recoverVfsClose(sqlite3_file *pFd){
! 16515: assert( pFd->pMethods!=&recover_methods );
! 16516: return pFd->pMethods->xClose(pFd);
1.5 misho 16517: }
16518:
16519: /*
1.6.2.1 ! misho 16520: ** Write value v to buffer a[] as a 16-bit big-endian unsigned integer.
1.5 misho 16521: */
1.6.2.1 ! misho 16522: static void recoverPutU16(u8 *a, u32 v){
! 16523: a[0] = (v>>8) & 0x00FF;
! 16524: a[1] = (v>>0) & 0x00FF;
! 16525: }
! 16526:
! 16527: /*
! 16528: ** Write value v to buffer a[] as a 32-bit big-endian unsigned integer.
! 16529: */
! 16530: static void recoverPutU32(u8 *a, u32 v){
! 16531: a[0] = (v>>24) & 0x00FF;
! 16532: a[1] = (v>>16) & 0x00FF;
! 16533: a[2] = (v>>8) & 0x00FF;
! 16534: a[3] = (v>>0) & 0x00FF;
! 16535: }
! 16536:
! 16537: /*
! 16538: ** Detect the page-size of the database opened by file-handle pFd by
! 16539: ** searching the first part of the file for a well-formed SQLite b-tree
! 16540: ** page. If parameter nReserve is non-zero, then as well as searching for
! 16541: ** a b-tree page with zero reserved bytes, this function searches for one
! 16542: ** with nReserve reserved bytes at the end of it.
! 16543: **
! 16544: ** If successful, set variable p->detected_pgsz to the detected page-size
! 16545: ** in bytes and return SQLITE_OK. Or, if no error occurs but no valid page
! 16546: ** can be found, return SQLITE_OK but leave p->detected_pgsz set to 0. Or,
! 16547: ** if an error occurs (e.g. an IO or OOM error), then an SQLite error code
! 16548: ** is returned. The final value of p->detected_pgsz is undefined in this
! 16549: ** case.
! 16550: */
! 16551: static int recoverVfsDetectPagesize(
! 16552: sqlite3_recover *p, /* Recover handle */
! 16553: sqlite3_file *pFd, /* File-handle open on input database */
! 16554: u32 nReserve, /* Possible nReserve value */
! 16555: i64 nSz /* Size of database file in bytes */
1.5 misho 16556: ){
1.6.2.1 ! misho 16557: int rc = SQLITE_OK;
! 16558: const int nMin = 512;
! 16559: const int nMax = 65536;
! 16560: const int nMaxBlk = 4;
! 16561: u32 pgsz = 0;
! 16562: int iBlk = 0;
! 16563: u8 *aPg = 0;
! 16564: u8 *aTmp = 0;
! 16565: int nBlk = 0;
! 16566:
! 16567: aPg = (u8*)sqlite3_malloc(2*nMax);
! 16568: if( aPg==0 ) return SQLITE_NOMEM;
! 16569: aTmp = &aPg[nMax];
! 16570:
! 16571: nBlk = (nSz+nMax-1)/nMax;
! 16572: if( nBlk>nMaxBlk ) nBlk = nMaxBlk;
! 16573:
! 16574: do {
! 16575: for(iBlk=0; rc==SQLITE_OK && iBlk<nBlk; iBlk++){
! 16576: int nByte = (nSz>=((iBlk+1)*nMax)) ? nMax : (nSz % nMax);
! 16577: memset(aPg, 0, nMax);
! 16578: rc = pFd->pMethods->xRead(pFd, aPg, nByte, iBlk*nMax);
! 16579: if( rc==SQLITE_OK ){
! 16580: int pgsz2;
! 16581: for(pgsz2=(pgsz ? pgsz*2 : nMin); pgsz2<=nMax; pgsz2=pgsz2*2){
! 16582: int iOff;
! 16583: for(iOff=0; iOff<nMax; iOff+=pgsz2){
! 16584: if( recoverIsValidPage(aTmp, &aPg[iOff], pgsz2-nReserve) ){
! 16585: pgsz = pgsz2;
! 16586: break;
! 16587: }
! 16588: }
1.5 misho 16589: }
16590: }
16591: }
1.6.2.1 ! misho 16592: if( pgsz>(u32)p->detected_pgsz ){
! 16593: p->detected_pgsz = pgsz;
! 16594: p->nReserve = nReserve;
! 16595: }
! 16596: if( nReserve==0 ) break;
! 16597: nReserve = 0;
! 16598: }while( 1 );
! 16599:
! 16600: p->detected_pgsz = pgsz;
! 16601: sqlite3_free(aPg);
! 16602: return rc;
1.5 misho 16603: }
16604:
16605: /*
1.6.2.1 ! misho 16606: ** The xRead() method of the wrapper VFS. This is used to intercept calls
! 16607: ** to read page 1 of the input database.
1.5 misho 16608: */
1.6.2.1 ! misho 16609: static int recoverVfsRead(sqlite3_file *pFd, void *aBuf, int nByte, i64 iOff){
! 16610: int rc = SQLITE_OK;
! 16611: if( pFd->pMethods==&recover_methods ){
! 16612: pFd->pMethods = recover_g.pMethods;
! 16613: rc = pFd->pMethods->xRead(pFd, aBuf, nByte, iOff);
! 16614: if( nByte==16 ){
! 16615: sqlite3_randomness(16, aBuf);
! 16616: }else
! 16617: if( rc==SQLITE_OK && iOff==0 && nByte>=108 ){
! 16618: /* Ensure that the database has a valid header file. The only fields
! 16619: ** that really matter to recovery are:
! 16620: **
! 16621: ** + Database page size (16-bits at offset 16)
! 16622: ** + Size of db in pages (32-bits at offset 28)
! 16623: ** + Database encoding (32-bits at offset 56)
! 16624: **
! 16625: ** Also preserved are:
! 16626: **
! 16627: ** + first freelist page (32-bits at offset 32)
! 16628: ** + size of freelist (32-bits at offset 36)
! 16629: ** + the wal-mode flags (16-bits at offset 18)
! 16630: **
! 16631: ** We also try to preserve the auto-vacuum, incr-value, user-version
! 16632: ** and application-id fields - all 32 bit quantities at offsets
! 16633: ** 52, 60, 64 and 68. All other fields are set to known good values.
! 16634: **
! 16635: ** Byte offset 105 should also contain the page-size as a 16-bit
! 16636: ** integer.
! 16637: */
! 16638: const int aPreserve[] = {32, 36, 52, 60, 64, 68};
! 16639: u8 aHdr[108] = {
! 16640: 0x53, 0x51, 0x4c, 0x69, 0x74, 0x65, 0x20, 0x66,
! 16641: 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x33, 0x00,
! 16642: 0xFF, 0xFF, 0x01, 0x01, 0x00, 0x40, 0x20, 0x20,
! 16643: 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
! 16644: 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
! 16645: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
! 16646: 0x00, 0x00, 0x10, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
! 16647: 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
! 16648: 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
! 16649: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
! 16650: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
! 16651: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
! 16652: 0x00, 0x2e, 0x5b, 0x30,
! 16653:
! 16654: 0x0D, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00
! 16655: };
! 16656: u8 *a = (u8*)aBuf;
! 16657:
! 16658: u32 pgsz = recoverGetU16(&a[16]);
! 16659: u32 nReserve = a[20];
! 16660: u32 enc = recoverGetU32(&a[56]);
! 16661: u32 dbsz = 0;
! 16662: i64 dbFileSize = 0;
! 16663: int ii;
! 16664: sqlite3_recover *p = recover_g.p;
1.5 misho 16665:
1.6.2.1 ! misho 16666: if( pgsz==0x01 ) pgsz = 65536;
! 16667: rc = pFd->pMethods->xFileSize(pFd, &dbFileSize);
1.5 misho 16668:
1.6.2.1 ! misho 16669: if( rc==SQLITE_OK && p->detected_pgsz==0 ){
! 16670: rc = recoverVfsDetectPagesize(p, pFd, nReserve, dbFileSize);
1.5 misho 16671: }
1.6.2.1 ! misho 16672: if( p->detected_pgsz ){
! 16673: pgsz = p->detected_pgsz;
! 16674: nReserve = p->nReserve;
! 16675: }
! 16676:
! 16677: if( pgsz ){
! 16678: dbsz = dbFileSize / pgsz;
! 16679: }
! 16680: if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF16BE && enc!=SQLITE_UTF16LE ){
! 16681: enc = SQLITE_UTF8;
! 16682: }
! 16683:
! 16684: sqlite3_free(p->pPage1Cache);
! 16685: p->pPage1Cache = 0;
! 16686: p->pPage1Disk = 0;
! 16687:
! 16688: p->pgsz = nByte;
! 16689: p->pPage1Cache = (u8*)recoverMalloc(p, nByte*2);
! 16690: if( p->pPage1Cache ){
! 16691: p->pPage1Disk = &p->pPage1Cache[nByte];
! 16692: memcpy(p->pPage1Disk, aBuf, nByte);
! 16693: aHdr[18] = a[18];
! 16694: aHdr[19] = a[19];
! 16695: recoverPutU32(&aHdr[28], dbsz);
! 16696: recoverPutU32(&aHdr[56], enc);
! 16697: recoverPutU16(&aHdr[105], pgsz-nReserve);
! 16698: if( pgsz==65536 ) pgsz = 1;
! 16699: recoverPutU16(&aHdr[16], pgsz);
! 16700: aHdr[20] = nReserve;
! 16701: for(ii=0; ii<(int)(sizeof(aPreserve)/sizeof(aPreserve[0])); ii++){
! 16702: memcpy(&aHdr[aPreserve[ii]], &a[aPreserve[ii]], 4);
! 16703: }
! 16704: memcpy(aBuf, aHdr, sizeof(aHdr));
! 16705: memset(&((u8*)aBuf)[sizeof(aHdr)], 0, nByte-sizeof(aHdr));
1.5 misho 16706:
1.6.2.1 ! misho 16707: memcpy(p->pPage1Cache, aBuf, nByte);
1.5 misho 16708: }else{
1.6.2.1 ! misho 16709: rc = p->errCode;
1.5 misho 16710: }
16711:
1.6.2.1 ! misho 16712: }
! 16713: pFd->pMethods = &recover_methods;
! 16714: }else{
! 16715: rc = pFd->pMethods->xRead(pFd, aBuf, nByte, iOff);
! 16716: }
! 16717: return rc;
! 16718: }
1.5 misho 16719:
1.6.2.1 ! misho 16720: /*
! 16721: ** Used to make sqlite3_io_methods wrapper methods less verbose.
! 16722: */
! 16723: #define RECOVER_VFS_WRAPPER(code) \
! 16724: int rc = SQLITE_OK; \
! 16725: if( pFd->pMethods==&recover_methods ){ \
! 16726: pFd->pMethods = recover_g.pMethods; \
! 16727: rc = code; \
! 16728: pFd->pMethods = &recover_methods; \
! 16729: }else{ \
! 16730: rc = code; \
! 16731: } \
! 16732: return rc;
1.5 misho 16733:
1.6.2.1 ! misho 16734: /*
! 16735: ** Methods of the wrapper VFS. All methods except for xRead() and xClose()
! 16736: ** simply uninstall the sqlite3_io_methods wrapper, invoke the equivalent
! 16737: ** method on the lower level VFS, then reinstall the wrapper before returning.
! 16738: ** Those that return an integer value use the RECOVER_VFS_WRAPPER macro.
! 16739: */
! 16740: static int recoverVfsWrite(
! 16741: sqlite3_file *pFd, const void *aBuf, int nByte, i64 iOff
! 16742: ){
! 16743: RECOVER_VFS_WRAPPER (
! 16744: pFd->pMethods->xWrite(pFd, aBuf, nByte, iOff)
! 16745: );
! 16746: }
! 16747: static int recoverVfsTruncate(sqlite3_file *pFd, sqlite3_int64 size){
! 16748: RECOVER_VFS_WRAPPER (
! 16749: pFd->pMethods->xTruncate(pFd, size)
! 16750: );
! 16751: }
! 16752: static int recoverVfsSync(sqlite3_file *pFd, int flags){
! 16753: RECOVER_VFS_WRAPPER (
! 16754: pFd->pMethods->xSync(pFd, flags)
! 16755: );
! 16756: }
! 16757: static int recoverVfsFileSize(sqlite3_file *pFd, sqlite3_int64 *pSize){
! 16758: RECOVER_VFS_WRAPPER (
! 16759: pFd->pMethods->xFileSize(pFd, pSize)
! 16760: );
! 16761: }
! 16762: static int recoverVfsLock(sqlite3_file *pFd, int eLock){
! 16763: RECOVER_VFS_WRAPPER (
! 16764: pFd->pMethods->xLock(pFd, eLock)
! 16765: );
! 16766: }
! 16767: static int recoverVfsUnlock(sqlite3_file *pFd, int eLock){
! 16768: RECOVER_VFS_WRAPPER (
! 16769: pFd->pMethods->xUnlock(pFd, eLock)
! 16770: );
! 16771: }
! 16772: static int recoverVfsCheckReservedLock(sqlite3_file *pFd, int *pResOut){
! 16773: RECOVER_VFS_WRAPPER (
! 16774: pFd->pMethods->xCheckReservedLock(pFd, pResOut)
! 16775: );
! 16776: }
! 16777: static int recoverVfsFileControl(sqlite3_file *pFd, int op, void *pArg){
! 16778: RECOVER_VFS_WRAPPER (
! 16779: (pFd->pMethods ? pFd->pMethods->xFileControl(pFd, op, pArg) : SQLITE_NOTFOUND)
! 16780: );
! 16781: }
! 16782: static int recoverVfsSectorSize(sqlite3_file *pFd){
! 16783: RECOVER_VFS_WRAPPER (
! 16784: pFd->pMethods->xSectorSize(pFd)
! 16785: );
! 16786: }
! 16787: static int recoverVfsDeviceCharacteristics(sqlite3_file *pFd){
! 16788: RECOVER_VFS_WRAPPER (
! 16789: pFd->pMethods->xDeviceCharacteristics(pFd)
! 16790: );
! 16791: }
! 16792: static int recoverVfsShmMap(
! 16793: sqlite3_file *pFd, int iPg, int pgsz, int bExtend, void volatile **pp
! 16794: ){
! 16795: RECOVER_VFS_WRAPPER (
! 16796: pFd->pMethods->xShmMap(pFd, iPg, pgsz, bExtend, pp)
! 16797: );
! 16798: }
! 16799: static int recoverVfsShmLock(sqlite3_file *pFd, int offset, int n, int flags){
! 16800: RECOVER_VFS_WRAPPER (
! 16801: pFd->pMethods->xShmLock(pFd, offset, n, flags)
! 16802: );
! 16803: }
! 16804: static void recoverVfsShmBarrier(sqlite3_file *pFd){
! 16805: if( pFd->pMethods==&recover_methods ){
! 16806: pFd->pMethods = recover_g.pMethods;
! 16807: pFd->pMethods->xShmBarrier(pFd);
! 16808: pFd->pMethods = &recover_methods;
! 16809: }else{
! 16810: pFd->pMethods->xShmBarrier(pFd);
! 16811: }
! 16812: }
! 16813: static int recoverVfsShmUnmap(sqlite3_file *pFd, int deleteFlag){
! 16814: RECOVER_VFS_WRAPPER (
! 16815: pFd->pMethods->xShmUnmap(pFd, deleteFlag)
! 16816: );
! 16817: }
1.5 misho 16818:
1.6.2.1 ! misho 16819: static int recoverVfsFetch(
! 16820: sqlite3_file *pFd,
! 16821: sqlite3_int64 iOff,
! 16822: int iAmt,
! 16823: void **pp
! 16824: ){
! 16825: (void)pFd;
! 16826: (void)iOff;
! 16827: (void)iAmt;
! 16828: *pp = 0;
! 16829: return SQLITE_OK;
! 16830: }
! 16831: static int recoverVfsUnfetch(sqlite3_file *pFd, sqlite3_int64 iOff, void *p){
! 16832: (void)pFd;
! 16833: (void)iOff;
! 16834: (void)p;
! 16835: return SQLITE_OK;
! 16836: }
1.5 misho 16837:
1.6.2.1 ! misho 16838: /*
! 16839: ** Install the VFS wrapper around the file-descriptor open on the input
! 16840: ** database for recover handle p. Mutex RECOVER_MUTEX_ID must be held
! 16841: ** when this function is called.
! 16842: */
! 16843: static void recoverInstallWrapper(sqlite3_recover *p){
! 16844: sqlite3_file *pFd = 0;
! 16845: assert( recover_g.pMethods==0 );
! 16846: recoverAssertMutexHeld();
! 16847: sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_FILE_POINTER, (void*)&pFd);
! 16848: assert( pFd==0 || pFd->pMethods!=&recover_methods );
! 16849: if( pFd && pFd->pMethods ){
! 16850: int iVersion = 1 + (pFd->pMethods->iVersion>1 && pFd->pMethods->xShmMap!=0);
! 16851: recover_g.pMethods = pFd->pMethods;
! 16852: recover_g.p = p;
! 16853: recover_methods.iVersion = iVersion;
! 16854: pFd->pMethods = &recover_methods;
! 16855: }
! 16856: }
1.5 misho 16857:
1.6.2.1 ! misho 16858: /*
! 16859: ** Uninstall the VFS wrapper that was installed around the file-descriptor open
! 16860: ** on the input database for recover handle p. Mutex RECOVER_MUTEX_ID must be
! 16861: ** held when this function is called.
! 16862: */
! 16863: static void recoverUninstallWrapper(sqlite3_recover *p){
! 16864: sqlite3_file *pFd = 0;
! 16865: recoverAssertMutexHeld();
! 16866: sqlite3_file_control(p->dbIn, p->zDb,SQLITE_FCNTL_FILE_POINTER,(void*)&pFd);
! 16867: if( pFd && pFd->pMethods ){
! 16868: pFd->pMethods = recover_g.pMethods;
! 16869: recover_g.pMethods = 0;
! 16870: recover_g.p = 0;
! 16871: }
! 16872: }
1.5 misho 16873:
1.6.2.1 ! misho 16874: /*
! 16875: ** This function does the work of a single sqlite3_recover_step() call. It
! 16876: ** is guaranteed that the handle is not in an error state when this
! 16877: ** function is called.
! 16878: */
! 16879: static void recoverStep(sqlite3_recover *p){
! 16880: assert( p && p->errCode==SQLITE_OK );
! 16881: switch( p->eState ){
! 16882: case RECOVER_STATE_INIT:
! 16883: /* This is the very first call to sqlite3_recover_step() on this object.
! 16884: */
! 16885: recoverSqlCallback(p, "BEGIN");
! 16886: recoverSqlCallback(p, "PRAGMA writable_schema = on");
! 16887:
! 16888: recoverEnterMutex();
! 16889: recoverInstallWrapper(p);
! 16890:
! 16891: /* Open the output database. And register required virtual tables and
! 16892: ** user functions with the new handle. */
! 16893: recoverOpenOutput(p);
! 16894:
! 16895: /* Open transactions on both the input and output databases. */
! 16896: sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_RESET_CACHE, 0);
! 16897: recoverExec(p, p->dbIn, "PRAGMA writable_schema = on");
! 16898: recoverExec(p, p->dbIn, "BEGIN");
! 16899: if( p->errCode==SQLITE_OK ) p->bCloseTransaction = 1;
! 16900: recoverExec(p, p->dbIn, "SELECT 1 FROM sqlite_schema");
! 16901: recoverTransferSettings(p);
! 16902: recoverOpenRecovery(p);
! 16903: recoverCacheSchema(p);
! 16904:
! 16905: recoverUninstallWrapper(p);
! 16906: recoverLeaveMutex();
! 16907:
! 16908: recoverExec(p, p->dbOut, "BEGIN");
! 16909:
! 16910: recoverWriteSchema1(p);
! 16911: p->eState = RECOVER_STATE_WRITING;
! 16912: break;
! 16913:
! 16914: case RECOVER_STATE_WRITING: {
! 16915: if( p->w1.pTbls==0 ){
! 16916: recoverWriteDataInit(p);
! 16917: }
! 16918: if( SQLITE_DONE==recoverWriteDataStep(p) ){
! 16919: recoverWriteDataCleanup(p);
! 16920: if( p->zLostAndFound ){
! 16921: p->eState = RECOVER_STATE_LOSTANDFOUND1;
! 16922: }else{
! 16923: p->eState = RECOVER_STATE_SCHEMA2;
1.5 misho 16924: }
16925: }
1.6.2.1 ! misho 16926: break;
! 16927: }
1.5 misho 16928:
1.6.2.1 ! misho 16929: case RECOVER_STATE_LOSTANDFOUND1: {
! 16930: if( p->laf.pUsed==0 ){
! 16931: recoverLostAndFound1Init(p);
! 16932: }
! 16933: if( SQLITE_DONE==recoverLostAndFound1Step(p) ){
! 16934: p->eState = RECOVER_STATE_LOSTANDFOUND2;
! 16935: }
! 16936: break;
! 16937: }
! 16938: case RECOVER_STATE_LOSTANDFOUND2: {
! 16939: if( p->laf.pAllAndParent==0 ){
! 16940: recoverLostAndFound2Init(p);
! 16941: }
! 16942: if( SQLITE_DONE==recoverLostAndFound2Step(p) ){
! 16943: p->eState = RECOVER_STATE_LOSTANDFOUND3;
! 16944: }
! 16945: break;
! 16946: }
1.5 misho 16947:
1.6.2.1 ! misho 16948: case RECOVER_STATE_LOSTANDFOUND3: {
! 16949: if( p->laf.pInsert==0 ){
! 16950: recoverLostAndFound3Init(p);
1.5 misho 16951: }
1.6.2.1 ! misho 16952: if( SQLITE_DONE==recoverLostAndFound3Step(p) ){
! 16953: p->eState = RECOVER_STATE_SCHEMA2;
! 16954: }
! 16955: break;
1.5 misho 16956: }
16957:
1.6.2.1 ! misho 16958: case RECOVER_STATE_SCHEMA2: {
! 16959: int rc = SQLITE_OK;
1.5 misho 16960:
1.6.2.1 ! misho 16961: recoverWriteSchema2(p);
! 16962: p->eState = RECOVER_STATE_DONE;
! 16963:
! 16964: /* If no error has occurred, commit the write transaction on the output
! 16965: ** database. Regardless of whether or not an error has occurred, make
! 16966: ** an attempt to end the read transaction on the input database. */
! 16967: recoverExec(p, p->dbOut, "COMMIT");
! 16968: rc = sqlite3_exec(p->dbIn, "END", 0, 0, 0);
! 16969: if( p->errCode==SQLITE_OK ) p->errCode = rc;
! 16970:
! 16971: recoverSqlCallback(p, "PRAGMA writable_schema = off");
! 16972: recoverSqlCallback(p, "COMMIT");
! 16973: p->eState = RECOVER_STATE_DONE;
! 16974: recoverFinalCleanup(p);
! 16975: break;
! 16976: };
! 16977:
! 16978: case RECOVER_STATE_DONE: {
! 16979: /* no-op */
! 16980: break;
! 16981: };
! 16982: }
1.5 misho 16983: }
16984:
16985:
1.6.2.1 ! misho 16986: /*
! 16987: ** This is a worker function that does the heavy lifting for both init
! 16988: ** functions:
! 16989: **
! 16990: ** sqlite3_recover_init()
! 16991: ** sqlite3_recover_init_sql()
! 16992: **
! 16993: ** All this function does is allocate space for the recover handle and
! 16994: ** take copies of the input parameters. All the real work is done within
! 16995: ** sqlite3_recover_run().
! 16996: */
! 16997: sqlite3_recover *recoverInit(
! 16998: sqlite3* db,
! 16999: const char *zDb,
! 17000: const char *zUri, /* Output URI for _recover_init() */
! 17001: int (*xSql)(void*, const char*),/* SQL callback for _recover_init_sql() */
! 17002: void *pSqlCtx /* Context arg for _recover_init_sql() */
! 17003: ){
! 17004: sqlite3_recover *pRet = 0;
! 17005: int nDb = 0;
! 17006: int nUri = 0;
! 17007: int nByte = 0;
! 17008:
! 17009: if( zDb==0 ){ zDb = "main"; }
! 17010:
! 17011: nDb = recoverStrlen(zDb);
! 17012: nUri = recoverStrlen(zUri);
! 17013:
! 17014: nByte = sizeof(sqlite3_recover) + nDb+1 + nUri+1;
! 17015: pRet = (sqlite3_recover*)sqlite3_malloc(nByte);
! 17016: if( pRet ){
! 17017: memset(pRet, 0, nByte);
! 17018: pRet->dbIn = db;
! 17019: pRet->zDb = (char*)&pRet[1];
! 17020: pRet->zUri = &pRet->zDb[nDb+1];
! 17021: memcpy(pRet->zDb, zDb, nDb);
! 17022: if( nUri>0 && zUri ) memcpy(pRet->zUri, zUri, nUri);
! 17023: pRet->xSql = xSql;
! 17024: pRet->pSqlCtx = pSqlCtx;
! 17025: pRet->bRecoverRowid = RECOVER_ROWID_DEFAULT;
1.5 misho 17026: }
1.6.2.1 ! misho 17027:
! 17028: return pRet;
1.5 misho 17029: }
17030:
1.6.2.1 ! misho 17031: /*
! 17032: ** Initialize a recovery handle that creates a new database containing
! 17033: ** the recovered data.
1.5 misho 17034: */
1.6.2.1 ! misho 17035: sqlite3_recover *sqlite3_recover_init(
! 17036: sqlite3* db,
! 17037: const char *zDb,
! 17038: const char *zUri
1.5 misho 17039: ){
1.6.2.1 ! misho 17040: return recoverInit(db, zDb, zUri, 0, 0);
! 17041: }
1.5 misho 17042:
1.6.2.1 ! misho 17043: /*
! 17044: ** Initialize a recovery handle that returns recovered data in the
! 17045: ** form of SQL statements via a callback.
! 17046: */
! 17047: sqlite3_recover *sqlite3_recover_init_sql(
! 17048: sqlite3* db,
! 17049: const char *zDb,
! 17050: int (*xSql)(void*, const char*),
! 17051: void *pSqlCtx
! 17052: ){
! 17053: return recoverInit(db, zDb, 0, xSql, pSqlCtx);
! 17054: }
1.5 misho 17055:
1.6.2.1 ! misho 17056: /*
! 17057: ** Return the handle error message, if any.
! 17058: */
! 17059: const char *sqlite3_recover_errmsg(sqlite3_recover *p){
! 17060: return (p && p->errCode!=SQLITE_NOMEM) ? p->zErrMsg : "out of memory";
1.5 misho 17061: }
17062:
1.6.2.1 ! misho 17063: /*
! 17064: ** Return the handle error code.
1.5 misho 17065: */
1.6.2.1 ! misho 17066: int sqlite3_recover_errcode(sqlite3_recover *p){
! 17067: return p ? p->errCode : SQLITE_NOMEM;
! 17068: }
! 17069:
! 17070: /*
! 17071: ** Configure the handle.
! 17072: */
! 17073: int sqlite3_recover_config(sqlite3_recover *p, int op, void *pArg){
! 17074: int rc = SQLITE_OK;
! 17075: if( p==0 ){
! 17076: rc = SQLITE_NOMEM;
! 17077: }else if( p->eState!=RECOVER_STATE_INIT ){
! 17078: rc = SQLITE_MISUSE;
! 17079: }else{
! 17080: switch( op ){
! 17081: case 789:
! 17082: /* This undocumented magic configuration option is used to set the
! 17083: ** name of the auxiliary database that is ATTACH-ed to the database
! 17084: ** connection and used to hold state information during the
! 17085: ** recovery process. This option is for debugging use only and
! 17086: ** is subject to change or removal at any time. */
! 17087: sqlite3_free(p->zStateDb);
! 17088: p->zStateDb = recoverMPrintf(p, "%s", (char*)pArg);
1.5 misho 17089: break;
1.6.2.1 ! misho 17090:
! 17091: case SQLITE_RECOVER_LOST_AND_FOUND: {
! 17092: const char *zArg = (const char*)pArg;
! 17093: sqlite3_free(p->zLostAndFound);
! 17094: if( zArg ){
! 17095: p->zLostAndFound = recoverMPrintf(p, "%s", zArg);
1.5 misho 17096: }else{
1.6.2.1 ! misho 17097: p->zLostAndFound = 0;
1.5 misho 17098: }
17099: break;
17100: }
1.6.2.1 ! misho 17101:
! 17102: case SQLITE_RECOVER_FREELIST_CORRUPT:
! 17103: p->bFreelistCorrupt = *(int*)pArg;
1.5 misho 17104: break;
1.6.2.1 ! misho 17105:
! 17106: case SQLITE_RECOVER_ROWIDS:
! 17107: p->bRecoverRowid = *(int*)pArg;
1.5 misho 17108: break;
1.6.2.1 ! misho 17109:
! 17110: case SQLITE_RECOVER_SLOWINDEXES:
! 17111: p->bSlowIndexes = *(int*)pArg;
1.5 misho 17112: break;
1.6.2.1 ! misho 17113:
! 17114: default:
! 17115: rc = SQLITE_NOTFOUND;
1.5 misho 17116: break;
17117: }
17118: }
17119:
1.6.2.1 ! misho 17120: return rc;
1.5 misho 17121: }
17122:
17123: /*
1.6.2.1 ! misho 17124: ** Do a unit of work towards the recovery job. Return SQLITE_OK if
! 17125: ** no error has occurred but database recovery is not finished, SQLITE_DONE
! 17126: ** if database recovery has been successfully completed, or an SQLite
! 17127: ** error code if an error has occurred.
1.5 misho 17128: */
1.6.2.1 ! misho 17129: int sqlite3_recover_step(sqlite3_recover *p){
! 17130: if( p==0 ) return SQLITE_NOMEM;
! 17131: if( p->errCode==SQLITE_OK ) recoverStep(p);
! 17132: if( p->eState==RECOVER_STATE_DONE && p->errCode==SQLITE_OK ){
! 17133: return SQLITE_DONE;
! 17134: }
! 17135: return p->errCode;
! 17136: }
1.5 misho 17137:
1.6.2.1 ! misho 17138: /*
! 17139: ** Do the configured recovery operation. Return SQLITE_OK if successful, or
! 17140: ** else an SQLite error code.
! 17141: */
! 17142: int sqlite3_recover_run(sqlite3_recover *p){
! 17143: while( SQLITE_OK==sqlite3_recover_step(p) );
! 17144: return sqlite3_recover_errcode(p);
! 17145: }
! 17146:
! 17147:
! 17148: /*
! 17149: ** Free all resources associated with the recover handle passed as the only
! 17150: ** argument. The results of using a handle with any sqlite3_recover_**
! 17151: ** API function after it has been passed to this function are undefined.
! 17152: **
! 17153: ** A copy of the value returned by the first call made to sqlite3_recover_run()
! 17154: ** on this handle is returned, or SQLITE_OK if sqlite3_recover_run() has
! 17155: ** not been called on this handle.
! 17156: */
! 17157: int sqlite3_recover_finish(sqlite3_recover *p){
! 17158: int rc;
! 17159: if( p==0 ){
! 17160: rc = SQLITE_NOMEM;
! 17161: }else{
! 17162: recoverFinalCleanup(p);
! 17163: if( p->bCloseTransaction && sqlite3_get_autocommit(p->dbIn)==0 ){
! 17164: rc = sqlite3_exec(p->dbIn, "END", 0, 0, 0);
! 17165: if( p->errCode==SQLITE_OK ) p->errCode = rc;
! 17166: }
! 17167: rc = p->errCode;
! 17168: sqlite3_free(p->zErrMsg);
! 17169: sqlite3_free(p->zStateDb);
! 17170: sqlite3_free(p->zLostAndFound);
! 17171: sqlite3_free(p->pPage1Cache);
! 17172: sqlite3_free(p);
1.5 misho 17173: }
17174: return rc;
17175: }
17176:
1.6.2.1 ! misho 17177: #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
1.5 misho 17178:
1.6.2.1 ! misho 17179: /************************* End ../ext/recover/sqlite3recover.c ********************/
! 17180: # endif /* SQLITE_HAVE_SQLITE3R */
1.5 misho 17181: #endif
1.6.2.1 ! misho 17182: #ifdef SQLITE_SHELL_EXTSRC
! 17183: # include SHELL_STRINGIFY(SQLITE_SHELL_EXTSRC)
1.5 misho 17184: #endif
17185:
17186: #if defined(SQLITE_ENABLE_SESSION)
17187: /*
17188: ** State information for a single open session
17189: */
17190: typedef struct OpenSession OpenSession;
17191: struct OpenSession {
17192: char *zName; /* Symbolic name for this session */
17193: int nFilter; /* Number of xFilter rejection GLOB patterns */
17194: char **azFilter; /* Array of xFilter rejection GLOB patterns */
17195: sqlite3_session *p; /* The open session */
17196: };
17197: #endif
17198:
17199: typedef struct ExpertInfo ExpertInfo;
17200: struct ExpertInfo {
17201: sqlite3expert *pExpert;
17202: int bVerbose;
17203: };
17204:
17205: /* A single line in the EQP output */
17206: typedef struct EQPGraphRow EQPGraphRow;
17207: struct EQPGraphRow {
17208: int iEqpId; /* ID for this row */
17209: int iParentId; /* ID of the parent row */
17210: EQPGraphRow *pNext; /* Next row in sequence */
17211: char zText[1]; /* Text to display for this row */
17212: };
17213:
17214: /* All EQP output is collected into an instance of the following */
17215: typedef struct EQPGraph EQPGraph;
17216: struct EQPGraph {
17217: EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */
17218: EQPGraphRow *pLast; /* Last element of the pRow list */
17219: char zPrefix[100]; /* Graph prefix */
17220: };
17221:
1.6.2.1 ! misho 17222: /* Parameters affecting columnar mode result display (defaulting together) */
! 17223: typedef struct ColModeOpts {
! 17224: int iWrap; /* In columnar modes, wrap lines reaching this limit */
! 17225: u8 bQuote; /* Quote results for .mode box and table */
! 17226: u8 bWordWrap; /* In columnar modes, wrap at word boundaries */
! 17227: } ColModeOpts;
! 17228: #define ColModeOpts_default { 60, 0, 0 }
! 17229: #define ColModeOpts_default_qbox { 60, 1, 0 }
! 17230:
1.5 misho 17231: /*
17232: ** State information about the database connection is contained in an
17233: ** instance of the following structure.
17234: */
17235: typedef struct ShellState ShellState;
17236: struct ShellState {
17237: sqlite3 *db; /* The database */
17238: u8 autoExplain; /* Automatically turn on .explain mode */
1.6.2.1 ! misho 17239: u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to each SQL stmt */
1.5 misho 17240: u8 autoEQPtest; /* autoEQP is in test mode */
17241: u8 autoEQPtrace; /* autoEQP is in trace mode */
17242: u8 scanstatsOn; /* True to display scan stats before each finalize */
17243: u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
17244: u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
17245: u8 nEqpLevel; /* Depth of the EQP output graph */
17246: u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
1.6.2.1 ! misho 17247: u8 bSafeMode; /* True to prohibit unsafe operations */
! 17248: u8 bSafeModePersist; /* The long-term value of bSafeMode */
! 17249: ColModeOpts cmOpts; /* Option values affecting columnar mode output */
1.6 misho 17250: unsigned statsOn; /* True to display memory stats before each finalize */
1.6.2.1 ! misho 17251: unsigned mEqpLines; /* Mask of vertical lines in the EQP output graph */
! 17252: int inputNesting; /* Track nesting level of .read and other redirects */
1.5 misho 17253: int outCount; /* Revert to stdout when reaching zero */
17254: int cnt; /* Number of records displayed so far */
17255: int lineno; /* Line number of last line read from in */
17256: int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */
17257: FILE *in; /* Read commands from this stream */
17258: FILE *out; /* Write results here */
17259: FILE *traceOut; /* Output for sqlite3_trace() */
17260: int nErr; /* Number of errors seen */
17261: int mode; /* An output mode setting */
17262: int modePrior; /* Saved mode */
17263: int cMode; /* temporary output mode for the current query */
17264: int normalMode; /* Output mode before ".explain on" */
17265: int writableSchema; /* True if PRAGMA writable_schema=ON */
17266: int showHeader; /* True to show column names in List or Column mode */
17267: int nCheck; /* Number of ".check" commands run */
17268: unsigned nProgress; /* Number of progress callbacks encountered */
17269: unsigned mxProgress; /* Maximum progress callbacks before failing */
17270: unsigned flgProgress; /* Flags for the progress callback */
17271: unsigned shellFlgs; /* Various flags */
17272: unsigned priorShFlgs; /* Saved copy of flags */
17273: sqlite3_int64 szMax; /* --maxsize argument to .open */
17274: char *zDestTable; /* Name of destination table when MODE_Insert */
17275: char *zTempFile; /* Temporary file that might need deleting */
17276: char zTestcase[30]; /* Name of current test case */
17277: char colSeparator[20]; /* Column separator character for several modes */
17278: char rowSeparator[20]; /* Row separator character for MODE_Ascii */
17279: char colSepPrior[20]; /* Saved column separator */
17280: char rowSepPrior[20]; /* Saved row separator */
17281: int *colWidth; /* Requested width of each column in columnar modes */
17282: int *actualWidth; /* Actual width of each column */
17283: int nWidth; /* Number of slots in colWidth[] and actualWidth[] */
17284: char nullValue[20]; /* The text to print when a NULL comes back from
17285: ** the database */
17286: char outfile[FILENAME_MAX]; /* Filename for *out */
17287: sqlite3_stmt *pStmt; /* Current statement if any. */
17288: FILE *pLog; /* Write log output here */
1.6.2.1 ! misho 17289: struct AuxDb { /* Storage space for auxiliary database connections */
! 17290: sqlite3 *db; /* Connection pointer */
! 17291: const char *zDbFilename; /* Filename used to open the connection */
! 17292: char *zFreeOnClose; /* Free this memory allocation on close */
! 17293: #if defined(SQLITE_ENABLE_SESSION)
! 17294: int nSession; /* Number of active sessions */
! 17295: OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */
! 17296: #endif
! 17297: } aAuxDb[5], /* Array of all database connections */
! 17298: *pAuxDb; /* Currently active database connection */
1.5 misho 17299: int *aiIndent; /* Array of indents used in MODE_Explain */
17300: int nIndent; /* Size of array aiIndent[] */
17301: int iIndent; /* Index of current op in aiIndent[] */
1.6.2.1 ! misho 17302: char *zNonce; /* Nonce for temporary safe-mode escapes */
1.5 misho 17303: EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */
1.6.2.1 ! misho 17304: ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
! 17305: #ifdef SQLITE_SHELL_FIDDLE
! 17306: struct {
! 17307: const char * zInput; /* Input string from wasm/JS proxy */
! 17308: const char * zPos; /* Cursor pos into zInput */
! 17309: const char * zDefaultDbName; /* Default name for db file */
! 17310: } wasm;
1.5 misho 17311: #endif
17312: };
17313:
1.6.2.1 ! misho 17314: #ifdef SQLITE_SHELL_FIDDLE
! 17315: static ShellState shellState;
! 17316: #endif
! 17317:
1.5 misho 17318:
17319: /* Allowed values for ShellState.autoEQP
17320: */
17321: #define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */
17322: #define AUTOEQP_on 1 /* Automatic EQP is on */
17323: #define AUTOEQP_trigger 2 /* On and also show plans for triggers */
17324: #define AUTOEQP_full 3 /* Show full EXPLAIN */
17325:
17326: /* Allowed values for ShellState.openMode
17327: */
17328: #define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
17329: #define SHELL_OPEN_NORMAL 1 /* Normal database file */
17330: #define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
17331: #define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
17332: #define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
17333: #define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
17334: #define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */
17335:
17336: /* Allowed values for ShellState.eTraceType
17337: */
17338: #define SHELL_TRACE_PLAIN 0 /* Show input SQL text */
17339: #define SHELL_TRACE_EXPANDED 1 /* Show expanded SQL text */
17340: #define SHELL_TRACE_NORMALIZED 2 /* Show normalized SQL text */
17341:
17342: /* Bits in the ShellState.flgProgress variable */
17343: #define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */
1.6.2.1 ! misho 17344: #define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progress
1.5 misho 17345: ** callback limit is reached, and for each
17346: ** top-level SQL statement */
17347: #define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */
17348:
17349: /*
17350: ** These are the allowed shellFlgs values
17351: */
17352: #define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */
17353: #define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */
17354: #define SHFLG_Backslash 0x00000004 /* The --backslash option is used */
17355: #define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */
17356: #define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
17357: #define SHFLG_CountChanges 0x00000020 /* .changes setting */
1.6.2.1 ! misho 17358: #define SHFLG_Echo 0x00000040 /* .echo on/off, or --echo setting */
! 17359: #define SHFLG_HeaderSet 0x00000080 /* showHeader has been specified */
1.6 misho 17360: #define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */
17361: #define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */
1.6.2.1 ! misho 17362: #define SHFLG_TestingMode 0x00000400 /* allow unsafe testing features */
1.5 misho 17363:
17364: /*
17365: ** Macros for testing and setting shellFlgs
17366: */
17367: #define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0)
17368: #define ShellSetFlag(P,X) ((P)->shellFlgs|=(X))
17369: #define ShellClearFlag(P,X) ((P)->shellFlgs&=(~(X)))
17370:
17371: /*
17372: ** These are the allowed modes.
17373: */
17374: #define MODE_Line 0 /* One column per line. Blank line between records */
17375: #define MODE_Column 1 /* One record per line in neat columns */
17376: #define MODE_List 2 /* One record per line with a separator */
17377: #define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
17378: #define MODE_Html 4 /* Generate an XHTML table */
17379: #define MODE_Insert 5 /* Generate SQL "insert" statements */
17380: #define MODE_Quote 6 /* Quote values as for SQL */
17381: #define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */
17382: #define MODE_Csv 8 /* Quote strings, numbers are plain */
17383: #define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */
17384: #define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
17385: #define MODE_Pretty 11 /* Pretty-print schemas */
17386: #define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
17387: #define MODE_Json 13 /* Output JSON */
17388: #define MODE_Markdown 14 /* Markdown formatting */
17389: #define MODE_Table 15 /* MySQL-style table formatting */
17390: #define MODE_Box 16 /* Unicode box-drawing characters */
1.6.2.1 ! misho 17391: #define MODE_Count 17 /* Output only a count of the rows of output */
! 17392: #define MODE_Off 18 /* No query output shown */
! 17393: #define MODE_ScanExp 19 /* Like MODE_Explain, but for ".scanstats vm" */
1.5 misho 17394:
17395: static const char *modeDescr[] = {
17396: "line",
17397: "column",
17398: "list",
17399: "semi",
17400: "html",
17401: "insert",
17402: "quote",
17403: "tcl",
17404: "csv",
17405: "explain",
17406: "ascii",
17407: "prettyprint",
17408: "eqp",
17409: "json",
17410: "markdown",
17411: "table",
1.6.2.1 ! misho 17412: "box",
! 17413: "count",
! 17414: "off"
1.5 misho 17415: };
17416:
17417: /*
17418: ** These are the column/row/line separators used by the various
17419: ** import/export modes.
17420: */
17421: #define SEP_Column "|"
17422: #define SEP_Row "\n"
17423: #define SEP_Tab "\t"
17424: #define SEP_Space " "
17425: #define SEP_Comma ","
17426: #define SEP_CrLf "\r\n"
17427: #define SEP_Unit "\x1F"
17428: #define SEP_Record "\x1E"
17429:
17430: /*
1.6.2.1 ! misho 17431: ** Limit input nesting via .read or any other input redirect.
! 17432: ** It's not too expensive, so a generous allowance can be made.
! 17433: */
! 17434: #define MAX_INPUT_NESTING 25
! 17435:
! 17436: /*
1.5 misho 17437: ** A callback for the sqlite3_log() interface.
17438: */
17439: static void shellLog(void *pArg, int iErrCode, const char *zMsg){
17440: ShellState *p = (ShellState*)pArg;
17441: if( p->pLog==0 ) return;
17442: utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
17443: fflush(p->pLog);
17444: }
17445:
17446: /*
17447: ** SQL function: shell_putsnl(X)
17448: **
17449: ** Write the text X to the screen (or whatever output is being directed)
17450: ** adding a newline at the end, and then return X.
17451: */
17452: static void shellPutsFunc(
17453: sqlite3_context *pCtx,
17454: int nVal,
17455: sqlite3_value **apVal
17456: ){
17457: ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
17458: (void)nVal;
17459: utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
17460: sqlite3_result_value(pCtx, apVal[0]);
17461: }
17462:
17463: /*
1.6.2.1 ! misho 17464: ** If in safe mode, print an error message described by the arguments
! 17465: ** and exit immediately.
! 17466: */
! 17467: static void failIfSafeMode(
! 17468: ShellState *p,
! 17469: const char *zErrMsg,
! 17470: ...
! 17471: ){
! 17472: if( p->bSafeMode ){
! 17473: va_list ap;
! 17474: char *zMsg;
! 17475: va_start(ap, zErrMsg);
! 17476: zMsg = sqlite3_vmprintf(zErrMsg, ap);
! 17477: va_end(ap);
! 17478: raw_printf(stderr, "line %d: ", p->lineno);
! 17479: utf8_printf(stderr, "%s\n", zMsg);
! 17480: exit(1);
! 17481: }
! 17482: }
! 17483:
! 17484: /*
1.5 misho 17485: ** SQL function: edit(VALUE)
17486: ** edit(VALUE,EDITOR)
17487: **
17488: ** These steps:
17489: **
17490: ** (1) Write VALUE into a temporary file.
17491: ** (2) Run program EDITOR on that temporary file.
17492: ** (3) Read the temporary file back and return its content as the result.
17493: ** (4) Delete the temporary file
17494: **
17495: ** If the EDITOR argument is omitted, use the value in the VISUAL
17496: ** environment variable. If still there is no EDITOR, through an error.
17497: **
17498: ** Also throw an error if the EDITOR program returns a non-zero exit code.
17499: */
17500: #ifndef SQLITE_NOHAVE_SYSTEM
17501: static void editFunc(
17502: sqlite3_context *context,
17503: int argc,
17504: sqlite3_value **argv
17505: ){
17506: const char *zEditor;
17507: char *zTempFile = 0;
17508: sqlite3 *db;
17509: char *zCmd = 0;
17510: int bBin;
17511: int rc;
17512: int hasCRNL = 0;
17513: FILE *f = 0;
17514: sqlite3_int64 sz;
17515: sqlite3_int64 x;
17516: unsigned char *p = 0;
17517:
17518: if( argc==2 ){
17519: zEditor = (const char*)sqlite3_value_text(argv[1]);
17520: }else{
17521: zEditor = getenv("VISUAL");
17522: }
17523: if( zEditor==0 ){
17524: sqlite3_result_error(context, "no editor for edit()", -1);
17525: return;
17526: }
17527: if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
17528: sqlite3_result_error(context, "NULL input to edit()", -1);
17529: return;
17530: }
17531: db = sqlite3_context_db_handle(context);
17532: zTempFile = 0;
17533: sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile);
17534: if( zTempFile==0 ){
17535: sqlite3_uint64 r = 0;
17536: sqlite3_randomness(sizeof(r), &r);
17537: zTempFile = sqlite3_mprintf("temp%llx", r);
17538: if( zTempFile==0 ){
17539: sqlite3_result_error_nomem(context);
17540: return;
17541: }
17542: }
17543: bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB;
17544: /* When writing the file to be edited, do \n to \r\n conversions on systems
17545: ** that want \r\n line endings */
17546: f = fopen(zTempFile, bBin ? "wb" : "w");
17547: if( f==0 ){
17548: sqlite3_result_error(context, "edit() cannot open temp file", -1);
17549: goto edit_func_end;
17550: }
17551: sz = sqlite3_value_bytes(argv[0]);
17552: if( bBin ){
17553: x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f);
17554: }else{
17555: const char *z = (const char*)sqlite3_value_text(argv[0]);
17556: /* Remember whether or not the value originally contained \r\n */
17557: if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
17558: x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f);
17559: }
17560: fclose(f);
17561: f = 0;
17562: if( x!=sz ){
17563: sqlite3_result_error(context, "edit() could not write the whole file", -1);
17564: goto edit_func_end;
17565: }
17566: zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile);
17567: if( zCmd==0 ){
17568: sqlite3_result_error_nomem(context);
17569: goto edit_func_end;
17570: }
17571: rc = system(zCmd);
17572: sqlite3_free(zCmd);
17573: if( rc ){
17574: sqlite3_result_error(context, "EDITOR returned non-zero", -1);
17575: goto edit_func_end;
17576: }
17577: f = fopen(zTempFile, "rb");
17578: if( f==0 ){
17579: sqlite3_result_error(context,
17580: "edit() cannot reopen temp file after edit", -1);
17581: goto edit_func_end;
17582: }
17583: fseek(f, 0, SEEK_END);
17584: sz = ftell(f);
17585: rewind(f);
17586: p = sqlite3_malloc64( sz+1 );
17587: if( p==0 ){
17588: sqlite3_result_error_nomem(context);
17589: goto edit_func_end;
17590: }
17591: x = fread(p, 1, (size_t)sz, f);
17592: fclose(f);
17593: f = 0;
17594: if( x!=sz ){
17595: sqlite3_result_error(context, "could not read back the whole file", -1);
17596: goto edit_func_end;
17597: }
17598: if( bBin ){
17599: sqlite3_result_blob64(context, p, sz, sqlite3_free);
17600: }else{
17601: sqlite3_int64 i, j;
17602: if( hasCRNL ){
17603: /* If the original contains \r\n then do no conversions back to \n */
17604: }else{
17605: /* If the file did not originally contain \r\n then convert any new
17606: ** \r\n back into \n */
1.6.2.1 ! misho 17607: p[sz] = 0;
1.5 misho 17608: for(i=j=0; i<sz; i++){
17609: if( p[i]=='\r' && p[i+1]=='\n' ) i++;
17610: p[j++] = p[i];
17611: }
17612: sz = j;
17613: p[sz] = 0;
1.6.2.1 ! misho 17614: }
1.5 misho 17615: sqlite3_result_text64(context, (const char*)p, sz,
17616: sqlite3_free, SQLITE_UTF8);
17617: }
17618: p = 0;
17619:
17620: edit_func_end:
17621: if( f ) fclose(f);
17622: unlink(zTempFile);
17623: sqlite3_free(zTempFile);
17624: sqlite3_free(p);
17625: }
17626: #endif /* SQLITE_NOHAVE_SYSTEM */
17627:
17628: /*
17629: ** Save or restore the current output mode
17630: */
17631: static void outputModePush(ShellState *p){
17632: p->modePrior = p->mode;
17633: p->priorShFlgs = p->shellFlgs;
17634: memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));
17635: memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));
17636: }
17637: static void outputModePop(ShellState *p){
17638: p->mode = p->modePrior;
17639: p->shellFlgs = p->priorShFlgs;
17640: memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
17641: memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
17642: }
17643:
17644: /*
17645: ** Output the given string as a hex-encoded blob (eg. X'1234' )
17646: */
17647: static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
17648: int i;
1.6.2.1 ! misho 17649: unsigned char *aBlob = (unsigned char*)pBlob;
! 17650:
! 17651: char *zStr = sqlite3_malloc(nBlob*2 + 1);
! 17652: shell_check_oom(zStr);
! 17653:
! 17654: for(i=0; i<nBlob; i++){
! 17655: static const char aHex[] = {
! 17656: '0', '1', '2', '3', '4', '5', '6', '7',
! 17657: '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
! 17658: };
! 17659: zStr[i*2] = aHex[ (aBlob[i] >> 4) ];
! 17660: zStr[i*2+1] = aHex[ (aBlob[i] & 0x0F) ];
! 17661: }
! 17662: zStr[i*2] = '\0';
! 17663:
! 17664: raw_printf(out,"X'%s'", zStr);
! 17665: sqlite3_free(zStr);
1.5 misho 17666: }
17667:
17668: /*
17669: ** Find a string that is not found anywhere in z[]. Return a pointer
17670: ** to that string.
17671: **
17672: ** Try to use zA and zB first. If both of those are already found in z[]
17673: ** then make up some string and store it in the buffer zBuf.
17674: */
17675: static const char *unused_string(
17676: const char *z, /* Result must not appear anywhere in z */
17677: const char *zA, const char *zB, /* Try these first */
17678: char *zBuf /* Space to store a generated string */
17679: ){
17680: unsigned i = 0;
17681: if( strstr(z, zA)==0 ) return zA;
17682: if( strstr(z, zB)==0 ) return zB;
17683: do{
17684: sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
17685: }while( strstr(z,zBuf)!=0 );
17686: return zBuf;
17687: }
17688:
17689: /*
17690: ** Output the given string as a quoted string using SQL quoting conventions.
17691: **
17692: ** See also: output_quoted_escaped_string()
17693: */
17694: static void output_quoted_string(FILE *out, const char *z){
17695: int i;
17696: char c;
17697: setBinaryMode(out, 1);
1.6.2.1 ! misho 17698: if( z==0 ) return;
1.5 misho 17699: for(i=0; (c = z[i])!=0 && c!='\''; i++){}
17700: if( c==0 ){
17701: utf8_printf(out,"'%s'",z);
17702: }else{
17703: raw_printf(out, "'");
17704: while( *z ){
17705: for(i=0; (c = z[i])!=0 && c!='\''; i++){}
17706: if( c=='\'' ) i++;
17707: if( i ){
17708: utf8_printf(out, "%.*s", i, z);
17709: z += i;
17710: }
17711: if( c=='\'' ){
17712: raw_printf(out, "'");
17713: continue;
17714: }
17715: if( c==0 ){
17716: break;
17717: }
17718: z++;
17719: }
17720: raw_printf(out, "'");
17721: }
17722: setTextMode(out, 1);
17723: }
17724:
17725: /*
17726: ** Output the given string as a quoted string using SQL quoting conventions.
17727: ** Additionallly , escape the "\n" and "\r" characters so that they do not
17728: ** get corrupted by end-of-line translation facilities in some operating
17729: ** systems.
17730: **
17731: ** This is like output_quoted_string() but with the addition of the \r\n
17732: ** escape mechanism.
17733: */
17734: static void output_quoted_escaped_string(FILE *out, const char *z){
17735: int i;
17736: char c;
17737: setBinaryMode(out, 1);
17738: for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
17739: if( c==0 ){
17740: utf8_printf(out,"'%s'",z);
17741: }else{
17742: const char *zNL = 0;
17743: const char *zCR = 0;
17744: int nNL = 0;
17745: int nCR = 0;
17746: char zBuf1[20], zBuf2[20];
17747: for(i=0; z[i]; i++){
17748: if( z[i]=='\n' ) nNL++;
17749: if( z[i]=='\r' ) nCR++;
17750: }
17751: if( nNL ){
17752: raw_printf(out, "replace(");
17753: zNL = unused_string(z, "\\n", "\\012", zBuf1);
17754: }
17755: if( nCR ){
17756: raw_printf(out, "replace(");
17757: zCR = unused_string(z, "\\r", "\\015", zBuf2);
17758: }
17759: raw_printf(out, "'");
17760: while( *z ){
17761: for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
17762: if( c=='\'' ) i++;
17763: if( i ){
17764: utf8_printf(out, "%.*s", i, z);
17765: z += i;
17766: }
17767: if( c=='\'' ){
17768: raw_printf(out, "'");
17769: continue;
17770: }
17771: if( c==0 ){
17772: break;
17773: }
17774: z++;
17775: if( c=='\n' ){
17776: raw_printf(out, "%s", zNL);
17777: continue;
17778: }
17779: raw_printf(out, "%s", zCR);
17780: }
17781: raw_printf(out, "'");
17782: if( nCR ){
17783: raw_printf(out, ",'%s',char(13))", zCR);
17784: }
17785: if( nNL ){
17786: raw_printf(out, ",'%s',char(10))", zNL);
17787: }
17788: }
17789: setTextMode(out, 1);
17790: }
17791:
17792: /*
17793: ** Output the given string as a quoted according to C or TCL quoting rules.
17794: */
17795: static void output_c_string(FILE *out, const char *z){
17796: unsigned int c;
17797: fputc('"', out);
17798: while( (c = *(z++))!=0 ){
17799: if( c=='\\' ){
17800: fputc(c, out);
17801: fputc(c, out);
17802: }else if( c=='"' ){
17803: fputc('\\', out);
17804: fputc('"', out);
17805: }else if( c=='\t' ){
17806: fputc('\\', out);
17807: fputc('t', out);
17808: }else if( c=='\n' ){
17809: fputc('\\', out);
17810: fputc('n', out);
17811: }else if( c=='\r' ){
17812: fputc('\\', out);
17813: fputc('r', out);
17814: }else if( !isprint(c&0xff) ){
17815: raw_printf(out, "\\%03o", c&0xff);
17816: }else{
17817: fputc(c, out);
17818: }
17819: }
17820: fputc('"', out);
17821: }
17822:
17823: /*
17824: ** Output the given string as a quoted according to JSON quoting rules.
17825: */
1.6.2.1 ! misho 17826: static void output_json_string(FILE *out, const char *z, i64 n){
1.5 misho 17827: unsigned int c;
1.6.2.1 ! misho 17828: if( z==0 ) z = "";
! 17829: if( n<0 ) n = strlen(z);
1.5 misho 17830: fputc('"', out);
17831: while( n-- ){
17832: c = *(z++);
17833: if( c=='\\' || c=='"' ){
17834: fputc('\\', out);
17835: fputc(c, out);
17836: }else if( c<=0x1f ){
17837: fputc('\\', out);
17838: if( c=='\b' ){
17839: fputc('b', out);
17840: }else if( c=='\f' ){
17841: fputc('f', out);
17842: }else if( c=='\n' ){
17843: fputc('n', out);
17844: }else if( c=='\r' ){
17845: fputc('r', out);
17846: }else if( c=='\t' ){
17847: fputc('t', out);
17848: }else{
17849: raw_printf(out, "u%04x",c);
17850: }
17851: }else{
17852: fputc(c, out);
17853: }
17854: }
17855: fputc('"', out);
17856: }
17857:
17858: /*
17859: ** Output the given string with characters that are special to
17860: ** HTML escaped.
17861: */
17862: static void output_html_string(FILE *out, const char *z){
17863: int i;
17864: if( z==0 ) z = "";
17865: while( *z ){
17866: for(i=0; z[i]
17867: && z[i]!='<'
17868: && z[i]!='&'
17869: && z[i]!='>'
17870: && z[i]!='\"'
17871: && z[i]!='\'';
17872: i++){}
17873: if( i>0 ){
17874: utf8_printf(out,"%.*s",i,z);
17875: }
17876: if( z[i]=='<' ){
17877: raw_printf(out,"<");
17878: }else if( z[i]=='&' ){
17879: raw_printf(out,"&");
17880: }else if( z[i]=='>' ){
17881: raw_printf(out,">");
17882: }else if( z[i]=='\"' ){
17883: raw_printf(out,""");
17884: }else if( z[i]=='\'' ){
17885: raw_printf(out,"'");
17886: }else{
17887: break;
17888: }
17889: z += i + 1;
17890: }
17891: }
17892:
17893: /*
17894: ** If a field contains any character identified by a 1 in the following
17895: ** array, then the string must be quoted for CSV.
17896: */
17897: static const char needCsvQuote[] = {
17898: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17899: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17900: 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
17901: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17902: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17903: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17904: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17905: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
17906: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17907: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17908: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17909: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17910: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17911: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17912: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17913: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17914: };
17915:
17916: /*
17917: ** Output a single term of CSV. Actually, p->colSeparator is used for
17918: ** the separator, which may or may not be a comma. p->nullValue is
17919: ** the null value. Strings are quoted if necessary. The separator
17920: ** is only issued if bSep is true.
17921: */
17922: static void output_csv(ShellState *p, const char *z, int bSep){
17923: FILE *out = p->out;
17924: if( z==0 ){
17925: utf8_printf(out,"%s",p->nullValue);
17926: }else{
1.6.2.1 ! misho 17927: unsigned i;
1.5 misho 17928: for(i=0; z[i]; i++){
1.6.2.1 ! misho 17929: if( needCsvQuote[((unsigned char*)z)[i]] ){
1.5 misho 17930: i = 0;
17931: break;
17932: }
17933: }
1.6.2.1 ! misho 17934: if( i==0 || strstr(z, p->colSeparator)!=0 ){
1.5 misho 17935: char *zQuoted = sqlite3_mprintf("\"%w\"", z);
1.6.2.1 ! misho 17936: shell_check_oom(zQuoted);
1.5 misho 17937: utf8_printf(out, "%s", zQuoted);
17938: sqlite3_free(zQuoted);
17939: }else{
17940: utf8_printf(out, "%s", z);
17941: }
17942: }
17943: if( bSep ){
17944: utf8_printf(p->out, "%s", p->colSeparator);
17945: }
17946: }
17947:
17948: /*
17949: ** This routine runs when the user presses Ctrl-C
17950: */
17951: static void interrupt_handler(int NotUsed){
17952: UNUSED_PARAMETER(NotUsed);
1.6.2.1 ! misho 17953: if( ++seenInterrupt>1 ) exit(1);
1.5 misho 17954: if( globalDb ) sqlite3_interrupt(globalDb);
17955: }
17956:
17957: #if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
17958: /*
17959: ** This routine runs for console events (e.g. Ctrl-C) on Win32
17960: */
17961: static BOOL WINAPI ConsoleCtrlHandler(
17962: DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */
17963: ){
17964: if( dwCtrlType==CTRL_C_EVENT ){
17965: interrupt_handler(0);
17966: return TRUE;
17967: }
17968: return FALSE;
17969: }
17970: #endif
17971:
17972: #ifndef SQLITE_OMIT_AUTHORIZATION
17973: /*
1.6.2.1 ! misho 17974: ** This authorizer runs in safe mode.
! 17975: */
! 17976: static int safeModeAuth(
! 17977: void *pClientData,
! 17978: int op,
! 17979: const char *zA1,
! 17980: const char *zA2,
! 17981: const char *zA3,
! 17982: const char *zA4
! 17983: ){
! 17984: ShellState *p = (ShellState*)pClientData;
! 17985: static const char *azProhibitedFunctions[] = {
! 17986: "edit",
! 17987: "fts3_tokenizer",
! 17988: "load_extension",
! 17989: "readfile",
! 17990: "writefile",
! 17991: "zipfile",
! 17992: "zipfile_cds",
! 17993: };
! 17994: UNUSED_PARAMETER(zA1);
! 17995: UNUSED_PARAMETER(zA3);
! 17996: UNUSED_PARAMETER(zA4);
! 17997: switch( op ){
! 17998: case SQLITE_ATTACH: {
! 17999: #ifndef SQLITE_SHELL_FIDDLE
! 18000: /* In WASM builds the filesystem is a virtual sandbox, so
! 18001: ** there's no harm in using ATTACH. */
! 18002: failIfSafeMode(p, "cannot run ATTACH in safe mode");
! 18003: #endif
! 18004: break;
! 18005: }
! 18006: case SQLITE_FUNCTION: {
! 18007: int i;
! 18008: for(i=0; i<ArraySize(azProhibitedFunctions); i++){
! 18009: if( sqlite3_stricmp(zA2, azProhibitedFunctions[i])==0 ){
! 18010: failIfSafeMode(p, "cannot use the %s() function in safe mode",
! 18011: azProhibitedFunctions[i]);
! 18012: }
! 18013: }
! 18014: break;
! 18015: }
! 18016: }
! 18017: return SQLITE_OK;
! 18018: }
! 18019:
! 18020: /*
1.5 misho 18021: ** When the ".auth ON" is set, the following authorizer callback is
18022: ** invoked. It always returns SQLITE_OK.
18023: */
18024: static int shellAuth(
18025: void *pClientData,
18026: int op,
18027: const char *zA1,
18028: const char *zA2,
18029: const char *zA3,
18030: const char *zA4
18031: ){
18032: ShellState *p = (ShellState*)pClientData;
18033: static const char *azAction[] = { 0,
18034: "CREATE_INDEX", "CREATE_TABLE", "CREATE_TEMP_INDEX",
18035: "CREATE_TEMP_TABLE", "CREATE_TEMP_TRIGGER", "CREATE_TEMP_VIEW",
18036: "CREATE_TRIGGER", "CREATE_VIEW", "DELETE",
18037: "DROP_INDEX", "DROP_TABLE", "DROP_TEMP_INDEX",
18038: "DROP_TEMP_TABLE", "DROP_TEMP_TRIGGER", "DROP_TEMP_VIEW",
18039: "DROP_TRIGGER", "DROP_VIEW", "INSERT",
18040: "PRAGMA", "READ", "SELECT",
18041: "TRANSACTION", "UPDATE", "ATTACH",
18042: "DETACH", "ALTER_TABLE", "REINDEX",
18043: "ANALYZE", "CREATE_VTABLE", "DROP_VTABLE",
18044: "FUNCTION", "SAVEPOINT", "RECURSIVE"
18045: };
18046: int i;
18047: const char *az[4];
18048: az[0] = zA1;
18049: az[1] = zA2;
18050: az[2] = zA3;
18051: az[3] = zA4;
18052: utf8_printf(p->out, "authorizer: %s", azAction[op]);
18053: for(i=0; i<4; i++){
18054: raw_printf(p->out, " ");
18055: if( az[i] ){
18056: output_c_string(p->out, az[i]);
18057: }else{
18058: raw_printf(p->out, "NULL");
18059: }
18060: }
18061: raw_printf(p->out, "\n");
1.6.2.1 ! misho 18062: if( p->bSafeMode ) (void)safeModeAuth(pClientData, op, zA1, zA2, zA3, zA4);
1.5 misho 18063: return SQLITE_OK;
18064: }
18065: #endif
18066:
18067: /*
18068: ** Print a schema statement. Part of MODE_Semi and MODE_Pretty output.
18069: **
18070: ** This routine converts some CREATE TABLE statements for shadow tables
18071: ** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
1.6.2.1 ! misho 18072: **
! 18073: ** If the schema statement in z[] contains a start-of-comment and if
! 18074: ** sqlite3_complete() returns false, try to terminate the comment before
! 18075: ** printing the result. https://sqlite.org/forum/forumpost/d7be961c5c
1.5 misho 18076: */
18077: static void printSchemaLine(FILE *out, const char *z, const char *zTail){
1.6.2.1 ! misho 18078: char *zToFree = 0;
1.5 misho 18079: if( z==0 ) return;
18080: if( zTail==0 ) return;
1.6.2.1 ! misho 18081: if( zTail[0]==';' && (strstr(z, "/*")!=0 || strstr(z,"--")!=0) ){
! 18082: const char *zOrig = z;
! 18083: static const char *azTerm[] = { "", "*/", "\n" };
! 18084: int i;
! 18085: for(i=0; i<ArraySize(azTerm); i++){
! 18086: char *zNew = sqlite3_mprintf("%s%s;", zOrig, azTerm[i]);
! 18087: shell_check_oom(zNew);
! 18088: if( sqlite3_complete(zNew) ){
! 18089: size_t n = strlen(zNew);
! 18090: zNew[n-1] = 0;
! 18091: zToFree = zNew;
! 18092: z = zNew;
! 18093: break;
! 18094: }
! 18095: sqlite3_free(zNew);
! 18096: }
! 18097: }
1.5 misho 18098: if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
18099: utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
18100: }else{
18101: utf8_printf(out, "%s%s", z, zTail);
18102: }
1.6.2.1 ! misho 18103: sqlite3_free(zToFree);
1.5 misho 18104: }
18105: static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
18106: char c = z[n];
18107: z[n] = 0;
18108: printSchemaLine(out, z, zTail);
18109: z[n] = c;
18110: }
18111:
18112: /*
18113: ** Return true if string z[] has nothing but whitespace and comments to the
18114: ** end of the first line.
18115: */
18116: static int wsToEol(const char *z){
18117: int i;
18118: for(i=0; z[i]; i++){
18119: if( z[i]=='\n' ) return 1;
18120: if( IsSpace(z[i]) ) continue;
18121: if( z[i]=='-' && z[i+1]=='-' ) return 1;
18122: return 0;
18123: }
18124: return 1;
18125: }
18126:
18127: /*
18128: ** Add a new entry to the EXPLAIN QUERY PLAN data
18129: */
18130: static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
18131: EQPGraphRow *pNew;
1.6.2.1 ! misho 18132: i64 nText;
! 18133: if( zText==0 ) return;
! 18134: nText = strlen(zText);
1.5 misho 18135: if( p->autoEQPtest ){
18136: utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
18137: }
18138: pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
1.6.2.1 ! misho 18139: shell_check_oom(pNew);
1.5 misho 18140: pNew->iEqpId = iEqpId;
18141: pNew->iParentId = p2;
18142: memcpy(pNew->zText, zText, nText+1);
18143: pNew->pNext = 0;
18144: if( p->sGraph.pLast ){
18145: p->sGraph.pLast->pNext = pNew;
18146: }else{
18147: p->sGraph.pRow = pNew;
18148: }
18149: p->sGraph.pLast = pNew;
18150: }
18151:
18152: /*
18153: ** Free and reset the EXPLAIN QUERY PLAN data that has been collected
18154: ** in p->sGraph.
18155: */
18156: static void eqp_reset(ShellState *p){
18157: EQPGraphRow *pRow, *pNext;
18158: for(pRow = p->sGraph.pRow; pRow; pRow = pNext){
18159: pNext = pRow->pNext;
18160: sqlite3_free(pRow);
18161: }
18162: memset(&p->sGraph, 0, sizeof(p->sGraph));
18163: }
18164:
18165: /* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after
18166: ** pOld, or return the first such line if pOld is NULL
18167: */
18168: static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){
18169: EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow;
18170: while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext;
18171: return pRow;
18172: }
18173:
18174: /* Render a single level of the graph that has iEqpId as its parent. Called
18175: ** recursively to render sublevels.
18176: */
18177: static void eqp_render_level(ShellState *p, int iEqpId){
18178: EQPGraphRow *pRow, *pNext;
1.6.2.1 ! misho 18179: i64 n = strlen(p->sGraph.zPrefix);
1.5 misho 18180: char *z;
18181: for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
18182: pNext = eqp_next_row(p, iEqpId, pRow);
18183: z = pRow->zText;
18184: utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
18185: pNext ? "|--" : "`--", z);
1.6.2.1 ! misho 18186: if( n<(i64)sizeof(p->sGraph.zPrefix)-7 ){
1.5 misho 18187: memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4);
18188: eqp_render_level(p, pRow->iEqpId);
18189: p->sGraph.zPrefix[n] = 0;
18190: }
18191: }
18192: }
18193:
18194: /*
18195: ** Display and reset the EXPLAIN QUERY PLAN data
18196: */
1.6.2.1 ! misho 18197: static void eqp_render(ShellState *p, i64 nCycle){
1.5 misho 18198: EQPGraphRow *pRow = p->sGraph.pRow;
18199: if( pRow ){
18200: if( pRow->zText[0]=='-' ){
18201: if( pRow->pNext==0 ){
18202: eqp_reset(p);
18203: return;
18204: }
18205: utf8_printf(p->out, "%s\n", pRow->zText+3);
18206: p->sGraph.pRow = pRow->pNext;
18207: sqlite3_free(pRow);
1.6.2.1 ! misho 18208: }else if( nCycle>0 ){
! 18209: utf8_printf(p->out, "QUERY PLAN (cycles=%lld [100%%])\n", nCycle);
1.5 misho 18210: }else{
18211: utf8_printf(p->out, "QUERY PLAN\n");
18212: }
18213: p->sGraph.zPrefix[0] = 0;
18214: eqp_render_level(p, 0);
18215: eqp_reset(p);
18216: }
18217: }
18218:
18219: #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
18220: /*
18221: ** Progress handler callback.
18222: */
18223: static int progress_handler(void *pClientData) {
18224: ShellState *p = (ShellState*)pClientData;
18225: p->nProgress++;
18226: if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
18227: raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
18228: if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
18229: if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
18230: return 1;
18231: }
18232: if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
18233: raw_printf(p->out, "Progress %u\n", p->nProgress);
18234: }
18235: return 0;
18236: }
18237: #endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
18238:
18239: /*
18240: ** Print N dashes
18241: */
18242: static void print_dashes(FILE *out, int N){
18243: const char zDash[] = "--------------------------------------------------";
18244: const int nDash = sizeof(zDash) - 1;
18245: while( N>nDash ){
18246: fputs(zDash, out);
18247: N -= nDash;
18248: }
18249: raw_printf(out, "%.*s", N, zDash);
18250: }
18251:
18252: /*
18253: ** Print a markdown or table-style row separator using ascii-art
18254: */
18255: static void print_row_separator(
18256: ShellState *p,
18257: int nArg,
18258: const char *zSep
18259: ){
18260: int i;
18261: if( nArg>0 ){
18262: fputs(zSep, p->out);
18263: print_dashes(p->out, p->actualWidth[0]+2);
18264: for(i=1; i<nArg; i++){
18265: fputs(zSep, p->out);
18266: print_dashes(p->out, p->actualWidth[i]+2);
18267: }
18268: fputs(zSep, p->out);
18269: }
18270: fputs("\n", p->out);
18271: }
18272:
18273: /*
18274: ** This is the callback routine that the shell
18275: ** invokes for each row of a query result.
18276: */
18277: static int shell_callback(
18278: void *pArg,
18279: int nArg, /* Number of result columns */
18280: char **azArg, /* Text of each result column */
18281: char **azCol, /* Column names */
18282: int *aiType /* Column types. Might be NULL */
18283: ){
18284: int i;
18285: ShellState *p = (ShellState*)pArg;
18286:
18287: if( azArg==0 ) return 0;
18288: switch( p->cMode ){
1.6.2.1 ! misho 18289: case MODE_Count:
! 18290: case MODE_Off: {
! 18291: break;
! 18292: }
1.5 misho 18293: case MODE_Line: {
18294: int w = 5;
18295: if( azArg==0 ) break;
18296: for(i=0; i<nArg; i++){
18297: int len = strlen30(azCol[i] ? azCol[i] : "");
18298: if( len>w ) w = len;
18299: }
18300: if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
18301: for(i=0; i<nArg; i++){
18302: utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
18303: azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
18304: }
18305: break;
18306: }
1.6.2.1 ! misho 18307: case MODE_ScanExp:
1.5 misho 18308: case MODE_Explain: {
1.6.2.1 ! misho 18309: static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
! 18310: static const int aExplainMap[] = {0, 1, 2, 3, 4, 5, 6, 7 };
! 18311: static const int aScanExpWidth[] = {4, 6, 6, 13, 4, 4, 4, 13, 2, 13};
! 18312: static const int aScanExpMap[] = {0, 9, 8, 1, 2, 3, 4, 5, 6, 7 };
! 18313:
! 18314: const int *aWidth = aExplainWidth;
! 18315: const int *aMap = aExplainMap;
! 18316: int nWidth = ArraySize(aExplainWidth);
! 18317: int iIndent = 1;
! 18318:
! 18319: if( p->cMode==MODE_ScanExp ){
! 18320: aWidth = aScanExpWidth;
! 18321: aMap = aScanExpMap;
! 18322: nWidth = ArraySize(aScanExpWidth);
! 18323: iIndent = 3;
1.5 misho 18324: }
1.6.2.1 ! misho 18325: if( nArg>nWidth ) nArg = nWidth;
! 18326:
! 18327: /* If this is the first row seen, print out the headers */
1.5 misho 18328: if( p->cnt++==0 ){
18329: for(i=0; i<nArg; i++){
1.6.2.1 ! misho 18330: utf8_width_print(p->out, aWidth[i], azCol[ aMap[i] ]);
1.5 misho 18331: fputs(i==nArg-1 ? "\n" : " ", p->out);
18332: }
18333: for(i=0; i<nArg; i++){
1.6.2.1 ! misho 18334: print_dashes(p->out, aWidth[i]);
1.5 misho 18335: fputs(i==nArg-1 ? "\n" : " ", p->out);
18336: }
18337: }
1.6.2.1 ! misho 18338:
! 18339: /* If there is no data, exit early. */
1.5 misho 18340: if( azArg==0 ) break;
1.6.2.1 ! misho 18341:
1.5 misho 18342: for(i=0; i<nArg; i++){
1.6.2.1 ! misho 18343: const char *zSep = " ";
! 18344: int w = aWidth[i];
! 18345: const char *zVal = azArg[ aMap[i] ];
1.6 misho 18346: if( i==nArg-1 ) w = 0;
1.6.2.1 ! misho 18347: if( zVal && strlenChar(zVal)>w ){
! 18348: w = strlenChar(zVal);
! 18349: zSep = " ";
1.5 misho 18350: }
1.6.2.1 ! misho 18351: if( i==iIndent && p->aiIndent && p->pStmt ){
1.5 misho 18352: if( p->iIndent<p->nIndent ){
18353: utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
18354: }
18355: p->iIndent++;
18356: }
1.6.2.1 ! misho 18357: utf8_width_print(p->out, w, zVal ? zVal : p->nullValue);
! 18358: fputs(i==nArg-1 ? "\n" : zSep, p->out);
1.5 misho 18359: }
18360: break;
18361: }
18362: case MODE_Semi: { /* .schema and .fullschema output */
18363: printSchemaLine(p->out, azArg[0], ";\n");
18364: break;
18365: }
18366: case MODE_Pretty: { /* .schema and .fullschema with --indent */
18367: char *z;
18368: int j;
18369: int nParen = 0;
18370: char cEnd = 0;
18371: char c;
18372: int nLine = 0;
18373: assert( nArg==1 );
18374: if( azArg[0]==0 ) break;
18375: if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
18376: || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
18377: ){
18378: utf8_printf(p->out, "%s;\n", azArg[0]);
18379: break;
18380: }
18381: z = sqlite3_mprintf("%s", azArg[0]);
1.6.2.1 ! misho 18382: shell_check_oom(z);
1.5 misho 18383: j = 0;
18384: for(i=0; IsSpace(z[i]); i++){}
18385: for(; (c = z[i])!=0; i++){
18386: if( IsSpace(c) ){
18387: if( z[j-1]=='\r' ) z[j-1] = '\n';
18388: if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
18389: }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
18390: j--;
18391: }
18392: z[j++] = c;
18393: }
18394: while( j>0 && IsSpace(z[j-1]) ){ j--; }
18395: z[j] = 0;
18396: if( strlen30(z)>=79 ){
18397: for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */
18398: if( c==cEnd ){
18399: cEnd = 0;
18400: }else if( c=='"' || c=='\'' || c=='`' ){
18401: cEnd = c;
18402: }else if( c=='[' ){
18403: cEnd = ']';
18404: }else if( c=='-' && z[i+1]=='-' ){
18405: cEnd = '\n';
18406: }else if( c=='(' ){
18407: nParen++;
18408: }else if( c==')' ){
18409: nParen--;
18410: if( nLine>0 && nParen==0 && j>0 ){
18411: printSchemaLineN(p->out, z, j, "\n");
18412: j = 0;
18413: }
18414: }
18415: z[j++] = c;
18416: if( nParen==1 && cEnd==0
18417: && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
18418: ){
18419: if( c=='\n' ) j--;
18420: printSchemaLineN(p->out, z, j, "\n ");
18421: j = 0;
18422: nLine++;
18423: while( IsSpace(z[i+1]) ){ i++; }
18424: }
18425: }
18426: z[j] = 0;
18427: }
18428: printSchemaLine(p->out, z, ";\n");
18429: sqlite3_free(z);
18430: break;
18431: }
18432: case MODE_List: {
18433: if( p->cnt++==0 && p->showHeader ){
18434: for(i=0; i<nArg; i++){
18435: utf8_printf(p->out,"%s%s",azCol[i],
18436: i==nArg-1 ? p->rowSeparator : p->colSeparator);
18437: }
18438: }
18439: if( azArg==0 ) break;
18440: for(i=0; i<nArg; i++){
18441: char *z = azArg[i];
18442: if( z==0 ) z = p->nullValue;
18443: utf8_printf(p->out, "%s", z);
18444: if( i<nArg-1 ){
18445: utf8_printf(p->out, "%s", p->colSeparator);
18446: }else{
18447: utf8_printf(p->out, "%s", p->rowSeparator);
18448: }
18449: }
18450: break;
18451: }
18452: case MODE_Html: {
18453: if( p->cnt++==0 && p->showHeader ){
18454: raw_printf(p->out,"<TR>");
18455: for(i=0; i<nArg; i++){
18456: raw_printf(p->out,"<TH>");
18457: output_html_string(p->out, azCol[i]);
18458: raw_printf(p->out,"</TH>\n");
18459: }
18460: raw_printf(p->out,"</TR>\n");
18461: }
18462: if( azArg==0 ) break;
18463: raw_printf(p->out,"<TR>");
18464: for(i=0; i<nArg; i++){
18465: raw_printf(p->out,"<TD>");
18466: output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
18467: raw_printf(p->out,"</TD>\n");
18468: }
18469: raw_printf(p->out,"</TR>\n");
18470: break;
18471: }
18472: case MODE_Tcl: {
18473: if( p->cnt++==0 && p->showHeader ){
18474: for(i=0; i<nArg; i++){
18475: output_c_string(p->out,azCol[i] ? azCol[i] : "");
18476: if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
18477: }
18478: utf8_printf(p->out, "%s", p->rowSeparator);
18479: }
18480: if( azArg==0 ) break;
18481: for(i=0; i<nArg; i++){
18482: output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
18483: if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
18484: }
18485: utf8_printf(p->out, "%s", p->rowSeparator);
18486: break;
18487: }
18488: case MODE_Csv: {
18489: setBinaryMode(p->out, 1);
18490: if( p->cnt++==0 && p->showHeader ){
18491: for(i=0; i<nArg; i++){
18492: output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
18493: }
18494: utf8_printf(p->out, "%s", p->rowSeparator);
18495: }
18496: if( nArg>0 ){
18497: for(i=0; i<nArg; i++){
18498: output_csv(p, azArg[i], i<nArg-1);
18499: }
18500: utf8_printf(p->out, "%s", p->rowSeparator);
18501: }
18502: setTextMode(p->out, 1);
18503: break;
18504: }
18505: case MODE_Insert: {
18506: if( azArg==0 ) break;
18507: utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
18508: if( p->showHeader ){
18509: raw_printf(p->out,"(");
18510: for(i=0; i<nArg; i++){
18511: if( i>0 ) raw_printf(p->out, ",");
18512: if( quoteChar(azCol[i]) ){
18513: char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
1.6.2.1 ! misho 18514: shell_check_oom(z);
1.5 misho 18515: utf8_printf(p->out, "%s", z);
18516: sqlite3_free(z);
18517: }else{
18518: raw_printf(p->out, "%s", azCol[i]);
18519: }
18520: }
18521: raw_printf(p->out,")");
18522: }
18523: p->cnt++;
18524: for(i=0; i<nArg; i++){
18525: raw_printf(p->out, i>0 ? "," : " VALUES(");
18526: if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
18527: utf8_printf(p->out,"NULL");
18528: }else if( aiType && aiType[i]==SQLITE_TEXT ){
18529: if( ShellHasFlag(p, SHFLG_Newlines) ){
18530: output_quoted_string(p->out, azArg[i]);
18531: }else{
18532: output_quoted_escaped_string(p->out, azArg[i]);
18533: }
18534: }else if( aiType && aiType[i]==SQLITE_INTEGER ){
18535: utf8_printf(p->out,"%s", azArg[i]);
18536: }else if( aiType && aiType[i]==SQLITE_FLOAT ){
18537: char z[50];
18538: double r = sqlite3_column_double(p->pStmt, i);
18539: sqlite3_uint64 ur;
18540: memcpy(&ur,&r,sizeof(r));
18541: if( ur==0x7ff0000000000000LL ){
1.6.2.1 ! misho 18542: raw_printf(p->out, "9.0e+999");
1.5 misho 18543: }else if( ur==0xfff0000000000000LL ){
1.6.2.1 ! misho 18544: raw_printf(p->out, "-9.0e+999");
1.5 misho 18545: }else{
1.6.2.1 ! misho 18546: sqlite3_int64 ir = (sqlite3_int64)r;
! 18547: if( r==(double)ir ){
! 18548: sqlite3_snprintf(50,z,"%lld.0", ir);
! 18549: }else{
! 18550: sqlite3_snprintf(50,z,"%!.20g", r);
! 18551: }
1.5 misho 18552: raw_printf(p->out, "%s", z);
18553: }
18554: }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
18555: const void *pBlob = sqlite3_column_blob(p->pStmt, i);
18556: int nBlob = sqlite3_column_bytes(p->pStmt, i);
18557: output_hex_blob(p->out, pBlob, nBlob);
18558: }else if( isNumber(azArg[i], 0) ){
18559: utf8_printf(p->out,"%s", azArg[i]);
18560: }else if( ShellHasFlag(p, SHFLG_Newlines) ){
18561: output_quoted_string(p->out, azArg[i]);
18562: }else{
18563: output_quoted_escaped_string(p->out, azArg[i]);
18564: }
18565: }
18566: raw_printf(p->out,");\n");
18567: break;
18568: }
18569: case MODE_Json: {
18570: if( azArg==0 ) break;
18571: if( p->cnt==0 ){
18572: fputs("[{", p->out);
18573: }else{
18574: fputs(",\n{", p->out);
18575: }
18576: p->cnt++;
18577: for(i=0; i<nArg; i++){
18578: output_json_string(p->out, azCol[i], -1);
18579: putc(':', p->out);
18580: if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
18581: fputs("null",p->out);
18582: }else if( aiType && aiType[i]==SQLITE_FLOAT ){
18583: char z[50];
18584: double r = sqlite3_column_double(p->pStmt, i);
18585: sqlite3_uint64 ur;
18586: memcpy(&ur,&r,sizeof(r));
18587: if( ur==0x7ff0000000000000LL ){
1.6.2.1 ! misho 18588: raw_printf(p->out, "9.0e+999");
1.5 misho 18589: }else if( ur==0xfff0000000000000LL ){
1.6.2.1 ! misho 18590: raw_printf(p->out, "-9.0e+999");
1.5 misho 18591: }else{
18592: sqlite3_snprintf(50,z,"%!.20g", r);
18593: raw_printf(p->out, "%s", z);
18594: }
18595: }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
18596: const void *pBlob = sqlite3_column_blob(p->pStmt, i);
18597: int nBlob = sqlite3_column_bytes(p->pStmt, i);
18598: output_json_string(p->out, pBlob, nBlob);
18599: }else if( aiType && aiType[i]==SQLITE_TEXT ){
18600: output_json_string(p->out, azArg[i], -1);
18601: }else{
18602: utf8_printf(p->out,"%s", azArg[i]);
18603: }
18604: if( i<nArg-1 ){
18605: putc(',', p->out);
18606: }
18607: }
18608: putc('}', p->out);
18609: break;
18610: }
18611: case MODE_Quote: {
18612: if( azArg==0 ) break;
18613: if( p->cnt==0 && p->showHeader ){
18614: for(i=0; i<nArg; i++){
18615: if( i>0 ) fputs(p->colSeparator, p->out);
18616: output_quoted_string(p->out, azCol[i]);
18617: }
18618: fputs(p->rowSeparator, p->out);
18619: }
18620: p->cnt++;
18621: for(i=0; i<nArg; i++){
18622: if( i>0 ) fputs(p->colSeparator, p->out);
18623: if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
18624: utf8_printf(p->out,"NULL");
18625: }else if( aiType && aiType[i]==SQLITE_TEXT ){
18626: output_quoted_string(p->out, azArg[i]);
18627: }else if( aiType && aiType[i]==SQLITE_INTEGER ){
18628: utf8_printf(p->out,"%s", azArg[i]);
18629: }else if( aiType && aiType[i]==SQLITE_FLOAT ){
18630: char z[50];
18631: double r = sqlite3_column_double(p->pStmt, i);
18632: sqlite3_snprintf(50,z,"%!.20g", r);
18633: raw_printf(p->out, "%s", z);
18634: }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
18635: const void *pBlob = sqlite3_column_blob(p->pStmt, i);
18636: int nBlob = sqlite3_column_bytes(p->pStmt, i);
18637: output_hex_blob(p->out, pBlob, nBlob);
18638: }else if( isNumber(azArg[i], 0) ){
18639: utf8_printf(p->out,"%s", azArg[i]);
18640: }else{
18641: output_quoted_string(p->out, azArg[i]);
18642: }
18643: }
18644: fputs(p->rowSeparator, p->out);
18645: break;
18646: }
18647: case MODE_Ascii: {
18648: if( p->cnt++==0 && p->showHeader ){
18649: for(i=0; i<nArg; i++){
18650: if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
18651: utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
18652: }
18653: utf8_printf(p->out, "%s", p->rowSeparator);
18654: }
18655: if( azArg==0 ) break;
18656: for(i=0; i<nArg; i++){
18657: if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
18658: utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
18659: }
18660: utf8_printf(p->out, "%s", p->rowSeparator);
18661: break;
18662: }
18663: case MODE_EQP: {
18664: eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]);
18665: break;
18666: }
18667: }
18668: return 0;
18669: }
18670:
18671: /*
18672: ** This is the callback routine that the SQLite library
18673: ** invokes for each row of a query result.
18674: */
18675: static int callback(void *pArg, int nArg, char **azArg, char **azCol){
18676: /* since we don't have type info, call the shell_callback with a NULL value */
18677: return shell_callback(pArg, nArg, azArg, azCol, NULL);
18678: }
18679:
18680: /*
18681: ** This is the callback routine from sqlite3_exec() that appends all
18682: ** output onto the end of a ShellText object.
18683: */
18684: static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
18685: ShellText *p = (ShellText*)pArg;
18686: int i;
18687: UNUSED_PARAMETER(az);
18688: if( azArg==0 ) return 0;
18689: if( p->n ) appendText(p, "|", 0);
18690: for(i=0; i<nArg; i++){
18691: if( i ) appendText(p, ",", 0);
18692: if( azArg[i] ) appendText(p, azArg[i], 0);
18693: }
18694: return 0;
18695: }
18696:
18697: /*
18698: ** Generate an appropriate SELFTEST table in the main database.
18699: */
18700: static void createSelftestTable(ShellState *p){
18701: char *zErrMsg = 0;
18702: sqlite3_exec(p->db,
18703: "SAVEPOINT selftest_init;\n"
18704: "CREATE TABLE IF NOT EXISTS selftest(\n"
18705: " tno INTEGER PRIMARY KEY,\n" /* Test number */
18706: " op TEXT,\n" /* Operator: memo run */
18707: " cmd TEXT,\n" /* Command text */
18708: " ans TEXT\n" /* Desired answer */
18709: ");"
18710: "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n"
18711: "INSERT INTO [_shell$self](rowid,op,cmd)\n"
18712: " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n"
18713: " 'memo','Tests generated by --init');\n"
18714: "INSERT INTO [_shell$self]\n"
18715: " SELECT 'run',\n"
18716: " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql "
18717: "FROM sqlite_schema ORDER BY 2'',224))',\n"
18718: " hex(sha3_query('SELECT type,name,tbl_name,sql "
18719: "FROM sqlite_schema ORDER BY 2',224));\n"
18720: "INSERT INTO [_shell$self]\n"
18721: " SELECT 'run',"
18722: " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||"
18723: " printf('%w',name) || '\" NOT INDEXED'',224))',\n"
18724: " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"
18725: " FROM (\n"
18726: " SELECT name FROM sqlite_schema\n"
18727: " WHERE type='table'\n"
18728: " AND name<>'selftest'\n"
18729: " AND coalesce(rootpage,0)>0\n"
18730: " )\n"
18731: " ORDER BY name;\n"
18732: "INSERT INTO [_shell$self]\n"
18733: " VALUES('run','PRAGMA integrity_check','ok');\n"
18734: "INSERT INTO selftest(tno,op,cmd,ans)"
18735: " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n"
18736: "DROP TABLE [_shell$self];"
18737: ,0,0,&zErrMsg);
18738: if( zErrMsg ){
18739: utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
18740: sqlite3_free(zErrMsg);
18741: }
18742: sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
18743: }
18744:
18745:
18746: /*
18747: ** Set the destination table field of the ShellState structure to
18748: ** the name of the table given. Escape any quote characters in the
18749: ** table name.
18750: */
18751: static void set_table_name(ShellState *p, const char *zName){
18752: int i, n;
18753: char cQuote;
18754: char *z;
18755:
18756: if( p->zDestTable ){
18757: free(p->zDestTable);
18758: p->zDestTable = 0;
18759: }
18760: if( zName==0 ) return;
18761: cQuote = quoteChar(zName);
18762: n = strlen30(zName);
18763: if( cQuote ) n += n+2;
18764: z = p->zDestTable = malloc( n+1 );
1.6.2.1 ! misho 18765: shell_check_oom(z);
1.5 misho 18766: n = 0;
18767: if( cQuote ) z[n++] = cQuote;
18768: for(i=0; zName[i]; i++){
18769: z[n++] = zName[i];
18770: if( zName[i]==cQuote ) z[n++] = cQuote;
18771: }
18772: if( cQuote ) z[n++] = cQuote;
18773: z[n] = 0;
18774: }
18775:
1.6.2.1 ! misho 18776: /*
! 18777: ** Maybe construct two lines of text that point out the position of a
! 18778: ** syntax error. Return a pointer to the text, in memory obtained from
! 18779: ** sqlite3_malloc(). Or, if the most recent error does not involve a
! 18780: ** specific token that we can point to, return an empty string.
! 18781: **
! 18782: ** In all cases, the memory returned is obtained from sqlite3_malloc64()
! 18783: ** and should be released by the caller invoking sqlite3_free().
! 18784: */
! 18785: static char *shell_error_context(const char *zSql, sqlite3 *db){
! 18786: int iOffset;
! 18787: size_t len;
! 18788: char *zCode;
! 18789: char *zMsg;
! 18790: int i;
! 18791: if( db==0
! 18792: || zSql==0
! 18793: || (iOffset = sqlite3_error_offset(db))<0
! 18794: || iOffset>=(int)strlen(zSql)
! 18795: ){
! 18796: return sqlite3_mprintf("");
! 18797: }
! 18798: while( iOffset>50 ){
! 18799: iOffset--;
! 18800: zSql++;
! 18801: while( (zSql[0]&0xc0)==0x80 ){ zSql++; iOffset--; }
! 18802: }
! 18803: len = strlen(zSql);
! 18804: if( len>78 ){
! 18805: len = 78;
! 18806: while( len>0 && (zSql[len]&0xc0)==0x80 ) len--;
! 18807: }
! 18808: zCode = sqlite3_mprintf("%.*s", len, zSql);
! 18809: shell_check_oom(zCode);
! 18810: for(i=0; zCode[i]; i++){ if( IsSpace(zSql[i]) ) zCode[i] = ' '; }
! 18811: if( iOffset<25 ){
! 18812: zMsg = sqlite3_mprintf("\n %z\n %*s^--- error here", zCode,iOffset,"");
! 18813: }else{
! 18814: zMsg = sqlite3_mprintf("\n %z\n %*serror here ---^", zCode,iOffset-14,"");
! 18815: }
! 18816: return zMsg;
! 18817: }
! 18818:
1.5 misho 18819:
18820: /*
18821: ** Execute a query statement that will generate SQL output. Print
18822: ** the result columns, comma-separated, on a line and then add a
18823: ** semicolon terminator to the end of that line.
18824: **
18825: ** If the number of columns is 1 and that column contains text "--"
18826: ** then write the semicolon on a separate line. That way, if a
18827: ** "--" comment occurs at the end of the statement, the comment
18828: ** won't consume the semicolon terminator.
18829: */
18830: static int run_table_dump_query(
18831: ShellState *p, /* Query context */
18832: const char *zSelect /* SELECT statement to extract content */
18833: ){
18834: sqlite3_stmt *pSelect;
18835: int rc;
18836: int nResult;
18837: int i;
18838: const char *z;
18839: rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
18840: if( rc!=SQLITE_OK || !pSelect ){
1.6.2.1 ! misho 18841: char *zContext = shell_error_context(zSelect, p->db);
! 18842: utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n%s", rc,
! 18843: sqlite3_errmsg(p->db), zContext);
! 18844: sqlite3_free(zContext);
1.5 misho 18845: if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
18846: return rc;
18847: }
18848: rc = sqlite3_step(pSelect);
18849: nResult = sqlite3_column_count(pSelect);
18850: while( rc==SQLITE_ROW ){
18851: z = (const char*)sqlite3_column_text(pSelect, 0);
18852: utf8_printf(p->out, "%s", z);
18853: for(i=1; i<nResult; i++){
18854: utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
18855: }
18856: if( z==0 ) z = "";
18857: while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
18858: if( z[0] ){
18859: raw_printf(p->out, "\n;\n");
18860: }else{
18861: raw_printf(p->out, ";\n");
18862: }
18863: rc = sqlite3_step(pSelect);
18864: }
18865: rc = sqlite3_finalize(pSelect);
18866: if( rc!=SQLITE_OK ){
18867: utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
18868: sqlite3_errmsg(p->db));
18869: if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
18870: }
18871: return rc;
18872: }
18873:
18874: /*
1.6.2.1 ! misho 18875: ** Allocate space and save off string indicating current error.
1.5 misho 18876: */
18877: static char *save_err_msg(
1.6.2.1 ! misho 18878: sqlite3 *db, /* Database to query */
! 18879: const char *zPhase, /* When the error occurs */
! 18880: int rc, /* Error code returned from API */
! 18881: const char *zSql /* SQL string, or NULL */
! 18882: ){
! 18883: char *zErr;
! 18884: char *zContext;
! 18885: sqlite3_str *pStr = sqlite3_str_new(0);
! 18886: sqlite3_str_appendf(pStr, "%s, %s", zPhase, sqlite3_errmsg(db));
! 18887: if( rc>1 ){
! 18888: sqlite3_str_appendf(pStr, " (%d)", rc);
! 18889: }
! 18890: zContext = shell_error_context(zSql, db);
! 18891: if( zContext ){
! 18892: sqlite3_str_appendall(pStr, zContext);
! 18893: sqlite3_free(zContext);
! 18894: }
! 18895: zErr = sqlite3_str_finish(pStr);
! 18896: shell_check_oom(zErr);
! 18897: return zErr;
1.5 misho 18898: }
18899:
18900: #ifdef __linux__
18901: /*
18902: ** Attempt to display I/O stats on Linux using /proc/PID/io
18903: */
18904: static void displayLinuxIoStats(FILE *out){
18905: FILE *in;
18906: char z[200];
18907: sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
18908: in = fopen(z, "rb");
18909: if( in==0 ) return;
18910: while( fgets(z, sizeof(z), in)!=0 ){
18911: static const struct {
18912: const char *zPattern;
18913: const char *zDesc;
18914: } aTrans[] = {
18915: { "rchar: ", "Bytes received by read():" },
18916: { "wchar: ", "Bytes sent to write():" },
18917: { "syscr: ", "Read() system calls:" },
18918: { "syscw: ", "Write() system calls:" },
18919: { "read_bytes: ", "Bytes read from storage:" },
18920: { "write_bytes: ", "Bytes written to storage:" },
18921: { "cancelled_write_bytes: ", "Cancelled write bytes:" },
18922: };
18923: int i;
18924: for(i=0; i<ArraySize(aTrans); i++){
18925: int n = strlen30(aTrans[i].zPattern);
1.6.2.1 ! misho 18926: if( cli_strncmp(aTrans[i].zPattern, z, n)==0 ){
1.5 misho 18927: utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
18928: break;
18929: }
18930: }
18931: }
18932: fclose(in);
18933: }
18934: #endif
18935:
18936: /*
18937: ** Display a single line of status using 64-bit values.
18938: */
18939: static void displayStatLine(
18940: ShellState *p, /* The shell context */
18941: char *zLabel, /* Label for this one line */
18942: char *zFormat, /* Format for the result */
18943: int iStatusCtrl, /* Which status to display */
18944: int bReset /* True to reset the stats */
18945: ){
18946: sqlite3_int64 iCur = -1;
18947: sqlite3_int64 iHiwtr = -1;
18948: int i, nPercent;
18949: char zLine[200];
18950: sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset);
18951: for(i=0, nPercent=0; zFormat[i]; i++){
18952: if( zFormat[i]=='%' ) nPercent++;
18953: }
18954: if( nPercent>1 ){
18955: sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr);
18956: }else{
18957: sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
18958: }
18959: raw_printf(p->out, "%-36s %s\n", zLabel, zLine);
18960: }
18961:
18962: /*
18963: ** Display memory stats.
18964: */
18965: static int display_stats(
18966: sqlite3 *db, /* Database to query */
18967: ShellState *pArg, /* Pointer to ShellState */
18968: int bReset /* True to reset the stats */
18969: ){
18970: int iCur;
18971: int iHiwtr;
18972: FILE *out;
18973: if( pArg==0 || pArg->out==0 ) return 0;
18974: out = pArg->out;
18975:
1.6 misho 18976: if( pArg->pStmt && pArg->statsOn==2 ){
1.5 misho 18977: int nCol, i, x;
18978: sqlite3_stmt *pStmt = pArg->pStmt;
18979: char z[100];
18980: nCol = sqlite3_column_count(pStmt);
18981: raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
18982: for(i=0; i<nCol; i++){
18983: sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
18984: utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
18985: #ifndef SQLITE_OMIT_DECLTYPE
18986: sqlite3_snprintf(30, z+x, "declared type:");
18987: utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
18988: #endif
18989: #ifdef SQLITE_ENABLE_COLUMN_METADATA
18990: sqlite3_snprintf(30, z+x, "database name:");
18991: utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
18992: sqlite3_snprintf(30, z+x, "table name:");
18993: utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
18994: sqlite3_snprintf(30, z+x, "origin name:");
18995: utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
18996: #endif
18997: }
18998: }
18999:
1.6 misho 19000: if( pArg->statsOn==3 ){
19001: if( pArg->pStmt ){
1.6.2.1 ! misho 19002: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP,bReset);
1.6 misho 19003: raw_printf(pArg->out, "VM-steps: %d\n", iCur);
19004: }
19005: return 0;
19006: }
19007:
1.5 misho 19008: displayStatLine(pArg, "Memory Used:",
19009: "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
19010: displayStatLine(pArg, "Number of Outstanding Allocations:",
19011: "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
19012: if( pArg->shellFlgs & SHFLG_Pagecache ){
19013: displayStatLine(pArg, "Number of Pcache Pages Used:",
19014: "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
19015: }
19016: displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
19017: "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
19018: displayStatLine(pArg, "Largest Allocation:",
19019: "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
19020: displayStatLine(pArg, "Largest Pcache Allocation:",
19021: "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
19022: #ifdef YYTRACKMAXSTACKDEPTH
19023: displayStatLine(pArg, "Deepest Parser Stack:",
19024: "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
19025: #endif
19026:
19027: if( db ){
19028: if( pArg->shellFlgs & SHFLG_Lookaside ){
19029: iHiwtr = iCur = -1;
19030: sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
19031: &iCur, &iHiwtr, bReset);
19032: raw_printf(pArg->out,
19033: "Lookaside Slots Used: %d (max %d)\n",
19034: iCur, iHiwtr);
19035: sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
19036: &iCur, &iHiwtr, bReset);
19037: raw_printf(pArg->out, "Successful lookaside attempts: %d\n",
19038: iHiwtr);
19039: sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
19040: &iCur, &iHiwtr, bReset);
19041: raw_printf(pArg->out, "Lookaside failures due to size: %d\n",
19042: iHiwtr);
19043: sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
19044: &iCur, &iHiwtr, bReset);
19045: raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n",
19046: iHiwtr);
19047: }
19048: iHiwtr = iCur = -1;
19049: sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
19050: raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n",
19051: iCur);
19052: iHiwtr = iCur = -1;
19053: sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
19054: raw_printf(pArg->out, "Page cache hits: %d\n", iCur);
19055: iHiwtr = iCur = -1;
19056: sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
19057: raw_printf(pArg->out, "Page cache misses: %d\n", iCur);
19058: iHiwtr = iCur = -1;
19059: sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
19060: raw_printf(pArg->out, "Page cache writes: %d\n", iCur);
19061: iHiwtr = iCur = -1;
19062: sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
19063: raw_printf(pArg->out, "Page cache spills: %d\n", iCur);
19064: iHiwtr = iCur = -1;
19065: sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
19066: raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n",
19067: iCur);
19068: iHiwtr = iCur = -1;
19069: sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
19070: raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
19071: iCur);
19072: }
19073:
19074: if( pArg->pStmt ){
1.6.2.1 ! misho 19075: int iHit, iMiss;
1.5 misho 19076: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
19077: bReset);
19078: raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
19079: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
19080: raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
19081: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
19082: raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
1.6.2.1 ! misho 19083: iHit = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_HIT,
! 19084: bReset);
! 19085: iMiss = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_MISS,
! 19086: bReset);
! 19087: if( iHit || iMiss ){
! 19088: raw_printf(pArg->out, "Bloom filter bypass taken: %d/%d\n",
! 19089: iHit, iHit+iMiss);
! 19090: }
1.5 misho 19091: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
19092: raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
19093: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
19094: raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
19095: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
19096: raw_printf(pArg->out, "Number of times run: %d\n", iCur);
19097: iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
19098: raw_printf(pArg->out, "Memory used by prepared stmt: %d\n", iCur);
19099: }
19100:
19101: #ifdef __linux__
19102: displayLinuxIoStats(pArg->out);
19103: #endif
19104:
19105: /* Do not remove this machine readable comment: extra-stats-output-here */
19106:
19107: return 0;
19108: }
19109:
1.6.2.1 ! misho 19110:
! 19111: #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
! 19112: static int scanStatsHeight(sqlite3_stmt *p, int iEntry){
! 19113: int iPid = 0;
! 19114: int ret = 1;
! 19115: sqlite3_stmt_scanstatus_v2(p, iEntry,
! 19116: SQLITE_SCANSTAT_SELECTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iPid
! 19117: );
! 19118: while( iPid!=0 ){
! 19119: int ii;
! 19120: for(ii=0; 1; ii++){
! 19121: int iId;
! 19122: int res;
! 19123: res = sqlite3_stmt_scanstatus_v2(p, ii,
! 19124: SQLITE_SCANSTAT_SELECTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iId
! 19125: );
! 19126: if( res ) break;
! 19127: if( iId==iPid ){
! 19128: sqlite3_stmt_scanstatus_v2(p, ii,
! 19129: SQLITE_SCANSTAT_PARENTID, SQLITE_SCANSTAT_COMPLEX, (void*)&iPid
! 19130: );
! 19131: }
! 19132: }
! 19133: ret++;
! 19134: }
! 19135: return ret;
! 19136: }
! 19137: #endif
! 19138:
! 19139: #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
! 19140: static void display_explain_scanstats(
1.5 misho 19141: sqlite3 *db, /* Database to query */
19142: ShellState *pArg /* Pointer to ShellState */
19143: ){
1.6.2.1 ! misho 19144: static const int f = SQLITE_SCANSTAT_COMPLEX;
! 19145: sqlite3_stmt *p = pArg->pStmt;
! 19146: int ii = 0;
! 19147: i64 nTotal = 0;
! 19148: int nWidth = 0;
! 19149: eqp_reset(pArg);
! 19150:
! 19151: for(ii=0; 1; ii++){
! 19152: const char *z = 0;
! 19153: int n = 0;
! 19154: if( sqlite3_stmt_scanstatus_v2(p,ii,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&z) ){
! 19155: break;
! 19156: }
! 19157: n = strlen(z) + scanStatsHeight(p, ii)*3;
! 19158: if( n>nWidth ) nWidth = n;
! 19159: }
! 19160: nWidth += 4;
! 19161:
! 19162: sqlite3_stmt_scanstatus_v2(p, -1, SQLITE_SCANSTAT_NCYCLE, f, (void*)&nTotal);
! 19163: for(ii=0; 1; ii++){
! 19164: i64 nLoop = 0;
! 19165: i64 nRow = 0;
! 19166: i64 nCycle = 0;
! 19167: int iId = 0;
! 19168: int iPid = 0;
! 19169: const char *z = 0;
! 19170: const char *zName = 0;
! 19171: char *zText = 0;
! 19172: double rEst = 0.0;
! 19173:
! 19174: if( sqlite3_stmt_scanstatus_v2(p,ii,SQLITE_SCANSTAT_EXPLAIN,f,(void*)&z) ){
! 19175: break;
! 19176: }
! 19177: sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_EST,f,(void*)&rEst);
! 19178: sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_NLOOP,f,(void*)&nLoop);
! 19179: sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_NVISIT,f,(void*)&nRow);
! 19180: sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_NCYCLE,f,(void*)&nCycle);
! 19181: sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_SELECTID,f,(void*)&iId);
! 19182: sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_PARENTID,f,(void*)&iPid);
! 19183: sqlite3_stmt_scanstatus_v2(p, ii, SQLITE_SCANSTAT_NAME,f,(void*)&zName);
! 19184:
! 19185: zText = sqlite3_mprintf("%s", z);
! 19186: if( nCycle>=0 || nLoop>=0 || nRow>=0 ){
! 19187: char *z = 0;
! 19188: if( nCycle>=0 && nTotal>0 ){
! 19189: z = sqlite3_mprintf("%zcycles=%lld [%d%%]", z,
! 19190: nCycle, ((nCycle*100)+nTotal/2) / nTotal
! 19191: );
1.5 misho 19192: }
1.6.2.1 ! misho 19193: if( nLoop>=0 ){
! 19194: z = sqlite3_mprintf("%z%sloops=%lld", z, z ? " " : "", nLoop);
1.5 misho 19195: }
1.6.2.1 ! misho 19196: if( nRow>=0 ){
! 19197: z = sqlite3_mprintf("%z%srows=%lld", z, z ? " " : "", nRow);
! 19198: }
! 19199:
! 19200: if( zName && pArg->scanstatsOn>1 ){
! 19201: double rpl = (double)nRow / (double)nLoop;
! 19202: z = sqlite3_mprintf("%z rpl=%.1f est=%.1f", z, rpl, rEst);
! 19203: }
! 19204:
! 19205: zText = sqlite3_mprintf(
! 19206: "% *z (%z)", -1*(nWidth-scanStatsHeight(p, ii)*3), zText, z
1.5 misho 19207: );
19208: }
1.6.2.1 ! misho 19209:
! 19210: eqp_append(pArg, iId, iPid, zText);
! 19211: sqlite3_free(zText);
1.5 misho 19212: }
1.6.2.1 ! misho 19213:
! 19214: eqp_render(pArg, nTotal);
1.5 misho 19215: }
1.6.2.1 ! misho 19216: #endif
! 19217:
1.5 misho 19218:
19219: /*
19220: ** Parameter azArray points to a zero-terminated array of strings. zStr
19221: ** points to a single nul-terminated string. Return non-zero if zStr
19222: ** is equal, according to strcmp(), to any of the strings in the array.
19223: ** Otherwise, return zero.
19224: */
19225: static int str_in_array(const char *zStr, const char **azArray){
19226: int i;
19227: for(i=0; azArray[i]; i++){
1.6.2.1 ! misho 19228: if( 0==cli_strcmp(zStr, azArray[i]) ) return 1;
1.5 misho 19229: }
19230: return 0;
19231: }
19232:
19233: /*
19234: ** If compiled statement pSql appears to be an EXPLAIN statement, allocate
19235: ** and populate the ShellState.aiIndent[] array with the number of
19236: ** spaces each opcode should be indented before it is output.
19237: **
19238: ** The indenting rules are:
19239: **
19240: ** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
19241: ** all opcodes that occur between the p2 jump destination and the opcode
19242: ** itself by 2 spaces.
19243: **
1.6.2.1 ! misho 19244: ** * Do the previous for "Return" instructions for when P2 is positive.
! 19245: ** See tag-20220407a in wherecode.c and vdbe.c.
! 19246: **
1.5 misho 19247: ** * For each "Goto", if the jump destination is earlier in the program
19248: ** and ends on one of:
19249: ** Yield SeekGt SeekLt RowSetRead Rewind
19250: ** or if the P1 parameter is one instead of zero,
19251: ** then indent all opcodes between the earlier instruction
19252: ** and "Goto" by 2 spaces.
19253: */
19254: static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
19255: int *abYield = 0; /* True if op is an OP_Yield */
19256: int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
19257: int iOp; /* Index of operation in p->aiIndent[] */
19258:
1.6.2.1 ! misho 19259: const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",
! 19260: "Return", 0 };
1.5 misho 19261: const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
19262: "Rewind", 0 };
19263: const char *azGoto[] = { "Goto", 0 };
19264:
1.6.2.1 ! misho 19265: /* The caller guarantees that the leftmost 4 columns of the statement
! 19266: ** passed to this function are equivalent to the leftmost 4 columns
! 19267: ** of EXPLAIN statement output. In practice the statement may be
! 19268: ** an EXPLAIN, or it may be a query on the bytecode() virtual table. */
! 19269: assert( sqlite3_column_count(pSql)>=4 );
! 19270: assert( 0==sqlite3_stricmp( sqlite3_column_name(pSql, 0), "addr" ) );
! 19271: assert( 0==sqlite3_stricmp( sqlite3_column_name(pSql, 1), "opcode" ) );
! 19272: assert( 0==sqlite3_stricmp( sqlite3_column_name(pSql, 2), "p1" ) );
! 19273: assert( 0==sqlite3_stricmp( sqlite3_column_name(pSql, 3), "p2" ) );
1.5 misho 19274:
19275: for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
19276: int i;
19277: int iAddr = sqlite3_column_int(pSql, 0);
19278: const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
1.6.2.1 ! misho 19279: int p1 = sqlite3_column_int(pSql, 2);
1.5 misho 19280: int p2 = sqlite3_column_int(pSql, 3);
1.6.2.1 ! misho 19281:
! 19282: /* Assuming that p2 is an instruction address, set variable p2op to the
! 19283: ** index of that instruction in the aiIndent[] array. p2 and p2op may be
! 19284: ** different if the current instruction is part of a sub-program generated
! 19285: ** by an SQL trigger or foreign key. */
1.5 misho 19286: int p2op = (p2 + (iOp-iAddr));
19287:
19288: /* Grow the p->aiIndent array as required */
19289: if( iOp>=nAlloc ){
19290: nAlloc += 100;
19291: p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
1.6.2.1 ! misho 19292: shell_check_oom(p->aiIndent);
1.5 misho 19293: abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
1.6.2.1 ! misho 19294: shell_check_oom(abYield);
1.5 misho 19295: }
1.6.2.1 ! misho 19296:
1.5 misho 19297: abYield[iOp] = str_in_array(zOp, azYield);
19298: p->aiIndent[iOp] = 0;
19299: p->nIndent = iOp+1;
1.6.2.1 ! misho 19300: if( str_in_array(zOp, azNext) && p2op>0 ){
1.5 misho 19301: for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
19302: }
1.6.2.1 ! misho 19303: if( str_in_array(zOp, azGoto) && p2op<iOp && (abYield[p2op] || p1) ){
1.5 misho 19304: for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
19305: }
19306: }
19307:
19308: p->iIndent = 0;
19309: sqlite3_free(abYield);
19310: sqlite3_reset(pSql);
19311: }
19312:
19313: /*
19314: ** Free the array allocated by explain_data_prepare().
19315: */
19316: static void explain_data_delete(ShellState *p){
19317: sqlite3_free(p->aiIndent);
19318: p->aiIndent = 0;
19319: p->nIndent = 0;
19320: p->iIndent = 0;
19321: }
19322:
1.6.2.1 ! misho 19323: static void exec_prepared_stmt(ShellState*, sqlite3_stmt*);
! 19324:
! 19325: /*
! 19326: ** Display scan stats.
! 19327: */
! 19328: static void display_scanstats(
! 19329: sqlite3 *db, /* Database to query */
! 19330: ShellState *pArg /* Pointer to ShellState */
! 19331: ){
! 19332: #ifndef SQLITE_ENABLE_STMT_SCANSTATUS
! 19333: UNUSED_PARAMETER(db);
! 19334: UNUSED_PARAMETER(pArg);
! 19335: #else
! 19336: if( pArg->scanstatsOn==3 ){
! 19337: const char *zSql =
! 19338: " SELECT addr, opcode, p1, p2, p3, p4, p5, comment, nexec,"
! 19339: " round(ncycle*100.0 / (sum(ncycle) OVER ()), 2)||'%' AS cycles"
! 19340: " FROM bytecode(?)";
! 19341:
! 19342: int rc = SQLITE_OK;
! 19343: sqlite3_stmt *pStmt = 0;
! 19344: rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
! 19345: if( rc==SQLITE_OK ){
! 19346: sqlite3_stmt *pSave = pArg->pStmt;
! 19347: pArg->pStmt = pStmt;
! 19348: sqlite3_bind_pointer(pStmt, 1, pSave, "stmt-pointer", 0);
! 19349:
! 19350: pArg->cnt = 0;
! 19351: pArg->cMode = MODE_ScanExp;
! 19352: explain_data_prepare(pArg, pStmt);
! 19353: exec_prepared_stmt(pArg, pStmt);
! 19354: explain_data_delete(pArg);
! 19355:
! 19356: sqlite3_finalize(pStmt);
! 19357: pArg->pStmt = pSave;
! 19358: }
! 19359: }else{
! 19360: display_explain_scanstats(db, pArg);
! 19361: }
! 19362: #endif
! 19363: }
! 19364:
1.5 misho 19365: /*
1.6.2.1 ! misho 19366: ** Disable and restore .wheretrace and .treetrace/.selecttrace settings.
1.5 misho 19367: */
1.6 misho 19368: static unsigned int savedSelectTrace;
19369: static unsigned int savedWhereTrace;
1.5 misho 19370: static void disable_debug_trace_modes(void){
1.6 misho 19371: unsigned int zero = 0;
19372: sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace);
19373: sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero);
19374: sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace);
19375: sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero);
1.5 misho 19376: }
19377: static void restore_debug_trace_modes(void){
1.6 misho 19378: sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &savedSelectTrace);
19379: sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &savedWhereTrace);
1.5 misho 19380: }
19381:
19382: /* Create the TEMP table used to store parameter bindings */
19383: static void bind_table_init(ShellState *p){
19384: int wrSchema = 0;
19385: int defensiveMode = 0;
19386: sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
19387: sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
19388: sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
19389: sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
19390: sqlite3_exec(p->db,
19391: "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
19392: " key TEXT PRIMARY KEY,\n"
1.6.2.1 ! misho 19393: " value\n"
1.5 misho 19394: ") WITHOUT ROWID;",
19395: 0, 0, 0);
19396: sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
19397: sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0);
19398: }
19399:
19400: /*
19401: ** Bind parameters on a prepared statement.
19402: **
19403: ** Parameter bindings are taken from a TEMP table of the form:
19404: **
19405: ** CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
19406: ** WITHOUT ROWID;
19407: **
19408: ** No bindings occur if this table does not exist. The name of the table
19409: ** begins with "sqlite_" so that it will not collide with ordinary application
19410: ** tables. The table must be in the TEMP schema.
19411: */
19412: static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
19413: int nVar;
19414: int i;
19415: int rc;
19416: sqlite3_stmt *pQ = 0;
19417:
19418: nVar = sqlite3_bind_parameter_count(pStmt);
19419: if( nVar==0 ) return; /* Nothing to do */
19420: if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters",
19421: "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
1.6.2.1 ! misho 19422: rc = SQLITE_NOTFOUND;
! 19423: pQ = 0;
! 19424: }else{
! 19425: rc = sqlite3_prepare_v2(pArg->db,
! 19426: "SELECT value FROM temp.sqlite_parameters"
! 19427: " WHERE key=?1", -1, &pQ, 0);
1.5 misho 19428: }
19429: for(i=1; i<=nVar; i++){
19430: char zNum[30];
19431: const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
19432: if( zVar==0 ){
19433: sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
19434: zVar = zNum;
19435: }
19436: sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
1.6.2.1 ! misho 19437: if( rc==SQLITE_OK && pQ && sqlite3_step(pQ)==SQLITE_ROW ){
1.5 misho 19438: sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
1.6.2.1 ! misho 19439: #ifdef NAN
! 19440: }else if( sqlite3_strlike("_NAN", zVar, 0)==0 ){
! 19441: sqlite3_bind_double(pStmt, i, NAN);
! 19442: #endif
! 19443: #ifdef INFINITY
! 19444: }else if( sqlite3_strlike("_INF", zVar, 0)==0 ){
! 19445: sqlite3_bind_double(pStmt, i, INFINITY);
! 19446: #endif
1.5 misho 19447: }else{
19448: sqlite3_bind_null(pStmt, i);
19449: }
19450: sqlite3_reset(pQ);
19451: }
19452: sqlite3_finalize(pQ);
19453: }
19454:
19455: /*
19456: ** UTF8 box-drawing characters. Imagine box lines like this:
19457: **
19458: ** 1
19459: ** |
19460: ** 4 --+-- 2
19461: ** |
19462: ** 3
19463: **
19464: ** Each box characters has between 2 and 4 of the lines leading from
19465: ** the center. The characters are here identified by the numbers of
19466: ** their corresponding lines.
19467: */
19468: #define BOX_24 "\342\224\200" /* U+2500 --- */
19469: #define BOX_13 "\342\224\202" /* U+2502 | */
19470: #define BOX_23 "\342\224\214" /* U+250c ,- */
19471: #define BOX_34 "\342\224\220" /* U+2510 -, */
19472: #define BOX_12 "\342\224\224" /* U+2514 '- */
19473: #define BOX_14 "\342\224\230" /* U+2518 -' */
19474: #define BOX_123 "\342\224\234" /* U+251c |- */
19475: #define BOX_134 "\342\224\244" /* U+2524 -| */
19476: #define BOX_234 "\342\224\254" /* U+252c -,- */
19477: #define BOX_124 "\342\224\264" /* U+2534 -'- */
19478: #define BOX_1234 "\342\224\274" /* U+253c -|- */
19479:
19480: /* Draw horizontal line N characters long using unicode box
19481: ** characters
19482: */
19483: static void print_box_line(FILE *out, int N){
1.6.2.1 ! misho 19484: const char zDash[] =
1.5 misho 19485: BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
19486: BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
19487: const int nDash = sizeof(zDash) - 1;
19488: N *= 3;
19489: while( N>nDash ){
19490: utf8_printf(out, zDash);
19491: N -= nDash;
19492: }
1.6.2.1 ! misho 19493: utf8_printf(out, "%.*s", N, zDash);
! 19494: }
! 19495:
! 19496: /*
! 19497: ** Draw a horizontal separator for a MODE_Box table.
! 19498: */
! 19499: static void print_box_row_separator(
! 19500: ShellState *p,
! 19501: int nArg,
! 19502: const char *zSep1,
! 19503: const char *zSep2,
! 19504: const char *zSep3
! 19505: ){
! 19506: int i;
! 19507: if( nArg>0 ){
! 19508: utf8_printf(p->out, "%s", zSep1);
! 19509: print_box_line(p->out, p->actualWidth[0]+2);
! 19510: for(i=1; i<nArg; i++){
! 19511: utf8_printf(p->out, "%s", zSep2);
! 19512: print_box_line(p->out, p->actualWidth[i]+2);
! 19513: }
! 19514: utf8_printf(p->out, "%s", zSep3);
! 19515: }
! 19516: fputs("\n", p->out);
! 19517: }
! 19518:
! 19519: /*
! 19520: ** z[] is a line of text that is to be displayed the .mode box or table or
! 19521: ** similar tabular formats. z[] might contain control characters such
! 19522: ** as \n, \t, \f, or \r.
! 19523: **
! 19524: ** Compute characters to display on the first line of z[]. Stop at the
! 19525: ** first \r, \n, or \f. Expand \t into spaces. Return a copy (obtained
! 19526: ** from malloc()) of that first line, which caller should free sometime.
! 19527: ** Write anything to display on the next line into *pzTail. If this is
! 19528: ** the last line, write a NULL into *pzTail. (*pzTail is not allocated.)
! 19529: */
! 19530: static char *translateForDisplayAndDup(
! 19531: const unsigned char *z, /* Input text to be transformed */
! 19532: const unsigned char **pzTail, /* OUT: Tail of the input for next line */
! 19533: int mxWidth, /* Max width. 0 means no limit */
! 19534: u8 bWordWrap /* If true, avoid breaking mid-word */
! 19535: ){
! 19536: int i; /* Input bytes consumed */
! 19537: int j; /* Output bytes generated */
! 19538: int k; /* Input bytes to be displayed */
! 19539: int n; /* Output column number */
! 19540: unsigned char *zOut; /* Output text */
! 19541:
! 19542: if( z==0 ){
! 19543: *pzTail = 0;
! 19544: return 0;
! 19545: }
! 19546: if( mxWidth<0 ) mxWidth = -mxWidth;
! 19547: if( mxWidth==0 ) mxWidth = 1000000;
! 19548: i = j = n = 0;
! 19549: while( n<mxWidth ){
! 19550: if( z[i]>=' ' ){
! 19551: n++;
! 19552: do{ i++; j++; }while( (z[i]&0xc0)==0x80 );
! 19553: continue;
! 19554: }
! 19555: if( z[i]=='\t' ){
! 19556: do{
! 19557: n++;
! 19558: j++;
! 19559: }while( (n&7)!=0 && n<mxWidth );
! 19560: i++;
! 19561: continue;
! 19562: }
! 19563: break;
! 19564: }
! 19565: if( n>=mxWidth && bWordWrap ){
! 19566: /* Perhaps try to back up to a better place to break the line */
! 19567: for(k=i; k>i/2; k--){
! 19568: if( isspace(z[k-1]) ) break;
! 19569: }
! 19570: if( k<=i/2 ){
! 19571: for(k=i; k>i/2; k--){
! 19572: if( isalnum(z[k-1])!=isalnum(z[k]) && (z[k]&0xc0)!=0x80 ) break;
! 19573: }
! 19574: }
! 19575: if( k<=i/2 ){
! 19576: k = i;
! 19577: }else{
! 19578: i = k;
! 19579: while( z[i]==' ' ) i++;
! 19580: }
! 19581: }else{
! 19582: k = i;
! 19583: }
! 19584: if( n>=mxWidth && z[i]>=' ' ){
! 19585: *pzTail = &z[i];
! 19586: }else if( z[i]=='\r' && z[i+1]=='\n' ){
! 19587: *pzTail = z[i+2] ? &z[i+2] : 0;
! 19588: }else if( z[i]==0 || z[i+1]==0 ){
! 19589: *pzTail = 0;
! 19590: }else{
! 19591: *pzTail = &z[i+1];
! 19592: }
! 19593: zOut = malloc( j+1 );
! 19594: shell_check_oom(zOut);
! 19595: i = j = n = 0;
! 19596: while( i<k ){
! 19597: if( z[i]>=' ' ){
! 19598: n++;
! 19599: do{ zOut[j++] = z[i++]; }while( (z[i]&0xc0)==0x80 );
! 19600: continue;
! 19601: }
! 19602: if( z[i]=='\t' ){
! 19603: do{
! 19604: n++;
! 19605: zOut[j++] = ' ';
! 19606: }while( (n&7)!=0 && n<mxWidth );
! 19607: i++;
! 19608: continue;
! 19609: }
! 19610: break;
! 19611: }
! 19612: zOut[j] = 0;
! 19613: return (char*)zOut;
1.5 misho 19614: }
19615:
1.6.2.1 ! misho 19616: /* Extract the value of the i-th current column for pStmt as an SQL literal
! 19617: ** value. Memory is obtained from sqlite3_malloc64() and must be freed by
! 19618: ** the caller.
1.5 misho 19619: */
1.6.2.1 ! misho 19620: static char *quoted_column(sqlite3_stmt *pStmt, int i){
! 19621: switch( sqlite3_column_type(pStmt, i) ){
! 19622: case SQLITE_NULL: {
! 19623: return sqlite3_mprintf("NULL");
! 19624: }
! 19625: case SQLITE_INTEGER:
! 19626: case SQLITE_FLOAT: {
! 19627: return sqlite3_mprintf("%s",sqlite3_column_text(pStmt,i));
! 19628: }
! 19629: case SQLITE_TEXT: {
! 19630: return sqlite3_mprintf("%Q",sqlite3_column_text(pStmt,i));
! 19631: }
! 19632: case SQLITE_BLOB: {
! 19633: int j;
! 19634: sqlite3_str *pStr = sqlite3_str_new(0);
! 19635: const unsigned char *a = sqlite3_column_blob(pStmt,i);
! 19636: int n = sqlite3_column_bytes(pStmt,i);
! 19637: sqlite3_str_append(pStr, "x'", 2);
! 19638: for(j=0; j<n; j++){
! 19639: sqlite3_str_appendf(pStr, "%02x", a[j]);
! 19640: }
! 19641: sqlite3_str_append(pStr, "'", 1);
! 19642: return sqlite3_str_finish(pStr);
1.5 misho 19643: }
19644: }
1.6.2.1 ! misho 19645: return 0; /* Not reached */
1.5 misho 19646: }
19647:
19648: /*
19649: ** Run a prepared statement and output the result in one of the
19650: ** table-oriented formats: MODE_Column, MODE_Markdown, MODE_Table,
19651: ** or MODE_Box.
19652: **
19653: ** This is different from ordinary exec_prepared_stmt() in that
19654: ** it has to run the entire query and gather the results into memory
19655: ** first, in order to determine column widths, before providing
19656: ** any output.
19657: */
19658: static void exec_prepared_stmt_columnar(
19659: ShellState *p, /* Pointer to ShellState */
1.6.2.1 ! misho 19660: sqlite3_stmt *pStmt /* Statement to run */
1.5 misho 19661: ){
19662: sqlite3_int64 nRow = 0;
19663: int nColumn = 0;
19664: char **azData = 0;
19665: sqlite3_int64 nAlloc = 0;
1.6.2.1 ! misho 19666: char *abRowDiv = 0;
! 19667: const unsigned char *uz;
1.5 misho 19668: const char *z;
1.6.2.1 ! misho 19669: char **azQuoted = 0;
1.5 misho 19670: int rc;
19671: sqlite3_int64 i, nData;
19672: int j, nTotal, w, n;
19673: const char *colSep = 0;
19674: const char *rowSep = 0;
1.6.2.1 ! misho 19675: const unsigned char **azNextLine = 0;
! 19676: int bNextLine = 0;
! 19677: int bMultiLineRowExists = 0;
! 19678: int bw = p->cmOpts.bWordWrap;
! 19679: const char *zEmpty = "";
! 19680: const char *zShowNull = p->nullValue;
1.5 misho 19681:
19682: rc = sqlite3_step(pStmt);
19683: if( rc!=SQLITE_ROW ) return;
19684: nColumn = sqlite3_column_count(pStmt);
19685: nAlloc = nColumn*4;
1.6.2.1 ! misho 19686: if( nAlloc<=0 ) nAlloc = 1;
1.5 misho 19687: azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
1.6.2.1 ! misho 19688: shell_check_oom(azData);
! 19689: azNextLine = sqlite3_malloc64( nColumn*sizeof(char*) );
! 19690: shell_check_oom(azNextLine);
! 19691: memset((void*)azNextLine, 0, nColumn*sizeof(char*) );
! 19692: if( p->cmOpts.bQuote ){
! 19693: azQuoted = sqlite3_malloc64( nColumn*sizeof(char*) );
! 19694: shell_check_oom(azQuoted);
! 19695: memset(azQuoted, 0, nColumn*sizeof(char*) );
1.5 misho 19696: }
1.6.2.1 ! misho 19697: abRowDiv = sqlite3_malloc64( nAlloc/nColumn );
! 19698: shell_check_oom(abRowDiv);
1.5 misho 19699: if( nColumn>p->nWidth ){
1.6.2.1 ! misho 19700: p->colWidth = realloc(p->colWidth, (nColumn+1)*2*sizeof(int));
! 19701: shell_check_oom(p->colWidth);
1.5 misho 19702: for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0;
19703: p->nWidth = nColumn;
19704: p->actualWidth = &p->colWidth[nColumn];
19705: }
19706: memset(p->actualWidth, 0, nColumn*sizeof(int));
19707: for(i=0; i<nColumn; i++){
19708: w = p->colWidth[i];
19709: if( w<0 ) w = -w;
19710: p->actualWidth[i] = w;
19711: }
1.6.2.1 ! misho 19712: for(i=0; i<nColumn; i++){
! 19713: const unsigned char *zNotUsed;
! 19714: int wx = p->colWidth[i];
! 19715: if( wx==0 ){
! 19716: wx = p->cmOpts.iWrap;
! 19717: }
! 19718: if( wx<0 ) wx = -wx;
! 19719: uz = (const unsigned char*)sqlite3_column_name(pStmt,i);
! 19720: if( uz==0 ) uz = (u8*)"";
! 19721: azData[i] = translateForDisplayAndDup(uz, &zNotUsed, wx, bw);
! 19722: }
! 19723: do{
! 19724: int useNextLine = bNextLine;
! 19725: bNextLine = 0;
! 19726: if( (nRow+2)*nColumn >= nAlloc ){
! 19727: nAlloc *= 2;
! 19728: azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*));
! 19729: shell_check_oom(azData);
! 19730: abRowDiv = sqlite3_realloc64(abRowDiv, nAlloc/nColumn);
! 19731: shell_check_oom(abRowDiv);
! 19732: }
! 19733: abRowDiv[nRow] = 1;
! 19734: nRow++;
! 19735: for(i=0; i<nColumn; i++){
! 19736: int wx = p->colWidth[i];
! 19737: if( wx==0 ){
! 19738: wx = p->cmOpts.iWrap;
! 19739: }
! 19740: if( wx<0 ) wx = -wx;
! 19741: if( useNextLine ){
! 19742: uz = azNextLine[i];
! 19743: if( uz==0 ) uz = (u8*)zEmpty;
! 19744: }else if( p->cmOpts.bQuote ){
! 19745: sqlite3_free(azQuoted[i]);
! 19746: azQuoted[i] = quoted_column(pStmt,i);
! 19747: uz = (const unsigned char*)azQuoted[i];
! 19748: }else{
! 19749: uz = (const unsigned char*)sqlite3_column_text(pStmt,i);
! 19750: if( uz==0 ) uz = (u8*)zShowNull;
! 19751: }
! 19752: azData[nRow*nColumn + i]
! 19753: = translateForDisplayAndDup(uz, &azNextLine[i], wx, bw);
! 19754: if( azNextLine[i] ){
! 19755: bNextLine = 1;
! 19756: abRowDiv[nRow-1] = 0;
! 19757: bMultiLineRowExists = 1;
! 19758: }
! 19759: }
! 19760: }while( bNextLine || sqlite3_step(pStmt)==SQLITE_ROW );
1.5 misho 19761: nTotal = nColumn*(nRow+1);
19762: for(i=0; i<nTotal; i++){
19763: z = azData[i];
1.6.2.1 ! misho 19764: if( z==0 ) z = (char*)zEmpty;
1.5 misho 19765: n = strlenChar(z);
19766: j = i%nColumn;
19767: if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
19768: }
19769: if( seenInterrupt ) goto columnar_end;
1.6.2.1 ! misho 19770: if( nColumn==0 ) goto columnar_end;
1.5 misho 19771: switch( p->cMode ){
19772: case MODE_Column: {
19773: colSep = " ";
19774: rowSep = "\n";
19775: if( p->showHeader ){
19776: for(i=0; i<nColumn; i++){
19777: w = p->actualWidth[i];
19778: if( p->colWidth[i]<0 ) w = -w;
19779: utf8_width_print(p->out, w, azData[i]);
19780: fputs(i==nColumn-1?"\n":" ", p->out);
19781: }
19782: for(i=0; i<nColumn; i++){
19783: print_dashes(p->out, p->actualWidth[i]);
19784: fputs(i==nColumn-1?"\n":" ", p->out);
19785: }
19786: }
19787: break;
19788: }
19789: case MODE_Table: {
19790: colSep = " | ";
19791: rowSep = " |\n";
19792: print_row_separator(p, nColumn, "+");
19793: fputs("| ", p->out);
19794: for(i=0; i<nColumn; i++){
19795: w = p->actualWidth[i];
19796: n = strlenChar(azData[i]);
19797: utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
19798: fputs(i==nColumn-1?" |\n":" | ", p->out);
19799: }
19800: print_row_separator(p, nColumn, "+");
19801: break;
19802: }
19803: case MODE_Markdown: {
19804: colSep = " | ";
19805: rowSep = " |\n";
19806: fputs("| ", p->out);
19807: for(i=0; i<nColumn; i++){
19808: w = p->actualWidth[i];
19809: n = strlenChar(azData[i]);
19810: utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
19811: fputs(i==nColumn-1?" |\n":" | ", p->out);
19812: }
19813: print_row_separator(p, nColumn, "|");
19814: break;
19815: }
19816: case MODE_Box: {
19817: colSep = " " BOX_13 " ";
19818: rowSep = " " BOX_13 "\n";
19819: print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34);
19820: utf8_printf(p->out, BOX_13 " ");
19821: for(i=0; i<nColumn; i++){
19822: w = p->actualWidth[i];
19823: n = strlenChar(azData[i]);
19824: utf8_printf(p->out, "%*s%s%*s%s",
19825: (w-n)/2, "", azData[i], (w-n+1)/2, "",
19826: i==nColumn-1?" "BOX_13"\n":" "BOX_13" ");
19827: }
19828: print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
19829: break;
19830: }
19831: }
19832: for(i=nColumn, j=0; i<nTotal; i++, j++){
19833: if( j==0 && p->cMode!=MODE_Column ){
19834: utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| ");
19835: }
19836: z = azData[i];
19837: if( z==0 ) z = p->nullValue;
19838: w = p->actualWidth[j];
19839: if( p->colWidth[j]<0 ) w = -w;
19840: utf8_width_print(p->out, w, z);
19841: if( j==nColumn-1 ){
19842: utf8_printf(p->out, "%s", rowSep);
1.6.2.1 ! misho 19843: if( bMultiLineRowExists && abRowDiv[i/nColumn-1] && i+1<nTotal ){
! 19844: if( p->cMode==MODE_Table ){
! 19845: print_row_separator(p, nColumn, "+");
! 19846: }else if( p->cMode==MODE_Box ){
! 19847: print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
! 19848: }else if( p->cMode==MODE_Column ){
! 19849: raw_printf(p->out, "\n");
! 19850: }
! 19851: }
1.5 misho 19852: j = -1;
19853: if( seenInterrupt ) goto columnar_end;
19854: }else{
19855: utf8_printf(p->out, "%s", colSep);
19856: }
19857: }
19858: if( p->cMode==MODE_Table ){
19859: print_row_separator(p, nColumn, "+");
19860: }else if( p->cMode==MODE_Box ){
19861: print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14);
19862: }
19863: columnar_end:
19864: if( seenInterrupt ){
19865: utf8_printf(p->out, "Interrupt\n");
19866: }
19867: nData = (nRow+1)*nColumn;
1.6.2.1 ! misho 19868: for(i=0; i<nData; i++){
! 19869: z = azData[i];
! 19870: if( z!=zEmpty && z!=zShowNull ) free(azData[i]);
! 19871: }
1.5 misho 19872: sqlite3_free(azData);
1.6.2.1 ! misho 19873: sqlite3_free((void*)azNextLine);
! 19874: sqlite3_free(abRowDiv);
! 19875: if( azQuoted ){
! 19876: for(i=0; i<nColumn; i++) sqlite3_free(azQuoted[i]);
! 19877: sqlite3_free(azQuoted);
! 19878: }
1.5 misho 19879: }
19880:
19881: /*
19882: ** Run a prepared statement
19883: */
19884: static void exec_prepared_stmt(
19885: ShellState *pArg, /* Pointer to ShellState */
1.6.2.1 ! misho 19886: sqlite3_stmt *pStmt /* Statement to run */
1.5 misho 19887: ){
19888: int rc;
1.6.2.1 ! misho 19889: sqlite3_uint64 nRow = 0;
1.5 misho 19890:
19891: if( pArg->cMode==MODE_Column
19892: || pArg->cMode==MODE_Table
19893: || pArg->cMode==MODE_Box
19894: || pArg->cMode==MODE_Markdown
19895: ){
19896: exec_prepared_stmt_columnar(pArg, pStmt);
19897: return;
19898: }
19899:
19900: /* perform the first step. this will tell us if we
19901: ** have a result set or not and how wide it is.
19902: */
19903: rc = sqlite3_step(pStmt);
19904: /* if we have a result set... */
19905: if( SQLITE_ROW == rc ){
19906: /* allocate space for col name ptr, value ptr, and type */
19907: int nCol = sqlite3_column_count(pStmt);
19908: void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
19909: if( !pData ){
1.6.2.1 ! misho 19910: shell_out_of_memory();
1.5 misho 19911: }else{
19912: char **azCols = (char **)pData; /* Names of result columns */
19913: char **azVals = &azCols[nCol]; /* Results */
19914: int *aiTypes = (int *)&azVals[nCol]; /* Result types */
19915: int i, x;
19916: assert(sizeof(int) <= sizeof(char *));
19917: /* save off ptrs to column names */
19918: for(i=0; i<nCol; i++){
19919: azCols[i] = (char *)sqlite3_column_name(pStmt, i);
19920: }
19921: do{
1.6.2.1 ! misho 19922: nRow++;
1.5 misho 19923: /* extract the data and data types */
19924: for(i=0; i<nCol; i++){
19925: aiTypes[i] = x = sqlite3_column_type(pStmt, i);
1.6.2.1 ! misho 19926: if( x==SQLITE_BLOB
! 19927: && pArg
! 19928: && (pArg->cMode==MODE_Insert || pArg->cMode==MODE_Quote)
! 19929: ){
1.5 misho 19930: azVals[i] = "";
19931: }else{
19932: azVals[i] = (char*)sqlite3_column_text(pStmt, i);
19933: }
19934: if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
19935: rc = SQLITE_NOMEM;
19936: break; /* from for */
19937: }
19938: } /* end for */
19939:
19940: /* if data and types extracted successfully... */
19941: if( SQLITE_ROW == rc ){
19942: /* call the supplied callback with the result row data */
19943: if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){
19944: rc = SQLITE_ABORT;
19945: }else{
19946: rc = sqlite3_step(pStmt);
19947: }
19948: }
19949: } while( SQLITE_ROW == rc );
19950: sqlite3_free(pData);
19951: if( pArg->cMode==MODE_Json ){
19952: fputs("]\n", pArg->out);
1.6.2.1 ! misho 19953: }else if( pArg->cMode==MODE_Count ){
! 19954: char zBuf[200];
! 19955: sqlite3_snprintf(sizeof(zBuf), zBuf, "%llu row%s\n",
! 19956: nRow, nRow!=1 ? "s" : "");
! 19957: printf("%s", zBuf);
1.5 misho 19958: }
19959: }
19960: }
19961: }
19962:
19963: #ifndef SQLITE_OMIT_VIRTUALTABLE
19964: /*
19965: ** This function is called to process SQL if the previous shell command
19966: ** was ".expert". It passes the SQL in the second argument directly to
19967: ** the sqlite3expert object.
19968: **
19969: ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
19970: ** code. In this case, (*pzErr) may be set to point to a buffer containing
19971: ** an English language error message. It is the responsibility of the
19972: ** caller to eventually free this buffer using sqlite3_free().
19973: */
19974: static int expertHandleSQL(
1.6.2.1 ! misho 19975: ShellState *pState,
! 19976: const char *zSql,
1.5 misho 19977: char **pzErr
19978: ){
19979: assert( pState->expert.pExpert );
19980: assert( pzErr==0 || *pzErr==0 );
19981: return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr);
19982: }
19983:
19984: /*
19985: ** This function is called either to silently clean up the object
1.6.2.1 ! misho 19986: ** created by the ".expert" command (if bCancel==1), or to generate a
1.5 misho 19987: ** report from it and then clean it up (if bCancel==0).
19988: **
19989: ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
19990: ** code. In this case, (*pzErr) may be set to point to a buffer containing
19991: ** an English language error message. It is the responsibility of the
19992: ** caller to eventually free this buffer using sqlite3_free().
19993: */
19994: static int expertFinish(
19995: ShellState *pState,
19996: int bCancel,
19997: char **pzErr
19998: ){
19999: int rc = SQLITE_OK;
20000: sqlite3expert *p = pState->expert.pExpert;
20001: assert( p );
20002: assert( bCancel || pzErr==0 || *pzErr==0 );
20003: if( bCancel==0 ){
20004: FILE *out = pState->out;
20005: int bVerbose = pState->expert.bVerbose;
20006:
20007: rc = sqlite3_expert_analyze(p, pzErr);
20008: if( rc==SQLITE_OK ){
20009: int nQuery = sqlite3_expert_count(p);
20010: int i;
20011:
20012: if( bVerbose ){
20013: const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
20014: raw_printf(out, "-- Candidates -----------------------------\n");
20015: raw_printf(out, "%s\n", zCand);
20016: }
20017: for(i=0; i<nQuery; i++){
20018: const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
20019: const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
20020: const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
20021: if( zIdx==0 ) zIdx = "(no new indexes)\n";
20022: if( bVerbose ){
20023: raw_printf(out, "-- Query %d --------------------------------\n",i+1);
20024: raw_printf(out, "%s\n\n", zSql);
20025: }
20026: raw_printf(out, "%s\n", zIdx);
20027: raw_printf(out, "%s\n", zEQP);
20028: }
20029: }
20030: }
20031: sqlite3_expert_destroy(p);
20032: pState->expert.pExpert = 0;
20033: return rc;
20034: }
20035:
20036: /*
20037: ** Implementation of ".expert" dot command.
20038: */
20039: static int expertDotCommand(
20040: ShellState *pState, /* Current shell tool state */
20041: char **azArg, /* Array of arguments passed to dot command */
20042: int nArg /* Number of entries in azArg[] */
20043: ){
20044: int rc = SQLITE_OK;
20045: char *zErr = 0;
20046: int i;
20047: int iSample = 0;
20048:
20049: assert( pState->expert.pExpert==0 );
20050: memset(&pState->expert, 0, sizeof(ExpertInfo));
20051:
20052: for(i=1; rc==SQLITE_OK && i<nArg; i++){
20053: char *z = azArg[i];
20054: int n;
20055: if( z[0]=='-' && z[1]=='-' ) z++;
20056: n = strlen30(z);
1.6.2.1 ! misho 20057: if( n>=2 && 0==cli_strncmp(z, "-verbose", n) ){
1.5 misho 20058: pState->expert.bVerbose = 1;
20059: }
1.6.2.1 ! misho 20060: else if( n>=2 && 0==cli_strncmp(z, "-sample", n) ){
1.5 misho 20061: if( i==(nArg-1) ){
20062: raw_printf(stderr, "option requires an argument: %s\n", z);
20063: rc = SQLITE_ERROR;
20064: }else{
20065: iSample = (int)integerValue(azArg[++i]);
20066: if( iSample<0 || iSample>100 ){
20067: raw_printf(stderr, "value out of range: %s\n", azArg[i]);
20068: rc = SQLITE_ERROR;
20069: }
20070: }
20071: }
20072: else{
20073: raw_printf(stderr, "unknown option: %s\n", z);
20074: rc = SQLITE_ERROR;
20075: }
20076: }
20077:
20078: if( rc==SQLITE_OK ){
20079: pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
20080: if( pState->expert.pExpert==0 ){
1.6.2.1 ! misho 20081: raw_printf(stderr, "sqlite3_expert_new: %s\n",
! 20082: zErr ? zErr : "out of memory");
1.5 misho 20083: rc = SQLITE_ERROR;
20084: }else{
20085: sqlite3_expert_config(
20086: pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
20087: );
20088: }
20089: }
1.6.2.1 ! misho 20090: sqlite3_free(zErr);
1.5 misho 20091:
20092: return rc;
20093: }
20094: #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
20095:
20096: /*
20097: ** Execute a statement or set of statements. Print
20098: ** any result rows/columns depending on the current mode
20099: ** set via the supplied callback.
20100: **
20101: ** This is very similar to SQLite's built-in sqlite3_exec()
20102: ** function except it takes a slightly different callback
20103: ** and callback data argument.
20104: */
20105: static int shell_exec(
20106: ShellState *pArg, /* Pointer to ShellState */
20107: const char *zSql, /* SQL to be evaluated */
20108: char **pzErrMsg /* Error msg written here */
20109: ){
20110: sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
20111: int rc = SQLITE_OK; /* Return Code */
20112: int rc2;
20113: const char *zLeftover; /* Tail of unprocessed SQL */
20114: sqlite3 *db = pArg->db;
20115:
20116: if( pzErrMsg ){
20117: *pzErrMsg = NULL;
20118: }
20119:
20120: #ifndef SQLITE_OMIT_VIRTUALTABLE
20121: if( pArg->expert.pExpert ){
20122: rc = expertHandleSQL(pArg, zSql, pzErrMsg);
20123: return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
20124: }
20125: #endif
20126:
20127: while( zSql[0] && (SQLITE_OK == rc) ){
20128: static const char *zStmtSql;
20129: rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
20130: if( SQLITE_OK != rc ){
20131: if( pzErrMsg ){
1.6.2.1 ! misho 20132: *pzErrMsg = save_err_msg(db, "in prepare", rc, zSql);
1.5 misho 20133: }
20134: }else{
20135: if( !pStmt ){
20136: /* this happens for a comment or white-space */
20137: zSql = zLeftover;
20138: while( IsSpace(zSql[0]) ) zSql++;
20139: continue;
20140: }
20141: zStmtSql = sqlite3_sql(pStmt);
20142: if( zStmtSql==0 ) zStmtSql = "";
20143: while( IsSpace(zStmtSql[0]) ) zStmtSql++;
20144:
1.6.2.1 ! misho 20145: /* save off the prepared statement handle and reset row count */
1.5 misho 20146: if( pArg ){
20147: pArg->pStmt = pStmt;
20148: pArg->cnt = 0;
20149: }
20150:
20151: /* Show the EXPLAIN QUERY PLAN if .eqp is on */
20152: if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
20153: sqlite3_stmt *pExplain;
20154: int triggerEQP = 0;
20155: disable_debug_trace_modes();
20156: sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
20157: if( pArg->autoEQP>=AUTOEQP_trigger ){
20158: sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
20159: }
1.6.2.1 ! misho 20160: pExplain = pStmt;
! 20161: sqlite3_reset(pExplain);
! 20162: rc = sqlite3_stmt_explain(pExplain, 2);
1.5 misho 20163: if( rc==SQLITE_OK ){
20164: while( sqlite3_step(pExplain)==SQLITE_ROW ){
20165: const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
20166: int iEqpId = sqlite3_column_int(pExplain, 0);
20167: int iParentId = sqlite3_column_int(pExplain, 1);
20168: if( zEQPLine==0 ) zEQPLine = "";
1.6.2.1 ! misho 20169: if( zEQPLine[0]=='-' ) eqp_render(pArg, 0);
1.5 misho 20170: eqp_append(pArg, iEqpId, iParentId, zEQPLine);
20171: }
1.6.2.1 ! misho 20172: eqp_render(pArg, 0);
1.5 misho 20173: }
20174: if( pArg->autoEQP>=AUTOEQP_full ){
20175: /* Also do an EXPLAIN for ".eqp full" mode */
1.6.2.1 ! misho 20176: sqlite3_reset(pExplain);
! 20177: rc = sqlite3_stmt_explain(pExplain, 1);
1.5 misho 20178: if( rc==SQLITE_OK ){
20179: pArg->cMode = MODE_Explain;
1.6.2.1 ! misho 20180: assert( sqlite3_stmt_isexplain(pExplain)==1 );
1.5 misho 20181: explain_data_prepare(pArg, pExplain);
20182: exec_prepared_stmt(pArg, pExplain);
20183: explain_data_delete(pArg);
20184: }
20185: }
20186: if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
20187: sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
20188: }
1.6.2.1 ! misho 20189: sqlite3_reset(pStmt);
! 20190: sqlite3_stmt_explain(pStmt, 0);
1.5 misho 20191: restore_debug_trace_modes();
20192: }
20193:
20194: if( pArg ){
1.6.2.1 ! misho 20195: int bIsExplain = (sqlite3_stmt_isexplain(pStmt)==1);
1.5 misho 20196: pArg->cMode = pArg->mode;
20197: if( pArg->autoExplain ){
1.6.2.1 ! misho 20198: if( bIsExplain ){
1.5 misho 20199: pArg->cMode = MODE_Explain;
20200: }
20201: if( sqlite3_stmt_isexplain(pStmt)==2 ){
20202: pArg->cMode = MODE_EQP;
20203: }
20204: }
20205:
20206: /* If the shell is currently in ".explain" mode, gather the extra
20207: ** data required to add indents to the output.*/
1.6.2.1 ! misho 20208: if( pArg->cMode==MODE_Explain && bIsExplain ){
1.5 misho 20209: explain_data_prepare(pArg, pStmt);
20210: }
20211: }
20212:
20213: bind_prepared_stmt(pArg, pStmt);
20214: exec_prepared_stmt(pArg, pStmt);
20215: explain_data_delete(pArg);
1.6.2.1 ! misho 20216: eqp_render(pArg, 0);
1.5 misho 20217:
20218: /* print usage stats if stats on */
20219: if( pArg && pArg->statsOn ){
20220: display_stats(db, pArg, 0);
20221: }
20222:
20223: /* print loop-counters if required */
20224: if( pArg && pArg->scanstatsOn ){
20225: display_scanstats(db, pArg);
20226: }
20227:
20228: /* Finalize the statement just executed. If this fails, save a
20229: ** copy of the error message. Otherwise, set zSql to point to the
20230: ** next statement to execute. */
20231: rc2 = sqlite3_finalize(pStmt);
20232: if( rc!=SQLITE_NOMEM ) rc = rc2;
20233: if( rc==SQLITE_OK ){
20234: zSql = zLeftover;
20235: while( IsSpace(zSql[0]) ) zSql++;
20236: }else if( pzErrMsg ){
1.6.2.1 ! misho 20237: *pzErrMsg = save_err_msg(db, "stepping", rc, 0);
1.5 misho 20238: }
20239:
20240: /* clear saved stmt handle */
20241: if( pArg ){
20242: pArg->pStmt = NULL;
20243: }
20244: }
20245: } /* end while */
20246:
20247: return rc;
20248: }
20249:
20250: /*
20251: ** Release memory previously allocated by tableColumnList().
20252: */
20253: static void freeColumnList(char **azCol){
20254: int i;
20255: for(i=1; azCol[i]; i++){
20256: sqlite3_free(azCol[i]);
20257: }
20258: /* azCol[0] is a static string */
20259: sqlite3_free(azCol);
20260: }
20261:
20262: /*
20263: ** Return a list of pointers to strings which are the names of all
20264: ** columns in table zTab. The memory to hold the names is dynamically
20265: ** allocated and must be released by the caller using a subsequent call
20266: ** to freeColumnList().
20267: **
20268: ** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
20269: ** value that needs to be preserved, then azCol[0] is filled in with the
20270: ** name of the rowid column.
20271: **
20272: ** The first regular column in the table is azCol[1]. The list is terminated
20273: ** by an entry with azCol[i]==0.
20274: */
20275: static char **tableColumnList(ShellState *p, const char *zTab){
20276: char **azCol = 0;
20277: sqlite3_stmt *pStmt;
20278: char *zSql;
20279: int nCol = 0;
20280: int nAlloc = 0;
20281: int nPK = 0; /* Number of PRIMARY KEY columns seen */
20282: int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
20283: int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
20284: int rc;
20285:
20286: zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
1.6.2.1 ! misho 20287: shell_check_oom(zSql);
1.5 misho 20288: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
20289: sqlite3_free(zSql);
20290: if( rc ) return 0;
20291: while( sqlite3_step(pStmt)==SQLITE_ROW ){
20292: if( nCol>=nAlloc-2 ){
20293: nAlloc = nAlloc*2 + nCol + 10;
20294: azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
1.6.2.1 ! misho 20295: shell_check_oom(azCol);
1.5 misho 20296: }
20297: azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
1.6.2.1 ! misho 20298: shell_check_oom(azCol[nCol]);
1.5 misho 20299: if( sqlite3_column_int(pStmt, 5) ){
20300: nPK++;
20301: if( nPK==1
20302: && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
20303: "INTEGER")==0
20304: ){
20305: isIPK = 1;
20306: }else{
20307: isIPK = 0;
20308: }
20309: }
20310: }
20311: sqlite3_finalize(pStmt);
20312: if( azCol==0 ) return 0;
20313: azCol[0] = 0;
20314: azCol[nCol+1] = 0;
20315:
20316: /* The decision of whether or not a rowid really needs to be preserved
20317: ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
20318: ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
20319: ** rowids on tables where the rowid is inaccessible because there are other
20320: ** columns in the table named "rowid", "_rowid_", and "oid".
20321: */
20322: if( preserveRowid && isIPK ){
20323: /* If a single PRIMARY KEY column with type INTEGER was seen, then it
1.6.2.1 ! misho 20324: ** might be an alias for the ROWID. But it might also be a WITHOUT ROWID
1.5 misho 20325: ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
20326: ** ROWID aliases. To distinguish these cases, check to see if
20327: ** there is a "pk" entry in "PRAGMA index_list". There will be
20328: ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
20329: */
20330: zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
20331: " WHERE origin='pk'", zTab);
1.6.2.1 ! misho 20332: shell_check_oom(zSql);
1.5 misho 20333: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
20334: sqlite3_free(zSql);
20335: if( rc ){
20336: freeColumnList(azCol);
20337: return 0;
20338: }
20339: rc = sqlite3_step(pStmt);
20340: sqlite3_finalize(pStmt);
20341: preserveRowid = rc==SQLITE_ROW;
20342: }
20343: if( preserveRowid ){
20344: /* Only preserve the rowid if we can find a name to use for the
20345: ** rowid */
20346: static char *azRowid[] = { "rowid", "_rowid_", "oid" };
20347: int i, j;
20348: for(j=0; j<3; j++){
20349: for(i=1; i<=nCol; i++){
20350: if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
20351: }
20352: if( i>nCol ){
20353: /* At this point, we know that azRowid[j] is not the name of any
20354: ** ordinary column in the table. Verify that azRowid[j] is a valid
20355: ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
20356: ** tables will fail this last check */
20357: rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
20358: if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
20359: break;
20360: }
20361: }
20362: }
20363: return azCol;
20364: }
20365:
20366: /*
20367: ** Toggle the reverse_unordered_selects setting.
20368: */
20369: static void toggleSelectOrder(sqlite3 *db){
20370: sqlite3_stmt *pStmt = 0;
20371: int iSetting = 0;
20372: char zStmt[100];
20373: sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0);
20374: if( sqlite3_step(pStmt)==SQLITE_ROW ){
20375: iSetting = sqlite3_column_int(pStmt, 0);
20376: }
20377: sqlite3_finalize(pStmt);
20378: sqlite3_snprintf(sizeof(zStmt), zStmt,
20379: "PRAGMA reverse_unordered_selects(%d)", !iSetting);
20380: sqlite3_exec(db, zStmt, 0, 0, 0);
20381: }
20382:
20383: /*
20384: ** This is a different callback routine used for dumping the database.
20385: ** Each row received by this callback consists of a table name,
20386: ** the table type ("index" or "table") and SQL to create the table.
20387: ** This routine should print text sufficient to recreate the table.
20388: */
20389: static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
20390: int rc;
20391: const char *zTable;
20392: const char *zType;
20393: const char *zSql;
20394: ShellState *p = (ShellState *)pArg;
1.6 misho 20395: int dataOnly;
20396: int noSys;
1.5 misho 20397:
20398: UNUSED_PARAMETER(azNotUsed);
20399: if( nArg!=3 || azArg==0 ) return 0;
20400: zTable = azArg[0];
20401: zType = azArg[1];
20402: zSql = azArg[2];
1.6.2.1 ! misho 20403: if( zTable==0 ) return 0;
! 20404: if( zType==0 ) return 0;
1.6 misho 20405: dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
20406: noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
1.5 misho 20407:
1.6.2.1 ! misho 20408: if( cli_strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
1.6 misho 20409: if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
20410: }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
20411: if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
1.6.2.1 ! misho 20412: }else if( cli_strncmp(zTable, "sqlite_", 7)==0 ){
1.5 misho 20413: return 0;
1.6 misho 20414: }else if( dataOnly ){
20415: /* no-op */
1.6.2.1 ! misho 20416: }else if( cli_strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
1.5 misho 20417: char *zIns;
20418: if( !p->writableSchema ){
20419: raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
20420: p->writableSchema = 1;
20421: }
20422: zIns = sqlite3_mprintf(
20423: "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
20424: "VALUES('table','%q','%q',0,'%q');",
20425: zTable, zTable, zSql);
1.6.2.1 ! misho 20426: shell_check_oom(zIns);
1.5 misho 20427: utf8_printf(p->out, "%s\n", zIns);
20428: sqlite3_free(zIns);
20429: return 0;
20430: }else{
20431: printSchemaLine(p->out, zSql, ";\n");
20432: }
20433:
1.6.2.1 ! misho 20434: if( cli_strcmp(zType, "table")==0 ){
1.5 misho 20435: ShellText sSelect;
20436: ShellText sTable;
20437: char **azCol;
20438: int i;
20439: char *savedDestTable;
20440: int savedMode;
20441:
20442: azCol = tableColumnList(p, zTable);
20443: if( azCol==0 ){
20444: p->nErr++;
20445: return 0;
20446: }
20447:
20448: /* Always quote the table name, even if it appears to be pure ascii,
20449: ** in case it is a keyword. Ex: INSERT INTO "table" ... */
20450: initText(&sTable);
20451: appendText(&sTable, zTable, quoteChar(zTable));
20452: /* If preserving the rowid, add a column list after the table name.
20453: ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
20454: ** instead of the usual "INSERT INTO tab VALUES(...)".
20455: */
20456: if( azCol[0] ){
20457: appendText(&sTable, "(", 0);
20458: appendText(&sTable, azCol[0], 0);
20459: for(i=1; azCol[i]; i++){
20460: appendText(&sTable, ",", 0);
20461: appendText(&sTable, azCol[i], quoteChar(azCol[i]));
20462: }
20463: appendText(&sTable, ")", 0);
20464: }
20465:
20466: /* Build an appropriate SELECT statement */
20467: initText(&sSelect);
20468: appendText(&sSelect, "SELECT ", 0);
20469: if( azCol[0] ){
20470: appendText(&sSelect, azCol[0], 0);
20471: appendText(&sSelect, ",", 0);
20472: }
20473: for(i=1; azCol[i]; i++){
20474: appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
20475: if( azCol[i+1] ){
20476: appendText(&sSelect, ",", 0);
20477: }
20478: }
20479: freeColumnList(azCol);
20480: appendText(&sSelect, " FROM ", 0);
20481: appendText(&sSelect, zTable, quoteChar(zTable));
20482:
20483: savedDestTable = p->zDestTable;
20484: savedMode = p->mode;
20485: p->zDestTable = sTable.z;
20486: p->mode = p->cMode = MODE_Insert;
20487: rc = shell_exec(p, sSelect.z, 0);
20488: if( (rc&0xff)==SQLITE_CORRUPT ){
20489: raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
20490: toggleSelectOrder(p->db);
20491: shell_exec(p, sSelect.z, 0);
20492: toggleSelectOrder(p->db);
20493: }
20494: p->zDestTable = savedDestTable;
20495: p->mode = savedMode;
20496: freeText(&sTable);
20497: freeText(&sSelect);
20498: if( rc ) p->nErr++;
20499: }
20500: return 0;
20501: }
20502:
20503: /*
20504: ** Run zQuery. Use dump_callback() as the callback routine so that
20505: ** the contents of the query are output as SQL statements.
20506: **
20507: ** If we get a SQLITE_CORRUPT error, rerun the query after appending
20508: ** "ORDER BY rowid DESC" to the end.
20509: */
20510: static int run_schema_dump_query(
20511: ShellState *p,
20512: const char *zQuery
20513: ){
20514: int rc;
20515: char *zErr = 0;
20516: rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
20517: if( rc==SQLITE_CORRUPT ){
20518: char *zQ2;
20519: int len = strlen30(zQuery);
20520: raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
20521: if( zErr ){
20522: utf8_printf(p->out, "/****** %s ******/\n", zErr);
20523: sqlite3_free(zErr);
20524: zErr = 0;
20525: }
20526: zQ2 = malloc( len+100 );
20527: if( zQ2==0 ) return rc;
20528: sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
20529: rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
20530: if( rc ){
20531: utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
20532: }else{
20533: rc = SQLITE_CORRUPT;
20534: }
20535: sqlite3_free(zErr);
20536: free(zQ2);
20537: }
20538: return rc;
20539: }
20540:
20541: /*
20542: ** Text of help messages.
20543: **
20544: ** The help text for each individual command begins with a line that starts
1.6.2.1 ! misho 20545: ** with ".". Subsequent lines are supplemental information.
1.5 misho 20546: **
20547: ** There must be two or more spaces between the end of the command and the
20548: ** start of the description of what that command does.
20549: */
20550: static const char *(azHelp[]) = {
1.6.2.1 ! misho 20551: #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE) \
! 20552: && !defined(SQLITE_SHELL_FIDDLE)
1.5 misho 20553: ".archive ... Manage SQL archives",
20554: " Each command must have exactly one of the following options:",
20555: " -c, --create Create a new archive",
20556: " -u, --update Add or update files with changed mtime",
20557: " -i, --insert Like -u but always add even if unchanged",
1.6.2.1 ! misho 20558: " -r, --remove Remove files from archive",
1.5 misho 20559: " -t, --list List contents of archive",
20560: " -x, --extract Extract files from archive",
20561: " Optional arguments:",
20562: " -v, --verbose Print each filename as it is processed",
20563: " -f FILE, --file FILE Use archive FILE (default is current db)",
20564: " -a FILE, --append FILE Open FILE using the apndvfs VFS",
20565: " -C DIR, --directory DIR Read/extract files from directory DIR",
1.6.2.1 ! misho 20566: " -g, --glob Use glob matching for names in archive",
1.5 misho 20567: " -n, --dryrun Show the SQL that would have occurred",
20568: " Examples:",
20569: " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
20570: " .ar -tf ARCHIVE # List members of ARCHIVE",
20571: " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE",
20572: " See also:",
1.6.2.1 ! misho 20573: " http://sqlite.org/cli.html#sqlite_archive_support",
1.5 misho 20574: #endif
20575: #ifndef SQLITE_OMIT_AUTHORIZATION
20576: ".auth ON|OFF Show authorizer callbacks",
20577: #endif
1.6.2.1 ! misho 20578: #ifndef SQLITE_SHELL_FIDDLE
1.5 misho 20579: ".backup ?DB? FILE Backup DB (default \"main\") to FILE",
1.6.2.1 ! misho 20580: " Options:",
1.5 misho 20581: " --append Use the appendvfs",
20582: " --async Write to FILE without journal and fsync()",
1.6.2.1 ! misho 20583: #endif
1.5 misho 20584: ".bail on|off Stop after hitting an error. Default OFF",
1.6.2.1 ! misho 20585: #ifndef SQLITE_SHELL_FIDDLE
1.5 misho 20586: ".cd DIRECTORY Change the working directory to DIRECTORY",
1.6.2.1 ! misho 20587: #endif
1.5 misho 20588: ".changes on|off Show number of rows changed by SQL",
1.6.2.1 ! misho 20589: #ifndef SQLITE_SHELL_FIDDLE
1.5 misho 20590: ".check GLOB Fail if output since .testcase does not match",
20591: ".clone NEWDB Clone data into NEWDB from the existing database",
1.6.2.1 ! misho 20592: #endif
! 20593: ".connection [close] [#] Open or close an auxiliary database connection",
! 20594: #if defined(_WIN32) || defined(WIN32)
! 20595: ".crnl on|off Translate \\n to \\r\\n. Default ON",
! 20596: #endif
1.5 misho 20597: ".databases List names and files of attached databases",
20598: ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
1.6.2.1 ! misho 20599: #if SQLITE_SHELL_HAVE_RECOVER
1.5 misho 20600: ".dbinfo ?DB? Show status information about the database",
1.6.2.1 ! misho 20601: #endif
1.6 misho 20602: ".dump ?OBJECTS? Render database content as SQL",
1.5 misho 20603: " Options:",
1.6 misho 20604: " --data-only Output only INSERT statements",
20605: " --newlines Allow unescaped newline characters in output",
20606: " --nosys Omit system tables (ex: \"sqlite_stat1\")",
1.5 misho 20607: " --preserve-rowids Include ROWID values in the output",
1.6 misho 20608: " OBJECTS is a LIKE pattern for tables, indexes, triggers or views to dump",
1.5 misho 20609: " Additional LIKE patterns can be given in subsequent arguments",
20610: ".echo on|off Turn command echo on or off",
20611: ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
20612: " Other Modes:",
20613: #ifdef SQLITE_DEBUG
20614: " test Show raw EXPLAIN QUERY PLAN output",
20615: " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"",
20616: #endif
20617: " trigger Like \"full\" but also show trigger bytecode",
1.6.2.1 ! misho 20618: #ifndef SQLITE_SHELL_FIDDLE
1.5 misho 20619: ".excel Display the output of next command in spreadsheet",
20620: " --bom Put a UTF8 byte-order mark on intermediate file",
1.6.2.1 ! misho 20621: #endif
! 20622: #ifndef SQLITE_SHELL_FIDDLE
1.5 misho 20623: ".exit ?CODE? Exit this program with return-code CODE",
1.6.2.1 ! misho 20624: #endif
1.5 misho 20625: ".expert EXPERIMENTAL. Suggest indexes for queries",
20626: ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto",
20627: ".filectrl CMD ... Run various sqlite3_file_control() operations",
20628: " --schema SCHEMA Use SCHEMA instead of \"main\"",
20629: " --help Show CMD details",
20630: ".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
20631: ".headers on|off Turn display of headers on or off",
20632: ".help ?-all? ?PATTERN? Show help text for PATTERN",
1.6.2.1 ! misho 20633: #ifndef SQLITE_SHELL_FIDDLE
1.5 misho 20634: ".import FILE TABLE Import data from FILE into TABLE",
20635: " Options:",
20636: " --ascii Use \\037 and \\036 as column and row separators",
20637: " --csv Use , and \\n as column and row separators",
20638: " --skip N Skip the first N rows of input",
1.6.2.1 ! misho 20639: " --schema S Target table to be S.TABLE",
1.5 misho 20640: " -v \"Verbose\" - increase auxiliary output",
20641: " Notes:",
20642: " * If TABLE does not exist, it is created. The first row of input",
20643: " determines the column names.",
20644: " * If neither --csv or --ascii are used, the input mode is derived",
20645: " from the \".mode\" output mode",
20646: " * If FILE begins with \"|\" then it is a command that generates the",
20647: " input text.",
1.6.2.1 ! misho 20648: #endif
1.5 misho 20649: #ifndef SQLITE_OMIT_TEST_CONTROL
1.6.2.1 ! misho 20650: ",imposter INDEX TABLE Create imposter table TABLE on index INDEX",
1.5 misho 20651: #endif
20652: ".indexes ?TABLE? Show names of indexes",
20653: " If TABLE is specified, only show indexes for",
20654: " tables matching TABLE using the LIKE operator.",
20655: #ifdef SQLITE_ENABLE_IOTRACE
1.6.2.1 ! misho 20656: ",iotrace FILE Enable I/O diagnostic logging to FILE",
1.5 misho 20657: #endif
20658: ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
20659: ".lint OPTIONS Report potential schema issues.",
20660: " Options:",
20661: " fkey-indexes Find missing foreign key indexes",
1.6.2.1 ! misho 20662: #if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_FIDDLE)
1.5 misho 20663: ".load FILE ?ENTRY? Load an extension library",
20664: #endif
1.6.2.1 ! misho 20665: #if !defined(SQLITE_SHELL_FIDDLE)
! 20666: ".log FILE|on|off Turn logging on or off. FILE can be stderr/stdout",
! 20667: #else
! 20668: ".log on|off Turn logging on or off.",
! 20669: #endif
! 20670: ".mode MODE ?OPTIONS? Set output mode",
1.5 misho 20671: " MODE is one of:",
1.6.2.1 ! misho 20672: " ascii Columns/rows delimited by 0x1F and 0x1E",
! 20673: " box Tables using unicode box-drawing characters",
! 20674: " csv Comma-separated values",
! 20675: " column Output in columns. (See .width)",
! 20676: " html HTML <table> code",
! 20677: " insert SQL insert statements for TABLE",
! 20678: " json Results in a JSON array",
! 20679: " line One value per line",
! 20680: " list Values delimited by \"|\"",
! 20681: " markdown Markdown table format",
! 20682: " qbox Shorthand for \"box --wrap 60 --quote\"",
! 20683: " quote Escape answers as for SQL",
! 20684: " table ASCII-art table",
! 20685: " tabs Tab-separated values",
! 20686: " tcl TCL list elements",
! 20687: " OPTIONS: (for columnar modes or insert mode):",
! 20688: " --wrap N Wrap output lines to no longer than N characters",
! 20689: " --wordwrap B Wrap or not at word boundaries per B (on/off)",
! 20690: " --ww Shorthand for \"--wordwrap 1\"",
! 20691: " --quote Quote output text as SQL literals",
! 20692: " --noquote Do not quote output text",
! 20693: " TABLE The name of SQL table used for \"insert\" mode",
! 20694: #ifndef SQLITE_SHELL_FIDDLE
! 20695: ".nonce STRING Suspend safe mode for one command if nonce matches",
! 20696: #endif
1.5 misho 20697: ".nullvalue STRING Use STRING in place of NULL values",
1.6.2.1 ! misho 20698: #ifndef SQLITE_SHELL_FIDDLE
1.5 misho 20699: ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE",
20700: " If FILE begins with '|' then open as a pipe",
20701: " --bom Put a UTF8 byte-order mark at the beginning",
20702: " -e Send output to the system text editor",
20703: " -x Send output as CSV to a spreadsheet (same as \".excel\")",
1.6.2.1 ! misho 20704: /* Note that .open is (partially) available in WASM builds but is
! 20705: ** currently only intended to be used by the fiddle tool, not
! 20706: ** end users, so is "undocumented." */
1.5 misho 20707: ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
20708: " Options:",
20709: " --append Use appendvfs to append database to the end of FILE",
1.6.2.1 ! misho 20710: #endif
! 20711: #ifndef SQLITE_OMIT_DESERIALIZE
! 20712: " --deserialize Load into memory using sqlite3_deserialize()",
1.5 misho 20713: " --hexdb Load the output of \"dbtotxt\" as an in-memory db",
20714: " --maxsize N Maximum size for --hexdb or --deserialized database",
20715: #endif
20716: " --new Initialize FILE to an empty database",
20717: " --nofollow Do not follow symbolic links",
20718: " --readonly Open FILE readonly",
20719: " --zip FILE is a ZIP archive",
1.6.2.1 ! misho 20720: #ifndef SQLITE_SHELL_FIDDLE
1.5 misho 20721: ".output ?FILE? Send output to FILE or stdout if FILE is omitted",
20722: " If FILE begins with '|' then open it as a pipe.",
20723: " Options:",
20724: " --bom Prefix output with a UTF8 byte-order mark",
20725: " -e Send output to the system text editor",
20726: " -x Send output as CSV to a spreadsheet",
1.6.2.1 ! misho 20727: #endif
1.5 misho 20728: ".parameter CMD ... Manage SQL parameter bindings",
20729: " clear Erase all bindings",
20730: " init Initialize the TEMP table that holds bindings",
20731: " list List the current parameter bindings",
20732: " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE",
20733: " PARAMETER should start with one of: $ : @ ?",
20734: " unset PARAMETER Remove PARAMETER from the binding table",
20735: ".print STRING... Print literal STRING",
20736: #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
20737: ".progress N Invoke progress handler after every N opcodes",
20738: " --limit N Interrupt after N progress callbacks",
20739: " --once Do no more than one progress interrupt",
20740: " --quiet|-q No output except at interrupts",
20741: " --reset Reset the count for each input and interrupt",
20742: #endif
20743: ".prompt MAIN CONTINUE Replace the standard prompts",
1.6.2.1 ! misho 20744: #ifndef SQLITE_SHELL_FIDDLE
! 20745: ".quit Stop interpreting input stream, exit if primary.",
! 20746: ".read FILE Read input from FILE or command output",
! 20747: " If FILE begins with \"|\", it is a command that generates the input.",
! 20748: #endif
! 20749: #if SQLITE_SHELL_HAVE_RECOVER
1.5 misho 20750: ".recover Recover as much data as possible from corrupt db.",
1.6.2.1 ! misho 20751: " --ignore-freelist Ignore pages that appear to be on db freelist",
1.5 misho 20752: " --lost-and-found TABLE Alternative name for the lost-and-found table",
20753: " --no-rowids Do not attempt to recover rowid values",
20754: " that are not also INTEGER PRIMARY KEYs",
20755: #endif
1.6.2.1 ! misho 20756: #ifndef SQLITE_SHELL_FIDDLE
1.5 misho 20757: ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
1.6.2.1 ! misho 20758: ".save ?OPTIONS? FILE Write database to FILE (an alias for .backup ...)",
! 20759: #endif
! 20760: ".scanstats on|off|est Turn sqlite3_stmt_scanstatus() metrics on or off",
1.5 misho 20761: ".schema ?PATTERN? Show the CREATE statements matching PATTERN",
1.6 misho 20762: " Options:",
20763: " --indent Try to pretty-print the schema",
20764: " --nosys Omit objects whose names start with \"sqlite_\"",
1.6.2.1 ! misho 20765: ",selftest ?OPTIONS? Run tests defined in the SELFTEST table",
1.5 misho 20766: " Options:",
20767: " --init Create a new SELFTEST table",
20768: " -v Verbose output",
20769: ".separator COL ?ROW? Change the column and row separators",
20770: #if defined(SQLITE_ENABLE_SESSION)
20771: ".session ?NAME? CMD ... Create or control sessions",
20772: " Subcommands:",
20773: " attach TABLE Attach TABLE",
20774: " changeset FILE Write a changeset into FILE",
20775: " close Close one session",
20776: " enable ?BOOLEAN? Set or query the enable bit",
20777: " filter GLOB... Reject tables matching GLOBs",
20778: " indirect ?BOOLEAN? Mark or query the indirect status",
20779: " isempty Query whether the session is empty",
20780: " list List currently open session names",
20781: " open DB NAME Open a new session on DB",
20782: " patchset FILE Write a patchset into FILE",
20783: " If ?NAME? is omitted, the first defined session is used.",
20784: #endif
20785: ".sha3sum ... Compute a SHA3 hash of database content",
20786: " Options:",
20787: " --schema Also hash the sqlite_schema table",
20788: " --sha3-224 Use the sha3-224 algorithm",
20789: " --sha3-256 Use the sha3-256 algorithm (default)",
20790: " --sha3-384 Use the sha3-384 algorithm",
20791: " --sha3-512 Use the sha3-512 algorithm",
20792: " Any other argument is a LIKE pattern for tables to hash",
1.6.2.1 ! misho 20793: #if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
1.5 misho 20794: ".shell CMD ARGS... Run CMD ARGS... in a system shell",
20795: #endif
20796: ".show Show the current values for various settings",
1.6 misho 20797: ".stats ?ARG? Show stats or turn stats on or off",
20798: " off Turn off automatic stat display",
20799: " on Turn on automatic stat display",
20800: " stmt Show statement stats",
20801: " vmstep Show the virtual machine step count only",
1.6.2.1 ! misho 20802: #if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
1.5 misho 20803: ".system CMD ARGS... Run CMD ARGS... in a system shell",
20804: #endif
20805: ".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
1.6.2.1 ! misho 20806: #ifndef SQLITE_SHELL_FIDDLE
! 20807: ",testcase NAME Begin redirecting output to 'testcase-out.txt'",
! 20808: #endif
! 20809: ",testctrl CMD ... Run various sqlite3_test_control() operations",
1.5 misho 20810: " Run \".testctrl\" with no arguments for details",
20811: ".timeout MS Try opening locked tables for MS milliseconds",
20812: ".timer on|off Turn SQL timer on or off",
20813: #ifndef SQLITE_OMIT_TRACE
20814: ".trace ?OPTIONS? Output each SQL statement as it is run",
20815: " FILE Send output to FILE",
20816: " stdout Send output to stdout",
20817: " stderr Send output to stderr",
20818: " off Disable tracing",
20819: " --expanded Expand query parameters",
20820: #ifdef SQLITE_ENABLE_NORMALIZE
20821: " --normalized Normal the SQL statements",
20822: #endif
20823: " --plain Show SQL as it is input",
20824: " --stmt Trace statement execution (SQLITE_TRACE_STMT)",
20825: " --profile Profile statements (SQLITE_TRACE_PROFILE)",
20826: " --row Trace each row (SQLITE_TRACE_ROW)",
20827: " --close Trace connection close (SQLITE_TRACE_CLOSE)",
20828: #endif /* SQLITE_OMIT_TRACE */
20829: #ifdef SQLITE_DEBUG
20830: ".unmodule NAME ... Unregister virtual table modules",
20831: " --allexcept Unregister everything except those named",
20832: #endif
1.6.2.1 ! misho 20833: ".version Show source, library and compiler versions",
1.5 misho 20834: ".vfsinfo ?AUX? Information about the top-level VFS",
20835: ".vfslist List all available VFSes",
20836: ".vfsname ?AUX? Print the name of the VFS stack",
20837: ".width NUM1 NUM2 ... Set minimum column widths for columnar output",
20838: " Negative values right-justify",
20839: };
20840:
20841: /*
20842: ** Output help text.
20843: **
20844: ** zPattern describes the set of commands for which help text is provided.
20845: ** If zPattern is NULL, then show all commands, but only give a one-line
20846: ** description of each.
20847: **
20848: ** Return the number of matches.
20849: */
20850: static int showHelp(FILE *out, const char *zPattern){
20851: int i = 0;
20852: int j = 0;
20853: int n = 0;
20854: char *zPat;
20855: if( zPattern==0
20856: || zPattern[0]=='0'
1.6.2.1 ! misho 20857: || cli_strcmp(zPattern,"-a")==0
! 20858: || cli_strcmp(zPattern,"-all")==0
! 20859: || cli_strcmp(zPattern,"--all")==0
1.5 misho 20860: ){
1.6.2.1 ! misho 20861: enum HelpWanted { HW_NoCull = 0, HW_SummaryOnly = 1, HW_Undoc = 2 };
! 20862: enum HelpHave { HH_Undoc = 2, HH_Summary = 1, HH_More = 0 };
! 20863: /* Show all or most commands
! 20864: ** *zPattern==0 => summary of documented commands only
! 20865: ** *zPattern=='0' => whole help for undocumented commands
! 20866: ** Otherwise => whole help for documented commands
! 20867: */
! 20868: enum HelpWanted hw = HW_SummaryOnly;
! 20869: enum HelpHave hh = HH_More;
! 20870: if( zPattern!=0 ){
! 20871: hw = (*zPattern=='0')? HW_NoCull|HW_Undoc : HW_NoCull;
! 20872: }
1.5 misho 20873: for(i=0; i<ArraySize(azHelp); i++){
1.6.2.1 ! misho 20874: switch( azHelp[i][0] ){
! 20875: case ',':
! 20876: hh = HH_Summary|HH_Undoc;
! 20877: break;
! 20878: case '.':
! 20879: hh = HH_Summary;
! 20880: break;
! 20881: default:
! 20882: hh &= ~HH_Summary;
! 20883: break;
! 20884: }
! 20885: if( ((hw^hh)&HH_Undoc)==0 ){
! 20886: if( (hh&HH_Summary)!=0 ){
! 20887: utf8_printf(out, ".%s\n", azHelp[i]+1);
! 20888: ++n;
! 20889: }else if( (hw&HW_SummaryOnly)==0 ){
! 20890: utf8_printf(out, "%s\n", azHelp[i]);
! 20891: }
1.5 misho 20892: }
20893: }
20894: }else{
1.6.2.1 ! misho 20895: /* Seek documented commands for which zPattern is an exact prefix */
1.5 misho 20896: zPat = sqlite3_mprintf(".%s*", zPattern);
1.6.2.1 ! misho 20897: shell_check_oom(zPat);
1.5 misho 20898: for(i=0; i<ArraySize(azHelp); i++){
20899: if( sqlite3_strglob(zPat, azHelp[i])==0 ){
20900: utf8_printf(out, "%s\n", azHelp[i]);
20901: j = i+1;
20902: n++;
20903: }
20904: }
20905: sqlite3_free(zPat);
20906: if( n ){
20907: if( n==1 ){
1.6.2.1 ! misho 20908: /* when zPattern is a prefix of exactly one command, then include
! 20909: ** the details of that command, which should begin at offset j */
! 20910: while( j<ArraySize(azHelp)-1 && azHelp[j][0]==' ' ){
1.5 misho 20911: utf8_printf(out, "%s\n", azHelp[j]);
20912: j++;
20913: }
20914: }
20915: return n;
20916: }
1.6.2.1 ! misho 20917: /* Look for documented commands that contain zPattern anywhere.
! 20918: ** Show complete text of all documented commands that match. */
1.5 misho 20919: zPat = sqlite3_mprintf("%%%s%%", zPattern);
1.6.2.1 ! misho 20920: shell_check_oom(zPat);
1.5 misho 20921: for(i=0; i<ArraySize(azHelp); i++){
1.6.2.1 ! misho 20922: if( azHelp[i][0]==',' ){
! 20923: while( i<ArraySize(azHelp)-1 && azHelp[i+1][0]==' ' ) ++i;
! 20924: continue;
! 20925: }
1.5 misho 20926: if( azHelp[i][0]=='.' ) j = i;
20927: if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
20928: utf8_printf(out, "%s\n", azHelp[j]);
1.6.2.1 ! misho 20929: while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]==' ' ){
1.5 misho 20930: j++;
20931: utf8_printf(out, "%s\n", azHelp[j]);
20932: }
20933: i = j;
20934: n++;
20935: }
20936: }
20937: sqlite3_free(zPat);
20938: }
20939: return n;
20940: }
20941:
20942: /* Forward reference */
20943: static int process_input(ShellState *p);
20944:
20945: /*
20946: ** Read the content of file zName into memory obtained from sqlite3_malloc64()
20947: ** and return a pointer to the buffer. The caller is responsible for freeing
20948: ** the memory.
20949: **
20950: ** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
20951: ** read.
20952: **
20953: ** For convenience, a nul-terminator byte is always appended to the data read
20954: ** from the file before the buffer is returned. This byte is not included in
20955: ** the final value of (*pnByte), if applicable.
20956: **
20957: ** NULL is returned if any error is encountered. The final value of *pnByte
20958: ** is undefined in this case.
20959: */
20960: static char *readFile(const char *zName, int *pnByte){
20961: FILE *in = fopen(zName, "rb");
20962: long nIn;
20963: size_t nRead;
20964: char *pBuf;
1.6.2.1 ! misho 20965: int rc;
1.5 misho 20966: if( in==0 ) return 0;
1.6.2.1 ! misho 20967: rc = fseek(in, 0, SEEK_END);
! 20968: if( rc!=0 ){
! 20969: raw_printf(stderr, "Error: '%s' not seekable\n", zName);
! 20970: fclose(in);
! 20971: return 0;
! 20972: }
1.5 misho 20973: nIn = ftell(in);
20974: rewind(in);
20975: pBuf = sqlite3_malloc64( nIn+1 );
1.6.2.1 ! misho 20976: if( pBuf==0 ){
! 20977: raw_printf(stderr, "Error: out of memory\n");
! 20978: fclose(in);
! 20979: return 0;
! 20980: }
1.5 misho 20981: nRead = fread(pBuf, nIn, 1, in);
20982: fclose(in);
20983: if( nRead!=1 ){
20984: sqlite3_free(pBuf);
1.6.2.1 ! misho 20985: raw_printf(stderr, "Error: cannot read '%s'\n", zName);
1.5 misho 20986: return 0;
20987: }
20988: pBuf[nIn] = 0;
20989: if( pnByte ) *pnByte = nIn;
20990: return pBuf;
20991: }
20992:
20993: #if defined(SQLITE_ENABLE_SESSION)
20994: /*
20995: ** Close a single OpenSession object and release all of its associated
20996: ** resources.
20997: */
20998: static void session_close(OpenSession *pSession){
20999: int i;
21000: sqlite3session_delete(pSession->p);
21001: sqlite3_free(pSession->zName);
21002: for(i=0; i<pSession->nFilter; i++){
21003: sqlite3_free(pSession->azFilter[i]);
21004: }
21005: sqlite3_free(pSession->azFilter);
21006: memset(pSession, 0, sizeof(OpenSession));
21007: }
21008: #endif
21009:
21010: /*
21011: ** Close all OpenSession objects and release all associated resources.
21012: */
21013: #if defined(SQLITE_ENABLE_SESSION)
1.6.2.1 ! misho 21014: static void session_close_all(ShellState *p, int i){
! 21015: int j;
! 21016: struct AuxDb *pAuxDb = i<0 ? p->pAuxDb : &p->aAuxDb[i];
! 21017: for(j=0; j<pAuxDb->nSession; j++){
! 21018: session_close(&pAuxDb->aSession[j]);
1.5 misho 21019: }
1.6.2.1 ! misho 21020: pAuxDb->nSession = 0;
1.5 misho 21021: }
21022: #else
1.6.2.1 ! misho 21023: # define session_close_all(X,Y)
1.5 misho 21024: #endif
21025:
21026: /*
21027: ** Implementation of the xFilter function for an open session. Omit
21028: ** any tables named by ".session filter" but let all other table through.
21029: */
21030: #if defined(SQLITE_ENABLE_SESSION)
21031: static int session_filter(void *pCtx, const char *zTab){
21032: OpenSession *pSession = (OpenSession*)pCtx;
21033: int i;
21034: for(i=0; i<pSession->nFilter; i++){
21035: if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
21036: }
21037: return 1;
21038: }
21039: #endif
21040:
21041: /*
21042: ** Try to deduce the type of file for zName based on its content. Return
21043: ** one of the SHELL_OPEN_* constants.
21044: **
21045: ** If the file does not exist or is empty but its name looks like a ZIP
21046: ** archive and the dfltZip flag is true, then assume it is a ZIP archive.
21047: ** Otherwise, assume an ordinary database regardless of the filename if
21048: ** the type cannot be determined from content.
21049: */
21050: int deduceDatabaseType(const char *zName, int dfltZip){
21051: FILE *f = fopen(zName, "rb");
21052: size_t n;
21053: int rc = SHELL_OPEN_UNSPEC;
21054: char zBuf[100];
21055: if( f==0 ){
21056: if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
21057: return SHELL_OPEN_ZIPFILE;
21058: }else{
21059: return SHELL_OPEN_NORMAL;
21060: }
21061: }
21062: n = fread(zBuf, 16, 1, f);
21063: if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
21064: fclose(f);
21065: return SHELL_OPEN_NORMAL;
21066: }
21067: fseek(f, -25, SEEK_END);
21068: n = fread(zBuf, 25, 1, f);
21069: if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
21070: rc = SHELL_OPEN_APPENDVFS;
21071: }else{
21072: fseek(f, -22, SEEK_END);
21073: n = fread(zBuf, 22, 1, f);
21074: if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
21075: && zBuf[3]==0x06 ){
21076: rc = SHELL_OPEN_ZIPFILE;
21077: }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
21078: rc = SHELL_OPEN_ZIPFILE;
21079: }
21080: }
21081: fclose(f);
1.6.2.1 ! misho 21082: return rc;
1.5 misho 21083: }
21084:
1.6.2.1 ! misho 21085: #ifndef SQLITE_OMIT_DESERIALIZE
1.5 misho 21086: /*
21087: ** Reconstruct an in-memory database using the output from the "dbtotxt"
1.6.2.1 ! misho 21088: ** program. Read content from the file in p->aAuxDb[].zDbFilename.
! 21089: ** If p->aAuxDb[].zDbFilename is 0, then read from standard input.
1.5 misho 21090: */
21091: static unsigned char *readHexDb(ShellState *p, int *pnData){
21092: unsigned char *a = 0;
21093: int nLine;
21094: int n = 0;
21095: int pgsz = 0;
21096: int iOffset = 0;
21097: int j, k;
21098: int rc;
21099: FILE *in;
1.6.2.1 ! misho 21100: const char *zDbFilename = p->pAuxDb->zDbFilename;
1.5 misho 21101: unsigned int x[16];
21102: char zLine[1000];
1.6.2.1 ! misho 21103: if( zDbFilename ){
! 21104: in = fopen(zDbFilename, "r");
1.5 misho 21105: if( in==0 ){
1.6.2.1 ! misho 21106: utf8_printf(stderr, "cannot open \"%s\" for reading\n", zDbFilename);
1.5 misho 21107: return 0;
21108: }
21109: nLine = 0;
21110: }else{
21111: in = p->in;
21112: nLine = p->lineno;
21113: if( in==0 ) in = stdin;
21114: }
21115: *pnData = 0;
21116: nLine++;
21117: if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
21118: rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
21119: if( rc!=2 ) goto readHexDb_error;
21120: if( n<0 ) goto readHexDb_error;
21121: if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
21122: n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */
21123: a = sqlite3_malloc( n ? n : 1 );
1.6.2.1 ! misho 21124: shell_check_oom(a);
1.5 misho 21125: memset(a, 0, n);
21126: if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
21127: utf8_printf(stderr, "invalid pagesize\n");
21128: goto readHexDb_error;
21129: }
21130: for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
21131: rc = sscanf(zLine, "| page %d offset %d", &j, &k);
21132: if( rc==2 ){
21133: iOffset = k;
21134: continue;
21135: }
1.6.2.1 ! misho 21136: if( cli_strncmp(zLine, "| end ", 6)==0 ){
1.5 misho 21137: break;
21138: }
21139: rc = sscanf(zLine,"| %d: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
21140: &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
1.6.2.1 ! misho 21141: &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
! 21142: if( rc==17 ){
! 21143: k = iOffset+j;
! 21144: if( k+16<=n && k>=0 ){
! 21145: int ii;
! 21146: for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
1.5 misho 21147: }
1.6.2.1 ! misho 21148: }
! 21149: }
! 21150: *pnData = n;
! 21151: if( in!=p->in ){
! 21152: fclose(in);
! 21153: }else{
! 21154: p->lineno = nLine;
! 21155: }
! 21156: return a;
1.5 misho 21157:
1.6.2.1 ! misho 21158: readHexDb_error:
! 21159: if( in!=p->in ){
! 21160: fclose(in);
! 21161: }else{
! 21162: while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
! 21163: nLine++;
! 21164: if(cli_strncmp(zLine, "| end ", 6)==0 ) break;
1.4 misho 21165: }
1.6.2.1 ! misho 21166: p->lineno = nLine;
1.5 misho 21167: }
1.6.2.1 ! misho 21168: sqlite3_free(a);
! 21169: utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
! 21170: return 0;
! 21171: }
! 21172: #endif /* SQLITE_OMIT_DESERIALIZE */
1.5 misho 21173:
1.6.2.1 ! misho 21174: /*
! 21175: ** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
! 21176: */
! 21177: static void shellUSleepFunc(
! 21178: sqlite3_context *context,
! 21179: int argcUnused,
! 21180: sqlite3_value **argv
! 21181: ){
! 21182: int sleep = sqlite3_value_int(argv[0]);
! 21183: (void)argcUnused;
! 21184: sqlite3_sleep(sleep/1000);
! 21185: sqlite3_result_int(context, sleep);
1.5 misho 21186: }
21187:
21188: /* Flags for open_db().
21189: **
21190: ** The default behavior of open_db() is to exit(1) if the database fails to
21191: ** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
21192: ** but still returns without calling exit.
21193: **
21194: ** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a
21195: ** ZIP archive if the file does not exist or is empty and its name matches
21196: ** the *.zip pattern.
21197: */
21198: #define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */
21199: #define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */
21200:
21201: /*
21202: ** Make sure the database is open. If it is not, then open it. If
21203: ** the database fails to open, print an error message and exit.
21204: */
21205: static void open_db(ShellState *p, int openFlags){
21206: if( p->db==0 ){
1.6.2.1 ! misho 21207: const char *zDbFilename = p->pAuxDb->zDbFilename;
1.5 misho 21208: if( p->openMode==SHELL_OPEN_UNSPEC ){
1.6.2.1 ! misho 21209: if( zDbFilename==0 || zDbFilename[0]==0 ){
1.5 misho 21210: p->openMode = SHELL_OPEN_NORMAL;
21211: }else{
1.6.2.1 ! misho 21212: p->openMode = (u8)deduceDatabaseType(zDbFilename,
1.5 misho 21213: (openFlags & OPEN_DB_ZIPFILE)!=0);
21214: }
1.4 misho 21215: }
1.5 misho 21216: switch( p->openMode ){
21217: case SHELL_OPEN_APPENDVFS: {
1.6.2.1 ! misho 21218: sqlite3_open_v2(zDbFilename, &p->db,
1.5 misho 21219: SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
21220: break;
21221: }
21222: case SHELL_OPEN_HEXDB:
21223: case SHELL_OPEN_DESERIALIZE: {
21224: sqlite3_open(0, &p->db);
21225: break;
21226: }
21227: case SHELL_OPEN_ZIPFILE: {
21228: sqlite3_open(":memory:", &p->db);
21229: break;
21230: }
21231: case SHELL_OPEN_READONLY: {
1.6.2.1 ! misho 21232: sqlite3_open_v2(zDbFilename, &p->db,
1.5 misho 21233: SQLITE_OPEN_READONLY|p->openFlags, 0);
1.4 misho 21234: break;
21235: }
1.5 misho 21236: case SHELL_OPEN_UNSPEC:
21237: case SHELL_OPEN_NORMAL: {
1.6.2.1 ! misho 21238: sqlite3_open_v2(zDbFilename, &p->db,
1.5 misho 21239: SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
21240: break;
1.4 misho 21241: }
1.5 misho 21242: }
21243: globalDb = p->db;
21244: if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
21245: utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
1.6.2.1 ! misho 21246: zDbFilename, sqlite3_errmsg(p->db));
! 21247: if( (openFlags & OPEN_DB_KEEPALIVE)==0 ){
! 21248: exit(1);
! 21249: }
! 21250: sqlite3_close(p->db);
! 21251: sqlite3_open(":memory:", &p->db);
! 21252: if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
! 21253: utf8_printf(stderr,
! 21254: "Also: unable to open substitute in-memory database.\n"
! 21255: );
! 21256: exit(1);
! 21257: }else{
! 21258: utf8_printf(stderr,
! 21259: "Notice: using substitute in-memory database instead of \"%s\"\n",
! 21260: zDbFilename);
1.2 misho 21261: }
21262: }
1.6.2.1 ! misho 21263: sqlite3_db_config(p->db, SQLITE_DBCONFIG_STMT_SCANSTATUS, (int)0, (int*)0);
! 21264:
! 21265: /* Reflect the use or absence of --unsafe-testing invocation. */
! 21266: {
! 21267: int testmode_on = ShellHasFlag(p,SHFLG_TestingMode);
! 21268: sqlite3_db_config(p->db, SQLITE_DBCONFIG_TRUSTED_SCHEMA, testmode_on,0);
! 21269: sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, !testmode_on,0);
! 21270: }
! 21271:
1.5 misho 21272: #ifndef SQLITE_OMIT_LOAD_EXTENSION
21273: sqlite3_enable_load_extension(p->db, 1);
21274: #endif
21275: sqlite3_shathree_init(p->db, 0, 0);
21276: sqlite3_uint_init(p->db, 0, 0);
21277: sqlite3_decimal_init(p->db, 0, 0);
1.6.2.1 ! misho 21278: sqlite3_base64_init(p->db, 0, 0);
! 21279: sqlite3_base85_init(p->db, 0, 0);
! 21280: sqlite3_regexp_init(p->db, 0, 0);
1.5 misho 21281: sqlite3_ieee_init(p->db, 0, 0);
1.6 misho 21282: sqlite3_series_init(p->db, 0, 0);
1.6.2.1 ! misho 21283: #ifndef SQLITE_SHELL_FIDDLE
! 21284: sqlite3_fileio_init(p->db, 0, 0);
! 21285: sqlite3_completion_init(p->db, 0, 0);
1.5 misho 21286: #endif
21287: #ifdef SQLITE_HAVE_ZLIB
1.6.2.1 ! misho 21288: if( !p->bSafeModePersist ){
! 21289: sqlite3_zipfile_init(p->db, 0, 0);
! 21290: sqlite3_sqlar_init(p->db, 0, 0);
! 21291: }
! 21292: #endif
! 21293: #ifdef SQLITE_SHELL_EXTFUNCS
! 21294: /* Create a preprocessing mechanism for extensions to make
! 21295: * their own provisions for being built into the shell.
! 21296: * This is a short-span macro. See further below for usage.
! 21297: */
! 21298: #define SHELL_SUB_MACRO(base, variant) base ## _ ## variant
! 21299: #define SHELL_SUBMACRO(base, variant) SHELL_SUB_MACRO(base, variant)
! 21300: /* Let custom-included extensions get their ..._init() called.
! 21301: * The WHATEVER_INIT( db, pzErrorMsg, pApi ) macro should cause
! 21302: * the extension's sqlite3_*_init( db, pzErrorMsg, pApi )
! 21303: * initialization routine to be called.
! 21304: */
! 21305: {
! 21306: int irc = SHELL_SUBMACRO(SQLITE_SHELL_EXTFUNCS, INIT)(p->db);
! 21307: /* Let custom-included extensions expose their functionality.
! 21308: * The WHATEVER_EXPOSE( db, pzErrorMsg ) macro should cause
! 21309: * the SQL functions, virtual tables, collating sequences or
! 21310: * VFS's implemented by the extension to be registered.
! 21311: */
! 21312: if( irc==SQLITE_OK
! 21313: || irc==SQLITE_OK_LOAD_PERMANENTLY ){
! 21314: SHELL_SUBMACRO(SQLITE_SHELL_EXTFUNCS, EXPOSE)(p->db, 0);
! 21315: }
! 21316: #undef SHELL_SUB_MACRO
! 21317: #undef SHELL_SUBMACRO
! 21318: }
1.5 misho 21319: #endif
1.6.2.1 ! misho 21320:
! 21321: sqlite3_create_function(p->db, "strtod", 1, SQLITE_UTF8, 0,
! 21322: shellStrtod, 0, 0);
! 21323: sqlite3_create_function(p->db, "dtostr", 1, SQLITE_UTF8, 0,
! 21324: shellDtostr, 0, 0);
! 21325: sqlite3_create_function(p->db, "dtostr", 2, SQLITE_UTF8, 0,
! 21326: shellDtostr, 0, 0);
1.5 misho 21327: sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
21328: shellAddSchemaName, 0, 0);
21329: sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
21330: shellModuleSchema, 0, 0);
21331: sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
21332: shellPutsFunc, 0, 0);
1.6 misho 21333: sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
21334: shellUSleepFunc, 0, 0);
1.5 misho 21335: #ifndef SQLITE_NOHAVE_SYSTEM
21336: sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
21337: editFunc, 0, 0);
21338: sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
21339: editFunc, 0, 0);
21340: #endif
1.6.2.1 ! misho 21341:
1.5 misho 21342: if( p->openMode==SHELL_OPEN_ZIPFILE ){
21343: char *zSql = sqlite3_mprintf(
1.6.2.1 ! misho 21344: "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename);
! 21345: shell_check_oom(zSql);
1.5 misho 21346: sqlite3_exec(p->db, zSql, 0, 0, 0);
21347: sqlite3_free(zSql);
21348: }
1.6.2.1 ! misho 21349: #ifndef SQLITE_OMIT_DESERIALIZE
1.5 misho 21350: else
21351: if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
21352: int rc;
21353: int nData = 0;
21354: unsigned char *aData;
21355: if( p->openMode==SHELL_OPEN_DESERIALIZE ){
1.6.2.1 ! misho 21356: aData = (unsigned char*)readFile(zDbFilename, &nData);
1.5 misho 21357: }else{
21358: aData = readHexDb(p, &nData);
1.6.2.1 ! misho 21359: }
! 21360: if( aData==0 ){
! 21361: return;
1.2 misho 21362: }
1.5 misho 21363: rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
21364: SQLITE_DESERIALIZE_RESIZEABLE |
21365: SQLITE_DESERIALIZE_FREEONCLOSE);
21366: if( rc ){
21367: utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
21368: }
21369: if( p->szMax>0 ){
21370: sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
21371: }
21372: }
21373: #endif
21374: }
1.6.2.1 ! misho 21375: if( p->db!=0 ){
! 21376: if( p->bSafeModePersist ){
! 21377: sqlite3_set_authorizer(p->db, safeModeAuth, p);
! 21378: }
! 21379: sqlite3_db_config(
! 21380: p->db, SQLITE_DBCONFIG_STMT_SCANSTATUS, p->scanstatsOn, (int*)0
! 21381: );
! 21382: }
1.5 misho 21383: }
21384:
21385: /*
1.6.2.1 ! misho 21386: ** Attempt to close the database connection. Report errors.
1.5 misho 21387: */
21388: void close_db(sqlite3 *db){
21389: int rc = sqlite3_close(db);
21390: if( rc ){
21391: utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
21392: rc, sqlite3_errmsg(db));
1.6.2.1 ! misho 21393: }
1.5 misho 21394: }
21395:
21396: #if HAVE_READLINE || HAVE_EDITLINE
21397: /*
21398: ** Readline completion callbacks
21399: */
21400: static char *readline_completion_generator(const char *text, int state){
21401: static sqlite3_stmt *pStmt = 0;
21402: char *zRet;
21403: if( state==0 ){
21404: char *zSql;
21405: sqlite3_finalize(pStmt);
21406: zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
21407: " FROM completion(%Q) ORDER BY 1", text);
1.6.2.1 ! misho 21408: shell_check_oom(zSql);
1.5 misho 21409: sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
21410: sqlite3_free(zSql);
21411: }
21412: if( sqlite3_step(pStmt)==SQLITE_ROW ){
1.6.2.1 ! misho 21413: const char *z = (const char*)sqlite3_column_text(pStmt,0);
! 21414: zRet = z ? strdup(z) : 0;
1.5 misho 21415: }else{
21416: sqlite3_finalize(pStmt);
21417: pStmt = 0;
21418: zRet = 0;
21419: }
21420: return zRet;
21421: }
21422: static char **readline_completion(const char *zText, int iStart, int iEnd){
1.6.2.1 ! misho 21423: (void)iStart;
! 21424: (void)iEnd;
1.5 misho 21425: rl_attempted_completion_over = 1;
21426: return rl_completion_matches(zText, readline_completion_generator);
21427: }
21428:
21429: #elif HAVE_LINENOISE
21430: /*
21431: ** Linenoise completion callback
21432: */
21433: static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
1.6.2.1 ! misho 21434: i64 nLine = strlen(zLine);
! 21435: i64 i, iStart;
1.5 misho 21436: sqlite3_stmt *pStmt = 0;
21437: char *zSql;
21438: char zBuf[1000];
21439:
1.6.2.1 ! misho 21440: if( nLine>(i64)sizeof(zBuf)-30 ) return;
1.5 misho 21441: if( zLine[0]=='.' || zLine[0]=='#') return;
21442: for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
21443: if( i==nLine-1 ) return;
21444: iStart = i+1;
21445: memcpy(zBuf, zLine, iStart);
21446: zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
21447: " FROM completion(%Q,%Q) ORDER BY 1",
21448: &zLine[iStart], zLine);
1.6.2.1 ! misho 21449: shell_check_oom(zSql);
1.5 misho 21450: sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
21451: sqlite3_free(zSql);
21452: sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
21453: while( sqlite3_step(pStmt)==SQLITE_ROW ){
21454: const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
21455: int nCompletion = sqlite3_column_bytes(pStmt, 0);
1.6.2.1 ! misho 21456: if( iStart+nCompletion < (i64)sizeof(zBuf)-1 && zCompletion ){
1.5 misho 21457: memcpy(zBuf+iStart, zCompletion, nCompletion+1);
21458: linenoiseAddCompletion(lc, zBuf);
21459: }
21460: }
21461: sqlite3_finalize(pStmt);
21462: }
21463: #endif
21464:
21465: /*
21466: ** Do C-language style dequoting.
21467: **
21468: ** \a -> alarm
21469: ** \b -> backspace
21470: ** \t -> tab
21471: ** \n -> newline
21472: ** \v -> vertical tab
21473: ** \f -> form feed
21474: ** \r -> carriage return
21475: ** \s -> space
21476: ** \" -> "
21477: ** \' -> '
21478: ** \\ -> backslash
21479: ** \NNN -> ascii character NNN in octal
1.6.2.1 ! misho 21480: ** \xHH -> ascii character HH in hexadecimal
1.5 misho 21481: */
21482: static void resolve_backslashes(char *z){
21483: int i, j;
21484: char c;
21485: while( *z && *z!='\\' ) z++;
21486: for(i=j=0; (c = z[i])!=0; i++, j++){
21487: if( c=='\\' && z[i+1]!=0 ){
21488: c = z[++i];
21489: if( c=='a' ){
21490: c = '\a';
21491: }else if( c=='b' ){
21492: c = '\b';
21493: }else if( c=='t' ){
21494: c = '\t';
21495: }else if( c=='n' ){
21496: c = '\n';
21497: }else if( c=='v' ){
21498: c = '\v';
21499: }else if( c=='f' ){
21500: c = '\f';
21501: }else if( c=='r' ){
21502: c = '\r';
21503: }else if( c=='"' ){
21504: c = '"';
21505: }else if( c=='\'' ){
21506: c = '\'';
21507: }else if( c=='\\' ){
21508: c = '\\';
1.6.2.1 ! misho 21509: }else if( c=='x' ){
! 21510: int nhd = 0, hdv;
! 21511: u8 hv = 0;
! 21512: while( nhd<2 && (c=z[i+1+nhd])!=0 && (hdv=hexDigitValue(c))>=0 ){
! 21513: hv = (u8)((hv<<4)|hdv);
! 21514: ++nhd;
! 21515: }
! 21516: i += nhd;
! 21517: c = (u8)hv;
1.5 misho 21518: }else if( c>='0' && c<='7' ){
21519: c -= '0';
21520: if( z[i+1]>='0' && z[i+1]<='7' ){
21521: i++;
21522: c = (c<<3) + z[i] - '0';
21523: if( z[i+1]>='0' && z[i+1]<='7' ){
21524: i++;
21525: c = (c<<3) + z[i] - '0';
21526: }
1.2 misho 21527: }
21528: }
21529: }
1.5 misho 21530: z[j] = c;
21531: }
21532: if( j<i ) z[j] = 0;
21533: }
21534:
21535: /*
21536: ** Interpret zArg as either an integer or a boolean value. Return 1 or 0
21537: ** for TRUE and FALSE. Return the integer value if appropriate.
21538: */
21539: static int booleanValue(const char *zArg){
21540: int i;
21541: if( zArg[0]=='0' && zArg[1]=='x' ){
21542: for(i=2; hexDigitValue(zArg[i])>=0; i++){}
21543: }else{
21544: for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
21545: }
21546: if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
21547: if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
21548: return 1;
21549: }
21550: if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
21551: return 0;
21552: }
21553: utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
21554: zArg);
21555: return 0;
21556: }
21557:
21558: /*
21559: ** Set or clear a shell flag according to a boolean value.
21560: */
21561: static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){
21562: if( booleanValue(zArg) ){
21563: ShellSetFlag(p, mFlag);
21564: }else{
21565: ShellClearFlag(p, mFlag);
21566: }
21567: }
21568:
21569: /*
21570: ** Close an output file, assuming it is not stderr or stdout
21571: */
21572: static void output_file_close(FILE *f){
21573: if( f && f!=stdout && f!=stderr ) fclose(f);
21574: }
21575:
21576: /*
21577: ** Try to open an output file. The names "stdout" and "stderr" are
21578: ** recognized and do the right thing. NULL is returned if the output
21579: ** filename is "off".
21580: */
21581: static FILE *output_file_open(const char *zFile, int bTextMode){
21582: FILE *f;
1.6.2.1 ! misho 21583: if( cli_strcmp(zFile,"stdout")==0 ){
1.5 misho 21584: f = stdout;
1.6.2.1 ! misho 21585: }else if( cli_strcmp(zFile, "stderr")==0 ){
1.5 misho 21586: f = stderr;
1.6.2.1 ! misho 21587: }else if( cli_strcmp(zFile, "off")==0 ){
1.5 misho 21588: f = 0;
21589: }else{
21590: f = fopen(zFile, bTextMode ? "w" : "wb");
21591: if( f==0 ){
21592: utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
1.2 misho 21593: }
1.5 misho 21594: }
21595: return f;
21596: }
21597:
21598: #ifndef SQLITE_OMIT_TRACE
21599: /*
21600: ** A routine for handling output from sqlite3_trace().
21601: */
21602: static int sql_trace_callback(
21603: unsigned mType, /* The trace type */
21604: void *pArg, /* The ShellState pointer */
21605: void *pP, /* Usually a pointer to sqlite_stmt */
21606: void *pX /* Auxiliary output */
21607: ){
21608: ShellState *p = (ShellState*)pArg;
21609: sqlite3_stmt *pStmt;
21610: const char *zSql;
1.6.2.1 ! misho 21611: i64 nSql;
1.5 misho 21612: if( p->traceOut==0 ) return 0;
21613: if( mType==SQLITE_TRACE_CLOSE ){
21614: utf8_printf(p->traceOut, "-- closing database connection\n");
21615: return 0;
21616: }
1.6.2.1 ! misho 21617: if( mType!=SQLITE_TRACE_ROW && pX!=0 && ((const char*)pX)[0]=='-' ){
1.5 misho 21618: zSql = (const char*)pX;
21619: }else{
21620: pStmt = (sqlite3_stmt*)pP;
21621: switch( p->eTraceType ){
21622: case SHELL_TRACE_EXPANDED: {
21623: zSql = sqlite3_expanded_sql(pStmt);
21624: break;
1.2 misho 21625: }
1.5 misho 21626: #ifdef SQLITE_ENABLE_NORMALIZE
21627: case SHELL_TRACE_NORMALIZED: {
21628: zSql = sqlite3_normalized_sql(pStmt);
21629: break;
1.2 misho 21630: }
1.5 misho 21631: #endif
21632: default: {
21633: zSql = sqlite3_sql(pStmt);
21634: break;
1.2 misho 21635: }
21636: }
1.5 misho 21637: }
21638: if( zSql==0 ) return 0;
1.6.2.1 ! misho 21639: nSql = strlen(zSql);
! 21640: if( nSql>1000000000 ) nSql = 1000000000;
1.5 misho 21641: while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
21642: switch( mType ){
21643: case SQLITE_TRACE_ROW:
21644: case SQLITE_TRACE_STMT: {
1.6.2.1 ! misho 21645: utf8_printf(p->traceOut, "%.*s;\n", (int)nSql, zSql);
1.4 misho 21646: break;
21647: }
1.5 misho 21648: case SQLITE_TRACE_PROFILE: {
1.6.2.1 ! misho 21649: sqlite3_int64 nNanosec = pX ? *(sqlite3_int64*)pX : 0;
! 21650: utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", (int)nSql, zSql, nNanosec);
1.2 misho 21651: break;
21652: }
21653: }
21654: return 0;
21655: }
1.5 misho 21656: #endif
1.2 misho 21657:
21658: /*
1.5 misho 21659: ** A no-op routine that runs with the ".breakpoint" doc-command. This is
21660: ** a useful spot to set a debugger breakpoint.
1.6.2.1 ! misho 21661: **
! 21662: ** This routine does not do anything practical. The code are there simply
! 21663: ** to prevent the compiler from optimizing this routine out.
1.2 misho 21664: */
1.5 misho 21665: static void test_breakpoint(void){
1.6.2.1 ! misho 21666: static unsigned int nCall = 0;
! 21667: if( (nCall++)==0xffffffff ) printf("Many .breakpoints have run\n");
1.2 misho 21668: }
21669:
21670: /*
1.5 misho 21671: ** An object used to read a CSV and other files for import.
1.2 misho 21672: */
1.5 misho 21673: typedef struct ImportCtx ImportCtx;
21674: struct ImportCtx {
21675: const char *zFile; /* Name of the input file */
21676: FILE *in; /* Read the CSV text from this input stream */
21677: int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */
21678: char *z; /* Accumulated text for a field */
21679: int n; /* Number of bytes in z */
21680: int nAlloc; /* Space allocated for z[] */
21681: int nLine; /* Current line number */
21682: int nRow; /* Number of rows imported */
21683: int nErr; /* Number of errors encountered */
21684: int bNotFirst; /* True if one or more bytes already read */
21685: int cTerm; /* Character that terminated the most recent field */
21686: int cColSep; /* The column separator character. (Usually ",") */
21687: int cRowSep; /* The row separator character. (Usually "\n") */
21688: };
1.2 misho 21689:
1.5 misho 21690: /* Clean up resourced used by an ImportCtx */
21691: static void import_cleanup(ImportCtx *p){
21692: if( p->in!=0 && p->xCloser!=0 ){
21693: p->xCloser(p->in);
21694: p->in = 0;
1.2 misho 21695: }
1.5 misho 21696: sqlite3_free(p->z);
21697: p->z = 0;
21698: }
21699:
21700: /* Append a single byte to z[] */
21701: static void import_append_char(ImportCtx *p, int c){
21702: if( p->n+1>=p->nAlloc ){
21703: p->nAlloc += p->nAlloc + 100;
21704: p->z = sqlite3_realloc64(p->z, p->nAlloc);
1.6.2.1 ! misho 21705: shell_check_oom(p->z);
1.2 misho 21706: }
1.5 misho 21707: p->z[p->n++] = (char)c;
1.2 misho 21708: }
21709:
1.5 misho 21710: /* Read a single field of CSV text. Compatible with rfc4180 and extended
21711: ** with the option of having a separator other than ",".
1.2 misho 21712: **
1.5 misho 21713: ** + Input comes from p->in.
21714: ** + Store results in p->z of length p->n. Space to hold p->z comes
21715: ** from sqlite3_malloc64().
21716: ** + Use p->cSep as the column separator. The default is ",".
21717: ** + Use p->rSep as the row separator. The default is "\n".
21718: ** + Keep track of the line number in p->nLine.
21719: ** + Store the character that terminates the field in p->cTerm. Store
21720: ** EOF on end-of-file.
21721: ** + Report syntax errors on stderr
1.2 misho 21722: */
1.5 misho 21723: static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
21724: int c;
1.6.2.1 ! misho 21725: int cSep = (u8)p->cColSep;
! 21726: int rSep = (u8)p->cRowSep;
1.5 misho 21727: p->n = 0;
21728: c = fgetc(p->in);
21729: if( c==EOF || seenInterrupt ){
21730: p->cTerm = EOF;
1.2 misho 21731: return 0;
21732: }
1.5 misho 21733: if( c=='"' ){
21734: int pc, ppc;
21735: int startLine = p->nLine;
21736: int cQuote = c;
21737: pc = ppc = 0;
21738: while( 1 ){
21739: c = fgetc(p->in);
21740: if( c==rSep ) p->nLine++;
21741: if( c==cQuote ){
21742: if( pc==cQuote ){
21743: pc = 0;
21744: continue;
21745: }
21746: }
21747: if( (c==cSep && pc==cQuote)
21748: || (c==rSep && pc==cQuote)
21749: || (c==rSep && pc=='\r' && ppc==cQuote)
21750: || (c==EOF && pc==cQuote)
21751: ){
21752: do{ p->n--; }while( p->z[p->n]!=cQuote );
21753: p->cTerm = c;
21754: break;
21755: }
21756: if( pc==cQuote && c!='\r' ){
21757: utf8_printf(stderr, "%s:%d: unescaped %c character\n",
21758: p->zFile, p->nLine, cQuote);
21759: }
21760: if( c==EOF ){
21761: utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
21762: p->zFile, startLine, cQuote);
21763: p->cTerm = c;
21764: break;
21765: }
21766: import_append_char(p, c);
21767: ppc = pc;
21768: pc = c;
1.2 misho 21769: }
21770: }else{
1.5 misho 21771: /* If this is the first field being parsed and it begins with the
21772: ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
21773: if( (c&0xff)==0xef && p->bNotFirst==0 ){
21774: import_append_char(p, c);
21775: c = fgetc(p->in);
21776: if( (c&0xff)==0xbb ){
21777: import_append_char(p, c);
21778: c = fgetc(p->in);
21779: if( (c&0xff)==0xbf ){
21780: p->bNotFirst = 1;
21781: p->n = 0;
21782: return csv_read_one_field(p);
21783: }
21784: }
1.2 misho 21785: }
1.5 misho 21786: while( c!=EOF && c!=cSep && c!=rSep ){
21787: import_append_char(p, c);
21788: c = fgetc(p->in);
1.3 misho 21789: }
1.5 misho 21790: if( c==rSep ){
21791: p->nLine++;
21792: if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
1.4 misho 21793: }
1.5 misho 21794: p->cTerm = c;
1.2 misho 21795: }
1.5 misho 21796: if( p->z ) p->z[p->n] = 0;
21797: p->bNotFirst = 1;
21798: return p->z;
1.2 misho 21799: }
21800:
1.5 misho 21801: /* Read a single field of ASCII delimited text.
21802: **
21803: ** + Input comes from p->in.
21804: ** + Store results in p->z of length p->n. Space to hold p->z comes
21805: ** from sqlite3_malloc64().
21806: ** + Use p->cSep as the column separator. The default is "\x1F".
21807: ** + Use p->rSep as the row separator. The default is "\x1E".
21808: ** + Keep track of the row number in p->nLine.
21809: ** + Store the character that terminates the field in p->cTerm. Store
21810: ** EOF on end-of-file.
21811: ** + Report syntax errors on stderr
1.2 misho 21812: */
1.5 misho 21813: static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
21814: int c;
1.6.2.1 ! misho 21815: int cSep = (u8)p->cColSep;
! 21816: int rSep = (u8)p->cRowSep;
1.5 misho 21817: p->n = 0;
21818: c = fgetc(p->in);
21819: if( c==EOF || seenInterrupt ){
21820: p->cTerm = EOF;
21821: return 0;
21822: }
21823: while( c!=EOF && c!=cSep && c!=rSep ){
21824: import_append_char(p, c);
21825: c = fgetc(p->in);
1.2 misho 21826: }
1.5 misho 21827: if( c==rSep ){
21828: p->nLine++;
1.4 misho 21829: }
1.5 misho 21830: p->cTerm = c;
21831: if( p->z ) p->z[p->n] = 0;
21832: return p->z;
1.4 misho 21833: }
21834:
1.2 misho 21835: /*
1.5 misho 21836: ** Try to transfer data for table zTable. If an error is seen while
21837: ** moving forward, try to go backwards. The backwards movement won't
21838: ** work for WITHOUT ROWID tables.
1.2 misho 21839: */
1.5 misho 21840: static void tryToCloneData(
21841: ShellState *p,
21842: sqlite3 *newDb,
21843: const char *zTable
1.2 misho 21844: ){
1.5 misho 21845: sqlite3_stmt *pQuery = 0;
21846: sqlite3_stmt *pInsert = 0;
21847: char *zQuery = 0;
21848: char *zInsert = 0;
21849: int rc;
21850: int i, j, n;
21851: int nTable = strlen30(zTable);
21852: int k = 0;
21853: int cnt = 0;
21854: const int spinRate = 10000;
1.2 misho 21855:
1.5 misho 21856: zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
1.6.2.1 ! misho 21857: shell_check_oom(zQuery);
1.5 misho 21858: rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
21859: if( rc ){
21860: utf8_printf(stderr, "Error %d: %s on [%s]\n",
21861: sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
21862: zQuery);
21863: goto end_data_xfer;
21864: }
21865: n = sqlite3_column_count(pQuery);
21866: zInsert = sqlite3_malloc64(200 + nTable + n*3);
1.6.2.1 ! misho 21867: shell_check_oom(zInsert);
1.5 misho 21868: sqlite3_snprintf(200+nTable,zInsert,
21869: "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
21870: i = strlen30(zInsert);
21871: for(j=1; j<n; j++){
21872: memcpy(zInsert+i, ",?", 2);
21873: i += 2;
21874: }
21875: memcpy(zInsert+i, ");", 3);
21876: rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
21877: if( rc ){
21878: utf8_printf(stderr, "Error %d: %s on [%s]\n",
21879: sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
1.6.2.1 ! misho 21880: zInsert);
1.5 misho 21881: goto end_data_xfer;
1.2 misho 21882: }
1.5 misho 21883: for(k=0; k<2; k++){
21884: while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
21885: for(i=0; i<n; i++){
21886: switch( sqlite3_column_type(pQuery, i) ){
21887: case SQLITE_NULL: {
21888: sqlite3_bind_null(pInsert, i+1);
21889: break;
21890: }
21891: case SQLITE_INTEGER: {
21892: sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
21893: break;
21894: }
21895: case SQLITE_FLOAT: {
21896: sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
21897: break;
21898: }
21899: case SQLITE_TEXT: {
21900: sqlite3_bind_text(pInsert, i+1,
21901: (const char*)sqlite3_column_text(pQuery,i),
21902: -1, SQLITE_STATIC);
21903: break;
21904: }
21905: case SQLITE_BLOB: {
21906: sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
21907: sqlite3_column_bytes(pQuery,i),
21908: SQLITE_STATIC);
21909: break;
21910: }
21911: }
21912: } /* End for */
21913: rc = sqlite3_step(pInsert);
21914: if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
21915: utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
21916: sqlite3_errmsg(newDb));
21917: }
21918: sqlite3_reset(pInsert);
21919: cnt++;
21920: if( (cnt%spinRate)==0 ){
21921: printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
21922: fflush(stdout);
21923: }
21924: } /* End while */
21925: if( rc==SQLITE_DONE ) break;
21926: sqlite3_finalize(pQuery);
21927: sqlite3_free(zQuery);
21928: zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
21929: zTable);
1.6.2.1 ! misho 21930: shell_check_oom(zQuery);
1.5 misho 21931: rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
21932: if( rc ){
21933: utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
21934: break;
1.4 misho 21935: }
1.5 misho 21936: } /* End for(k=0...) */
1.2 misho 21937:
1.5 misho 21938: end_data_xfer:
21939: sqlite3_finalize(pQuery);
21940: sqlite3_finalize(pInsert);
21941: sqlite3_free(zQuery);
21942: sqlite3_free(zInsert);
21943: }
1.4 misho 21944:
1.2 misho 21945:
21946: /*
1.5 misho 21947: ** Try to transfer all rows of the schema that match zWhere. For
21948: ** each row, invoke xForEach() on the object defined by that row.
21949: ** If an error is encountered while moving forward through the
21950: ** sqlite_schema table, try again moving backwards.
1.2 misho 21951: */
1.5 misho 21952: static void tryToCloneSchema(
21953: ShellState *p,
21954: sqlite3 *newDb,
21955: const char *zWhere,
21956: void (*xForEach)(ShellState*,sqlite3*,const char*)
1.2 misho 21957: ){
1.5 misho 21958: sqlite3_stmt *pQuery = 0;
21959: char *zQuery = 0;
21960: int rc;
21961: const unsigned char *zName;
21962: const unsigned char *zSql;
21963: char *zErrMsg = 0;
21964:
21965: zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
1.6.2.1 ! misho 21966: " WHERE %s ORDER BY rowid ASC", zWhere);
! 21967: shell_check_oom(zQuery);
1.5 misho 21968: rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
21969: if( rc ){
21970: utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
21971: sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
21972: zQuery);
21973: goto end_schema_xfer;
21974: }
21975: while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
21976: zName = sqlite3_column_text(pQuery, 0);
21977: zSql = sqlite3_column_text(pQuery, 1);
1.6.2.1 ! misho 21978: if( zName==0 || zSql==0 ) continue;
! 21979: if( sqlite3_stricmp((char*)zName, "sqlite_sequence")!=0 ){
! 21980: printf("%s... ", zName); fflush(stdout);
! 21981: sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
! 21982: if( zErrMsg ){
! 21983: utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
! 21984: sqlite3_free(zErrMsg);
! 21985: zErrMsg = 0;
! 21986: }
1.5 misho 21987: }
21988: if( xForEach ){
21989: xForEach(p, newDb, (const char*)zName);
21990: }
21991: printf("done\n");
21992: }
21993: if( rc!=SQLITE_DONE ){
21994: sqlite3_finalize(pQuery);
21995: sqlite3_free(zQuery);
21996: zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
21997: " WHERE %s ORDER BY rowid DESC", zWhere);
1.6.2.1 ! misho 21998: shell_check_oom(zQuery);
1.5 misho 21999: rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
22000: if( rc ){
22001: utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
22002: sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
22003: zQuery);
22004: goto end_schema_xfer;
22005: }
1.6.2.1 ! misho 22006: while( sqlite3_step(pQuery)==SQLITE_ROW ){
1.5 misho 22007: zName = sqlite3_column_text(pQuery, 0);
22008: zSql = sqlite3_column_text(pQuery, 1);
1.6.2.1 ! misho 22009: if( zName==0 || zSql==0 ) continue;
! 22010: if( sqlite3_stricmp((char*)zName, "sqlite_sequence")==0 ) continue;
1.5 misho 22011: printf("%s... ", zName); fflush(stdout);
22012: sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
22013: if( zErrMsg ){
22014: utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
22015: sqlite3_free(zErrMsg);
22016: zErrMsg = 0;
1.2 misho 22017: }
1.5 misho 22018: if( xForEach ){
22019: xForEach(p, newDb, (const char*)zName);
1.2 misho 22020: }
1.5 misho 22021: printf("done\n");
1.4 misho 22022: }
22023: }
1.5 misho 22024: end_schema_xfer:
22025: sqlite3_finalize(pQuery);
22026: sqlite3_free(zQuery);
1.4 misho 22027: }
1.2 misho 22028:
1.4 misho 22029: /*
1.5 misho 22030: ** Open a new database file named "zNewDb". Try to recover as much information
22031: ** as possible out of the main database (which might be corrupt) and write it
22032: ** into zNewDb.
1.4 misho 22033: */
1.5 misho 22034: static void tryToClone(ShellState *p, const char *zNewDb){
22035: int rc;
22036: sqlite3 *newDb = 0;
22037: if( access(zNewDb,0)==0 ){
22038: utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
1.4 misho 22039: return;
22040: }
1.5 misho 22041: rc = sqlite3_open(zNewDb, &newDb);
22042: if( rc ){
22043: utf8_printf(stderr, "Cannot create output database: %s\n",
22044: sqlite3_errmsg(newDb));
22045: }else{
22046: sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
22047: sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
22048: tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
22049: tryToCloneSchema(p, newDb, "type!='table'", 0);
22050: sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
22051: sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
1.4 misho 22052: }
1.5 misho 22053: close_db(newDb);
1.4 misho 22054: }
22055:
22056: /*
1.5 misho 22057: ** Change the output file back to stdout.
22058: **
22059: ** If the p->doXdgOpen flag is set, that means the output was being
22060: ** redirected to a temporary file named by p->zTempFile. In that case,
22061: ** launch start/open/xdg-open on that temporary file.
1.4 misho 22062: */
1.5 misho 22063: static void output_reset(ShellState *p){
22064: if( p->outfile[0]=='|' ){
22065: #ifndef SQLITE_OMIT_POPEN
22066: pclose(p->out);
22067: #endif
22068: }else{
22069: output_file_close(p->out);
22070: #ifndef SQLITE_NOHAVE_SYSTEM
22071: if( p->doXdgOpen ){
22072: const char *zXdgOpenCmd =
22073: #if defined(_WIN32)
22074: "start";
22075: #elif defined(__APPLE__)
22076: "open";
22077: #else
22078: "xdg-open";
22079: #endif
22080: char *zCmd;
22081: zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
22082: if( system(zCmd) ){
22083: utf8_printf(stderr, "Failed: [%s]\n", zCmd);
22084: }else{
22085: /* Give the start/open/xdg-open command some time to get
22086: ** going before we continue, and potential delete the
22087: ** p->zTempFile data file out from under it */
22088: sqlite3_sleep(2000);
22089: }
22090: sqlite3_free(zCmd);
22091: outputModePop(p);
22092: p->doXdgOpen = 0;
22093: }
22094: #endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
22095: }
22096: p->outfile[0] = 0;
22097: p->out = stdout;
1.4 misho 22098: }
22099:
22100: /*
1.5 misho 22101: ** Run an SQL command and return the single integer result.
1.4 misho 22102: */
1.6.2.1 ! misho 22103: static int db_int(sqlite3 *db, const char *zSql){
1.5 misho 22104: sqlite3_stmt *pStmt;
22105: int res = 0;
1.6.2.1 ! misho 22106: sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
1.5 misho 22107: if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
22108: res = sqlite3_column_int(pStmt,0);
22109: }
22110: sqlite3_finalize(pStmt);
22111: return res;
1.4 misho 22112: }
22113:
1.6.2.1 ! misho 22114: #if SQLITE_SHELL_HAVE_RECOVER
1.4 misho 22115: /*
1.5 misho 22116: ** Convert a 2-byte or 4-byte big-endian integer into a native integer
1.4 misho 22117: */
1.5 misho 22118: static unsigned int get2byteInt(unsigned char *a){
22119: return (a[0]<<8) + a[1];
22120: }
22121: static unsigned int get4byteInt(unsigned char *a){
22122: return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
1.4 misho 22123: }
22124:
22125: /*
1.5 misho 22126: ** Implementation of the ".dbinfo" command.
1.4 misho 22127: **
1.5 misho 22128: ** Return 1 on error, 2 to exit, and 0 otherwise.
1.4 misho 22129: */
1.5 misho 22130: static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
22131: static const struct { const char *zName; int ofst; } aField[] = {
22132: { "file change counter:", 24 },
22133: { "database page count:", 28 },
22134: { "freelist page count:", 36 },
22135: { "schema cookie:", 40 },
22136: { "schema format:", 44 },
22137: { "default cache size:", 48 },
22138: { "autovacuum top root:", 52 },
22139: { "incremental vacuum:", 64 },
22140: { "text encoding:", 56 },
22141: { "user version:", 60 },
22142: { "application id:", 68 },
22143: { "software version:", 96 },
22144: };
22145: static const struct { const char *zName; const char *zSql; } aQuery[] = {
22146: { "number of tables:",
22147: "SELECT count(*) FROM %s WHERE type='table'" },
22148: { "number of indexes:",
22149: "SELECT count(*) FROM %s WHERE type='index'" },
22150: { "number of triggers:",
22151: "SELECT count(*) FROM %s WHERE type='trigger'" },
22152: { "number of views:",
22153: "SELECT count(*) FROM %s WHERE type='view'" },
22154: { "schema size:",
22155: "SELECT total(length(sql)) FROM %s" },
22156: };
22157: int i, rc;
22158: unsigned iDataVersion;
22159: char *zSchemaTab;
22160: char *zDb = nArg>=2 ? azArg[1] : "main";
22161: sqlite3_stmt *pStmt = 0;
22162: unsigned char aHdr[100];
22163: open_db(p, 0);
22164: if( p->db==0 ) return 1;
22165: rc = sqlite3_prepare_v2(p->db,
22166: "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
22167: -1, &pStmt, 0);
22168: if( rc ){
22169: utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
22170: sqlite3_finalize(pStmt);
22171: return 1;
22172: }
22173: sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
22174: if( sqlite3_step(pStmt)==SQLITE_ROW
22175: && sqlite3_column_bytes(pStmt,0)>100
22176: ){
1.6.2.1 ! misho 22177: const u8 *pb = sqlite3_column_blob(pStmt,0);
! 22178: shell_check_oom(pb);
! 22179: memcpy(aHdr, pb, 100);
1.5 misho 22180: sqlite3_finalize(pStmt);
22181: }else{
22182: raw_printf(stderr, "unable to read database header\n");
22183: sqlite3_finalize(pStmt);
22184: return 1;
1.4 misho 22185: }
1.5 misho 22186: i = get2byteInt(aHdr+16);
22187: if( i==1 ) i = 65536;
22188: utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
22189: utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
22190: utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
22191: utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
22192: for(i=0; i<ArraySize(aField); i++){
22193: int ofst = aField[i].ofst;
22194: unsigned int val = get4byteInt(aHdr + ofst);
22195: utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
22196: switch( ofst ){
22197: case 56: {
22198: if( val==1 ) raw_printf(p->out, " (utf8)");
22199: if( val==2 ) raw_printf(p->out, " (utf16le)");
22200: if( val==3 ) raw_printf(p->out, " (utf16be)");
1.2 misho 22201: }
22202: }
1.5 misho 22203: raw_printf(p->out, "\n");
22204: }
22205: if( zDb==0 ){
22206: zSchemaTab = sqlite3_mprintf("main.sqlite_schema");
1.6.2.1 ! misho 22207: }else if( cli_strcmp(zDb,"temp")==0 ){
1.5 misho 22208: zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
22209: }else{
22210: zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
22211: }
22212: for(i=0; i<ArraySize(aQuery); i++){
22213: char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
1.6.2.1 ! misho 22214: int val = db_int(p->db, zSql);
1.5 misho 22215: sqlite3_free(zSql);
22216: utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
22217: }
22218: sqlite3_free(zSchemaTab);
22219: sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
22220: utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
22221: return 0;
1.2 misho 22222: }
1.6.2.1 ! misho 22223: #endif /* SQLITE_SHELL_HAVE_RECOVER */
1.2 misho 22224:
22225: /*
1.5 misho 22226: ** Print the current sqlite3_errmsg() value to stderr and return 1.
1.2 misho 22227: */
1.5 misho 22228: static int shellDatabaseError(sqlite3 *db){
22229: const char *zErr = sqlite3_errmsg(db);
22230: utf8_printf(stderr, "Error: %s\n", zErr);
22231: return 1;
1.2 misho 22232: }
22233:
22234: /*
1.5 misho 22235: ** Compare the pattern in zGlob[] against the text in z[]. Return TRUE
22236: ** if they match and FALSE (0) if they do not match.
22237: **
22238: ** Globbing rules:
22239: **
22240: ** '*' Matches any sequence of zero or more characters.
22241: **
22242: ** '?' Matches exactly one character.
22243: **
22244: ** [...] Matches one character from the enclosed list of
22245: ** characters.
22246: **
22247: ** [^...] Matches one character not in the enclosed list.
22248: **
22249: ** '#' Matches any sequence of one or more digits with an
22250: ** optional + or - sign in front
22251: **
22252: ** ' ' Any span of whitespace matches any other span of
22253: ** whitespace.
1.2 misho 22254: **
1.5 misho 22255: ** Extra whitespace at the end of z[] is ignored.
1.2 misho 22256: */
1.5 misho 22257: static int testcase_glob(const char *zGlob, const char *z){
22258: int c, c2;
22259: int invert;
22260: int seen;
22261:
22262: while( (c = (*(zGlob++)))!=0 ){
22263: if( IsSpace(c) ){
22264: if( !IsSpace(*z) ) return 0;
22265: while( IsSpace(*zGlob) ) zGlob++;
22266: while( IsSpace(*z) ) z++;
22267: }else if( c=='*' ){
22268: while( (c=(*(zGlob++))) == '*' || c=='?' ){
22269: if( c=='?' && (*(z++))==0 ) return 0;
22270: }
22271: if( c==0 ){
22272: return 1;
22273: }else if( c=='[' ){
22274: while( *z && testcase_glob(zGlob-1,z)==0 ){
22275: z++;
22276: }
22277: return (*z)!=0;
22278: }
22279: while( (c2 = (*(z++)))!=0 ){
22280: while( c2!=c ){
22281: c2 = *(z++);
22282: if( c2==0 ) return 0;
22283: }
22284: if( testcase_glob(zGlob,z) ) return 1;
22285: }
22286: return 0;
22287: }else if( c=='?' ){
22288: if( (*(z++))==0 ) return 0;
22289: }else if( c=='[' ){
22290: int prior_c = 0;
22291: seen = 0;
22292: invert = 0;
22293: c = *(z++);
22294: if( c==0 ) return 0;
22295: c2 = *(zGlob++);
22296: if( c2=='^' ){
22297: invert = 1;
22298: c2 = *(zGlob++);
22299: }
22300: if( c2==']' ){
22301: if( c==']' ) seen = 1;
22302: c2 = *(zGlob++);
22303: }
22304: while( c2 && c2!=']' ){
22305: if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
22306: c2 = *(zGlob++);
22307: if( c>=prior_c && c<=c2 ) seen = 1;
22308: prior_c = 0;
22309: }else{
22310: if( c==c2 ){
22311: seen = 1;
22312: }
22313: prior_c = c2;
22314: }
22315: c2 = *(zGlob++);
22316: }
22317: if( c2==0 || (seen ^ invert)==0 ) return 0;
22318: }else if( c=='#' ){
22319: if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++;
22320: if( !IsDigit(z[0]) ) return 0;
22321: z++;
22322: while( IsDigit(z[0]) ){ z++; }
1.2 misho 22323: }else{
1.5 misho 22324: if( c!=(*(z++)) ) return 0;
1.2 misho 22325: }
22326: }
1.5 misho 22327: while( IsSpace(*z) ){ z++; }
22328: return *z==0;
1.2 misho 22329: }
22330:
1.5 misho 22331:
1.2 misho 22332: /*
1.5 misho 22333: ** Compare the string as a command-line option with either one or two
22334: ** initial "-" characters.
1.2 misho 22335: */
1.5 misho 22336: static int optionMatch(const char *zStr, const char *zOpt){
22337: if( zStr[0]!='-' ) return 0;
22338: zStr++;
22339: if( zStr[0]=='-' ) zStr++;
1.6.2.1 ! misho 22340: return cli_strcmp(zStr, zOpt)==0;
1.5 misho 22341: }
1.2 misho 22342:
1.4 misho 22343: /*
1.5 misho 22344: ** Delete a file.
1.4 misho 22345: */
1.5 misho 22346: int shellDeleteFile(const char *zFilename){
22347: int rc;
22348: #ifdef _WIN32
22349: wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
22350: rc = _wunlink(z);
22351: sqlite3_free(z);
22352: #else
22353: rc = unlink(zFilename);
22354: #endif
22355: return rc;
1.4 misho 22356: }
22357:
22358: /*
1.5 misho 22359: ** Try to delete the temporary file (if there is one) and free the
22360: ** memory used to hold the name of the temp file.
1.4 misho 22361: */
1.5 misho 22362: static void clearTempFile(ShellState *p){
22363: if( p->zTempFile==0 ) return;
22364: if( p->doXdgOpen ) return;
22365: if( shellDeleteFile(p->zTempFile) ) return;
22366: sqlite3_free(p->zTempFile);
22367: p->zTempFile = 0;
22368: }
1.4 misho 22369:
1.5 misho 22370: /*
22371: ** Create a new temp file name with the given suffix.
22372: */
22373: static void newTempFile(ShellState *p, const char *zSuffix){
22374: clearTempFile(p);
22375: sqlite3_free(p->zTempFile);
22376: p->zTempFile = 0;
22377: if( p->db ){
22378: sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
22379: }
22380: if( p->zTempFile==0 ){
22381: /* If p->db is an in-memory database then the TEMPFILENAME file-control
22382: ** will not work and we will need to fallback to guessing */
22383: char *zTemp;
22384: sqlite3_uint64 r;
22385: sqlite3_randomness(sizeof(r), &r);
22386: zTemp = getenv("TEMP");
22387: if( zTemp==0 ) zTemp = getenv("TMP");
22388: if( zTemp==0 ){
22389: #ifdef _WIN32
22390: zTemp = "\\tmp";
22391: #else
22392: zTemp = "/tmp";
22393: #endif
22394: }
22395: p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix);
1.4 misho 22396: }else{
1.5 misho 22397: p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
22398: }
1.6.2.1 ! misho 22399: shell_check_oom(p->zTempFile);
1.4 misho 22400: }
22401:
1.5 misho 22402:
1.4 misho 22403: /*
1.5 misho 22404: ** The implementation of SQL scalar function fkey_collate_clause(), used
22405: ** by the ".lint fkey-indexes" command. This scalar function is always
22406: ** called with four arguments - the parent table name, the parent column name,
22407: ** the child table name and the child column name.
22408: **
22409: ** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
22410: **
22411: ** If either of the named tables or columns do not exist, this function
22412: ** returns an empty string. An empty string is also returned if both tables
22413: ** and columns exist but have the same default collation sequence. Or,
22414: ** if both exist but the default collation sequences are different, this
22415: ** function returns the string " COLLATE <parent-collation>", where
22416: ** <parent-collation> is the default collation sequence of the parent column.
22417: */
22418: static void shellFkeyCollateClause(
22419: sqlite3_context *pCtx,
22420: int nVal,
22421: sqlite3_value **apVal
1.4 misho 22422: ){
1.5 misho 22423: sqlite3 *db = sqlite3_context_db_handle(pCtx);
22424: const char *zParent;
22425: const char *zParentCol;
22426: const char *zParentSeq;
22427: const char *zChild;
22428: const char *zChildCol;
22429: const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */
22430: int rc;
22431:
22432: assert( nVal==4 );
22433: zParent = (const char*)sqlite3_value_text(apVal[0]);
22434: zParentCol = (const char*)sqlite3_value_text(apVal[1]);
22435: zChild = (const char*)sqlite3_value_text(apVal[2]);
22436: zChildCol = (const char*)sqlite3_value_text(apVal[3]);
22437:
22438: sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
22439: rc = sqlite3_table_column_metadata(
22440: db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0
22441: );
22442: if( rc==SQLITE_OK ){
22443: rc = sqlite3_table_column_metadata(
22444: db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0
22445: );
22446: }
1.4 misho 22447:
1.5 misho 22448: if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){
22449: char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq);
22450: sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
22451: sqlite3_free(z);
1.4 misho 22452: }
22453: }
22454:
1.5 misho 22455:
1.4 misho 22456: /*
1.5 misho 22457: ** The implementation of dot-command ".lint fkey-indexes".
1.4 misho 22458: */
1.5 misho 22459: static int lintFkeyIndexes(
22460: ShellState *pState, /* Current shell tool state */
22461: char **azArg, /* Array of arguments passed to dot command */
22462: int nArg /* Number of entries in azArg[] */
22463: ){
22464: sqlite3 *db = pState->db; /* Database handle to query "main" db of */
22465: FILE *out = pState->out; /* Stream to write non-error output to */
22466: int bVerbose = 0; /* If -verbose is present */
22467: int bGroupByParent = 0; /* If -groupbyparent is present */
22468: int i; /* To iterate through azArg[] */
22469: const char *zIndent = ""; /* How much to indent CREATE INDEX by */
22470: int rc; /* Return code */
22471: sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */
22472:
22473: /*
22474: ** This SELECT statement returns one row for each foreign key constraint
22475: ** in the schema of the main database. The column values are:
22476: **
22477: ** 0. The text of an SQL statement similar to:
22478: **
22479: ** "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?"
22480: **
22481: ** This SELECT is similar to the one that the foreign keys implementation
22482: ** needs to run internally on child tables. If there is an index that can
22483: ** be used to optimize this query, then it can also be used by the FK
22484: ** implementation to optimize DELETE or UPDATE statements on the parent
22485: ** table.
22486: **
22487: ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by
22488: ** the EXPLAIN QUERY PLAN command matches this pattern, then the schema
22489: ** contains an index that can be used to optimize the query.
22490: **
22491: ** 2. Human readable text that describes the child table and columns. e.g.
22492: **
22493: ** "child_table(child_key1, child_key2)"
22494: **
22495: ** 3. Human readable text that describes the parent table and columns. e.g.
22496: **
22497: ** "parent_table(parent_key1, parent_key2)"
22498: **
22499: ** 4. A full CREATE INDEX statement for an index that could be used to
22500: ** optimize DELETE or UPDATE statements on the parent table. e.g.
22501: **
22502: ** "CREATE INDEX child_table_child_key ON child_table(child_key)"
22503: **
22504: ** 5. The name of the parent table.
22505: **
22506: ** These six values are used by the C logic below to generate the report.
22507: */
22508: const char *zSql =
22509: "SELECT "
22510: " 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
22511: " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
22512: " || fkey_collate_clause("
22513: " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
22514: ", "
1.6.2.1 ! misho 22515: " 'SEARCH ' || s.name || ' USING COVERING INDEX*('"
1.5 misho 22516: " || group_concat('*=?', ' AND ') || ')'"
22517: ", "
22518: " s.name || '(' || group_concat(f.[from], ', ') || ')'"
22519: ", "
22520: " f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
22521: ", "
22522: " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
22523: " || ' ON ' || quote(s.name) || '('"
22524: " || group_concat(quote(f.[from]) ||"
22525: " fkey_collate_clause("
22526: " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
22527: " || ');'"
22528: ", "
22529: " f.[table] "
22530: "FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f "
22531: "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
22532: "GROUP BY s.name, f.id "
22533: "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
22534: ;
1.6.2.1 ! misho 22535: const char *zGlobIPK = "SEARCH * USING INTEGER PRIMARY KEY (rowid=?)";
1.5 misho 22536:
22537: for(i=2; i<nArg; i++){
22538: int n = strlen30(azArg[i]);
22539: if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
22540: bVerbose = 1;
22541: }
22542: else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
22543: bGroupByParent = 1;
22544: zIndent = " ";
22545: }
22546: else{
22547: raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
22548: azArg[0], azArg[1]
22549: );
22550: return SQLITE_ERROR;
22551: }
22552: }
22553:
22554: /* Register the fkey_collate_clause() SQL function */
22555: rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
22556: 0, shellFkeyCollateClause, 0, 0
22557: );
22558:
22559:
22560: if( rc==SQLITE_OK ){
22561: rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
22562: }
22563: if( rc==SQLITE_OK ){
22564: sqlite3_bind_int(pSql, 1, bGroupByParent);
1.4 misho 22565: }
22566:
1.5 misho 22567: if( rc==SQLITE_OK ){
22568: int rc2;
22569: char *zPrev = 0;
22570: while( SQLITE_ROW==sqlite3_step(pSql) ){
22571: int res = -1;
22572: sqlite3_stmt *pExplain = 0;
22573: const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
22574: const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
22575: const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
22576: const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
22577: const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
22578: const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
22579:
1.6.2.1 ! misho 22580: if( zEQP==0 ) continue;
! 22581: if( zGlob==0 ) continue;
1.5 misho 22582: rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
22583: if( rc!=SQLITE_OK ) break;
22584: if( SQLITE_ROW==sqlite3_step(pExplain) ){
22585: const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
1.6.2.1 ! misho 22586: res = zPlan!=0 && ( 0==sqlite3_strglob(zGlob, zPlan)
! 22587: || 0==sqlite3_strglob(zGlobIPK, zPlan));
1.5 misho 22588: }
22589: rc = sqlite3_finalize(pExplain);
22590: if( rc!=SQLITE_OK ) break;
22591:
22592: if( res<0 ){
22593: raw_printf(stderr, "Error: internal error");
22594: break;
22595: }else{
22596: if( bGroupByParent
22597: && (bVerbose || res==0)
22598: && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
22599: ){
22600: raw_printf(out, "-- Parent table %s\n", zParent);
22601: sqlite3_free(zPrev);
22602: zPrev = sqlite3_mprintf("%s", zParent);
22603: }
22604:
22605: if( res==0 ){
22606: raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
22607: }else if( bVerbose ){
22608: raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
22609: zIndent, zFrom, zTarget
22610: );
22611: }
22612: }
22613: }
22614: sqlite3_free(zPrev);
22615:
22616: if( rc!=SQLITE_OK ){
22617: raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
22618: }
22619:
22620: rc2 = sqlite3_finalize(pSql);
22621: if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
22622: rc = rc2;
22623: raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
22624: }
22625: }else{
22626: raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
1.4 misho 22627: }
1.5 misho 22628:
22629: return rc;
1.4 misho 22630: }
22631:
22632: /*
1.5 misho 22633: ** Implementation of ".lint" dot command.
1.4 misho 22634: */
1.5 misho 22635: static int lintDotCommand(
22636: ShellState *pState, /* Current shell tool state */
22637: char **azArg, /* Array of arguments passed to dot command */
22638: int nArg /* Number of entries in azArg[] */
22639: ){
22640: int n;
22641: n = (nArg>=2 ? strlen30(azArg[1]) : 0);
22642: if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
22643: return lintFkeyIndexes(pState, azArg, nArg);
22644:
22645: usage:
22646: raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
22647: raw_printf(stderr, "Where sub-commands are:\n");
22648: raw_printf(stderr, " fkey-indexes\n");
22649: return SQLITE_ERROR;
22650: }
22651:
22652: #if !defined SQLITE_OMIT_VIRTUALTABLE
22653: static void shellPrepare(
1.6.2.1 ! misho 22654: sqlite3 *db,
! 22655: int *pRc,
! 22656: const char *zSql,
1.5 misho 22657: sqlite3_stmt **ppStmt
22658: ){
22659: *ppStmt = 0;
22660: if( *pRc==SQLITE_OK ){
22661: int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
22662: if( rc!=SQLITE_OK ){
1.6.2.1 ! misho 22663: raw_printf(stderr, "sql error: %s (%d)\n",
1.5 misho 22664: sqlite3_errmsg(db), sqlite3_errcode(db)
22665: );
22666: *pRc = rc;
22667: }
1.4 misho 22668: }
22669: }
1.2 misho 22670:
22671: /*
1.5 misho 22672: ** Create a prepared statement using printf-style arguments for the SQL.
22673: **
22674: ** This routine is could be marked "static". But it is not always used,
22675: ** depending on compile-time options. By omitting the "static", we avoid
22676: ** nuisance compiler warnings about "defined but not used".
22677: */
22678: void shellPreparePrintf(
1.6.2.1 ! misho 22679: sqlite3 *db,
! 22680: int *pRc,
1.5 misho 22681: sqlite3_stmt **ppStmt,
1.6.2.1 ! misho 22682: const char *zFmt,
1.5 misho 22683: ...
22684: ){
22685: *ppStmt = 0;
22686: if( *pRc==SQLITE_OK ){
22687: va_list ap;
22688: char *z;
22689: va_start(ap, zFmt);
22690: z = sqlite3_vmprintf(zFmt, ap);
22691: va_end(ap);
22692: if( z==0 ){
22693: *pRc = SQLITE_NOMEM;
22694: }else{
22695: shellPrepare(db, pRc, z, ppStmt);
22696: sqlite3_free(z);
1.2 misho 22697: }
1.5 misho 22698: }
22699: }
22700:
22701: /* Finalize the prepared statement created using shellPreparePrintf().
22702: **
22703: ** This routine is could be marked "static". But it is not always used,
22704: ** depending on compile-time options. By omitting the "static", we avoid
22705: ** nuisance compiler warnings about "defined but not used".
22706: */
22707: void shellFinalize(
1.6.2.1 ! misho 22708: int *pRc,
1.5 misho 22709: sqlite3_stmt *pStmt
22710: ){
22711: if( pStmt ){
22712: sqlite3 *db = sqlite3_db_handle(pStmt);
22713: int rc = sqlite3_finalize(pStmt);
22714: if( *pRc==SQLITE_OK ){
22715: if( rc!=SQLITE_OK ){
22716: raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
22717: }
22718: *pRc = rc;
1.2 misho 22719: }
22720: }
22721: }
22722:
1.5 misho 22723: /* Reset the prepared statement created using shellPreparePrintf().
1.2 misho 22724: **
1.5 misho 22725: ** This routine is could be marked "static". But it is not always used,
22726: ** depending on compile-time options. By omitting the "static", we avoid
22727: ** nuisance compiler warnings about "defined but not used".
22728: */
22729: void shellReset(
1.6.2.1 ! misho 22730: int *pRc,
1.5 misho 22731: sqlite3_stmt *pStmt
22732: ){
22733: int rc = sqlite3_reset(pStmt);
22734: if( *pRc==SQLITE_OK ){
22735: if( rc!=SQLITE_OK ){
22736: sqlite3 *db = sqlite3_db_handle(pStmt);
22737: raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
1.2 misho 22738: }
1.5 misho 22739: *pRc = rc;
1.2 misho 22740: }
1.4 misho 22741: }
1.5 misho 22742: #endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
22743:
22744: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
22745: /******************************************************************************
22746: ** The ".archive" or ".ar" command.
22747: */
22748: /*
22749: ** Structure representing a single ".ar" command.
22750: */
22751: typedef struct ArCommand ArCommand;
22752: struct ArCommand {
22753: u8 eCmd; /* An AR_CMD_* value */
22754: u8 bVerbose; /* True if --verbose */
22755: u8 bZip; /* True if the archive is a ZIP */
22756: u8 bDryRun; /* True if --dry-run */
22757: u8 bAppend; /* True if --append */
1.6.2.1 ! misho 22758: u8 bGlob; /* True if --glob */
1.5 misho 22759: u8 fromCmdLine; /* Run from -A instead of .archive */
22760: int nArg; /* Number of command arguments */
22761: char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
22762: const char *zFile; /* --file argument, or NULL */
22763: const char *zDir; /* --directory argument, or NULL */
22764: char **azArg; /* Array of command arguments */
22765: ShellState *p; /* Shell state */
22766: sqlite3 *db; /* Database containing the archive */
22767: };
1.4 misho 22768:
22769: /*
1.5 misho 22770: ** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
1.4 misho 22771: */
1.5 misho 22772: static int arUsage(FILE *f){
22773: showHelp(f,"archive");
22774: return SQLITE_ERROR;
1.4 misho 22775: }
22776:
22777: /*
1.6.2.1 ! misho 22778: ** Print an error message for the .ar command to stderr and return
1.5 misho 22779: ** SQLITE_ERROR.
1.4 misho 22780: */
1.5 misho 22781: static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
22782: va_list ap;
22783: char *z;
22784: va_start(ap, zFmt);
22785: z = sqlite3_vmprintf(zFmt, ap);
22786: va_end(ap);
22787: utf8_printf(stderr, "Error: %s\n", z);
22788: if( pAr->fromCmdLine ){
22789: utf8_printf(stderr, "Use \"-A\" for more help\n");
1.4 misho 22790: }else{
1.5 misho 22791: utf8_printf(stderr, "Use \".archive --help\" for more help\n");
1.4 misho 22792: }
1.5 misho 22793: sqlite3_free(z);
22794: return SQLITE_ERROR;
22795: }
22796:
22797: /*
22798: ** Values for ArCommand.eCmd.
22799: */
22800: #define AR_CMD_CREATE 1
22801: #define AR_CMD_UPDATE 2
22802: #define AR_CMD_INSERT 3
22803: #define AR_CMD_EXTRACT 4
22804: #define AR_CMD_LIST 5
22805: #define AR_CMD_HELP 6
1.6.2.1 ! misho 22806: #define AR_CMD_REMOVE 7
1.5 misho 22807:
22808: /*
22809: ** Other (non-command) switches.
22810: */
1.6.2.1 ! misho 22811: #define AR_SWITCH_VERBOSE 8
! 22812: #define AR_SWITCH_FILE 9
! 22813: #define AR_SWITCH_DIRECTORY 10
! 22814: #define AR_SWITCH_APPEND 11
! 22815: #define AR_SWITCH_DRYRUN 12
! 22816: #define AR_SWITCH_GLOB 13
1.5 misho 22817:
22818: static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
22819: switch( eSwitch ){
22820: case AR_CMD_CREATE:
22821: case AR_CMD_EXTRACT:
22822: case AR_CMD_LIST:
1.6.2.1 ! misho 22823: case AR_CMD_REMOVE:
1.5 misho 22824: case AR_CMD_UPDATE:
22825: case AR_CMD_INSERT:
22826: case AR_CMD_HELP:
22827: if( pAr->eCmd ){
22828: return arErrorMsg(pAr, "multiple command options");
22829: }
22830: pAr->eCmd = eSwitch;
22831: break;
22832:
22833: case AR_SWITCH_DRYRUN:
22834: pAr->bDryRun = 1;
22835: break;
1.6.2.1 ! misho 22836: case AR_SWITCH_GLOB:
! 22837: pAr->bGlob = 1;
! 22838: break;
1.5 misho 22839: case AR_SWITCH_VERBOSE:
22840: pAr->bVerbose = 1;
22841: break;
22842: case AR_SWITCH_APPEND:
22843: pAr->bAppend = 1;
1.6.2.1 ! misho 22844: deliberate_fall_through;
1.5 misho 22845: case AR_SWITCH_FILE:
22846: pAr->zFile = zArg;
22847: break;
22848: case AR_SWITCH_DIRECTORY:
22849: pAr->zDir = zArg;
1.4 misho 22850: break;
22851: }
1.5 misho 22852:
22853: return SQLITE_OK;
1.2 misho 22854: }
22855:
22856: /*
1.5 misho 22857: ** Parse the command line for an ".ar" command. The results are written into
22858: ** structure (*pAr). SQLITE_OK is returned if the command line is parsed
1.6.2.1 ! misho 22859: ** successfully, otherwise an error message is written to stderr and
1.5 misho 22860: ** SQLITE_ERROR returned.
22861: */
22862: static int arParseCommand(
22863: char **azArg, /* Array of arguments passed to dot command */
22864: int nArg, /* Number of entries in azArg[] */
22865: ArCommand *pAr /* Populate this object */
22866: ){
22867: struct ArSwitch {
22868: const char *zLong;
22869: char cShort;
22870: u8 eSwitch;
22871: u8 bArg;
22872: } aSwitch[] = {
22873: { "create", 'c', AR_CMD_CREATE, 0 },
22874: { "extract", 'x', AR_CMD_EXTRACT, 0 },
22875: { "insert", 'i', AR_CMD_INSERT, 0 },
22876: { "list", 't', AR_CMD_LIST, 0 },
1.6.2.1 ! misho 22877: { "remove", 'r', AR_CMD_REMOVE, 0 },
1.5 misho 22878: { "update", 'u', AR_CMD_UPDATE, 0 },
22879: { "help", 'h', AR_CMD_HELP, 0 },
22880: { "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
22881: { "file", 'f', AR_SWITCH_FILE, 1 },
22882: { "append", 'a', AR_SWITCH_APPEND, 1 },
22883: { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
22884: { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
1.6.2.1 ! misho 22885: { "glob", 'g', AR_SWITCH_GLOB, 0 },
1.5 misho 22886: };
22887: int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
22888: struct ArSwitch *pEnd = &aSwitch[nSwitch];
22889:
22890: if( nArg<=1 ){
22891: utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
22892: return arUsage(stderr);
1.4 misho 22893: }else{
1.5 misho 22894: char *z = azArg[1];
22895: if( z[0]!='-' ){
22896: /* Traditional style [tar] invocation */
22897: int i;
22898: int iArg = 2;
22899: for(i=0; z[i]; i++){
22900: const char *zArg = 0;
22901: struct ArSwitch *pOpt;
22902: for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
22903: if( z[i]==pOpt->cShort ) break;
22904: }
22905: if( pOpt==pEnd ){
22906: return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
22907: }
22908: if( pOpt->bArg ){
22909: if( iArg>=nArg ){
22910: return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
22911: }
22912: zArg = azArg[iArg++];
22913: }
22914: if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
22915: }
22916: pAr->nArg = nArg-iArg;
22917: if( pAr->nArg>0 ){
22918: pAr->azArg = &azArg[iArg];
22919: }
22920: }else{
22921: /* Non-traditional invocation */
22922: int iArg;
22923: for(iArg=1; iArg<nArg; iArg++){
22924: int n;
22925: z = azArg[iArg];
22926: if( z[0]!='-' ){
22927: /* All remaining command line words are command arguments. */
22928: pAr->azArg = &azArg[iArg];
22929: pAr->nArg = nArg-iArg;
22930: break;
22931: }
22932: n = strlen30(z);
22933:
22934: if( z[1]!='-' ){
22935: int i;
22936: /* One or more short options */
22937: for(i=1; i<n; i++){
22938: const char *zArg = 0;
22939: struct ArSwitch *pOpt;
22940: for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
22941: if( z[i]==pOpt->cShort ) break;
22942: }
22943: if( pOpt==pEnd ){
22944: return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
22945: }
22946: if( pOpt->bArg ){
22947: if( i<(n-1) ){
22948: zArg = &z[i+1];
22949: i = n;
22950: }else{
22951: if( iArg>=(nArg-1) ){
22952: return arErrorMsg(pAr, "option requires an argument: %c",
22953: z[i]);
22954: }
22955: zArg = azArg[++iArg];
22956: }
22957: }
22958: if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
22959: }
22960: }else if( z[2]=='\0' ){
22961: /* A -- option, indicating that all remaining command line words
22962: ** are command arguments. */
22963: pAr->azArg = &azArg[iArg+1];
22964: pAr->nArg = nArg-iArg-1;
22965: break;
22966: }else{
22967: /* A long option */
22968: const char *zArg = 0; /* Argument for option, if any */
22969: struct ArSwitch *pMatch = 0; /* Matching option */
22970: struct ArSwitch *pOpt; /* Iterator */
22971: for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
22972: const char *zLong = pOpt->zLong;
22973: if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
22974: if( pMatch ){
22975: return arErrorMsg(pAr, "ambiguous option: %s",z);
22976: }else{
22977: pMatch = pOpt;
22978: }
22979: }
22980: }
22981:
22982: if( pMatch==0 ){
22983: return arErrorMsg(pAr, "unrecognized option: %s", z);
22984: }
22985: if( pMatch->bArg ){
22986: if( iArg>=(nArg-1) ){
22987: return arErrorMsg(pAr, "option requires an argument: %s", z);
22988: }
22989: zArg = azArg[++iArg];
22990: }
22991: if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
22992: }
22993: }
22994: }
1.4 misho 22995: }
1.6.2.1 ! misho 22996: if( pAr->eCmd==0 ){
! 22997: utf8_printf(stderr, "Required argument missing. Usage:\n");
! 22998: return arUsage(stderr);
! 22999: }
1.5 misho 23000: return SQLITE_OK;
1.3 misho 23001: }
23002:
23003: /*
1.5 misho 23004: ** This function assumes that all arguments within the ArCommand.azArg[]
1.6.2.1 ! misho 23005: ** array refer to archive members, as for the --extract, --list or --remove
! 23006: ** commands. It checks that each of them are "present". If any specified
! 23007: ** file is not present in the archive, an error is printed to stderr and an
! 23008: ** error code returned. Otherwise, if all specified arguments are present
! 23009: ** in the archive, SQLITE_OK is returned. Here, "present" means either an
! 23010: ** exact equality when pAr->bGlob is false or a "name GLOB pattern" match
! 23011: ** when pAr->bGlob is true.
1.5 misho 23012: **
23013: ** This function strips any trailing '/' characters from each argument.
23014: ** This is consistent with the way the [tar] command seems to work on
23015: ** Linux.
23016: */
23017: static int arCheckEntries(ArCommand *pAr){
23018: int rc = SQLITE_OK;
23019: if( pAr->nArg ){
23020: int i, j;
23021: sqlite3_stmt *pTest = 0;
1.6.2.1 ! misho 23022: const char *zSel = (pAr->bGlob)
! 23023: ? "SELECT name FROM %s WHERE glob($name,name)"
! 23024: : "SELECT name FROM %s WHERE name=$name";
1.5 misho 23025:
1.6.2.1 ! misho 23026: shellPreparePrintf(pAr->db, &rc, &pTest, zSel, pAr->zSrcTable);
1.5 misho 23027: j = sqlite3_bind_parameter_index(pTest, "$name");
23028: for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
23029: char *z = pAr->azArg[i];
23030: int n = strlen30(z);
23031: int bOk = 0;
23032: while( n>0 && z[n-1]=='/' ) n--;
23033: z[n] = '\0';
23034: sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
23035: if( SQLITE_ROW==sqlite3_step(pTest) ){
23036: bOk = 1;
23037: }
23038: shellReset(&rc, pTest);
23039: if( rc==SQLITE_OK && bOk==0 ){
23040: utf8_printf(stderr, "not found in archive: %s\n", z);
23041: rc = SQLITE_ERROR;
23042: }
1.3 misho 23043: }
1.5 misho 23044: shellFinalize(&rc, pTest);
1.3 misho 23045: }
1.5 misho 23046: return rc;
1.3 misho 23047: }
23048:
23049: /*
1.5 misho 23050: ** Format a WHERE clause that can be used against the "sqlar" table to
23051: ** identify all archive members that match the command arguments held
23052: ** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
23053: ** The caller is responsible for eventually calling sqlite3_free() on
1.6.2.1 ! misho 23054: ** any non-NULL (*pzWhere) value. Here, "match" means strict equality
! 23055: ** when pAr->bGlob is false and GLOB match when pAr->bGlob is true.
1.5 misho 23056: */
23057: static void arWhereClause(
1.6.2.1 ! misho 23058: int *pRc,
! 23059: ArCommand *pAr,
1.5 misho 23060: char **pzWhere /* OUT: New WHERE clause */
23061: ){
23062: char *zWhere = 0;
1.6.2.1 ! misho 23063: const char *zSameOp = (pAr->bGlob)? "GLOB" : "=";
1.5 misho 23064: if( *pRc==SQLITE_OK ){
23065: if( pAr->nArg==0 ){
23066: zWhere = sqlite3_mprintf("1");
23067: }else{
23068: int i;
23069: const char *zSep = "";
23070: for(i=0; i<pAr->nArg; i++){
23071: const char *z = pAr->azArg[i];
23072: zWhere = sqlite3_mprintf(
1.6.2.1 ! misho 23073: "%z%s name %s '%q' OR substr(name,1,%d) %s '%q/'",
! 23074: zWhere, zSep, zSameOp, z, strlen30(z)+1, zSameOp, z
1.5 misho 23075: );
23076: if( zWhere==0 ){
23077: *pRc = SQLITE_NOMEM;
23078: break;
23079: }
23080: zSep = " OR ";
23081: }
23082: }
1.4 misho 23083: }
1.5 misho 23084: *pzWhere = zWhere;
1.3 misho 23085: }
23086:
23087: /*
1.6.2.1 ! misho 23088: ** Implementation of .ar "lisT" command.
1.3 misho 23089: */
1.5 misho 23090: static int arListCommand(ArCommand *pAr){
1.6.2.1 ! misho 23091: const char *zSql = "SELECT %s FROM %s WHERE %s";
1.5 misho 23092: const char *azCols[] = {
23093: "name",
23094: "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
23095: };
23096:
23097: char *zWhere = 0;
23098: sqlite3_stmt *pSql = 0;
23099: int rc;
23100:
23101: rc = arCheckEntries(pAr);
23102: arWhereClause(&rc, pAr, &zWhere);
23103:
23104: shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
23105: pAr->zSrcTable, zWhere);
23106: if( pAr->bDryRun ){
23107: utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
23108: }else{
23109: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
23110: if( pAr->bVerbose ){
23111: utf8_printf(pAr->p->out, "%s % 10d %s %s\n",
23112: sqlite3_column_text(pSql, 0),
1.6.2.1 ! misho 23113: sqlite3_column_int(pSql, 1),
1.5 misho 23114: sqlite3_column_text(pSql, 2),
23115: sqlite3_column_text(pSql, 3)
23116: );
23117: }else{
23118: utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
23119: }
23120: }
23121: }
23122: shellFinalize(&rc, pSql);
23123: sqlite3_free(zWhere);
23124: return rc;
1.3 misho 23125: }
23126:
1.5 misho 23127:
1.3 misho 23128: /*
1.6.2.1 ! misho 23129: ** Implementation of .ar "Remove" command.
! 23130: */
! 23131: static int arRemoveCommand(ArCommand *pAr){
! 23132: int rc = 0;
! 23133: char *zSql = 0;
! 23134: char *zWhere = 0;
! 23135:
! 23136: if( pAr->nArg ){
! 23137: /* Verify that args actually exist within the archive before proceeding.
! 23138: ** And formulate a WHERE clause to match them. */
! 23139: rc = arCheckEntries(pAr);
! 23140: arWhereClause(&rc, pAr, &zWhere);
! 23141: }
! 23142: if( rc==SQLITE_OK ){
! 23143: zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;",
! 23144: pAr->zSrcTable, zWhere);
! 23145: if( pAr->bDryRun ){
! 23146: utf8_printf(pAr->p->out, "%s\n", zSql);
! 23147: }else{
! 23148: char *zErr = 0;
! 23149: rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0);
! 23150: if( rc==SQLITE_OK ){
! 23151: rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
! 23152: if( rc!=SQLITE_OK ){
! 23153: sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
! 23154: }else{
! 23155: rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0);
! 23156: }
! 23157: }
! 23158: if( zErr ){
! 23159: utf8_printf(stdout, "ERROR: %s\n", zErr);
! 23160: sqlite3_free(zErr);
! 23161: }
! 23162: }
! 23163: }
! 23164: sqlite3_free(zWhere);
! 23165: sqlite3_free(zSql);
! 23166: return rc;
! 23167: }
! 23168:
! 23169: /*
! 23170: ** Implementation of .ar "eXtract" command.
1.4 misho 23171: */
1.5 misho 23172: static int arExtractCommand(ArCommand *pAr){
1.6.2.1 ! misho 23173: const char *zSql1 =
1.5 misho 23174: "SELECT "
23175: " ($dir || name),"
23176: " writefile(($dir || name), %s, mode, mtime) "
23177: "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
23178: " AND name NOT GLOB '*..[/\\]*'";
23179:
1.6.2.1 ! misho 23180: const char *azExtraArg[] = {
1.5 misho 23181: "sqlar_uncompress(data, sz)",
23182: "data"
23183: };
23184:
23185: sqlite3_stmt *pSql = 0;
23186: int rc = SQLITE_OK;
23187: char *zDir = 0;
23188: char *zWhere = 0;
23189: int i, j;
1.4 misho 23190:
1.5 misho 23191: /* If arguments are specified, check that they actually exist within
23192: ** the archive before proceeding. And formulate a WHERE clause to
23193: ** match them. */
23194: rc = arCheckEntries(pAr);
23195: arWhereClause(&rc, pAr, &zWhere);
23196:
23197: if( rc==SQLITE_OK ){
23198: if( pAr->zDir ){
23199: zDir = sqlite3_mprintf("%s/", pAr->zDir);
23200: }else{
23201: zDir = sqlite3_mprintf("");
1.4 misho 23202: }
1.5 misho 23203: if( zDir==0 ) rc = SQLITE_NOMEM;
1.4 misho 23204: }
23205:
1.6.2.1 ! misho 23206: shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
1.5 misho 23207: azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
23208: );
23209:
23210: if( rc==SQLITE_OK ){
23211: j = sqlite3_bind_parameter_index(pSql, "$dir");
23212: sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
23213:
23214: /* Run the SELECT statement twice. The first time, writefile() is called
23215: ** for all archive members that should be extracted. The second time,
23216: ** only for the directories. This is because the timestamps for
23217: ** extracted directories must be reset after they are populated (as
23218: ** populating them changes the timestamp). */
23219: for(i=0; i<2; i++){
23220: j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
23221: sqlite3_bind_int(pSql, j, i);
23222: if( pAr->bDryRun ){
23223: utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
23224: }else{
23225: while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
23226: if( i==0 && pAr->bVerbose ){
23227: utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
23228: }
1.4 misho 23229: }
23230: }
1.5 misho 23231: shellReset(&rc, pSql);
1.4 misho 23232: }
1.5 misho 23233: shellFinalize(&rc, pSql);
1.4 misho 23234: }
1.5 misho 23235:
23236: sqlite3_free(zDir);
23237: sqlite3_free(zWhere);
23238: return rc;
1.4 misho 23239: }
23240:
1.5 misho 23241: /*
23242: ** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out.
1.4 misho 23243: */
1.5 misho 23244: static int arExecSql(ArCommand *pAr, const char *zSql){
23245: int rc;
23246: if( pAr->bDryRun ){
23247: utf8_printf(pAr->p->out, "%s\n", zSql);
23248: rc = SQLITE_OK;
23249: }else{
23250: char *zErr = 0;
23251: rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
23252: if( zErr ){
23253: utf8_printf(stdout, "ERROR: %s\n", zErr);
23254: sqlite3_free(zErr);
23255: }
1.4 misho 23256: }
1.5 misho 23257: return rc;
1.4 misho 23258: }
23259:
1.5 misho 23260:
1.4 misho 23261: /*
1.5 misho 23262: ** Implementation of .ar "create", "insert", and "update" commands.
23263: **
23264: ** create -> Create a new SQL archive
23265: ** insert -> Insert or reinsert all files listed
23266: ** update -> Insert files that have changed or that were not
23267: ** previously in the archive
23268: **
23269: ** Create the "sqlar" table in the database if it does not already exist.
23270: ** Then add each file in the azFile[] array to the archive. Directories
23271: ** are added recursively. If argument bVerbose is non-zero, a message is
23272: ** printed on stdout for each file archived.
23273: **
23274: ** The create command is the same as update, except that it drops
23275: ** any existing "sqlar" table before beginning. The "insert" command
23276: ** always overwrites every file named on the command-line, where as
23277: ** "update" only overwrites if the size or mtime or mode has changed.
23278: */
23279: static int arCreateOrUpdateCommand(
23280: ArCommand *pAr, /* Command arguments and options */
23281: int bUpdate, /* true for a --create. */
23282: int bOnlyIfChanged /* Only update if file has changed */
1.4 misho 23283: ){
1.6.2.1 ! misho 23284: const char *zCreate =
1.5 misho 23285: "CREATE TABLE IF NOT EXISTS sqlar(\n"
23286: " name TEXT PRIMARY KEY, -- name of the file\n"
23287: " mode INT, -- access permissions\n"
23288: " mtime INT, -- last modification time\n"
23289: " sz INT, -- original file size\n"
23290: " data BLOB -- compressed content\n"
23291: ")";
23292: const char *zDrop = "DROP TABLE IF EXISTS sqlar";
23293: const char *zInsertFmt[2] = {
23294: "REPLACE INTO %s(name,mode,mtime,sz,data)\n"
23295: " SELECT\n"
23296: " %s,\n"
23297: " mode,\n"
23298: " mtime,\n"
23299: " CASE substr(lsmode(mode),1,1)\n"
23300: " WHEN '-' THEN length(data)\n"
23301: " WHEN 'd' THEN 0\n"
23302: " ELSE -1 END,\n"
23303: " sqlar_compress(data)\n"
23304: " FROM fsdir(%Q,%Q) AS disk\n"
23305: " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
23306: ,
23307: "REPLACE INTO %s(name,mode,mtime,data)\n"
23308: " SELECT\n"
23309: " %s,\n"
23310: " mode,\n"
23311: " mtime,\n"
23312: " data\n"
23313: " FROM fsdir(%Q,%Q) AS disk\n"
23314: " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
23315: };
23316: int i; /* For iterating through azFile[] */
23317: int rc; /* Return code */
23318: const char *zTab = 0; /* SQL table into which to insert */
23319: char *zSql;
23320: char zTemp[50];
23321: char *zExists = 0;
23322:
23323: arExecSql(pAr, "PRAGMA page_size=512");
23324: rc = arExecSql(pAr, "SAVEPOINT ar;");
23325: if( rc!=SQLITE_OK ) return rc;
1.6.2.1 ! misho 23326: zTemp[0] = 0;
1.5 misho 23327: if( pAr->bZip ){
23328: /* Initialize the zipfile virtual table, if necessary */
23329: if( pAr->zFile ){
23330: sqlite3_uint64 r;
23331: sqlite3_randomness(sizeof(r),&r);
23332: sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
23333: zTab = zTemp;
23334: zSql = sqlite3_mprintf(
23335: "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)",
23336: zTab, pAr->zFile
23337: );
23338: rc = arExecSql(pAr, zSql);
23339: sqlite3_free(zSql);
23340: }else{
23341: zTab = "zip";
23342: }
23343: }else{
23344: /* Initialize the table for an SQLAR */
23345: zTab = "sqlar";
23346: if( bUpdate==0 ){
23347: rc = arExecSql(pAr, zDrop);
23348: if( rc!=SQLITE_OK ) goto end_ar_transaction;
23349: }
23350: rc = arExecSql(pAr, zCreate);
23351: }
23352: if( bOnlyIfChanged ){
23353: zExists = sqlite3_mprintf(
23354: " AND NOT EXISTS("
23355: "SELECT 1 FROM %s AS mem"
23356: " WHERE mem.name=disk.name"
23357: " AND mem.mtime=disk.mtime"
23358: " AND mem.mode=disk.mode)", zTab);
23359: }else{
23360: zExists = sqlite3_mprintf("");
1.4 misho 23361: }
1.5 misho 23362: if( zExists==0 ) rc = SQLITE_NOMEM;
23363: for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
23364: char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
23365: pAr->bVerbose ? "shell_putsnl(name)" : "name",
23366: pAr->azArg[i], pAr->zDir, zExists);
23367: rc = arExecSql(pAr, zSql2);
23368: sqlite3_free(zSql2);
1.4 misho 23369: }
1.5 misho 23370: end_ar_transaction:
23371: if( rc!=SQLITE_OK ){
23372: sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
23373: }else{
23374: rc = arExecSql(pAr, "RELEASE ar;");
23375: if( pAr->bZip && pAr->zFile ){
23376: zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
23377: arExecSql(pAr, zSql);
23378: sqlite3_free(zSql);
1.4 misho 23379: }
1.5 misho 23380: }
23381: sqlite3_free(zExists);
23382: return rc;
1.4 misho 23383: }
23384:
23385: /*
1.5 misho 23386: ** Implementation of ".ar" dot command.
1.4 misho 23387: */
1.5 misho 23388: static int arDotCommand(
23389: ShellState *pState, /* Current shell tool state */
23390: int fromCmdLine, /* True if -A command-line option, not .ar cmd */
23391: char **azArg, /* Array of arguments passed to dot command */
23392: int nArg /* Number of entries in azArg[] */
1.4 misho 23393: ){
1.5 misho 23394: ArCommand cmd;
1.4 misho 23395: int rc;
1.5 misho 23396: memset(&cmd, 0, sizeof(cmd));
23397: cmd.fromCmdLine = fromCmdLine;
23398: rc = arParseCommand(azArg, nArg, &cmd);
23399: if( rc==SQLITE_OK ){
23400: int eDbType = SHELL_OPEN_UNSPEC;
23401: cmd.p = pState;
23402: cmd.db = pState->db;
23403: if( cmd.zFile ){
23404: eDbType = deduceDatabaseType(cmd.zFile, 1);
23405: }else{
23406: eDbType = pState->openMode;
23407: }
23408: if( eDbType==SHELL_OPEN_ZIPFILE ){
23409: if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){
23410: if( cmd.zFile==0 ){
23411: cmd.zSrcTable = sqlite3_mprintf("zip");
23412: }else{
23413: cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
23414: }
23415: }
23416: cmd.bZip = 1;
23417: }else if( cmd.zFile ){
23418: int flags;
23419: if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
1.6.2.1 ! misho 23420: if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
! 23421: || cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){
1.5 misho 23422: flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
23423: }else{
23424: flags = SQLITE_OPEN_READONLY;
23425: }
23426: cmd.db = 0;
23427: if( cmd.bDryRun ){
23428: utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
23429: eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
23430: }
1.6.2.1 ! misho 23431: rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
1.5 misho 23432: eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
23433: if( rc!=SQLITE_OK ){
1.6.2.1 ! misho 23434: utf8_printf(stderr, "cannot open file: %s (%s)\n",
1.5 misho 23435: cmd.zFile, sqlite3_errmsg(cmd.db)
23436: );
23437: goto end_ar_command;
23438: }
23439: sqlite3_fileio_init(cmd.db, 0, 0);
23440: sqlite3_sqlar_init(cmd.db, 0, 0);
23441: sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
23442: shellPutsFunc, 0, 0);
1.4 misho 23443:
23444: }
1.5 misho 23445: if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
23446: if( cmd.eCmd!=AR_CMD_CREATE
23447: && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
23448: ){
23449: utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
23450: rc = SQLITE_ERROR;
23451: goto end_ar_command;
23452: }
23453: cmd.zSrcTable = sqlite3_mprintf("sqlar");
23454: }
23455:
23456: switch( cmd.eCmd ){
23457: case AR_CMD_CREATE:
23458: rc = arCreateOrUpdateCommand(&cmd, 0, 0);
23459: break;
23460:
23461: case AR_CMD_EXTRACT:
23462: rc = arExtractCommand(&cmd);
23463: break;
23464:
23465: case AR_CMD_LIST:
23466: rc = arListCommand(&cmd);
23467: break;
23468:
23469: case AR_CMD_HELP:
23470: arUsage(pState->out);
1.6.2.1 ! misho 23471: break;
1.5 misho 23472:
1.6.2.1 ! misho 23473: case AR_CMD_INSERT:
! 23474: rc = arCreateOrUpdateCommand(&cmd, 1, 0);
! 23475: break;
1.5 misho 23476:
1.6.2.1 ! misho 23477: case AR_CMD_REMOVE:
! 23478: rc = arRemoveCommand(&cmd);
! 23479: break;
1.4 misho 23480:
1.6.2.1 ! misho 23481: default:
! 23482: assert( cmd.eCmd==AR_CMD_UPDATE );
! 23483: rc = arCreateOrUpdateCommand(&cmd, 1, 1);
! 23484: break;
1.5 misho 23485: }
23486: }
1.6.2.1 ! misho 23487: end_ar_command:
! 23488: if( cmd.db!=pState->db ){
! 23489: close_db(cmd.db);
! 23490: }
! 23491: sqlite3_free(cmd.zSrcTable);
1.5 misho 23492:
1.6.2.1 ! misho 23493: return rc;
1.4 misho 23494: }
1.6.2.1 ! misho 23495: /* End of the ".archive" or ".ar" command logic
! 23496: *******************************************************************************/
! 23497: #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
! 23498:
! 23499: #if SQLITE_SHELL_HAVE_RECOVER
1.4 misho 23500:
23501: /*
1.6.2.1 ! misho 23502: ** This function is used as a callback by the recover extension. Simply
! 23503: ** print the supplied SQL statement to stdout.
1.4 misho 23504: */
1.6.2.1 ! misho 23505: static int recoverSqlCb(void *pCtx, const char *zSql){
! 23506: ShellState *pState = (ShellState*)pCtx;
! 23507: utf8_printf(pState->out, "%s;\n", zSql);
! 23508: return SQLITE_OK;
1.4 misho 23509: }
23510:
23511: /*
1.5 misho 23512: ** This function is called to recover data from the database. A script
23513: ** to construct a new database containing all recovered data is output
23514: ** on stream pState->out.
1.4 misho 23515: */
1.5 misho 23516: static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
23517: int rc = SQLITE_OK;
1.6.2.1 ! misho 23518: const char *zRecoveryDb = ""; /* Name of "recovery" database. Debug only */
! 23519: const char *zLAF = "lost_and_found";
! 23520: int bFreelist = 1; /* 0 if --ignore-freelist is specified */
1.5 misho 23521: int bRowids = 1; /* 0 if --no-rowids */
1.6.2.1 ! misho 23522: sqlite3_recover *p = 0;
! 23523: int i = 0;
! 23524:
1.5 misho 23525: for(i=1; i<nArg; i++){
23526: char *z = azArg[i];
23527: int n;
23528: if( z[0]=='-' && z[1]=='-' ) z++;
23529: n = strlen30(z);
1.6.2.1 ! misho 23530: if( n<=17 && memcmp("-ignore-freelist", z, n)==0 ){
1.5 misho 23531: bFreelist = 0;
23532: }else
23533: if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
1.6.2.1 ! misho 23534: /* This option determines the name of the ATTACH-ed database used
! 23535: ** internally by the recovery extension. The default is "" which
! 23536: ** means to use a temporary database that is automatically deleted
! 23537: ** when closed. This option is undocumented and might disappear at
! 23538: ** any moment. */
1.5 misho 23539: i++;
23540: zRecoveryDb = azArg[i];
23541: }else
23542: if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
23543: i++;
1.6.2.1 ! misho 23544: zLAF = azArg[i];
1.5 misho 23545: }else
23546: if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
23547: bRowids = 0;
23548: }
23549: else{
1.6.2.1 ! misho 23550: utf8_printf(stderr, "unexpected option: %s\n", azArg[i]);
1.5 misho 23551: showHelp(pState->out, azArg[0]);
23552: return 1;
23553: }
23554: }
23555:
1.6.2.1 ! misho 23556: p = sqlite3_recover_init_sql(
! 23557: pState->db, "main", recoverSqlCb, (void*)pState
1.5 misho 23558: );
23559:
1.6.2.1 ! misho 23560: sqlite3_recover_config(p, 789, (void*)zRecoveryDb); /* Debug use only */
! 23561: sqlite3_recover_config(p, SQLITE_RECOVER_LOST_AND_FOUND, (void*)zLAF);
! 23562: sqlite3_recover_config(p, SQLITE_RECOVER_ROWIDS, (void*)&bRowids);
! 23563: sqlite3_recover_config(p, SQLITE_RECOVER_FREELIST_CORRUPT,(void*)&bFreelist);
! 23564:
! 23565: sqlite3_recover_run(p);
! 23566: if( sqlite3_recover_errcode(p)!=SQLITE_OK ){
! 23567: const char *zErr = sqlite3_recover_errmsg(p);
! 23568: int errCode = sqlite3_recover_errcode(p);
! 23569: raw_printf(stderr, "sql error: %s (%d)\n", zErr, errCode);
! 23570: }
! 23571: rc = sqlite3_recover_finish(p);
! 23572: return rc;
! 23573: }
! 23574: #endif /* SQLITE_SHELL_HAVE_RECOVER */
1.5 misho 23575:
23576:
1.6.2.1 ! misho 23577: /*
! 23578: * zAutoColumn(zCol, &db, ?) => Maybe init db, add column zCol to it.
! 23579: * zAutoColumn(0, &db, ?) => (db!=0) Form columns spec for CREATE TABLE,
! 23580: * close db and set it to 0, and return the columns spec, to later
! 23581: * be sqlite3_free()'ed by the caller.
! 23582: * The return is 0 when either:
! 23583: * (a) The db was not initialized and zCol==0 (There are no columns.)
! 23584: * (b) zCol!=0 (Column was added, db initialized as needed.)
! 23585: * The 3rd argument, pRenamed, references an out parameter. If the
! 23586: * pointer is non-zero, its referent will be set to a summary of renames
! 23587: * done if renaming was necessary, or set to 0 if none was done. The out
! 23588: * string (if any) must be sqlite3_free()'ed by the caller.
! 23589: */
! 23590: #ifdef SHELL_DEBUG
! 23591: #define rc_err_oom_die(rc) \
! 23592: if( rc==SQLITE_NOMEM ) shell_check_oom(0); \
! 23593: else if(!(rc==SQLITE_OK||rc==SQLITE_DONE)) \
! 23594: fprintf(stderr,"E:%d\n",rc), assert(0)
! 23595: #else
! 23596: static void rc_err_oom_die(int rc){
! 23597: if( rc==SQLITE_NOMEM ) shell_check_oom(0);
! 23598: assert(rc==SQLITE_OK||rc==SQLITE_DONE);
! 23599: }
! 23600: #endif
1.5 misho 23601:
1.6.2.1 ! misho 23602: #ifdef SHELL_COLFIX_DB /* If this is set, the DB can be in a file. */
! 23603: static char zCOL_DB[] = SHELL_STRINGIFY(SHELL_COLFIX_DB);
! 23604: #else /* Otherwise, memory is faster/better for the transient DB. */
! 23605: static const char *zCOL_DB = ":memory:";
! 23606: #endif
1.5 misho 23607:
1.6.2.1 ! misho 23608: /* Define character (as C string) to separate generated column ordinal
! 23609: * from protected part of incoming column names. This defaults to "_"
! 23610: * so that incoming column identifiers that did not need not be quoted
! 23611: * remain usable without being quoted. It must be one character.
! 23612: */
! 23613: #ifndef SHELL_AUTOCOLUMN_SEP
! 23614: # define AUTOCOLUMN_SEP "_"
! 23615: #else
! 23616: # define AUTOCOLUMN_SEP SHELL_STRINGIFY(SHELL_AUTOCOLUMN_SEP)
! 23617: #endif
1.5 misho 23618:
1.6.2.1 ! misho 23619: static char *zAutoColumn(const char *zColNew, sqlite3 **pDb, char **pzRenamed){
! 23620: /* Queries and D{D,M}L used here */
! 23621: static const char * const zTabMake = "\
! 23622: CREATE TABLE ColNames(\
! 23623: cpos INTEGER PRIMARY KEY,\
! 23624: name TEXT, nlen INT, chop INT, reps INT, suff TEXT);\
! 23625: CREATE VIEW RepeatedNames AS \
! 23626: SELECT DISTINCT t.name FROM ColNames t \
! 23627: WHERE t.name COLLATE NOCASE IN (\
! 23628: SELECT o.name FROM ColNames o WHERE o.cpos<>t.cpos\
! 23629: );\
! 23630: ";
! 23631: static const char * const zTabFill = "\
! 23632: INSERT INTO ColNames(name,nlen,chop,reps,suff)\
! 23633: VALUES(iif(length(?1)>0,?1,'?'),max(length(?1),1),0,0,'')\
! 23634: ";
! 23635: static const char * const zHasDupes = "\
! 23636: SELECT count(DISTINCT (substring(name,1,nlen-chop)||suff) COLLATE NOCASE)\
! 23637: <count(name) FROM ColNames\
! 23638: ";
! 23639: #ifdef SHELL_COLUMN_RENAME_CLEAN
! 23640: static const char * const zDedoctor = "\
! 23641: UPDATE ColNames SET chop=iif(\
! 23642: (substring(name,nlen,1) BETWEEN '0' AND '9')\
! 23643: AND (rtrim(name,'0123456790') glob '*"AUTOCOLUMN_SEP"'),\
! 23644: nlen-length(rtrim(name, '"AUTOCOLUMN_SEP"0123456789')),\
! 23645: 0\
! 23646: )\
! 23647: ";
! 23648: #endif
! 23649: static const char * const zSetReps = "\
! 23650: UPDATE ColNames AS t SET reps=\
! 23651: (SELECT count(*) FROM ColNames d \
! 23652: WHERE substring(t.name,1,t.nlen-t.chop)=substring(d.name,1,d.nlen-d.chop)\
! 23653: COLLATE NOCASE\
! 23654: )\
! 23655: ";
! 23656: #ifdef SQLITE_ENABLE_MATH_FUNCTIONS
! 23657: static const char * const zColDigits = "\
! 23658: SELECT CAST(ceil(log(count(*)+0.5)) AS INT) FROM ColNames \
! 23659: ";
! 23660: #else
! 23661: /* Counting on SQLITE_MAX_COLUMN < 100,000 here. (32767 is the hard limit.) */
! 23662: static const char * const zColDigits = "\
! 23663: SELECT CASE WHEN (nc < 10) THEN 1 WHEN (nc < 100) THEN 2 \
! 23664: WHEN (nc < 1000) THEN 3 WHEN (nc < 10000) THEN 4 \
! 23665: ELSE 5 FROM (SELECT count(*) AS nc FROM ColNames) \
! 23666: ";
! 23667: #endif
! 23668: static const char * const zRenameRank =
! 23669: #ifdef SHELL_COLUMN_RENAME_CLEAN
! 23670: "UPDATE ColNames AS t SET suff="
! 23671: "iif(reps>1, printf('%c%0*d', '"AUTOCOLUMN_SEP"', $1, cpos), '')"
! 23672: #else /* ...RENAME_MINIMAL_ONE_PASS */
! 23673: "WITH Lzn(nlz) AS (" /* Find minimum extraneous leading 0's for uniqueness */
! 23674: " SELECT 0 AS nlz"
! 23675: " UNION"
! 23676: " SELECT nlz+1 AS nlz FROM Lzn"
! 23677: " WHERE EXISTS("
! 23678: " SELECT 1"
! 23679: " FROM ColNames t, ColNames o"
! 23680: " WHERE"
! 23681: " iif(t.name IN (SELECT * FROM RepeatedNames),"
! 23682: " printf('%s"AUTOCOLUMN_SEP"%s',"
! 23683: " t.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,t.cpos),2)),"
! 23684: " t.name"
! 23685: " )"
! 23686: " ="
! 23687: " iif(o.name IN (SELECT * FROM RepeatedNames),"
! 23688: " printf('%s"AUTOCOLUMN_SEP"%s',"
! 23689: " o.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,o.cpos),2)),"
! 23690: " o.name"
! 23691: " )"
! 23692: " COLLATE NOCASE"
! 23693: " AND o.cpos<>t.cpos"
! 23694: " GROUP BY t.cpos"
! 23695: " )"
! 23696: ") UPDATE Colnames AS t SET"
! 23697: " chop = 0," /* No chopping, never touch incoming names. */
! 23698: " suff = iif(name IN (SELECT * FROM RepeatedNames),"
! 23699: " printf('"AUTOCOLUMN_SEP"%s', substring("
! 23700: " printf('%.*c%0.*d',(SELECT max(nlz) FROM Lzn)+1,'0',1,t.cpos),2)),"
! 23701: " ''"
! 23702: " )"
! 23703: #endif
! 23704: ;
! 23705: static const char * const zCollectVar = "\
! 23706: SELECT\
! 23707: '('||x'0a'\
! 23708: || group_concat(\
! 23709: cname||' TEXT',\
! 23710: ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\
! 23711: ||')' AS ColsSpec \
! 23712: FROM (\
! 23713: SELECT cpos, printf('\"%w\"',printf('%!.*s%s', nlen-chop,name,suff)) AS cname \
! 23714: FROM ColNames ORDER BY cpos\
! 23715: )";
! 23716: static const char * const zRenamesDone =
! 23717: "SELECT group_concat("
! 23718: " printf('\"%w\" to \"%w\"',name,printf('%!.*s%s', nlen-chop, name, suff)),"
! 23719: " ','||x'0a')"
! 23720: "FROM ColNames WHERE suff<>'' OR chop!=0"
! 23721: ;
! 23722: int rc;
! 23723: sqlite3_stmt *pStmt = 0;
! 23724: assert(pDb!=0);
! 23725: if( zColNew ){
! 23726: /* Add initial or additional column. Init db if necessary. */
! 23727: if( *pDb==0 ){
! 23728: if( SQLITE_OK!=sqlite3_open(zCOL_DB, pDb) ) return 0;
! 23729: #ifdef SHELL_COLFIX_DB
! 23730: if(*zCOL_DB!=':')
! 23731: sqlite3_exec(*pDb,"drop table if exists ColNames;"
! 23732: "drop view if exists RepeatedNames;",0,0,0);
! 23733: #endif
! 23734: rc = sqlite3_exec(*pDb, zTabMake, 0, 0, 0);
! 23735: rc_err_oom_die(rc);
! 23736: }
! 23737: assert(*pDb!=0);
! 23738: rc = sqlite3_prepare_v2(*pDb, zTabFill, -1, &pStmt, 0);
! 23739: rc_err_oom_die(rc);
! 23740: rc = sqlite3_bind_text(pStmt, 1, zColNew, -1, 0);
! 23741: rc_err_oom_die(rc);
! 23742: rc = sqlite3_step(pStmt);
! 23743: rc_err_oom_die(rc);
! 23744: sqlite3_finalize(pStmt);
! 23745: return 0;
! 23746: }else if( *pDb==0 ){
! 23747: return 0;
! 23748: }else{
! 23749: /* Formulate the columns spec, close the DB, zero *pDb. */
! 23750: char *zColsSpec = 0;
! 23751: int hasDupes = db_int(*pDb, zHasDupes);
! 23752: int nDigits = (hasDupes)? db_int(*pDb, zColDigits) : 0;
! 23753: if( hasDupes ){
! 23754: #ifdef SHELL_COLUMN_RENAME_CLEAN
! 23755: rc = sqlite3_exec(*pDb, zDedoctor, 0, 0, 0);
! 23756: rc_err_oom_die(rc);
! 23757: #endif
! 23758: rc = sqlite3_exec(*pDb, zSetReps, 0, 0, 0);
! 23759: rc_err_oom_die(rc);
! 23760: rc = sqlite3_prepare_v2(*pDb, zRenameRank, -1, &pStmt, 0);
! 23761: rc_err_oom_die(rc);
! 23762: sqlite3_bind_int(pStmt, 1, nDigits);
! 23763: rc = sqlite3_step(pStmt);
! 23764: sqlite3_finalize(pStmt);
! 23765: if( rc!=SQLITE_DONE ) rc_err_oom_die(SQLITE_NOMEM);
1.5 misho 23766: }
1.6.2.1 ! misho 23767: assert(db_int(*pDb, zHasDupes)==0); /* Consider: remove this */
! 23768: rc = sqlite3_prepare_v2(*pDb, zCollectVar, -1, &pStmt, 0);
! 23769: rc_err_oom_die(rc);
! 23770: rc = sqlite3_step(pStmt);
! 23771: if( rc==SQLITE_ROW ){
! 23772: zColsSpec = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
1.5 misho 23773: }else{
1.6.2.1 ! misho 23774: zColsSpec = 0;
1.5 misho 23775: }
1.6.2.1 ! misho 23776: if( pzRenamed!=0 ){
! 23777: if( !hasDupes ) *pzRenamed = 0;
! 23778: else{
! 23779: sqlite3_finalize(pStmt);
! 23780: if( SQLITE_OK==sqlite3_prepare_v2(*pDb, zRenamesDone, -1, &pStmt, 0)
! 23781: && SQLITE_ROW==sqlite3_step(pStmt) ){
! 23782: *pzRenamed = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
! 23783: }else
! 23784: *pzRenamed = 0;
1.5 misho 23785: }
23786: }
1.6.2.1 ! misho 23787: sqlite3_finalize(pStmt);
! 23788: sqlite3_close(*pDb);
! 23789: *pDb = 0;
! 23790: return zColsSpec;
1.5 misho 23791: }
1.4 misho 23792: }
23793:
23794: /*
1.2 misho 23795: ** If an input line begins with "." then invoke this routine to
23796: ** process that line.
23797: **
23798: ** Return 1 on error, 2 to exit, and 0 otherwise.
23799: */
1.4 misho 23800: static int do_meta_command(char *zLine, ShellState *p){
23801: int h = 1;
1.2 misho 23802: int nArg = 0;
23803: int n, c;
23804: int rc = 0;
1.5 misho 23805: char *azArg[52];
23806:
23807: #ifndef SQLITE_OMIT_VIRTUALTABLE
23808: if( p->expert.pExpert ){
23809: expertFinish(p, 1, 0);
23810: }
23811: #endif
1.2 misho 23812:
23813: /* Parse the input line into tokens.
23814: */
1.5 misho 23815: while( zLine[h] && nArg<ArraySize(azArg)-1 ){
1.4 misho 23816: while( IsSpace(zLine[h]) ){ h++; }
23817: if( zLine[h]==0 ) break;
23818: if( zLine[h]=='\'' || zLine[h]=='"' ){
23819: int delim = zLine[h++];
23820: azArg[nArg++] = &zLine[h];
23821: while( zLine[h] && zLine[h]!=delim ){
23822: if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
23823: h++;
23824: }
23825: if( zLine[h]==delim ){
23826: zLine[h++] = 0;
1.2 misho 23827: }
23828: if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
23829: }else{
1.4 misho 23830: azArg[nArg++] = &zLine[h];
23831: while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
23832: if( zLine[h] ) zLine[h++] = 0;
1.2 misho 23833: resolve_backslashes(azArg[nArg-1]);
23834: }
23835: }
1.5 misho 23836: azArg[nArg] = 0;
1.2 misho 23837:
23838: /* Process the input line.
23839: */
23840: if( nArg==0 ) return 0; /* no tokens, no error */
23841: n = strlen30(azArg[0]);
23842: c = azArg[0][0];
1.5 misho 23843: clearTempFile(p);
1.4 misho 23844:
1.5 misho 23845: #ifndef SQLITE_OMIT_AUTHORIZATION
1.6.2.1 ! misho 23846: if( c=='a' && cli_strncmp(azArg[0], "auth", n)==0 ){
1.4 misho 23847: if( nArg!=2 ){
23848: raw_printf(stderr, "Usage: .auth ON|OFF\n");
23849: rc = 1;
23850: goto meta_command_exit;
23851: }
23852: open_db(p, 0);
23853: if( booleanValue(azArg[1]) ){
23854: sqlite3_set_authorizer(p->db, shellAuth, p);
1.6.2.1 ! misho 23855: }else if( p->bSafeModePersist ){
! 23856: sqlite3_set_authorizer(p->db, safeModeAuth, p);
1.4 misho 23857: }else{
23858: sqlite3_set_authorizer(p->db, 0, 0);
23859: }
23860: }else
1.5 misho 23861: #endif
23862:
1.6.2.1 ! misho 23863: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) \
! 23864: && !defined(SQLITE_SHELL_FIDDLE)
! 23865: if( c=='a' && cli_strncmp(azArg[0], "archive", n)==0 ){
1.5 misho 23866: open_db(p, 0);
1.6.2.1 ! misho 23867: failIfSafeMode(p, "cannot run .archive in safe mode");
1.5 misho 23868: rc = arDotCommand(p, 0, azArg, nArg);
23869: }else
23870: #endif
1.4 misho 23871:
1.6.2.1 ! misho 23872: #ifndef SQLITE_SHELL_FIDDLE
! 23873: if( (c=='b' && n>=3 && cli_strncmp(azArg[0], "backup", n)==0)
! 23874: || (c=='s' && n>=3 && cli_strncmp(azArg[0], "save", n)==0)
1.4 misho 23875: ){
23876: const char *zDestFile = 0;
23877: const char *zDb = 0;
1.2 misho 23878: sqlite3 *pDest;
23879: sqlite3_backup *pBackup;
1.4 misho 23880: int j;
1.5 misho 23881: int bAsync = 0;
23882: const char *zVfs = 0;
1.6.2.1 ! misho 23883: failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
1.4 misho 23884: for(j=1; j<nArg; j++){
23885: const char *z = azArg[j];
23886: if( z[0]=='-' ){
1.5 misho 23887: if( z[1]=='-' ) z++;
1.6.2.1 ! misho 23888: if( cli_strcmp(z, "-append")==0 ){
1.5 misho 23889: zVfs = "apndvfs";
23890: }else
1.6.2.1 ! misho 23891: if( cli_strcmp(z, "-async")==0 ){
1.5 misho 23892: bAsync = 1;
23893: }else
1.4 misho 23894: {
23895: utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
23896: return 1;
23897: }
23898: }else if( zDestFile==0 ){
23899: zDestFile = azArg[j];
23900: }else if( zDb==0 ){
23901: zDb = zDestFile;
23902: zDestFile = azArg[j];
23903: }else{
1.5 misho 23904: raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
1.4 misho 23905: return 1;
23906: }
23907: }
23908: if( zDestFile==0 ){
23909: raw_printf(stderr, "missing FILENAME argument on .backup\n");
23910: return 1;
1.2 misho 23911: }
1.4 misho 23912: if( zDb==0 ) zDb = "main";
1.6.2.1 ! misho 23913: rc = sqlite3_open_v2(zDestFile, &pDest,
1.5 misho 23914: SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
1.2 misho 23915: if( rc!=SQLITE_OK ){
1.4 misho 23916: utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
1.5 misho 23917: close_db(pDest);
1.2 misho 23918: return 1;
23919: }
1.5 misho 23920: if( bAsync ){
23921: sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
23922: 0, 0, 0);
23923: }
1.4 misho 23924: open_db(p, 0);
1.2 misho 23925: pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
23926: if( pBackup==0 ){
1.4 misho 23927: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
1.5 misho 23928: close_db(pDest);
1.2 misho 23929: return 1;
23930: }
23931: while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
23932: sqlite3_backup_finish(pBackup);
23933: if( rc==SQLITE_DONE ){
23934: rc = 0;
23935: }else{
1.4 misho 23936: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
1.2 misho 23937: rc = 1;
23938: }
1.5 misho 23939: close_db(pDest);
1.2 misho 23940: }else
1.6.2.1 ! misho 23941: #endif /* !defined(SQLITE_SHELL_FIDDLE) */
1.2 misho 23942:
1.6.2.1 ! misho 23943: if( c=='b' && n>=3 && cli_strncmp(azArg[0], "bail", n)==0 ){
1.4 misho 23944: if( nArg==2 ){
23945: bail_on_error = booleanValue(azArg[1]);
23946: }else{
23947: raw_printf(stderr, "Usage: .bail on|off\n");
23948: rc = 1;
23949: }
23950: }else
23951:
1.6.2.1 ! misho 23952: /* Undocumented. Legacy only. See "crnl" below */
! 23953: if( c=='b' && n>=3 && cli_strncmp(azArg[0], "binary", n)==0 ){
1.4 misho 23954: if( nArg==2 ){
23955: if( booleanValue(azArg[1]) ){
23956: setBinaryMode(p->out, 1);
23957: }else{
23958: setTextMode(p->out, 1);
23959: }
23960: }else{
1.6.2.1 ! misho 23961: raw_printf(stderr, "The \".binary\" command is deprecated."
! 23962: " Use \".crnl\" instead.\n");
1.4 misho 23963: raw_printf(stderr, "Usage: .binary on|off\n");
23964: rc = 1;
23965: }
1.2 misho 23966: }else
23967:
1.6.2.1 ! misho 23968: /* The undocumented ".breakpoint" command causes a call to the no-op
! 23969: ** routine named test_breakpoint().
! 23970: */
! 23971: if( c=='b' && n>=3 && cli_strncmp(azArg[0], "breakpoint", n)==0 ){
! 23972: test_breakpoint();
! 23973: }else
! 23974:
! 23975: #ifndef SQLITE_SHELL_FIDDLE
! 23976: if( c=='c' && cli_strcmp(azArg[0],"cd")==0 ){
! 23977: failIfSafeMode(p, "cannot run .cd in safe mode");
1.5 misho 23978: if( nArg==2 ){
23979: #if defined(_WIN32) || defined(WIN32)
23980: wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
23981: rc = !SetCurrentDirectoryW(z);
23982: sqlite3_free(z);
23983: #else
23984: rc = chdir(azArg[1]);
23985: #endif
23986: if( rc ){
23987: utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
23988: rc = 1;
23989: }
23990: }else{
23991: raw_printf(stderr, "Usage: .cd DIRECTORY\n");
23992: rc = 1;
23993: }
23994: }else
1.6.2.1 ! misho 23995: #endif /* !defined(SQLITE_SHELL_FIDDLE) */
1.5 misho 23996:
1.6.2.1 ! misho 23997: if( c=='c' && n>=3 && cli_strncmp(azArg[0], "changes", n)==0 ){
1.4 misho 23998: if( nArg==2 ){
1.5 misho 23999: setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
1.4 misho 24000: }else{
24001: raw_printf(stderr, "Usage: .changes on|off\n");
24002: rc = 1;
24003: }
24004: }else
24005:
1.6.2.1 ! misho 24006: #ifndef SQLITE_SHELL_FIDDLE
1.5 misho 24007: /* Cancel output redirection, if it is currently set (by .testcase)
24008: ** Then read the content of the testcase-out.txt file and compare against
24009: ** azArg[1]. If there are differences, report an error and exit.
24010: */
1.6.2.1 ! misho 24011: if( c=='c' && n>=3 && cli_strncmp(azArg[0], "check", n)==0 ){
1.5 misho 24012: char *zRes = 0;
24013: output_reset(p);
24014: if( nArg!=2 ){
24015: raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
24016: rc = 2;
24017: }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
24018: rc = 2;
24019: }else if( testcase_glob(azArg[1],zRes)==0 ){
24020: utf8_printf(stderr,
24021: "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
24022: p->zTestcase, azArg[1], zRes);
24023: rc = 1;
24024: }else{
24025: utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
24026: p->nCheck++;
24027: }
24028: sqlite3_free(zRes);
24029: }else
1.6.2.1 ! misho 24030: #endif /* !defined(SQLITE_SHELL_FIDDLE) */
1.5 misho 24031:
1.6.2.1 ! misho 24032: #ifndef SQLITE_SHELL_FIDDLE
! 24033: if( c=='c' && cli_strncmp(azArg[0], "clone", n)==0 ){
! 24034: failIfSafeMode(p, "cannot run .clone in safe mode");
1.4 misho 24035: if( nArg==2 ){
24036: tryToClone(p, azArg[1]);
24037: }else{
24038: raw_printf(stderr, "Usage: .clone FILENAME\n");
24039: rc = 1;
24040: }
24041: }else
1.6.2.1 ! misho 24042: #endif /* !defined(SQLITE_SHELL_FIDDLE) */
! 24043:
! 24044: if( c=='c' && cli_strncmp(azArg[0], "connection", n)==0 ){
! 24045: if( nArg==1 ){
! 24046: /* List available connections */
! 24047: int i;
! 24048: for(i=0; i<ArraySize(p->aAuxDb); i++){
! 24049: const char *zFile = p->aAuxDb[i].zDbFilename;
! 24050: if( p->aAuxDb[i].db==0 && p->pAuxDb!=&p->aAuxDb[i] ){
! 24051: zFile = "(not open)";
! 24052: }else if( zFile==0 ){
! 24053: zFile = "(memory)";
! 24054: }else if( zFile[0]==0 ){
! 24055: zFile = "(temporary-file)";
! 24056: }
! 24057: if( p->pAuxDb == &p->aAuxDb[i] ){
! 24058: utf8_printf(stdout, "ACTIVE %d: %s\n", i, zFile);
! 24059: }else if( p->aAuxDb[i].db!=0 ){
! 24060: utf8_printf(stdout, " %d: %s\n", i, zFile);
! 24061: }
! 24062: }
! 24063: }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){
! 24064: int i = azArg[1][0] - '0';
! 24065: if( p->pAuxDb != &p->aAuxDb[i] && i>=0 && i<ArraySize(p->aAuxDb) ){
! 24066: p->pAuxDb->db = p->db;
! 24067: p->pAuxDb = &p->aAuxDb[i];
! 24068: globalDb = p->db = p->pAuxDb->db;
! 24069: p->pAuxDb->db = 0;
! 24070: }
! 24071: }else if( nArg==3 && cli_strcmp(azArg[1], "close")==0
! 24072: && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){
! 24073: int i = azArg[2][0] - '0';
! 24074: if( i<0 || i>=ArraySize(p->aAuxDb) ){
! 24075: /* No-op */
! 24076: }else if( p->pAuxDb == &p->aAuxDb[i] ){
! 24077: raw_printf(stderr, "cannot close the active database connection\n");
! 24078: rc = 1;
! 24079: }else if( p->aAuxDb[i].db ){
! 24080: session_close_all(p, i);
! 24081: close_db(p->aAuxDb[i].db);
! 24082: p->aAuxDb[i].db = 0;
! 24083: }
! 24084: }else{
! 24085: raw_printf(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n");
! 24086: rc = 1;
! 24087: }
! 24088: }else
! 24089:
! 24090: if( c=='c' && n==4 && cli_strncmp(azArg[0], "crnl", n)==0 ){
! 24091: if( nArg==2 ){
! 24092: if( booleanValue(azArg[1]) ){
! 24093: setTextMode(p->out, 1);
! 24094: }else{
! 24095: setBinaryMode(p->out, 1);
! 24096: }
! 24097: }else{
! 24098: #if !defined(_WIN32) && !defined(WIN32)
! 24099: raw_printf(stderr, "The \".crnl\" is a no-op on non-Windows machines.\n");
! 24100: #endif
! 24101: raw_printf(stderr, "Usage: .crnl on|off\n");
! 24102: rc = 1;
! 24103: }
! 24104: }else
1.4 misho 24105:
1.6.2.1 ! misho 24106: if( c=='d' && n>1 && cli_strncmp(azArg[0], "databases", n)==0 ){
1.6 misho 24107: char **azName = 0;
24108: int nName = 0;
24109: sqlite3_stmt *pStmt;
24110: int i;
1.4 misho 24111: open_db(p, 0);
1.6 misho 24112: rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
24113: if( rc ){
24114: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
1.2 misho 24115: rc = 1;
1.6 misho 24116: }else{
24117: while( sqlite3_step(pStmt)==SQLITE_ROW ){
24118: const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
24119: const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
1.6.2.1 ! misho 24120: if( zSchema==0 || zFile==0 ) continue;
1.6 misho 24121: azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
1.6.2.1 ! misho 24122: shell_check_oom(azName);
1.6 misho 24123: azName[nName*2] = strdup(zSchema);
24124: azName[nName*2+1] = strdup(zFile);
24125: nName++;
24126: }
24127: }
24128: sqlite3_finalize(pStmt);
24129: for(i=0; i<nName; i++){
24130: int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
24131: int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
24132: const char *z = azName[i*2+1];
24133: utf8_printf(p->out, "%s: %s %s%s\n",
24134: azName[i*2],
24135: z && z[0] ? z : "\"\"",
24136: bRdonly ? "r/o" : "r/w",
24137: eTxn==SQLITE_TXN_NONE ? "" :
24138: eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
24139: free(azName[i*2]);
24140: free(azName[i*2+1]);
1.2 misho 24141: }
1.6 misho 24142: sqlite3_free(azName);
1.2 misho 24143: }else
24144:
1.6.2.1 ! misho 24145: if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbconfig", n)==0 ){
1.5 misho 24146: static const struct DbConfigChoices {
24147: const char *zName;
24148: int op;
24149: } aDbConfig[] = {
24150: { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
24151: { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL },
24152: { "dqs_dml", SQLITE_DBCONFIG_DQS_DML },
24153: { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
24154: { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
24155: { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
24156: { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
24157: { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
24158: { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
24159: { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
24160: { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
24161: { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
24162: { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
1.6.2.1 ! misho 24163: { "reverse_scanorder", SQLITE_DBCONFIG_REVERSE_SCANORDER },
! 24164: { "stmt_scanstatus", SQLITE_DBCONFIG_STMT_SCANSTATUS },
1.5 misho 24165: { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
24166: { "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA },
24167: { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA },
24168: };
24169: int ii, v;
24170: open_db(p, 0);
24171: for(ii=0; ii<ArraySize(aDbConfig); ii++){
1.6.2.1 ! misho 24172: if( nArg>1 && cli_strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
1.5 misho 24173: if( nArg>=3 ){
24174: sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
24175: }
24176: sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
24177: utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
24178: if( nArg>1 ) break;
24179: }
24180: if( nArg>1 && ii==ArraySize(aDbConfig) ){
24181: utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
24182: utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
1.6.2.1 ! misho 24183: }
1.5 misho 24184: }else
24185:
1.6.2.1 ! misho 24186: #if SQLITE_SHELL_HAVE_RECOVER
! 24187: if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbinfo", n)==0 ){
1.4 misho 24188: rc = shell_dbinfo_command(p, nArg, azArg);
24189: }else
24190:
1.6.2.1 ! misho 24191: if( c=='r' && cli_strncmp(azArg[0], "recover", n)==0 ){
1.5 misho 24192: open_db(p, 0);
24193: rc = recoverDatabaseCmd(p, nArg, azArg);
24194: }else
1.6.2.1 ! misho 24195: #endif /* SQLITE_SHELL_HAVE_RECOVER */
1.5 misho 24196:
1.6.2.1 ! misho 24197: if( c=='d' && cli_strncmp(azArg[0], "dump", n)==0 ){
1.5 misho 24198: char *zLike = 0;
24199: char *zSql;
24200: int i;
24201: int savedShowHeader = p->showHeader;
24202: int savedShellFlags = p->shellFlgs;
1.6.2.1 ! misho 24203: ShellClearFlag(p,
1.6 misho 24204: SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
24205: |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
1.5 misho 24206: for(i=1; i<nArg; i++){
24207: if( azArg[i][0]=='-' ){
24208: const char *z = azArg[i]+1;
24209: if( z[0]=='-' ) z++;
1.6.2.1 ! misho 24210: if( cli_strcmp(z,"preserve-rowids")==0 ){
1.5 misho 24211: #ifdef SQLITE_OMIT_VIRTUALTABLE
24212: raw_printf(stderr, "The --preserve-rowids option is not compatible"
24213: " with SQLITE_OMIT_VIRTUALTABLE\n");
24214: rc = 1;
24215: sqlite3_free(zLike);
24216: goto meta_command_exit;
24217: #else
24218: ShellSetFlag(p, SHFLG_PreserveRowid);
24219: #endif
24220: }else
1.6.2.1 ! misho 24221: if( cli_strcmp(z,"newlines")==0 ){
1.5 misho 24222: ShellSetFlag(p, SHFLG_Newlines);
24223: }else
1.6.2.1 ! misho 24224: if( cli_strcmp(z,"data-only")==0 ){
1.6 misho 24225: ShellSetFlag(p, SHFLG_DumpDataOnly);
24226: }else
1.6.2.1 ! misho 24227: if( cli_strcmp(z,"nosys")==0 ){
1.6 misho 24228: ShellSetFlag(p, SHFLG_DumpNoSys);
24229: }else
1.5 misho 24230: {
24231: raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
24232: rc = 1;
24233: sqlite3_free(zLike);
24234: goto meta_command_exit;
24235: }
24236: }else{
1.6.2.1 ! misho 24237: /* azArg[i] contains a LIKE pattern. This ".dump" request should
! 24238: ** only dump data for tables for which either the table name matches
! 24239: ** the LIKE pattern, or the table appears to be a shadow table of
! 24240: ** a virtual table for which the name matches the LIKE pattern.
! 24241: */
! 24242: char *zExpr = sqlite3_mprintf(
! 24243: "name LIKE %Q ESCAPE '\\' OR EXISTS ("
! 24244: " SELECT 1 FROM sqlite_schema WHERE "
! 24245: " name LIKE %Q ESCAPE '\\' AND"
! 24246: " sql LIKE 'CREATE VIRTUAL TABLE%%' AND"
! 24247: " substr(o.name, 1, length(name)+1) == (name||'_')"
! 24248: ")", azArg[i], azArg[i]
! 24249: );
! 24250:
! 24251: if( zLike ){
! 24252: zLike = sqlite3_mprintf("%z OR %z", zLike, zExpr);
! 24253: }else{
! 24254: zLike = zExpr;
! 24255: }
1.5 misho 24256: }
24257: }
24258:
1.4 misho 24259: open_db(p, 0);
1.5 misho 24260:
1.6 misho 24261: if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
24262: /* When playing back a "dump", the content might appear in an order
24263: ** which causes immediate foreign key constraints to be violated.
24264: ** So disable foreign-key constraint enforcement to prevent problems. */
24265: raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
24266: raw_printf(p->out, "BEGIN TRANSACTION;\n");
24267: }
1.2 misho 24268: p->writableSchema = 0;
1.5 misho 24269: p->showHeader = 0;
24270: /* Set writable_schema=ON since doing so forces SQLite to initialize
24271: ** as much of the schema as it can even if the sqlite_schema table is
24272: ** corrupt. */
1.2 misho 24273: sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
24274: p->nErr = 0;
1.5 misho 24275: if( zLike==0 ) zLike = sqlite3_mprintf("true");
24276: zSql = sqlite3_mprintf(
1.6.2.1 ! misho 24277: "SELECT name, type, sql FROM sqlite_schema AS o "
1.5 misho 24278: "WHERE (%s) AND type=='table'"
24279: " AND sql NOT NULL"
24280: " ORDER BY tbl_name='sqlite_sequence', rowid",
24281: zLike
24282: );
24283: run_schema_dump_query(p,zSql);
24284: sqlite3_free(zSql);
1.6 misho 24285: if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
24286: zSql = sqlite3_mprintf(
1.6.2.1 ! misho 24287: "SELECT sql FROM sqlite_schema AS o "
1.6 misho 24288: "WHERE (%s) AND sql NOT NULL"
24289: " AND type IN ('index','trigger','view')",
24290: zLike
24291: );
24292: run_table_dump_query(p, zSql);
24293: sqlite3_free(zSql);
24294: }
1.5 misho 24295: sqlite3_free(zLike);
1.2 misho 24296: if( p->writableSchema ){
1.4 misho 24297: raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
1.2 misho 24298: p->writableSchema = 0;
24299: }
24300: sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
24301: sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
1.6 misho 24302: if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
24303: raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
24304: }
1.5 misho 24305: p->showHeader = savedShowHeader;
24306: p->shellFlgs = savedShellFlags;
1.4 misho 24307: }else
24308:
1.6.2.1 ! misho 24309: if( c=='e' && cli_strncmp(azArg[0], "echo", n)==0 ){
1.4 misho 24310: if( nArg==2 ){
1.5 misho 24311: setOrClearFlag(p, SHFLG_Echo, azArg[1]);
1.4 misho 24312: }else{
24313: raw_printf(stderr, "Usage: .echo on|off\n");
24314: rc = 1;
24315: }
1.2 misho 24316: }else
24317:
1.6.2.1 ! misho 24318: if( c=='e' && cli_strncmp(azArg[0], "eqp", n)==0 ){
1.4 misho 24319: if( nArg==2 ){
1.5 misho 24320: p->autoEQPtest = 0;
24321: if( p->autoEQPtrace ){
24322: if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
24323: p->autoEQPtrace = 0;
24324: }
1.6.2.1 ! misho 24325: if( cli_strcmp(azArg[1],"full")==0 ){
1.5 misho 24326: p->autoEQP = AUTOEQP_full;
1.6.2.1 ! misho 24327: }else if( cli_strcmp(azArg[1],"trigger")==0 ){
1.5 misho 24328: p->autoEQP = AUTOEQP_trigger;
24329: #ifdef SQLITE_DEBUG
1.6.2.1 ! misho 24330: }else if( cli_strcmp(azArg[1],"test")==0 ){
1.5 misho 24331: p->autoEQP = AUTOEQP_on;
24332: p->autoEQPtest = 1;
1.6.2.1 ! misho 24333: }else if( cli_strcmp(azArg[1],"trace")==0 ){
1.5 misho 24334: p->autoEQP = AUTOEQP_full;
24335: p->autoEQPtrace = 1;
24336: open_db(p, 0);
24337: sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0);
24338: sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
24339: #endif
1.4 misho 24340: }else{
1.5 misho 24341: p->autoEQP = (u8)booleanValue(azArg[1]);
1.4 misho 24342: }
24343: }else{
1.5 misho 24344: raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
1.4 misho 24345: rc = 1;
24346: }
1.2 misho 24347: }else
24348:
1.6.2.1 ! misho 24349: #ifndef SQLITE_SHELL_FIDDLE
! 24350: if( c=='e' && cli_strncmp(azArg[0], "exit", n)==0 ){
1.4 misho 24351: if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
1.2 misho 24352: rc = 2;
24353: }else
1.6.2.1 ! misho 24354: #endif
1.2 misho 24355:
1.5 misho 24356: /* The ".explain" command is automatic now. It is largely pointless. It
24357: ** retained purely for backwards compatibility */
1.6.2.1 ! misho 24358: if( c=='e' && cli_strncmp(azArg[0], "explain", n)==0 ){
1.4 misho 24359: int val = 1;
24360: if( nArg>=2 ){
1.6.2.1 ! misho 24361: if( cli_strcmp(azArg[1],"auto")==0 ){
1.4 misho 24362: val = 99;
24363: }else{
24364: val = booleanValue(azArg[1]);
24365: }
24366: }
24367: if( val==1 && p->mode!=MODE_Explain ){
24368: p->normalMode = p->mode;
1.2 misho 24369: p->mode = MODE_Explain;
1.4 misho 24370: p->autoExplain = 0;
24371: }else if( val==0 ){
24372: if( p->mode==MODE_Explain ) p->mode = p->normalMode;
24373: p->autoExplain = 0;
24374: }else if( val==99 ){
24375: if( p->mode==MODE_Explain ) p->mode = p->normalMode;
24376: p->autoExplain = 1;
24377: }
24378: }else
24379:
1.5 misho 24380: #ifndef SQLITE_OMIT_VIRTUALTABLE
1.6.2.1 ! misho 24381: if( c=='e' && cli_strncmp(azArg[0], "expert", n)==0 ){
! 24382: if( p->bSafeMode ){
! 24383: raw_printf(stderr,
! 24384: "Cannot run experimental commands such as \"%s\" in safe mode\n",
! 24385: azArg[0]);
! 24386: rc = 1;
! 24387: }else{
! 24388: open_db(p, 0);
! 24389: expertDotCommand(p, azArg, nArg);
! 24390: }
1.5 misho 24391: }else
24392: #endif
24393:
1.6.2.1 ! misho 24394: if( c=='f' && cli_strncmp(azArg[0], "filectrl", n)==0 ){
1.5 misho 24395: static const struct {
24396: const char *zCtrlName; /* Name of a test-control option */
24397: int ctrlCode; /* Integer code for that option */
24398: const char *zUsage; /* Usage notes */
24399: } aCtrl[] = {
24400: { "chunk_size", SQLITE_FCNTL_CHUNK_SIZE, "SIZE" },
1.6 misho 24401: { "data_version", SQLITE_FCNTL_DATA_VERSION, "" },
1.6.2.1 ! misho 24402: { "has_moved", SQLITE_FCNTL_HAS_MOVED, "" },
1.6 misho 24403: { "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" },
1.5 misho 24404: { "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" },
1.6 misho 24405: /* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/
1.5 misho 24406: { "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" },
1.6 misho 24407: { "reserve_bytes", SQLITE_FCNTL_RESERVE_BYTES, "[N]" },
24408: { "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" },
1.5 misho 24409: { "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" },
1.6 misho 24410: /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/
1.5 misho 24411: };
24412: int filectrl = -1;
24413: int iCtrl = -1;
24414: sqlite3_int64 iRes = 0; /* Integer result to display if rc2==1 */
24415: int isOk = 0; /* 0: usage 1: %lld 2: no-result */
24416: int n2, i;
24417: const char *zCmd = 0;
24418: const char *zSchema = 0;
24419:
24420: open_db(p, 0);
24421: zCmd = nArg>=2 ? azArg[1] : "help";
24422:
1.6.2.1 ! misho 24423: if( zCmd[0]=='-'
! 24424: && (cli_strcmp(zCmd,"--schema")==0 || cli_strcmp(zCmd,"-schema")==0)
1.5 misho 24425: && nArg>=4
24426: ){
24427: zSchema = azArg[2];
24428: for(i=3; i<nArg; i++) azArg[i-2] = azArg[i];
24429: nArg -= 2;
24430: zCmd = azArg[1];
24431: }
24432:
24433: /* The argument can optionally begin with "-" or "--" */
24434: if( zCmd[0]=='-' && zCmd[1] ){
24435: zCmd++;
24436: if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
24437: }
24438:
24439: /* --help lists all file-controls */
1.6.2.1 ! misho 24440: if( cli_strcmp(zCmd,"help")==0 ){
1.5 misho 24441: utf8_printf(p->out, "Available file-controls:\n");
24442: for(i=0; i<ArraySize(aCtrl); i++){
24443: utf8_printf(p->out, " .filectrl %s %s\n",
24444: aCtrl[i].zCtrlName, aCtrl[i].zUsage);
24445: }
24446: rc = 1;
24447: goto meta_command_exit;
24448: }
24449:
24450: /* convert filectrl text option to value. allow any unique prefix
24451: ** of the option name, or a numerical value. */
24452: n2 = strlen30(zCmd);
24453: for(i=0; i<ArraySize(aCtrl); i++){
1.6.2.1 ! misho 24454: if( cli_strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
1.5 misho 24455: if( filectrl<0 ){
24456: filectrl = aCtrl[i].ctrlCode;
24457: iCtrl = i;
24458: }else{
24459: utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n"
24460: "Use \".filectrl --help\" for help\n", zCmd);
24461: rc = 1;
24462: goto meta_command_exit;
24463: }
24464: }
24465: }
24466: if( filectrl<0 ){
24467: utf8_printf(stderr,"Error: unknown file-control: %s\n"
24468: "Use \".filectrl --help\" for help\n", zCmd);
24469: }else{
24470: switch(filectrl){
24471: case SQLITE_FCNTL_SIZE_LIMIT: {
24472: if( nArg!=2 && nArg!=3 ) break;
24473: iRes = nArg==3 ? integerValue(azArg[2]) : -1;
24474: sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
24475: isOk = 1;
24476: break;
24477: }
24478: case SQLITE_FCNTL_LOCK_TIMEOUT:
24479: case SQLITE_FCNTL_CHUNK_SIZE: {
24480: int x;
24481: if( nArg!=3 ) break;
24482: x = (int)integerValue(azArg[2]);
24483: sqlite3_file_control(p->db, zSchema, filectrl, &x);
24484: isOk = 2;
24485: break;
24486: }
24487: case SQLITE_FCNTL_PERSIST_WAL:
24488: case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
24489: int x;
24490: if( nArg!=2 && nArg!=3 ) break;
24491: x = nArg==3 ? booleanValue(azArg[2]) : -1;
24492: sqlite3_file_control(p->db, zSchema, filectrl, &x);
24493: iRes = x;
24494: isOk = 1;
24495: break;
24496: }
1.6 misho 24497: case SQLITE_FCNTL_DATA_VERSION:
1.5 misho 24498: case SQLITE_FCNTL_HAS_MOVED: {
24499: int x;
24500: if( nArg!=2 ) break;
24501: sqlite3_file_control(p->db, zSchema, filectrl, &x);
24502: iRes = x;
24503: isOk = 1;
24504: break;
24505: }
24506: case SQLITE_FCNTL_TEMPFILENAME: {
24507: char *z = 0;
24508: if( nArg!=2 ) break;
24509: sqlite3_file_control(p->db, zSchema, filectrl, &z);
24510: if( z ){
24511: utf8_printf(p->out, "%s\n", z);
24512: sqlite3_free(z);
24513: }
24514: isOk = 2;
24515: break;
24516: }
24517: case SQLITE_FCNTL_RESERVE_BYTES: {
24518: int x;
24519: if( nArg>=3 ){
24520: x = atoi(azArg[2]);
24521: sqlite3_file_control(p->db, zSchema, filectrl, &x);
24522: }
24523: x = -1;
24524: sqlite3_file_control(p->db, zSchema, filectrl, &x);
24525: utf8_printf(p->out,"%d\n", x);
24526: isOk = 2;
24527: break;
24528: }
24529: }
24530: }
24531: if( isOk==0 && iCtrl>=0 ){
24532: utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
24533: rc = 1;
24534: }else if( isOk==1 ){
24535: char zBuf[100];
24536: sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
24537: raw_printf(p->out, "%s\n", zBuf);
24538: }
24539: }else
24540:
1.6.2.1 ! misho 24541: if( c=='f' && cli_strncmp(azArg[0], "fullschema", n)==0 ){
1.4 misho 24542: ShellState data;
24543: int doStats = 0;
24544: memcpy(&data, p, sizeof(data));
24545: data.showHeader = 0;
24546: data.cMode = data.mode = MODE_Semi;
24547: if( nArg==2 && optionMatch(azArg[1], "indent") ){
24548: data.cMode = data.mode = MODE_Pretty;
24549: nArg = 1;
24550: }
24551: if( nArg!=1 ){
24552: raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
24553: rc = 1;
24554: goto meta_command_exit;
24555: }
24556: open_db(p, 0);
24557: rc = sqlite3_exec(p->db,
24558: "SELECT sql FROM"
24559: " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
1.5 misho 24560: " FROM sqlite_schema UNION ALL"
24561: " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
1.4 misho 24562: "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
1.6.2.1 ! misho 24563: "ORDER BY x",
! 24564: callback, &data, 0
1.4 misho 24565: );
24566: if( rc==SQLITE_OK ){
24567: sqlite3_stmt *pStmt;
24568: rc = sqlite3_prepare_v2(p->db,
1.5 misho 24569: "SELECT rowid FROM sqlite_schema"
1.4 misho 24570: " WHERE name GLOB 'sqlite_stat[134]'",
24571: -1, &pStmt, 0);
24572: doStats = sqlite3_step(pStmt)==SQLITE_ROW;
24573: sqlite3_finalize(pStmt);
24574: }
24575: if( doStats==0 ){
24576: raw_printf(p->out, "/* No STAT tables available */\n");
24577: }else{
1.5 misho 24578: raw_printf(p->out, "ANALYZE sqlite_schema;\n");
1.4 misho 24579: data.cMode = data.mode = MODE_Insert;
24580: data.zDestTable = "sqlite_stat1";
1.6.2.1 ! misho 24581: shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
1.4 misho 24582: data.zDestTable = "sqlite_stat4";
1.6.2.1 ! misho 24583: shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
1.5 misho 24584: raw_printf(p->out, "ANALYZE sqlite_schema;\n");
1.2 misho 24585: }
24586: }else
24587:
1.6.2.1 ! misho 24588: if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){
1.4 misho 24589: if( nArg==2 ){
24590: p->showHeader = booleanValue(azArg[1]);
1.5 misho 24591: p->shellFlgs |= SHFLG_HeaderSet;
1.4 misho 24592: }else{
24593: raw_printf(stderr, "Usage: .headers on|off\n");
24594: rc = 1;
24595: }
1.2 misho 24596: }else
24597:
1.6.2.1 ! misho 24598: if( c=='h' && cli_strncmp(azArg[0], "help", n)==0 ){
1.5 misho 24599: if( nArg>=2 ){
24600: n = showHelp(p->out, azArg[1]);
24601: if( n==0 ){
24602: utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
24603: }
24604: }else{
24605: showHelp(p->out, 0);
24606: }
24607: }else
24608:
1.6.2.1 ! misho 24609: #ifndef SQLITE_SHELL_FIDDLE
! 24610: if( c=='i' && cli_strncmp(azArg[0], "import", n)==0 ){
1.5 misho 24611: char *zTable = 0; /* Insert data into this table */
1.6.2.1 ! misho 24612: char *zSchema = 0; /* within this schema (may default to "main") */
1.5 misho 24613: char *zFile = 0; /* Name of file to extra content from */
24614: sqlite3_stmt *pStmt = NULL; /* A statement */
24615: int nCol; /* Number of columns in the table */
24616: int nByte; /* Number of bytes in an SQL string */
24617: int i, j; /* Loop counters */
24618: int needCommit; /* True to COMMIT or ROLLBACK at end */
24619: int nSep; /* Number of bytes in p->colSeparator[] */
24620: char *zSql; /* An SQL statement */
1.6.2.1 ! misho 24621: char *zFullTabName; /* Table name with schema if applicable */
1.5 misho 24622: ImportCtx sCtx; /* Reader context */
24623: char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
24624: int eVerbose = 0; /* Larger for more console output */
24625: int nSkip = 0; /* Initial lines to skip */
24626: int useOutputMode = 1; /* Use output mode to determine separators */
1.6.2.1 ! misho 24627: char *zCreate = 0; /* CREATE TABLE statement text */
1.5 misho 24628:
1.6.2.1 ! misho 24629: failIfSafeMode(p, "cannot run .import in safe mode");
1.5 misho 24630: memset(&sCtx, 0, sizeof(sCtx));
24631: if( p->mode==MODE_Ascii ){
24632: xRead = ascii_read_one_field;
24633: }else{
24634: xRead = csv_read_one_field;
24635: }
1.6.2.1 ! misho 24636: rc = 1;
1.5 misho 24637: for(i=1; i<nArg; i++){
24638: char *z = azArg[i];
24639: if( z[0]=='-' && z[1]=='-' ) z++;
24640: if( z[0]!='-' ){
24641: if( zFile==0 ){
24642: zFile = z;
24643: }else if( zTable==0 ){
24644: zTable = z;
24645: }else{
24646: utf8_printf(p->out, "ERROR: extra argument: \"%s\". Usage:\n", z);
24647: showHelp(p->out, "import");
24648: goto meta_command_exit;
24649: }
1.6.2.1 ! misho 24650: }else if( cli_strcmp(z,"-v")==0 ){
1.5 misho 24651: eVerbose++;
1.6.2.1 ! misho 24652: }else if( cli_strcmp(z,"-schema")==0 && i<nArg-1 ){
! 24653: zSchema = azArg[++i];
! 24654: }else if( cli_strcmp(z,"-skip")==0 && i<nArg-1 ){
1.5 misho 24655: nSkip = integerValue(azArg[++i]);
1.6.2.1 ! misho 24656: }else if( cli_strcmp(z,"-ascii")==0 ){
1.5 misho 24657: sCtx.cColSep = SEP_Unit[0];
24658: sCtx.cRowSep = SEP_Record[0];
24659: xRead = ascii_read_one_field;
24660: useOutputMode = 0;
1.6.2.1 ! misho 24661: }else if( cli_strcmp(z,"-csv")==0 ){
1.5 misho 24662: sCtx.cColSep = ',';
24663: sCtx.cRowSep = '\n';
24664: xRead = csv_read_one_field;
24665: useOutputMode = 0;
24666: }else{
24667: utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", z);
24668: showHelp(p->out, "import");
24669: goto meta_command_exit;
24670: }
24671: }
24672: if( zTable==0 ){
24673: utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
24674: zFile==0 ? "FILE" : "TABLE");
24675: showHelp(p->out, "import");
1.4 misho 24676: goto meta_command_exit;
24677: }
24678: seenInterrupt = 0;
24679: open_db(p, 0);
1.5 misho 24680: if( useOutputMode ){
24681: /* If neither the --csv or --ascii options are specified, then set
24682: ** the column and row separator characters from the output mode. */
24683: nSep = strlen30(p->colSeparator);
24684: if( nSep==0 ){
24685: raw_printf(stderr,
24686: "Error: non-null column separator required for import\n");
24687: goto meta_command_exit;
24688: }
24689: if( nSep>1 ){
1.6.2.1 ! misho 24690: raw_printf(stderr,
1.5 misho 24691: "Error: multi-character column separators not allowed"
24692: " for import\n");
24693: goto meta_command_exit;
24694: }
1.4 misho 24695: nSep = strlen30(p->rowSeparator);
1.5 misho 24696: if( nSep==0 ){
24697: raw_printf(stderr,
24698: "Error: non-null row separator required for import\n");
24699: goto meta_command_exit;
24700: }
1.6.2.1 ! misho 24701: if( nSep==2 && p->mode==MODE_Csv
! 24702: && cli_strcmp(p->rowSeparator,SEP_CrLf)==0
! 24703: ){
1.5 misho 24704: /* When importing CSV (only), if the row separator is set to the
24705: ** default output row separator, change it to the default input
24706: ** row separator. This avoids having to maintain different input
24707: ** and output row separators. */
24708: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
24709: nSep = strlen30(p->rowSeparator);
24710: }
24711: if( nSep>1 ){
24712: raw_printf(stderr, "Error: multi-character row separators not allowed"
24713: " for import\n");
24714: goto meta_command_exit;
24715: }
1.6.2.1 ! misho 24716: sCtx.cColSep = (u8)p->colSeparator[0];
! 24717: sCtx.cRowSep = (u8)p->rowSeparator[0];
1.4 misho 24718: }
24719: sCtx.zFile = zFile;
24720: sCtx.nLine = 1;
24721: if( sCtx.zFile[0]=='|' ){
24722: #ifdef SQLITE_OMIT_POPEN
24723: raw_printf(stderr, "Error: pipes are not supported in this OS\n");
1.5 misho 24724: goto meta_command_exit;
1.4 misho 24725: #else
24726: sCtx.in = popen(sCtx.zFile+1, "r");
24727: sCtx.zFile = "<pipe>";
1.5 misho 24728: sCtx.xCloser = pclose;
1.4 misho 24729: #endif
24730: }else{
24731: sCtx.in = fopen(sCtx.zFile, "rb");
1.5 misho 24732: sCtx.xCloser = fclose;
1.4 misho 24733: }
24734: if( sCtx.in==0 ){
24735: utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
1.5 misho 24736: goto meta_command_exit;
24737: }
24738: if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
24739: char zSep[2];
24740: zSep[1] = 0;
24741: zSep[0] = sCtx.cColSep;
24742: utf8_printf(p->out, "Column separator ");
24743: output_c_string(p->out, zSep);
24744: utf8_printf(p->out, ", row separator ");
24745: zSep[0] = sCtx.cRowSep;
24746: output_c_string(p->out, zSep);
24747: utf8_printf(p->out, "\n");
24748: }
1.6.2.1 ! misho 24749: sCtx.z = sqlite3_malloc64(120);
! 24750: if( sCtx.z==0 ){
! 24751: import_cleanup(&sCtx);
! 24752: shell_out_of_memory();
! 24753: }
! 24754: /* Below, resources must be freed before exit. */
1.5 misho 24755: while( (nSkip--)>0 ){
24756: while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
1.4 misho 24757: }
1.6.2.1 ! misho 24758: if( zSchema!=0 ){
! 24759: zFullTabName = sqlite3_mprintf("\"%w\".\"%w\"", zSchema, zTable);
! 24760: }else{
! 24761: zFullTabName = sqlite3_mprintf("\"%w\"", zTable);
! 24762: }
! 24763: zSql = sqlite3_mprintf("SELECT * FROM %s", zFullTabName);
! 24764: if( zSql==0 || zFullTabName==0 ){
1.5 misho 24765: import_cleanup(&sCtx);
24766: shell_out_of_memory();
1.2 misho 24767: }
24768: nByte = strlen30(zSql);
1.4 misho 24769: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
24770: import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
24771: if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
1.6.2.1 ! misho 24772: sqlite3 *dbCols = 0;
! 24773: char *zRenames = 0;
! 24774: char *zColDefs;
! 24775: zCreate = sqlite3_mprintf("CREATE TABLE %s", zFullTabName);
1.4 misho 24776: while( xRead(&sCtx) ){
1.6.2.1 ! misho 24777: zAutoColumn(sCtx.z, &dbCols, 0);
1.4 misho 24778: if( sCtx.cTerm!=sCtx.cColSep ) break;
24779: }
1.6.2.1 ! misho 24780: zColDefs = zAutoColumn(0, &dbCols, &zRenames);
! 24781: if( zRenames!=0 ){
! 24782: utf8_printf((stdin_is_interactive && p->in==stdin)? p->out : stderr,
! 24783: "Columns renamed during .import %s due to duplicates:\n"
! 24784: "%s\n", sCtx.zFile, zRenames);
! 24785: sqlite3_free(zRenames);
! 24786: }
! 24787: assert(dbCols==0);
! 24788: if( zColDefs==0 ){
! 24789: utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
! 24790: import_fail:
1.4 misho 24791: sqlite3_free(zCreate);
1.6.2.1 ! misho 24792: sqlite3_free(zSql);
! 24793: sqlite3_free(zFullTabName);
1.5 misho 24794: import_cleanup(&sCtx);
24795: rc = 1;
24796: goto meta_command_exit;
1.4 misho 24797: }
1.6.2.1 ! misho 24798: zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs);
1.5 misho 24799: if( eVerbose>=1 ){
24800: utf8_printf(p->out, "%s\n", zCreate);
24801: }
1.4 misho 24802: rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
24803: if( rc ){
1.6.2.1 ! misho 24804: utf8_printf(stderr, "%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
! 24805: goto import_fail;
1.4 misho 24806: }
1.6.2.1 ! misho 24807: sqlite3_free(zCreate);
! 24808: zCreate = 0;
1.4 misho 24809: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
24810: }
1.2 misho 24811: if( rc ){
24812: if (pStmt) sqlite3_finalize(pStmt);
1.4 misho 24813: utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
1.6.2.1 ! misho 24814: goto import_fail;
1.2 misho 24815: }
1.6.2.1 ! misho 24816: sqlite3_free(zSql);
1.2 misho 24817: nCol = sqlite3_column_count(pStmt);
24818: sqlite3_finalize(pStmt);
24819: pStmt = 0;
24820: if( nCol==0 ) return 0; /* no columns, no error */
1.4 misho 24821: zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
1.2 misho 24822: if( zSql==0 ){
1.5 misho 24823: import_cleanup(&sCtx);
24824: shell_out_of_memory();
1.2 misho 24825: }
1.6.2.1 ! misho 24826: sqlite3_snprintf(nByte+20, zSql, "INSERT INTO %s VALUES(?", zFullTabName);
1.2 misho 24827: j = strlen30(zSql);
24828: for(i=1; i<nCol; i++){
24829: zSql[j++] = ',';
24830: zSql[j++] = '?';
24831: }
24832: zSql[j++] = ')';
24833: zSql[j] = 0;
1.5 misho 24834: if( eVerbose>=2 ){
24835: utf8_printf(p->out, "Insert using: %s\n", zSql);
24836: }
1.4 misho 24837: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
1.2 misho 24838: if( rc ){
1.4 misho 24839: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
1.2 misho 24840: if (pStmt) sqlite3_finalize(pStmt);
1.6.2.1 ! misho 24841: goto import_fail;
1.2 misho 24842: }
1.6.2.1 ! misho 24843: sqlite3_free(zSql);
! 24844: sqlite3_free(zFullTabName);
1.4 misho 24845: needCommit = sqlite3_get_autocommit(p->db);
24846: if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
24847: do{
24848: int startLine = sCtx.nLine;
24849: for(i=0; i<nCol; i++){
24850: char *z = xRead(&sCtx);
24851: /*
24852: ** Did we reach end-of-file before finding any columns?
24853: ** If so, stop instead of NULL filling the remaining columns.
24854: */
24855: if( z==0 && i==0 ) break;
24856: /*
24857: ** Did we reach end-of-file OR end-of-line before finding any
24858: ** columns in ASCII mode? If so, stop instead of NULL filling
24859: ** the remaining columns.
24860: */
24861: if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
24862: sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
24863: if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
24864: utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
24865: "filling the rest with NULL\n",
24866: sCtx.zFile, startLine, nCol, i+1);
24867: i += 2;
24868: while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
24869: }
24870: }
24871: if( sCtx.cTerm==sCtx.cColSep ){
24872: do{
24873: xRead(&sCtx);
1.2 misho 24874: i++;
1.4 misho 24875: }while( sCtx.cTerm==sCtx.cColSep );
24876: utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
24877: "extras ignored\n",
24878: sCtx.zFile, startLine, nCol, i);
24879: }
24880: if( i>=nCol ){
24881: sqlite3_step(pStmt);
24882: rc = sqlite3_reset(pStmt);
24883: if( rc!=SQLITE_OK ){
24884: utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
24885: startLine, sqlite3_errmsg(p->db));
1.5 misho 24886: sCtx.nErr++;
24887: }else{
24888: sCtx.nRow++;
1.2 misho 24889: }
24890: }
1.4 misho 24891: }while( sCtx.cTerm!=EOF );
24892:
1.5 misho 24893: import_cleanup(&sCtx);
1.2 misho 24894: sqlite3_finalize(pStmt);
1.4 misho 24895: if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
1.5 misho 24896: if( eVerbose>0 ){
24897: utf8_printf(p->out,
24898: "Added %d rows with %d errors using %d lines of input\n",
24899: sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
24900: }
1.2 misho 24901: }else
1.6.2.1 ! misho 24902: #endif /* !defined(SQLITE_SHELL_FIDDLE) */
1.2 misho 24903:
1.5 misho 24904: #ifndef SQLITE_UNTESTABLE
1.6.2.1 ! misho 24905: if( c=='i' && cli_strncmp(azArg[0], "imposter", n)==0 ){
1.5 misho 24906: char *zSql;
24907: char *zCollist = 0;
24908: sqlite3_stmt *pStmt;
24909: int tnum = 0;
24910: int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */
24911: int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
24912: int i;
1.6.2.1 ! misho 24913: if( !ShellHasFlag(p,SHFLG_TestingMode) ){
! 24914: utf8_printf(stderr, ".%s unavailable without --unsafe-testing\n",
! 24915: "imposter");
! 24916: rc = 1;
! 24917: goto meta_command_exit;
! 24918: }
1.5 misho 24919: if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
24920: utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
24921: " .imposter off\n");
24922: /* Also allowed, but not documented:
24923: **
24924: ** .imposter TABLE IMPOSTER
24925: **
24926: ** where TABLE is a WITHOUT ROWID table. In that case, the
24927: ** imposter is another WITHOUT ROWID table with the columns in
24928: ** storage order. */
24929: rc = 1;
24930: goto meta_command_exit;
24931: }
1.4 misho 24932: open_db(p, 0);
1.5 misho 24933: if( nArg==2 ){
24934: sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
24935: goto meta_command_exit;
24936: }
24937: zSql = sqlite3_mprintf(
24938: "SELECT rootpage, 0 FROM sqlite_schema"
24939: " WHERE name='%q' AND type='index'"
24940: "UNION ALL "
24941: "SELECT rootpage, 1 FROM sqlite_schema"
24942: " WHERE name='%q' AND type='table'"
24943: " AND sql LIKE '%%without%%rowid%%'",
24944: azArg[1], azArg[1]
24945: );
24946: sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
24947: sqlite3_free(zSql);
24948: if( sqlite3_step(pStmt)==SQLITE_ROW ){
24949: tnum = sqlite3_column_int(pStmt, 0);
24950: isWO = sqlite3_column_int(pStmt, 1);
24951: }
24952: sqlite3_finalize(pStmt);
24953: zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
24954: rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
24955: sqlite3_free(zSql);
24956: i = 0;
1.6.2.1 ! misho 24957: while( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
1.5 misho 24958: char zLabel[20];
24959: const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
24960: i++;
24961: if( zCol==0 ){
24962: if( sqlite3_column_int(pStmt,1)==-1 ){
24963: zCol = "_ROWID_";
24964: }else{
24965: sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
24966: zCol = zLabel;
24967: }
24968: }
24969: if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){
24970: lenPK = (int)strlen(zCollist);
24971: }
24972: if( zCollist==0 ){
24973: zCollist = sqlite3_mprintf("\"%w\"", zCol);
24974: }else{
24975: zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
24976: }
24977: }
24978: sqlite3_finalize(pStmt);
24979: if( i==0 || tnum==0 ){
24980: utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
1.4 misho 24981: rc = 1;
1.5 misho 24982: sqlite3_free(zCollist);
1.4 misho 24983: goto meta_command_exit;
1.2 misho 24984: }
1.5 misho 24985: if( lenPK==0 ) lenPK = 100000;
24986: zSql = sqlite3_mprintf(
24987: "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
24988: azArg[2], zCollist, lenPK, zCollist);
24989: sqlite3_free(zCollist);
24990: rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
24991: if( rc==SQLITE_OK ){
24992: rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
24993: sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
24994: if( rc ){
24995: utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
24996: }else{
24997: utf8_printf(stdout, "%s;\n", zSql);
24998: raw_printf(stdout,
24999: "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
25000: azArg[1], isWO ? "table" : "index"
25001: );
25002: }
25003: }else{
25004: raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
1.2 misho 25005: rc = 1;
25006: }
1.5 misho 25007: sqlite3_free(zSql);
1.2 misho 25008: }else
1.5 misho 25009: #endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
1.2 misho 25010:
25011: #ifdef SQLITE_ENABLE_IOTRACE
1.6.2.1 ! misho 25012: if( c=='i' && cli_strncmp(azArg[0], "iotrace", n)==0 ){
1.4 misho 25013: SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
1.2 misho 25014: if( iotrace && iotrace!=stdout ) fclose(iotrace);
25015: iotrace = 0;
25016: if( nArg<2 ){
25017: sqlite3IoTrace = 0;
1.6.2.1 ! misho 25018: }else if( cli_strcmp(azArg[1], "-")==0 ){
1.2 misho 25019: sqlite3IoTrace = iotracePrintf;
25020: iotrace = stdout;
1.4 misho 25021: }else{
25022: iotrace = fopen(azArg[1], "w");
25023: if( iotrace==0 ){
25024: utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
25025: sqlite3IoTrace = 0;
25026: rc = 1;
25027: }else{
25028: sqlite3IoTrace = iotracePrintf;
25029: }
25030: }
25031: }else
25032: #endif
1.5 misho 25033:
1.6.2.1 ! misho 25034: if( c=='l' && n>=5 && cli_strncmp(azArg[0], "limits", n)==0 ){
1.4 misho 25035: static const struct {
25036: const char *zLimitName; /* Name of a limit */
25037: int limitCode; /* Integer code for that limit */
25038: } aLimit[] = {
25039: { "length", SQLITE_LIMIT_LENGTH },
25040: { "sql_length", SQLITE_LIMIT_SQL_LENGTH },
25041: { "column", SQLITE_LIMIT_COLUMN },
25042: { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
25043: { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
25044: { "vdbe_op", SQLITE_LIMIT_VDBE_OP },
25045: { "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
25046: { "attached", SQLITE_LIMIT_ATTACHED },
25047: { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
25048: { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER },
25049: { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
25050: { "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
25051: };
25052: int i, n2;
25053: open_db(p, 0);
25054: if( nArg==1 ){
25055: for(i=0; i<ArraySize(aLimit); i++){
25056: printf("%20s %d\n", aLimit[i].zLimitName,
25057: sqlite3_limit(p->db, aLimit[i].limitCode, -1));
25058: }
25059: }else if( nArg>3 ){
25060: raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
25061: rc = 1;
25062: goto meta_command_exit;
25063: }else{
25064: int iLimit = -1;
25065: n2 = strlen30(azArg[1]);
25066: for(i=0; i<ArraySize(aLimit); i++){
25067: if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
25068: if( iLimit<0 ){
25069: iLimit = i;
25070: }else{
25071: utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
25072: rc = 1;
25073: goto meta_command_exit;
25074: }
25075: }
25076: }
25077: if( iLimit<0 ){
25078: utf8_printf(stderr, "unknown limit: \"%s\"\n"
25079: "enter \".limits\" with no arguments for a list.\n",
25080: azArg[1]);
1.2 misho 25081: rc = 1;
1.4 misho 25082: goto meta_command_exit;
25083: }
25084: if( nArg==3 ){
25085: sqlite3_limit(p->db, aLimit[iLimit].limitCode,
25086: (int)integerValue(azArg[2]));
1.2 misho 25087: }
1.4 misho 25088: printf("%20s %d\n", aLimit[iLimit].zLimitName,
25089: sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
1.2 misho 25090: }
25091: }else
25092:
1.6.2.1 ! misho 25093: if( c=='l' && n>2 && cli_strncmp(azArg[0], "lint", n)==0 ){
1.5 misho 25094: open_db(p, 0);
25095: lintDotCommand(p, azArg, nArg);
25096: }else
25097:
1.6.2.1 ! misho 25098: #if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_FIDDLE)
! 25099: if( c=='l' && cli_strncmp(azArg[0], "load", n)==0 ){
1.2 misho 25100: const char *zFile, *zProc;
25101: char *zErrMsg = 0;
1.6.2.1 ! misho 25102: failIfSafeMode(p, "cannot run .load in safe mode");
! 25103: if( nArg<2 || azArg[1][0]==0 ){
! 25104: /* Must have a non-empty FILE. (Will not load self.) */
1.4 misho 25105: raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
25106: rc = 1;
25107: goto meta_command_exit;
25108: }
1.2 misho 25109: zFile = azArg[1];
25110: zProc = nArg>=3 ? azArg[2] : 0;
1.4 misho 25111: open_db(p, 0);
1.2 misho 25112: rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
25113: if( rc!=SQLITE_OK ){
1.4 misho 25114: utf8_printf(stderr, "Error: %s\n", zErrMsg);
1.2 misho 25115: sqlite3_free(zErrMsg);
25116: rc = 1;
25117: }
25118: }else
25119: #endif
25120:
1.6.2.1 ! misho 25121: if( c=='l' && cli_strncmp(azArg[0], "log", n)==0 ){
1.4 misho 25122: if( nArg!=2 ){
25123: raw_printf(stderr, "Usage: .log FILENAME\n");
25124: rc = 1;
25125: }else{
25126: const char *zFile = azArg[1];
1.6.2.1 ! misho 25127: if( p->bSafeMode
! 25128: && cli_strcmp(zFile,"on")!=0
! 25129: && cli_strcmp(zFile,"off")!=0
! 25130: ){
! 25131: raw_printf(stdout, "cannot set .log to anything other "
! 25132: "than \"on\" or \"off\"\n");
! 25133: zFile = "off";
! 25134: }
1.4 misho 25135: output_file_close(p->pLog);
1.6.2.1 ! misho 25136: if( cli_strcmp(zFile,"on")==0 ) zFile = "stdout";
1.5 misho 25137: p->pLog = output_file_open(zFile, 0);
1.4 misho 25138: }
1.2 misho 25139: }else
25140:
1.6.2.1 ! misho 25141: if( c=='m' && cli_strncmp(azArg[0], "mode", n)==0 ){
! 25142: const char *zMode = 0;
! 25143: const char *zTabname = 0;
! 25144: int i, n2;
! 25145: ColModeOpts cmOpts = ColModeOpts_default;
! 25146: for(i=1; i<nArg; i++){
! 25147: const char *z = azArg[i];
! 25148: if( optionMatch(z,"wrap") && i+1<nArg ){
! 25149: cmOpts.iWrap = integerValue(azArg[++i]);
! 25150: }else if( optionMatch(z,"ww") ){
! 25151: cmOpts.bWordWrap = 1;
! 25152: }else if( optionMatch(z,"wordwrap") && i+1<nArg ){
! 25153: cmOpts.bWordWrap = (u8)booleanValue(azArg[++i]);
! 25154: }else if( optionMatch(z,"quote") ){
! 25155: cmOpts.bQuote = 1;
! 25156: }else if( optionMatch(z,"noquote") ){
! 25157: cmOpts.bQuote = 0;
! 25158: }else if( zMode==0 ){
! 25159: zMode = z;
! 25160: /* Apply defaults for qbox pseudo-mode. If that
! 25161: * overwrites already-set values, user was informed of this.
! 25162: */
! 25163: if( cli_strcmp(z, "qbox")==0 ){
! 25164: ColModeOpts cmo = ColModeOpts_default_qbox;
! 25165: zMode = "box";
! 25166: cmOpts = cmo;
! 25167: }
! 25168: }else if( zTabname==0 ){
! 25169: zTabname = z;
! 25170: }else if( z[0]=='-' ){
! 25171: utf8_printf(stderr, "unknown option: %s\n", z);
! 25172: utf8_printf(stderr, "options:\n"
! 25173: " --noquote\n"
! 25174: " --quote\n"
! 25175: " --wordwrap on/off\n"
! 25176: " --wrap N\n"
! 25177: " --ww\n");
! 25178: rc = 1;
! 25179: goto meta_command_exit;
! 25180: }else{
! 25181: utf8_printf(stderr, "extra argument: \"%s\"\n", z);
! 25182: rc = 1;
! 25183: goto meta_command_exit;
! 25184: }
! 25185: }
! 25186: if( zMode==0 ){
! 25187: if( p->mode==MODE_Column
! 25188: || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
! 25189: ){
! 25190: raw_printf
! 25191: (p->out,
! 25192: "current output mode: %s --wrap %d --wordwrap %s --%squote\n",
! 25193: modeDescr[p->mode], p->cmOpts.iWrap,
! 25194: p->cmOpts.bWordWrap ? "on" : "off",
! 25195: p->cmOpts.bQuote ? "" : "no");
! 25196: }else{
! 25197: raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
! 25198: }
! 25199: zMode = modeDescr[p->mode];
! 25200: }
! 25201: n2 = strlen30(zMode);
! 25202: if( cli_strncmp(zMode,"lines",n2)==0 ){
1.2 misho 25203: p->mode = MODE_Line;
1.5 misho 25204: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
1.6.2.1 ! misho 25205: }else if( cli_strncmp(zMode,"columns",n2)==0 ){
1.2 misho 25206: p->mode = MODE_Column;
1.5 misho 25207: if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){
25208: p->showHeader = 1;
25209: }
25210: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
1.6.2.1 ! misho 25211: p->cmOpts = cmOpts;
! 25212: }else if( cli_strncmp(zMode,"list",n2)==0 ){
1.2 misho 25213: p->mode = MODE_List;
1.5 misho 25214: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
25215: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
1.6.2.1 ! misho 25216: }else if( cli_strncmp(zMode,"html",n2)==0 ){
1.2 misho 25217: p->mode = MODE_Html;
1.6.2.1 ! misho 25218: }else if( cli_strncmp(zMode,"tcl",n2)==0 ){
1.2 misho 25219: p->mode = MODE_Tcl;
1.4 misho 25220: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
1.5 misho 25221: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
1.6.2.1 ! misho 25222: }else if( cli_strncmp(zMode,"csv",n2)==0 ){
1.2 misho 25223: p->mode = MODE_Csv;
1.4 misho 25224: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
25225: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
1.6.2.1 ! misho 25226: }else if( cli_strncmp(zMode,"tabs",n2)==0 ){
1.2 misho 25227: p->mode = MODE_List;
1.4 misho 25228: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
1.6.2.1 ! misho 25229: }else if( cli_strncmp(zMode,"insert",n2)==0 ){
1.2 misho 25230: p->mode = MODE_Insert;
1.6.2.1 ! misho 25231: set_table_name(p, zTabname ? zTabname : "table");
! 25232: }else if( cli_strncmp(zMode,"quote",n2)==0 ){
1.5 misho 25233: p->mode = MODE_Quote;
25234: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
25235: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
1.6.2.1 ! misho 25236: }else if( cli_strncmp(zMode,"ascii",n2)==0 ){
1.4 misho 25237: p->mode = MODE_Ascii;
25238: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
25239: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
1.6.2.1 ! misho 25240: }else if( cli_strncmp(zMode,"markdown",n2)==0 ){
1.5 misho 25241: p->mode = MODE_Markdown;
1.6.2.1 ! misho 25242: p->cmOpts = cmOpts;
! 25243: }else if( cli_strncmp(zMode,"table",n2)==0 ){
1.5 misho 25244: p->mode = MODE_Table;
1.6.2.1 ! misho 25245: p->cmOpts = cmOpts;
! 25246: }else if( cli_strncmp(zMode,"box",n2)==0 ){
1.5 misho 25247: p->mode = MODE_Box;
1.6.2.1 ! misho 25248: p->cmOpts = cmOpts;
! 25249: }else if( cli_strncmp(zMode,"count",n2)==0 ){
! 25250: p->mode = MODE_Count;
! 25251: }else if( cli_strncmp(zMode,"off",n2)==0 ){
! 25252: p->mode = MODE_Off;
! 25253: }else if( cli_strncmp(zMode,"json",n2)==0 ){
1.5 misho 25254: p->mode = MODE_Json;
25255: }else{
1.4 misho 25256: raw_printf(stderr, "Error: mode should be one of: "
1.5 misho 25257: "ascii box column csv html insert json line list markdown "
1.6.2.1 ! misho 25258: "qbox quote table tabs tcl\n");
1.2 misho 25259: rc = 1;
25260: }
1.4 misho 25261: p->cMode = p->mode;
1.2 misho 25262: }else
25263:
1.6.2.1 ! misho 25264: #ifndef SQLITE_SHELL_FIDDLE
! 25265: if( c=='n' && cli_strcmp(azArg[0], "nonce")==0 ){
! 25266: if( nArg!=2 ){
! 25267: raw_printf(stderr, "Usage: .nonce NONCE\n");
! 25268: rc = 1;
! 25269: }else if( p->zNonce==0 || cli_strcmp(azArg[1],p->zNonce)!=0 ){
! 25270: raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n",
! 25271: p->lineno, azArg[1]);
! 25272: exit(1);
! 25273: }else{
! 25274: p->bSafeMode = 0;
! 25275: return 0; /* Return immediately to bypass the safe mode reset
! 25276: ** at the end of this procedure */
! 25277: }
! 25278: }else
! 25279: #endif /* !defined(SQLITE_SHELL_FIDDLE) */
! 25280:
! 25281: if( c=='n' && cli_strncmp(azArg[0], "nullvalue", n)==0 ){
1.4 misho 25282: if( nArg==2 ){
25283: sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
25284: "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
25285: }else{
25286: raw_printf(stderr, "Usage: .nullvalue STRING\n");
1.2 misho 25287: rc = 1;
25288: }
25289: }else
25290:
1.6.2.1 ! misho 25291: if( c=='o' && cli_strncmp(azArg[0], "open", n)==0 && n>=2 ){
! 25292: const char *zFN = 0; /* Pointer to constant filename */
1.6 misho 25293: char *zNewFilename = 0; /* Name of the database file to open */
25294: int iName = 1; /* Index in azArg[] of the filename */
25295: int newFlag = 0; /* True to delete file before opening */
1.6.2.1 ! misho 25296: int openMode = SHELL_OPEN_UNSPEC;
! 25297:
1.5 misho 25298: /* Check for command-line arguments */
1.6 misho 25299: for(iName=1; iName<nArg; iName++){
1.5 misho 25300: const char *z = azArg[iName];
1.6.2.1 ! misho 25301: #ifndef SQLITE_SHELL_FIDDLE
1.5 misho 25302: if( optionMatch(z,"new") ){
25303: newFlag = 1;
25304: #ifdef SQLITE_HAVE_ZLIB
25305: }else if( optionMatch(z, "zip") ){
1.6.2.1 ! misho 25306: openMode = SHELL_OPEN_ZIPFILE;
1.5 misho 25307: #endif
25308: }else if( optionMatch(z, "append") ){
1.6.2.1 ! misho 25309: openMode = SHELL_OPEN_APPENDVFS;
1.5 misho 25310: }else if( optionMatch(z, "readonly") ){
1.6.2.1 ! misho 25311: openMode = SHELL_OPEN_READONLY;
1.5 misho 25312: }else if( optionMatch(z, "nofollow") ){
25313: p->openFlags |= SQLITE_OPEN_NOFOLLOW;
1.6.2.1 ! misho 25314: #ifndef SQLITE_OMIT_DESERIALIZE
1.5 misho 25315: }else if( optionMatch(z, "deserialize") ){
1.6.2.1 ! misho 25316: openMode = SHELL_OPEN_DESERIALIZE;
1.5 misho 25317: }else if( optionMatch(z, "hexdb") ){
1.6.2.1 ! misho 25318: openMode = SHELL_OPEN_HEXDB;
1.5 misho 25319: }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
25320: p->szMax = integerValue(azArg[++iName]);
1.6.2.1 ! misho 25321: #endif /* SQLITE_OMIT_DESERIALIZE */
! 25322: }else
! 25323: #endif /* !SQLITE_SHELL_FIDDLE */
! 25324: if( z[0]=='-' ){
1.5 misho 25325: utf8_printf(stderr, "unknown option: %s\n", z);
25326: rc = 1;
25327: goto meta_command_exit;
1.6.2.1 ! misho 25328: }else if( zFN ){
1.6 misho 25329: utf8_printf(stderr, "extra argument: \"%s\"\n", z);
25330: rc = 1;
25331: goto meta_command_exit;
25332: }else{
1.6.2.1 ! misho 25333: zFN = z;
1.5 misho 25334: }
25335: }
1.6.2.1 ! misho 25336:
! 25337: /* Close the existing database */
! 25338: session_close_all(p, -1);
! 25339: close_db(p->db);
! 25340: p->db = 0;
! 25341: p->pAuxDb->zDbFilename = 0;
! 25342: sqlite3_free(p->pAuxDb->zFreeOnClose);
! 25343: p->pAuxDb->zFreeOnClose = 0;
! 25344: p->openMode = openMode;
! 25345: p->openFlags = 0;
! 25346: p->szMax = 0;
! 25347:
1.5 misho 25348: /* If a filename is specified, try to open it first */
1.6.2.1 ! misho 25349: if( zFN || p->openMode==SHELL_OPEN_HEXDB ){
! 25350: if( newFlag && zFN && !p->bSafeMode ) shellDeleteFile(zFN);
! 25351: #ifndef SQLITE_SHELL_FIDDLE
! 25352: if( p->bSafeMode
! 25353: && p->openMode!=SHELL_OPEN_HEXDB
! 25354: && zFN
! 25355: && cli_strcmp(zFN,":memory:")!=0
! 25356: ){
! 25357: failIfSafeMode(p, "cannot open disk-based database files in safe mode");
! 25358: }
! 25359: #else
! 25360: /* WASM mode has its own sandboxed pseudo-filesystem. */
! 25361: #endif
! 25362: if( zFN ){
! 25363: zNewFilename = sqlite3_mprintf("%s", zFN);
! 25364: shell_check_oom(zNewFilename);
! 25365: }else{
! 25366: zNewFilename = 0;
! 25367: }
! 25368: p->pAuxDb->zDbFilename = zNewFilename;
1.5 misho 25369: open_db(p, OPEN_DB_KEEPALIVE);
25370: if( p->db==0 ){
25371: utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
25372: sqlite3_free(zNewFilename);
25373: }else{
1.6.2.1 ! misho 25374: p->pAuxDb->zFreeOnClose = zNewFilename;
1.5 misho 25375: }
25376: }
25377: if( p->db==0 ){
25378: /* As a fall-back open a TEMP database */
1.6.2.1 ! misho 25379: p->pAuxDb->zDbFilename = 0;
1.5 misho 25380: open_db(p, 0);
1.4 misho 25381: }
1.2 misho 25382: }else
25383:
1.6.2.1 ! misho 25384: #ifndef SQLITE_SHELL_FIDDLE
1.5 misho 25385: if( (c=='o'
1.6.2.1 ! misho 25386: && (cli_strncmp(azArg[0], "output", n)==0
! 25387: || cli_strncmp(azArg[0], "once", n)==0))
! 25388: || (c=='e' && n==5 && cli_strcmp(azArg[0],"excel")==0)
1.4 misho 25389: ){
1.6 misho 25390: char *zFile = 0;
1.5 misho 25391: int bTxtMode = 0;
25392: int i;
25393: int eMode = 0;
1.6.2.1 ! misho 25394: int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */
! 25395: unsigned char zBOM[4]; /* Byte-order mark to using if --bom is present */
1.5 misho 25396:
1.6.2.1 ! misho 25397: zBOM[0] = 0;
! 25398: failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
1.5 misho 25399: if( c=='e' ){
25400: eMode = 'x';
25401: bOnce = 2;
1.6.2.1 ! misho 25402: }else if( cli_strncmp(azArg[0],"once",n)==0 ){
1.5 misho 25403: bOnce = 1;
1.4 misho 25404: }
1.5 misho 25405: for(i=1; i<nArg; i++){
25406: char *z = azArg[i];
25407: if( z[0]=='-' ){
25408: if( z[1]=='-' ) z++;
1.6.2.1 ! misho 25409: if( cli_strcmp(z,"-bom")==0 ){
! 25410: zBOM[0] = 0xef;
! 25411: zBOM[1] = 0xbb;
! 25412: zBOM[2] = 0xbf;
! 25413: zBOM[3] = 0;
! 25414: }else if( c!='e' && cli_strcmp(z,"-x")==0 ){
1.5 misho 25415: eMode = 'x'; /* spreadsheet */
1.6.2.1 ! misho 25416: }else if( c!='e' && cli_strcmp(z,"-e")==0 ){
1.5 misho 25417: eMode = 'e'; /* text editor */
25418: }else{
25419: utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n",
25420: azArg[i]);
25421: showHelp(p->out, azArg[0]);
25422: rc = 1;
25423: goto meta_command_exit;
25424: }
1.6 misho 25425: }else if( zFile==0 && eMode!='e' && eMode!='x' ){
25426: zFile = sqlite3_mprintf("%s", z);
1.6.2.1 ! misho 25427: if( zFile && zFile[0]=='|' ){
1.6 misho 25428: while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]);
25429: break;
25430: }
1.5 misho 25431: }else{
25432: utf8_printf(p->out,"ERROR: extra parameter: \"%s\". Usage:\n",
25433: azArg[i]);
25434: showHelp(p->out, azArg[0]);
1.4 misho 25435: rc = 1;
1.6 misho 25436: sqlite3_free(zFile);
1.4 misho 25437: goto meta_command_exit;
25438: }
1.5 misho 25439: }
1.6.2.1 ! misho 25440: if( zFile==0 ){
! 25441: zFile = sqlite3_mprintf("stdout");
! 25442: }
1.5 misho 25443: if( bOnce ){
1.4 misho 25444: p->outCount = 2;
1.3 misho 25445: }else{
1.4 misho 25446: p->outCount = 0;
1.2 misho 25447: }
1.4 misho 25448: output_reset(p);
1.5 misho 25449: #ifndef SQLITE_NOHAVE_SYSTEM
25450: if( eMode=='e' || eMode=='x' ){
25451: p->doXdgOpen = 1;
25452: outputModePush(p);
25453: if( eMode=='x' ){
25454: /* spreadsheet mode. Output as CSV. */
25455: newTempFile(p, "csv");
25456: ShellClearFlag(p, SHFLG_Echo);
25457: p->mode = MODE_Csv;
25458: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
25459: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
25460: }else{
25461: /* text editor mode */
25462: newTempFile(p, "txt");
25463: bTxtMode = 1;
25464: }
1.6 misho 25465: sqlite3_free(zFile);
25466: zFile = sqlite3_mprintf("%s", p->zTempFile);
1.5 misho 25467: }
25468: #endif /* SQLITE_NOHAVE_SYSTEM */
1.6.2.1 ! misho 25469: shell_check_oom(zFile);
1.4 misho 25470: if( zFile[0]=='|' ){
25471: #ifdef SQLITE_OMIT_POPEN
25472: raw_printf(stderr, "Error: pipes are not supported in this OS\n");
25473: rc = 1;
25474: p->out = stdout;
25475: #else
25476: p->out = popen(zFile + 1, "w");
1.3 misho 25477: if( p->out==0 ){
1.4 misho 25478: utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
1.3 misho 25479: p->out = stdout;
25480: rc = 1;
25481: }else{
1.6.2.1 ! misho 25482: if( zBOM[0] ) fwrite(zBOM, 1, 3, p->out);
1.4 misho 25483: sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
1.3 misho 25484: }
1.4 misho 25485: #endif
1.2 misho 25486: }else{
1.5 misho 25487: p->out = output_file_open(zFile, bTxtMode);
1.2 misho 25488: if( p->out==0 ){
1.6.2.1 ! misho 25489: if( cli_strcmp(zFile,"off")!=0 ){
1.4 misho 25490: utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
1.3 misho 25491: }
1.2 misho 25492: p->out = stdout;
25493: rc = 1;
25494: } else {
1.6.2.1 ! misho 25495: if( zBOM[0] ) fwrite(zBOM, 1, 3, p->out);
1.4 misho 25496: sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
1.2 misho 25497: }
25498: }
1.6 misho 25499: sqlite3_free(zFile);
1.2 misho 25500: }else
1.6.2.1 ! misho 25501: #endif /* !defined(SQLITE_SHELL_FIDDLE) */
1.2 misho 25502:
1.6.2.1 ! misho 25503: if( c=='p' && n>=3 && cli_strncmp(azArg[0], "parameter", n)==0 ){
1.5 misho 25504: open_db(p,0);
25505: if( nArg<=1 ) goto parameter_syntax_error;
25506:
25507: /* .parameter clear
25508: ** Clear all bind parameters by dropping the TEMP table that holds them.
25509: */
1.6.2.1 ! misho 25510: if( nArg==2 && cli_strcmp(azArg[1],"clear")==0 ){
1.5 misho 25511: sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
25512: 0, 0, 0);
25513: }else
25514:
25515: /* .parameter list
25516: ** List all bind parameters.
25517: */
1.6.2.1 ! misho 25518: if( nArg==2 && cli_strcmp(azArg[1],"list")==0 ){
1.5 misho 25519: sqlite3_stmt *pStmt = 0;
25520: int rx;
25521: int len = 0;
25522: rx = sqlite3_prepare_v2(p->db,
25523: "SELECT max(length(key)) "
25524: "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
25525: if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
25526: len = sqlite3_column_int(pStmt, 0);
25527: if( len>40 ) len = 40;
25528: }
25529: sqlite3_finalize(pStmt);
25530: pStmt = 0;
25531: if( len ){
25532: rx = sqlite3_prepare_v2(p->db,
25533: "SELECT key, quote(value) "
25534: "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
1.6.2.1 ! misho 25535: while( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
1.5 misho 25536: utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
25537: sqlite3_column_text(pStmt,1));
25538: }
25539: sqlite3_finalize(pStmt);
25540: }
25541: }else
25542:
25543: /* .parameter init
25544: ** Make sure the TEMP table used to hold bind parameters exists.
25545: ** Create it if necessary.
25546: */
1.6.2.1 ! misho 25547: if( nArg==2 && cli_strcmp(azArg[1],"init")==0 ){
1.5 misho 25548: bind_table_init(p);
25549: }else
25550:
25551: /* .parameter set NAME VALUE
25552: ** Set or reset a bind parameter. NAME should be the full parameter
25553: ** name exactly as it appears in the query. (ex: $abc, @def). The
25554: ** VALUE can be in either SQL literal notation, or if not it will be
25555: ** understood to be a text string.
25556: */
1.6.2.1 ! misho 25557: if( nArg==4 && cli_strcmp(azArg[1],"set")==0 ){
1.5 misho 25558: int rx;
25559: char *zSql;
25560: sqlite3_stmt *pStmt;
25561: const char *zKey = azArg[2];
25562: const char *zValue = azArg[3];
25563: bind_table_init(p);
25564: zSql = sqlite3_mprintf(
25565: "REPLACE INTO temp.sqlite_parameters(key,value)"
25566: "VALUES(%Q,%s);", zKey, zValue);
1.6.2.1 ! misho 25567: shell_check_oom(zSql);
1.5 misho 25568: pStmt = 0;
25569: rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
25570: sqlite3_free(zSql);
25571: if( rx!=SQLITE_OK ){
25572: sqlite3_finalize(pStmt);
25573: pStmt = 0;
25574: zSql = sqlite3_mprintf(
25575: "REPLACE INTO temp.sqlite_parameters(key,value)"
25576: "VALUES(%Q,%Q);", zKey, zValue);
1.6.2.1 ! misho 25577: shell_check_oom(zSql);
1.5 misho 25578: rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
25579: sqlite3_free(zSql);
25580: if( rx!=SQLITE_OK ){
25581: utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
25582: sqlite3_finalize(pStmt);
25583: pStmt = 0;
25584: rc = 1;
25585: }
25586: }
25587: sqlite3_step(pStmt);
25588: sqlite3_finalize(pStmt);
25589: }else
25590:
25591: /* .parameter unset NAME
25592: ** Remove the NAME binding from the parameter binding table, if it
25593: ** exists.
25594: */
1.6.2.1 ! misho 25595: if( nArg==3 && cli_strcmp(azArg[1],"unset")==0 ){
1.5 misho 25596: char *zSql = sqlite3_mprintf(
25597: "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
1.6.2.1 ! misho 25598: shell_check_oom(zSql);
1.5 misho 25599: sqlite3_exec(p->db, zSql, 0, 0, 0);
25600: sqlite3_free(zSql);
25601: }else
25602: /* If no command name matches, show a syntax error */
25603: parameter_syntax_error:
25604: showHelp(p->out, "parameter");
25605: }else
25606:
1.6.2.1 ! misho 25607: if( c=='p' && n>=3 && cli_strncmp(azArg[0], "print", n)==0 ){
1.3 misho 25608: int i;
25609: for(i=1; i<nArg; i++){
1.4 misho 25610: if( i>1 ) raw_printf(p->out, " ");
25611: utf8_printf(p->out, "%s", azArg[i]);
1.3 misho 25612: }
1.4 misho 25613: raw_printf(p->out, "\n");
1.3 misho 25614: }else
25615:
1.5 misho 25616: #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
1.6.2.1 ! misho 25617: if( c=='p' && n>=3 && cli_strncmp(azArg[0], "progress", n)==0 ){
1.5 misho 25618: int i;
25619: int nn = 0;
25620: p->flgProgress = 0;
25621: p->mxProgress = 0;
25622: p->nProgress = 0;
25623: for(i=1; i<nArg; i++){
25624: const char *z = azArg[i];
25625: if( z[0]=='-' ){
25626: z++;
25627: if( z[0]=='-' ) z++;
1.6.2.1 ! misho 25628: if( cli_strcmp(z,"quiet")==0 || cli_strcmp(z,"q")==0 ){
1.5 misho 25629: p->flgProgress |= SHELL_PROGRESS_QUIET;
25630: continue;
25631: }
1.6.2.1 ! misho 25632: if( cli_strcmp(z,"reset")==0 ){
1.5 misho 25633: p->flgProgress |= SHELL_PROGRESS_RESET;
25634: continue;
25635: }
1.6.2.1 ! misho 25636: if( cli_strcmp(z,"once")==0 ){
1.5 misho 25637: p->flgProgress |= SHELL_PROGRESS_ONCE;
25638: continue;
25639: }
1.6.2.1 ! misho 25640: if( cli_strcmp(z,"limit")==0 ){
1.5 misho 25641: if( i+1>=nArg ){
25642: utf8_printf(stderr, "Error: missing argument on --limit\n");
25643: rc = 1;
25644: goto meta_command_exit;
25645: }else{
25646: p->mxProgress = (int)integerValue(azArg[++i]);
25647: }
25648: continue;
25649: }
25650: utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
25651: rc = 1;
25652: goto meta_command_exit;
25653: }else{
25654: nn = (int)integerValue(z);
25655: }
25656: }
25657: open_db(p, 0);
25658: sqlite3_progress_handler(p->db, nn, progress_handler, p);
25659: }else
25660: #endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
25661:
1.6.2.1 ! misho 25662: if( c=='p' && cli_strncmp(azArg[0], "prompt", n)==0 ){
1.2 misho 25663: if( nArg >= 2) {
1.6.2.1 ! misho 25664: shell_strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
1.2 misho 25665: }
25666: if( nArg >= 3) {
1.6.2.1 ! misho 25667: shell_strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
1.2 misho 25668: }
25669: }else
25670:
1.6.2.1 ! misho 25671: #ifndef SQLITE_SHELL_FIDDLE
! 25672: if( c=='q' && cli_strncmp(azArg[0], "quit", n)==0 ){
1.2 misho 25673: rc = 2;
25674: }else
1.6.2.1 ! misho 25675: #endif
1.2 misho 25676:
1.6.2.1 ! misho 25677: #ifndef SQLITE_SHELL_FIDDLE
! 25678: if( c=='r' && n>=3 && cli_strncmp(azArg[0], "read", n)==0 ){
1.5 misho 25679: FILE *inSaved = p->in;
25680: int savedLineno = p->lineno;
1.6.2.1 ! misho 25681: failIfSafeMode(p, "cannot run .read in safe mode");
1.4 misho 25682: if( nArg!=2 ){
25683: raw_printf(stderr, "Usage: .read FILE\n");
25684: rc = 1;
25685: goto meta_command_exit;
25686: }
1.6 misho 25687: if( azArg[1][0]=='|' ){
25688: #ifdef SQLITE_OMIT_POPEN
25689: raw_printf(stderr, "Error: pipes are not supported in this OS\n");
25690: rc = 1;
25691: p->out = stdout;
25692: #else
25693: p->in = popen(azArg[1]+1, "r");
25694: if( p->in==0 ){
25695: utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
25696: rc = 1;
25697: }else{
25698: rc = process_input(p);
25699: pclose(p->in);
25700: }
25701: #endif
1.6.2.1 ! misho 25702: }else if( (p->in = openChrSource(azArg[1]))==0 ){
1.4 misho 25703: utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
1.2 misho 25704: rc = 1;
25705: }else{
1.5 misho 25706: rc = process_input(p);
25707: fclose(p->in);
1.2 misho 25708: }
1.5 misho 25709: p->in = inSaved;
25710: p->lineno = savedLineno;
1.2 misho 25711: }else
1.6.2.1 ! misho 25712: #endif /* !defined(SQLITE_SHELL_FIDDLE) */
1.2 misho 25713:
1.6.2.1 ! misho 25714: #ifndef SQLITE_SHELL_FIDDLE
! 25715: if( c=='r' && n>=3 && cli_strncmp(azArg[0], "restore", n)==0 ){
1.2 misho 25716: const char *zSrcFile;
25717: const char *zDb;
25718: sqlite3 *pSrc;
25719: sqlite3_backup *pBackup;
25720: int nTimeout = 0;
25721:
1.6.2.1 ! misho 25722: failIfSafeMode(p, "cannot run .restore in safe mode");
1.2 misho 25723: if( nArg==2 ){
25724: zSrcFile = azArg[1];
25725: zDb = "main";
1.4 misho 25726: }else if( nArg==3 ){
1.2 misho 25727: zSrcFile = azArg[2];
25728: zDb = azArg[1];
1.4 misho 25729: }else{
25730: raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
25731: rc = 1;
25732: goto meta_command_exit;
1.2 misho 25733: }
25734: rc = sqlite3_open(zSrcFile, &pSrc);
25735: if( rc!=SQLITE_OK ){
1.4 misho 25736: utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
1.5 misho 25737: close_db(pSrc);
1.2 misho 25738: return 1;
25739: }
1.4 misho 25740: open_db(p, 0);
1.2 misho 25741: pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
25742: if( pBackup==0 ){
1.4 misho 25743: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
1.5 misho 25744: close_db(pSrc);
1.2 misho 25745: return 1;
25746: }
25747: while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
25748: || rc==SQLITE_BUSY ){
25749: if( rc==SQLITE_BUSY ){
25750: if( nTimeout++ >= 3 ) break;
25751: sqlite3_sleep(100);
25752: }
25753: }
25754: sqlite3_backup_finish(pBackup);
25755: if( rc==SQLITE_DONE ){
25756: rc = 0;
25757: }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
1.4 misho 25758: raw_printf(stderr, "Error: source database is busy\n");
1.2 misho 25759: rc = 1;
25760: }else{
1.4 misho 25761: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
1.2 misho 25762: rc = 1;
25763: }
1.5 misho 25764: close_db(pSrc);
1.2 misho 25765: }else
1.6.2.1 ! misho 25766: #endif /* !defined(SQLITE_SHELL_FIDDLE) */
1.2 misho 25767:
1.6.2.1 ! misho 25768: if( c=='s' && cli_strncmp(azArg[0], "scanstats", n)==0 ){
1.4 misho 25769: if( nArg==2 ){
1.6.2.1 ! misho 25770: if( cli_strcmp(azArg[1], "vm")==0 ){
! 25771: p->scanstatsOn = 3;
! 25772: }else
! 25773: if( cli_strcmp(azArg[1], "est")==0 ){
! 25774: p->scanstatsOn = 2;
! 25775: }else{
! 25776: p->scanstatsOn = (u8)booleanValue(azArg[1]);
! 25777: }
! 25778: open_db(p, 0);
! 25779: sqlite3_db_config(
! 25780: p->db, SQLITE_DBCONFIG_STMT_SCANSTATUS, p->scanstatsOn, (int*)0
! 25781: );
1.4 misho 25782: #ifndef SQLITE_ENABLE_STMT_SCANSTATUS
25783: raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
25784: #endif
25785: }else{
1.6.2.1 ! misho 25786: raw_printf(stderr, "Usage: .scanstats on|off|est\n");
1.4 misho 25787: rc = 1;
25788: }
25789: }else
25790:
1.6.2.1 ! misho 25791: if( c=='s' && cli_strncmp(azArg[0], "schema", n)==0 ){
1.5 misho 25792: ShellText sSelect;
1.4 misho 25793: ShellState data;
1.2 misho 25794: char *zErrMsg = 0;
1.5 misho 25795: const char *zDiv = "(";
25796: const char *zName = 0;
25797: int iSchema = 0;
25798: int bDebug = 0;
1.6 misho 25799: int bNoSystemTabs = 0;
1.5 misho 25800: int ii;
25801:
1.4 misho 25802: open_db(p, 0);
1.2 misho 25803: memcpy(&data, p, sizeof(data));
25804: data.showHeader = 0;
1.4 misho 25805: data.cMode = data.mode = MODE_Semi;
1.5 misho 25806: initText(&sSelect);
25807: for(ii=1; ii<nArg; ii++){
25808: if( optionMatch(azArg[ii],"indent") ){
25809: data.cMode = data.mode = MODE_Pretty;
25810: }else if( optionMatch(azArg[ii],"debug") ){
25811: bDebug = 1;
1.6 misho 25812: }else if( optionMatch(azArg[ii],"nosys") ){
25813: bNoSystemTabs = 1;
25814: }else if( azArg[ii][0]=='-' ){
25815: utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
25816: rc = 1;
25817: goto meta_command_exit;
1.5 misho 25818: }else if( zName==0 ){
25819: zName = azArg[ii];
25820: }else{
1.6.2.1 ! misho 25821: raw_printf(stderr,
! 25822: "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
1.5 misho 25823: rc = 1;
25824: goto meta_command_exit;
25825: }
1.4 misho 25826: }
1.5 misho 25827: if( zName!=0 ){
25828: int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0
25829: || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
25830: || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
25831: || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
25832: if( isSchema ){
1.2 misho 25833: char *new_argv[2], *new_colv[2];
1.5 misho 25834: new_argv[0] = sqlite3_mprintf(
25835: "CREATE TABLE %s (\n"
1.2 misho 25836: " type text,\n"
25837: " name text,\n"
25838: " tbl_name text,\n"
25839: " rootpage integer,\n"
25840: " sql text\n"
1.5 misho 25841: ")", zName);
1.6.2.1 ! misho 25842: shell_check_oom(new_argv[0]);
1.2 misho 25843: new_argv[1] = 0;
25844: new_colv[0] = "sql";
25845: new_colv[1] = 0;
25846: callback(&data, 1, new_argv, new_colv);
1.5 misho 25847: sqlite3_free(new_argv[0]);
25848: }
25849: }
25850: if( zDiv ){
25851: sqlite3_stmt *pStmt = 0;
25852: rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
25853: -1, &pStmt, 0);
25854: if( rc ){
25855: utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
25856: sqlite3_finalize(pStmt);
25857: rc = 1;
25858: goto meta_command_exit;
25859: }
25860: appendText(&sSelect, "SELECT sql FROM", 0);
25861: iSchema = 0;
25862: while( sqlite3_step(pStmt)==SQLITE_ROW ){
25863: const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
25864: char zScNum[30];
25865: sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
25866: appendText(&sSelect, zDiv, 0);
25867: zDiv = " UNION ALL ";
25868: appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
25869: if( sqlite3_stricmp(zDb, "main")!=0 ){
25870: appendText(&sSelect, zDb, '\'');
25871: }else{
25872: appendText(&sSelect, "NULL", 0);
25873: }
25874: appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0);
25875: appendText(&sSelect, zScNum, 0);
25876: appendText(&sSelect, " AS snum, ", 0);
25877: appendText(&sSelect, zDb, '\'');
25878: appendText(&sSelect, " AS sname FROM ", 0);
25879: appendText(&sSelect, zDb, quoteChar(zDb));
25880: appendText(&sSelect, ".sqlite_schema", 0);
25881: }
25882: sqlite3_finalize(pStmt);
25883: #ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
25884: if( zName ){
25885: appendText(&sSelect,
25886: " UNION ALL SELECT shell_module_schema(name),"
25887: " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
25888: 0);
25889: }
25890: #endif
25891: appendText(&sSelect, ") WHERE ", 0);
25892: if( zName ){
25893: char *zQarg = sqlite3_mprintf("%Q", zName);
1.6.2.1 ! misho 25894: int bGlob;
! 25895: shell_check_oom(zQarg);
! 25896: bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
! 25897: strchr(zName, '[') != 0;
1.5 misho 25898: if( strchr(zName, '.') ){
25899: appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
25900: }else{
25901: appendText(&sSelect, "lower(tbl_name)", 0);
25902: }
25903: appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0);
25904: appendText(&sSelect, zQarg, 0);
25905: if( !bGlob ){
25906: appendText(&sSelect, " ESCAPE '\\' ", 0);
25907: }
25908: appendText(&sSelect, " AND ", 0);
25909: sqlite3_free(zQarg);
25910: }
1.6 misho 25911: if( bNoSystemTabs ){
25912: appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
25913: }
25914: appendText(&sSelect, "sql IS NOT NULL"
1.5 misho 25915: " ORDER BY snum, rowid", 0);
25916: if( bDebug ){
25917: utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
1.2 misho 25918: }else{
1.5 misho 25919: rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
1.2 misho 25920: }
1.5 misho 25921: freeText(&sSelect);
1.2 misho 25922: }
25923: if( zErrMsg ){
1.4 misho 25924: utf8_printf(stderr,"Error: %s\n", zErrMsg);
1.2 misho 25925: sqlite3_free(zErrMsg);
25926: rc = 1;
25927: }else if( rc != SQLITE_OK ){
1.4 misho 25928: raw_printf(stderr,"Error: querying schema information\n");
1.2 misho 25929: rc = 1;
25930: }else{
25931: rc = 0;
25932: }
25933: }else
25934:
1.6.2.1 ! misho 25935: if( (c=='s' && n==11 && cli_strncmp(azArg[0], "selecttrace", n)==0)
! 25936: || (c=='t' && n==9 && cli_strncmp(azArg[0], "treetrace", n)==0)
! 25937: ){
! 25938: unsigned int x = nArg>=2? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
1.6 misho 25939: sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
1.4 misho 25940: }else
25941:
25942: #if defined(SQLITE_ENABLE_SESSION)
1.6.2.1 ! misho 25943: if( c=='s' && cli_strncmp(azArg[0],"session",n)==0 && n>=3 ){
! 25944: struct AuxDb *pAuxDb = p->pAuxDb;
! 25945: OpenSession *pSession = &pAuxDb->aSession[0];
1.4 misho 25946: char **azCmd = &azArg[1];
25947: int iSes = 0;
25948: int nCmd = nArg - 1;
25949: int i;
25950: if( nArg<=1 ) goto session_syntax_error;
25951: open_db(p, 0);
25952: if( nArg>=3 ){
1.6.2.1 ! misho 25953: for(iSes=0; iSes<pAuxDb->nSession; iSes++){
! 25954: if( cli_strcmp(pAuxDb->aSession[iSes].zName, azArg[1])==0 ) break;
1.4 misho 25955: }
1.6.2.1 ! misho 25956: if( iSes<pAuxDb->nSession ){
! 25957: pSession = &pAuxDb->aSession[iSes];
1.4 misho 25958: azCmd++;
25959: nCmd--;
25960: }else{
1.6.2.1 ! misho 25961: pSession = &pAuxDb->aSession[0];
1.4 misho 25962: iSes = 0;
25963: }
25964: }
25965:
25966: /* .session attach TABLE
25967: ** Invoke the sqlite3session_attach() interface to attach a particular
25968: ** table so that it is never filtered.
25969: */
1.6.2.1 ! misho 25970: if( cli_strcmp(azCmd[0],"attach")==0 ){
1.4 misho 25971: if( nCmd!=2 ) goto session_syntax_error;
25972: if( pSession->p==0 ){
25973: session_not_open:
25974: raw_printf(stderr, "ERROR: No sessions are open\n");
25975: }else{
25976: rc = sqlite3session_attach(pSession->p, azCmd[1]);
25977: if( rc ){
25978: raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
25979: rc = 0;
25980: }
25981: }
25982: }else
25983:
25984: /* .session changeset FILE
25985: ** .session patchset FILE
25986: ** Write a changeset or patchset into a file. The file is overwritten.
25987: */
1.6.2.1 ! misho 25988: if( cli_strcmp(azCmd[0],"changeset")==0
! 25989: || cli_strcmp(azCmd[0],"patchset")==0
! 25990: ){
1.4 misho 25991: FILE *out = 0;
1.6.2.1 ! misho 25992: failIfSafeMode(p, "cannot run \".session %s\" in safe mode", azCmd[0]);
1.4 misho 25993: if( nCmd!=2 ) goto session_syntax_error;
25994: if( pSession->p==0 ) goto session_not_open;
25995: out = fopen(azCmd[1], "wb");
25996: if( out==0 ){
1.5 misho 25997: utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
25998: azCmd[1]);
1.4 misho 25999: }else{
26000: int szChng;
26001: void *pChng;
26002: if( azCmd[0][0]=='c' ){
26003: rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
26004: }else{
26005: rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
26006: }
26007: if( rc ){
26008: printf("Error: error code %d\n", rc);
26009: rc = 0;
26010: }
26011: if( pChng
26012: && fwrite(pChng, szChng, 1, out)!=1 ){
26013: raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
26014: szChng);
26015: }
26016: sqlite3_free(pChng);
26017: fclose(out);
26018: }
26019: }else
26020:
26021: /* .session close
26022: ** Close the identified session
26023: */
1.6.2.1 ! misho 26024: if( cli_strcmp(azCmd[0], "close")==0 ){
1.4 misho 26025: if( nCmd!=1 ) goto session_syntax_error;
1.6.2.1 ! misho 26026: if( pAuxDb->nSession ){
1.4 misho 26027: session_close(pSession);
1.6.2.1 ! misho 26028: pAuxDb->aSession[iSes] = pAuxDb->aSession[--pAuxDb->nSession];
1.4 misho 26029: }
26030: }else
26031:
26032: /* .session enable ?BOOLEAN?
26033: ** Query or set the enable flag
26034: */
1.6.2.1 ! misho 26035: if( cli_strcmp(azCmd[0], "enable")==0 ){
1.4 misho 26036: int ii;
26037: if( nCmd>2 ) goto session_syntax_error;
26038: ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
1.6.2.1 ! misho 26039: if( pAuxDb->nSession ){
1.4 misho 26040: ii = sqlite3session_enable(pSession->p, ii);
26041: utf8_printf(p->out, "session %s enable flag = %d\n",
26042: pSession->zName, ii);
26043: }
26044: }else
26045:
26046: /* .session filter GLOB ....
26047: ** Set a list of GLOB patterns of table names to be excluded.
26048: */
1.6.2.1 ! misho 26049: if( cli_strcmp(azCmd[0], "filter")==0 ){
1.4 misho 26050: int ii, nByte;
26051: if( nCmd<2 ) goto session_syntax_error;
1.6.2.1 ! misho 26052: if( pAuxDb->nSession ){
1.4 misho 26053: for(ii=0; ii<pSession->nFilter; ii++){
26054: sqlite3_free(pSession->azFilter[ii]);
26055: }
26056: sqlite3_free(pSession->azFilter);
26057: nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
26058: pSession->azFilter = sqlite3_malloc( nByte );
26059: if( pSession->azFilter==0 ){
26060: raw_printf(stderr, "Error: out or memory\n");
26061: exit(1);
26062: }
26063: for(ii=1; ii<nCmd; ii++){
1.6.2.1 ! misho 26064: char *x = pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
! 26065: shell_check_oom(x);
1.4 misho 26066: }
26067: pSession->nFilter = ii-1;
26068: }
26069: }else
26070:
26071: /* .session indirect ?BOOLEAN?
26072: ** Query or set the indirect flag
26073: */
1.6.2.1 ! misho 26074: if( cli_strcmp(azCmd[0], "indirect")==0 ){
1.4 misho 26075: int ii;
26076: if( nCmd>2 ) goto session_syntax_error;
26077: ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
1.6.2.1 ! misho 26078: if( pAuxDb->nSession ){
1.4 misho 26079: ii = sqlite3session_indirect(pSession->p, ii);
26080: utf8_printf(p->out, "session %s indirect flag = %d\n",
26081: pSession->zName, ii);
26082: }
26083: }else
26084:
26085: /* .session isempty
26086: ** Determine if the session is empty
26087: */
1.6.2.1 ! misho 26088: if( cli_strcmp(azCmd[0], "isempty")==0 ){
1.4 misho 26089: int ii;
26090: if( nCmd!=1 ) goto session_syntax_error;
1.6.2.1 ! misho 26091: if( pAuxDb->nSession ){
1.4 misho 26092: ii = sqlite3session_isempty(pSession->p);
26093: utf8_printf(p->out, "session %s isempty flag = %d\n",
26094: pSession->zName, ii);
26095: }
26096: }else
26097:
26098: /* .session list
26099: ** List all currently open sessions
26100: */
1.6.2.1 ! misho 26101: if( cli_strcmp(azCmd[0],"list")==0 ){
! 26102: for(i=0; i<pAuxDb->nSession; i++){
! 26103: utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName);
1.4 misho 26104: }
26105: }else
26106:
26107: /* .session open DB NAME
26108: ** Open a new session called NAME on the attached database DB.
26109: ** DB is normally "main".
26110: */
1.6.2.1 ! misho 26111: if( cli_strcmp(azCmd[0],"open")==0 ){
1.4 misho 26112: char *zName;
26113: if( nCmd!=3 ) goto session_syntax_error;
26114: zName = azCmd[2];
26115: if( zName[0]==0 ) goto session_syntax_error;
1.6.2.1 ! misho 26116: for(i=0; i<pAuxDb->nSession; i++){
! 26117: if( cli_strcmp(pAuxDb->aSession[i].zName,zName)==0 ){
1.4 misho 26118: utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
26119: goto meta_command_exit;
26120: }
26121: }
1.6.2.1 ! misho 26122: if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){
! 26123: raw_printf(stderr,
! 26124: "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession));
1.4 misho 26125: goto meta_command_exit;
26126: }
1.6.2.1 ! misho 26127: pSession = &pAuxDb->aSession[pAuxDb->nSession];
1.4 misho 26128: rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
26129: if( rc ){
26130: raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
26131: rc = 0;
26132: goto meta_command_exit;
26133: }
26134: pSession->nFilter = 0;
26135: sqlite3session_table_filter(pSession->p, session_filter, pSession);
1.6.2.1 ! misho 26136: pAuxDb->nSession++;
1.4 misho 26137: pSession->zName = sqlite3_mprintf("%s", zName);
1.6.2.1 ! misho 26138: shell_check_oom(pSession->zName);
1.4 misho 26139: }else
26140: /* If no command name matches, show a syntax error */
26141: session_syntax_error:
1.5 misho 26142: showHelp(p->out, "session");
1.4 misho 26143: }else
26144: #endif
26145:
26146: #ifdef SQLITE_DEBUG
26147: /* Undocumented commands for internal testing. Subject to change
26148: ** without notice. */
1.6.2.1 ! misho 26149: if( c=='s' && n>=10 && cli_strncmp(azArg[0], "selftest-", 9)==0 ){
! 26150: if( cli_strncmp(azArg[0]+9, "boolean", n-9)==0 ){
1.4 misho 26151: int i, v;
26152: for(i=1; i<nArg; i++){
26153: v = booleanValue(azArg[i]);
26154: utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
26155: }
26156: }
1.6.2.1 ! misho 26157: if( cli_strncmp(azArg[0]+9, "integer", n-9)==0 ){
1.4 misho 26158: int i; sqlite3_int64 v;
26159: for(i=1; i<nArg; i++){
26160: char zBuf[200];
26161: v = integerValue(azArg[i]);
26162: sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
26163: utf8_printf(p->out, "%s", zBuf);
26164: }
26165: }
26166: }else
26167: #endif
26168:
1.6.2.1 ! misho 26169: if( c=='s' && n>=4 && cli_strncmp(azArg[0],"selftest",n)==0 ){
1.5 misho 26170: int bIsInit = 0; /* True to initialize the SELFTEST table */
26171: int bVerbose = 0; /* Verbose output */
26172: int bSelftestExists; /* True if SELFTEST already exists */
26173: int i, k; /* Loop counters */
26174: int nTest = 0; /* Number of tests runs */
26175: int nErr = 0; /* Number of errors seen */
26176: ShellText str; /* Answer for a query */
26177: sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
26178:
26179: open_db(p,0);
26180: for(i=1; i<nArg; i++){
26181: const char *z = azArg[i];
26182: if( z[0]=='-' && z[1]=='-' ) z++;
1.6.2.1 ! misho 26183: if( cli_strcmp(z,"-init")==0 ){
1.5 misho 26184: bIsInit = 1;
26185: }else
1.6.2.1 ! misho 26186: if( cli_strcmp(z,"-v")==0 ){
1.5 misho 26187: bVerbose++;
26188: }else
26189: {
26190: utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
26191: azArg[i], azArg[0]);
26192: raw_printf(stderr, "Should be one of: --init -v\n");
26193: rc = 1;
26194: goto meta_command_exit;
26195: }
26196: }
26197: if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
26198: != SQLITE_OK ){
26199: bSelftestExists = 0;
26200: }else{
26201: bSelftestExists = 1;
26202: }
26203: if( bIsInit ){
26204: createSelftestTable(p);
26205: bSelftestExists = 1;
26206: }
26207: initText(&str);
26208: appendText(&str, "x", 0);
26209: for(k=bSelftestExists; k>=0; k--){
26210: if( k==1 ){
26211: rc = sqlite3_prepare_v2(p->db,
26212: "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
26213: -1, &pStmt, 0);
26214: }else{
26215: rc = sqlite3_prepare_v2(p->db,
26216: "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
26217: " (1,'run','PRAGMA integrity_check','ok')",
26218: -1, &pStmt, 0);
26219: }
26220: if( rc ){
26221: raw_printf(stderr, "Error querying the selftest table\n");
26222: rc = 1;
26223: sqlite3_finalize(pStmt);
26224: goto meta_command_exit;
26225: }
26226: for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
26227: int tno = sqlite3_column_int(pStmt, 0);
26228: const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
26229: const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
26230: const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
26231:
1.6.2.1 ! misho 26232: if( zOp==0 ) continue;
! 26233: if( zSql==0 ) continue;
! 26234: if( zAns==0 ) continue;
1.5 misho 26235: k = 0;
26236: if( bVerbose>0 ){
26237: printf("%d: %s %s\n", tno, zOp, zSql);
26238: }
1.6.2.1 ! misho 26239: if( cli_strcmp(zOp,"memo")==0 ){
1.5 misho 26240: utf8_printf(p->out, "%s\n", zSql);
26241: }else
1.6.2.1 ! misho 26242: if( cli_strcmp(zOp,"run")==0 ){
1.5 misho 26243: char *zErrMsg = 0;
26244: str.n = 0;
26245: str.z[0] = 0;
26246: rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
26247: nTest++;
26248: if( bVerbose ){
26249: utf8_printf(p->out, "Result: %s\n", str.z);
26250: }
26251: if( rc || zErrMsg ){
26252: nErr++;
26253: rc = 1;
26254: utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
26255: sqlite3_free(zErrMsg);
1.6.2.1 ! misho 26256: }else if( cli_strcmp(zAns,str.z)!=0 ){
1.5 misho 26257: nErr++;
26258: rc = 1;
26259: utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
26260: utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z);
26261: }
26262: }else
26263: {
26264: utf8_printf(stderr,
26265: "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
26266: rc = 1;
26267: break;
26268: }
26269: } /* End loop over rows of content from SELFTEST */
26270: sqlite3_finalize(pStmt);
26271: } /* End loop over k */
26272: freeText(&str);
26273: utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
26274: }else
26275:
1.6.2.1 ! misho 26276: if( c=='s' && cli_strncmp(azArg[0], "separator", n)==0 ){
1.4 misho 26277: if( nArg<2 || nArg>3 ){
26278: raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
26279: rc = 1;
26280: }
26281: if( nArg>=2 ){
26282: sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
26283: "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
26284: }
26285: if( nArg>=3 ){
26286: sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator,
26287: "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]);
26288: }
26289: }else
26290:
1.6.2.1 ! misho 26291: if( c=='s' && n>=4 && cli_strncmp(azArg[0],"sha3sum",n)==0 ){
1.5 misho 26292: const char *zLike = 0; /* Which table to checksum. 0 means everything */
26293: int i; /* Loop counter */
26294: int bSchema = 0; /* Also hash the schema */
26295: int bSeparate = 0; /* Hash each table separately */
26296: int iSize = 224; /* Hash algorithm to use */
26297: int bDebug = 0; /* Only show the query that would have run */
26298: sqlite3_stmt *pStmt; /* For querying tables names */
26299: char *zSql; /* SQL to be run */
26300: char *zSep; /* Separator */
26301: ShellText sSql; /* Complete SQL for the query to run the hash */
26302: ShellText sQuery; /* Set of queries used to read all content */
26303: open_db(p, 0);
26304: for(i=1; i<nArg; i++){
26305: const char *z = azArg[i];
26306: if( z[0]=='-' ){
26307: z++;
26308: if( z[0]=='-' ) z++;
1.6.2.1 ! misho 26309: if( cli_strcmp(z,"schema")==0 ){
1.5 misho 26310: bSchema = 1;
26311: }else
1.6.2.1 ! misho 26312: if( cli_strcmp(z,"sha3-224")==0 || cli_strcmp(z,"sha3-256")==0
! 26313: || cli_strcmp(z,"sha3-384")==0 || cli_strcmp(z,"sha3-512")==0
1.5 misho 26314: ){
26315: iSize = atoi(&z[5]);
26316: }else
1.6.2.1 ! misho 26317: if( cli_strcmp(z,"debug")==0 ){
1.5 misho 26318: bDebug = 1;
26319: }else
26320: {
26321: utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
26322: azArg[i], azArg[0]);
26323: showHelp(p->out, azArg[0]);
26324: rc = 1;
26325: goto meta_command_exit;
26326: }
26327: }else if( zLike ){
26328: raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
26329: rc = 1;
26330: goto meta_command_exit;
26331: }else{
26332: zLike = z;
26333: bSeparate = 1;
26334: if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1;
26335: }
26336: }
26337: if( bSchema ){
1.6.2.1 ! misho 26338: zSql = "SELECT lower(name) as tname FROM sqlite_schema"
1.5 misho 26339: " WHERE type='table' AND coalesce(rootpage,0)>1"
26340: " UNION ALL SELECT 'sqlite_schema'"
26341: " ORDER BY 1 collate nocase";
26342: }else{
1.6.2.1 ! misho 26343: zSql = "SELECT lower(name) as tname FROM sqlite_schema"
1.5 misho 26344: " WHERE type='table' AND coalesce(rootpage,0)>1"
26345: " AND name NOT LIKE 'sqlite_%'"
26346: " ORDER BY 1 collate nocase";
26347: }
26348: sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
26349: initText(&sQuery);
26350: initText(&sSql);
26351: appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
26352: zSep = "VALUES(";
26353: while( SQLITE_ROW==sqlite3_step(pStmt) ){
26354: const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
1.6.2.1 ! misho 26355: if( zTab==0 ) continue;
1.5 misho 26356: if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
1.6.2.1 ! misho 26357: if( cli_strncmp(zTab, "sqlite_",7)!=0 ){
1.5 misho 26358: appendText(&sQuery,"SELECT * FROM ", 0);
26359: appendText(&sQuery,zTab,'"');
26360: appendText(&sQuery," NOT INDEXED;", 0);
1.6.2.1 ! misho 26361: }else if( cli_strcmp(zTab, "sqlite_schema")==0 ){
1.5 misho 26362: appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema"
26363: " ORDER BY name;", 0);
1.6.2.1 ! misho 26364: }else if( cli_strcmp(zTab, "sqlite_sequence")==0 ){
1.5 misho 26365: appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
26366: " ORDER BY name;", 0);
1.6.2.1 ! misho 26367: }else if( cli_strcmp(zTab, "sqlite_stat1")==0 ){
1.5 misho 26368: appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
26369: " ORDER BY tbl,idx;", 0);
1.6.2.1 ! misho 26370: }else if( cli_strcmp(zTab, "sqlite_stat4")==0 ){
1.5 misho 26371: appendText(&sQuery, "SELECT * FROM ", 0);
26372: appendText(&sQuery, zTab, 0);
26373: appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
26374: }
26375: appendText(&sSql, zSep, 0);
26376: appendText(&sSql, sQuery.z, '\'');
26377: sQuery.n = 0;
26378: appendText(&sSql, ",", 0);
26379: appendText(&sSql, zTab, '\'');
26380: zSep = "),(";
26381: }
26382: sqlite3_finalize(pStmt);
26383: if( bSeparate ){
26384: zSql = sqlite3_mprintf(
26385: "%s))"
26386: " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
26387: " FROM [sha3sum$query]",
26388: sSql.z, iSize);
26389: }else{
26390: zSql = sqlite3_mprintf(
26391: "%s))"
26392: " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
26393: " FROM [sha3sum$query]",
26394: sSql.z, iSize);
26395: }
1.6.2.1 ! misho 26396: shell_check_oom(zSql);
1.5 misho 26397: freeText(&sQuery);
26398: freeText(&sSql);
26399: if( bDebug ){
26400: utf8_printf(p->out, "%s\n", zSql);
26401: }else{
26402: shell_exec(p, zSql, 0);
26403: }
1.6.2.1 ! misho 26404: #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && !defined(SQLITE_OMIT_VIRTUALTABLE)
! 26405: {
! 26406: int lrc;
! 26407: char *zRevText = /* Query for reversible to-blob-to-text check */
! 26408: "SELECT lower(name) as tname FROM sqlite_schema\n"
! 26409: "WHERE type='table' AND coalesce(rootpage,0)>1\n"
! 26410: "AND name NOT LIKE 'sqlite_%%'%s\n"
! 26411: "ORDER BY 1 collate nocase";
! 26412: zRevText = sqlite3_mprintf(zRevText, zLike? " AND name LIKE $tspec" : "");
! 26413: zRevText = sqlite3_mprintf(
! 26414: /* lower-case query is first run, producing upper-case query. */
! 26415: "with tabcols as materialized(\n"
! 26416: "select tname, cname\n"
! 26417: "from ("
! 26418: " select printf('\"%%w\"',ss.tname) as tname,"
! 26419: " printf('\"%%w\"',ti.name) as cname\n"
! 26420: " from (%z) ss\n inner join pragma_table_info(tname) ti))\n"
! 26421: "select 'SELECT total(bad_text_count) AS bad_text_count\n"
! 26422: "FROM ('||group_concat(query, ' UNION ALL ')||')' as btc_query\n"
! 26423: " from (select 'SELECT COUNT(*) AS bad_text_count\n"
! 26424: "FROM '||tname||' WHERE '\n"
! 26425: "||group_concat('CAST(CAST('||cname||' AS BLOB) AS TEXT)<>'||cname\n"
! 26426: "|| ' AND typeof('||cname||')=''text'' ',\n"
! 26427: "' OR ') as query, tname from tabcols group by tname)"
! 26428: , zRevText);
! 26429: shell_check_oom(zRevText);
! 26430: if( bDebug ) utf8_printf(p->out, "%s\n", zRevText);
! 26431: lrc = sqlite3_prepare_v2(p->db, zRevText, -1, &pStmt, 0);
! 26432: if( lrc!=SQLITE_OK ){
! 26433: /* assert(lrc==SQLITE_NOMEM); // might also be SQLITE_ERROR if the
! 26434: ** user does cruel and unnatural things like ".limit expr_depth 0". */
! 26435: rc = 1;
! 26436: }else{
! 26437: if( zLike ) sqlite3_bind_text(pStmt,1,zLike,-1,SQLITE_STATIC);
! 26438: lrc = SQLITE_ROW==sqlite3_step(pStmt);
! 26439: if( lrc ){
! 26440: const char *zGenQuery = (char*)sqlite3_column_text(pStmt,0);
! 26441: sqlite3_stmt *pCheckStmt;
! 26442: lrc = sqlite3_prepare_v2(p->db, zGenQuery, -1, &pCheckStmt, 0);
! 26443: if( bDebug ) utf8_printf(p->out, "%s\n", zGenQuery);
! 26444: if( lrc!=SQLITE_OK ){
! 26445: rc = 1;
! 26446: }else{
! 26447: if( SQLITE_ROW==sqlite3_step(pCheckStmt) ){
! 26448: double countIrreversible = sqlite3_column_double(pCheckStmt, 0);
! 26449: if( countIrreversible>0 ){
! 26450: int sz = (int)(countIrreversible + 0.5);
! 26451: utf8_printf(stderr,
! 26452: "Digest includes %d invalidly encoded text field%s.\n",
! 26453: sz, (sz>1)? "s": "");
! 26454: }
! 26455: }
! 26456: sqlite3_finalize(pCheckStmt);
! 26457: }
! 26458: sqlite3_finalize(pStmt);
! 26459: }
! 26460: }
! 26461: if( rc ) utf8_printf(stderr, ".sha3sum failed.\n");
! 26462: sqlite3_free(zRevText);
! 26463: }
! 26464: #endif /* !defined(*_OMIT_SCHEMA_PRAGMAS) && !defined(*_OMIT_VIRTUALTABLE) */
1.5 misho 26465: sqlite3_free(zSql);
26466: }else
26467:
1.6.2.1 ! misho 26468: #if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
1.4 misho 26469: if( c=='s'
1.6.2.1 ! misho 26470: && (cli_strncmp(azArg[0], "shell", n)==0
! 26471: || cli_strncmp(azArg[0],"system",n)==0)
1.4 misho 26472: ){
26473: char *zCmd;
26474: int i, x;
1.6.2.1 ! misho 26475: failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
1.4 misho 26476: if( nArg<2 ){
26477: raw_printf(stderr, "Usage: .system COMMAND\n");
26478: rc = 1;
26479: goto meta_command_exit;
26480: }
26481: zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
1.6.2.1 ! misho 26482: for(i=2; i<nArg && zCmd!=0; i++){
1.4 misho 26483: zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
26484: zCmd, azArg[i]);
26485: }
1.6.2.1 ! misho 26486: x = zCmd!=0 ? system(zCmd) : 1;
1.4 misho 26487: sqlite3_free(zCmd);
26488: if( x ) raw_printf(stderr, "System command returns %d\n", x);
1.2 misho 26489: }else
1.6.2.1 ! misho 26490: #endif /* !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE) */
1.2 misho 26491:
1.6.2.1 ! misho 26492: if( c=='s' && cli_strncmp(azArg[0], "show", n)==0 ){
1.5 misho 26493: static const char *azBool[] = { "off", "on", "trigger", "full"};
1.6 misho 26494: const char *zOut;
1.2 misho 26495: int i;
1.4 misho 26496: if( nArg!=1 ){
26497: raw_printf(stderr, "Usage: .show\n");
26498: rc = 1;
26499: goto meta_command_exit;
26500: }
1.5 misho 26501: utf8_printf(p->out, "%12.12s: %s\n","echo",
1.6.2.1 ! misho 26502: azBool[ShellHasFlag(p, SHFLG_Echo)]);
1.4 misho 26503: utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
26504: utf8_printf(p->out, "%12.12s: %s\n","explain",
26505: p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
26506: utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
1.6.2.1 ! misho 26507: if( p->mode==MODE_Column
! 26508: || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
! 26509: ){
! 26510: utf8_printf
! 26511: (p->out, "%12.12s: %s --wrap %d --wordwrap %s --%squote\n", "mode",
! 26512: modeDescr[p->mode], p->cmOpts.iWrap,
! 26513: p->cmOpts.bWordWrap ? "on" : "off",
! 26514: p->cmOpts.bQuote ? "" : "no");
! 26515: }else{
! 26516: utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
! 26517: }
1.4 misho 26518: utf8_printf(p->out, "%12.12s: ", "nullvalue");
26519: output_c_string(p->out, p->nullValue);
26520: raw_printf(p->out, "\n");
26521: utf8_printf(p->out,"%12.12s: %s\n","output",
1.2 misho 26522: strlen30(p->outfile) ? p->outfile : "stdout");
1.4 misho 26523: utf8_printf(p->out,"%12.12s: ", "colseparator");
26524: output_c_string(p->out, p->colSeparator);
26525: raw_printf(p->out, "\n");
26526: utf8_printf(p->out,"%12.12s: ", "rowseparator");
26527: output_c_string(p->out, p->rowSeparator);
26528: raw_printf(p->out, "\n");
1.6 misho 26529: switch( p->statsOn ){
26530: case 0: zOut = "off"; break;
26531: default: zOut = "on"; break;
26532: case 2: zOut = "stmt"; break;
26533: case 3: zOut = "vmstep"; break;
26534: }
26535: utf8_printf(p->out, "%12.12s: %s\n","stats", zOut);
1.4 misho 26536: utf8_printf(p->out, "%12.12s: ", "width");
1.5 misho 26537: for (i=0;i<p->nWidth;i++) {
1.4 misho 26538: raw_printf(p->out, "%d ", p->colWidth[i]);
1.2 misho 26539: }
1.4 misho 26540: raw_printf(p->out, "\n");
1.5 misho 26541: utf8_printf(p->out, "%12.12s: %s\n", "filename",
1.6.2.1 ! misho 26542: p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : "");
1.2 misho 26543: }else
26544:
1.6.2.1 ! misho 26545: if( c=='s' && cli_strncmp(azArg[0], "stats", n)==0 ){
1.4 misho 26546: if( nArg==2 ){
1.6.2.1 ! misho 26547: if( cli_strcmp(azArg[1],"stmt")==0 ){
1.6 misho 26548: p->statsOn = 2;
1.6.2.1 ! misho 26549: }else if( cli_strcmp(azArg[1],"vmstep")==0 ){
1.6 misho 26550: p->statsOn = 3;
26551: }else{
26552: p->statsOn = (u8)booleanValue(azArg[1]);
26553: }
1.4 misho 26554: }else if( nArg==1 ){
26555: display_stats(p->db, p, 0);
26556: }else{
1.6 misho 26557: raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n");
1.4 misho 26558: rc = 1;
26559: }
1.2 misho 26560: }else
26561:
1.6.2.1 ! misho 26562: if( (c=='t' && n>1 && cli_strncmp(azArg[0], "tables", n)==0)
! 26563: || (c=='i' && (cli_strncmp(azArg[0], "indices", n)==0
! 26564: || cli_strncmp(azArg[0], "indexes", n)==0) )
1.5 misho 26565: ){
1.3 misho 26566: sqlite3_stmt *pStmt;
1.2 misho 26567: char **azResult;
1.3 misho 26568: int nRow, nAlloc;
26569: int ii;
1.5 misho 26570: ShellText s;
26571: initText(&s);
1.4 misho 26572: open_db(p, 0);
1.3 misho 26573: rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
1.5 misho 26574: if( rc ){
26575: sqlite3_finalize(pStmt);
26576: return shellDatabaseError(p->db);
26577: }
1.4 misho 26578:
1.5 misho 26579: if( nArg>2 && c=='i' ){
26580: /* It is an historical accident that the .indexes command shows an error
26581: ** when called with the wrong number of arguments whereas the .tables
26582: ** command does not. */
26583: raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
26584: rc = 1;
26585: sqlite3_finalize(pStmt);
26586: goto meta_command_exit;
26587: }
26588: for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
1.3 misho 26589: const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
1.5 misho 26590: if( zDbName==0 ) continue;
26591: if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0);
26592: if( sqlite3_stricmp(zDbName, "main")==0 ){
26593: appendText(&s, "SELECT name FROM ", 0);
26594: }else{
26595: appendText(&s, "SELECT ", 0);
26596: appendText(&s, zDbName, '\'');
26597: appendText(&s, "||'.'||name FROM ", 0);
26598: }
26599: appendText(&s, zDbName, '"');
26600: appendText(&s, ".sqlite_schema ", 0);
26601: if( c=='t' ){
26602: appendText(&s," WHERE type IN ('table','view')"
26603: " AND name NOT LIKE 'sqlite_%'"
26604: " AND name LIKE ?1", 0);
1.3 misho 26605: }else{
1.5 misho 26606: appendText(&s," WHERE type='index'"
26607: " AND tbl_name LIKE ?1", 0);
1.3 misho 26608: }
26609: }
1.4 misho 26610: rc = sqlite3_finalize(pStmt);
1.6.2.1 ! misho 26611: if( rc==SQLITE_OK ){
! 26612: appendText(&s, " ORDER BY 1", 0);
! 26613: rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
! 26614: }
1.5 misho 26615: freeText(&s);
1.4 misho 26616: if( rc ) return shellDatabaseError(p->db);
26617:
26618: /* Run the SQL statement prepared by the above block. Store the results
26619: ** as an array of nul-terminated strings in azResult[]. */
1.3 misho 26620: nRow = nAlloc = 0;
26621: azResult = 0;
26622: if( nArg>1 ){
26623: sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
1.2 misho 26624: }else{
1.3 misho 26625: sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
26626: }
26627: while( sqlite3_step(pStmt)==SQLITE_ROW ){
26628: if( nRow>=nAlloc ){
26629: char **azNew;
1.4 misho 26630: int n2 = nAlloc*2 + 10;
26631: azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
1.6.2.1 ! misho 26632: shell_check_oom(azNew);
1.4 misho 26633: nAlloc = n2;
1.3 misho 26634: azResult = azNew;
26635: }
26636: azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
1.6.2.1 ! misho 26637: shell_check_oom(azResult[nRow]);
1.4 misho 26638: nRow++;
1.2 misho 26639: }
1.4 misho 26640: if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
26641: rc = shellDatabaseError(p->db);
26642: }
26643:
26644: /* Pretty-print the contents of array azResult[] to the output */
26645: if( rc==0 && nRow>0 ){
1.2 misho 26646: int len, maxlen = 0;
26647: int i, j;
26648: int nPrintCol, nPrintRow;
1.3 misho 26649: for(i=0; i<nRow; i++){
1.2 misho 26650: len = strlen30(azResult[i]);
26651: if( len>maxlen ) maxlen = len;
26652: }
26653: nPrintCol = 80/(maxlen+2);
26654: if( nPrintCol<1 ) nPrintCol = 1;
26655: nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
26656: for(i=0; i<nPrintRow; i++){
1.3 misho 26657: for(j=i; j<nRow; j+=nPrintRow){
26658: char *zSp = j<nPrintRow ? "" : " ";
1.4 misho 26659: utf8_printf(p->out, "%s%-*s", zSp, maxlen,
26660: azResult[j] ? azResult[j]:"");
1.2 misho 26661: }
1.4 misho 26662: raw_printf(p->out, "\n");
1.2 misho 26663: }
26664: }
1.4 misho 26665:
1.3 misho 26666: for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
26667: sqlite3_free(azResult);
1.2 misho 26668: }else
26669:
1.6.2.1 ! misho 26670: #ifndef SQLITE_SHELL_FIDDLE
1.5 misho 26671: /* Begin redirecting output to the file "testcase-out.txt" */
1.6.2.1 ! misho 26672: if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){
1.5 misho 26673: output_reset(p);
26674: p->out = output_file_open("testcase-out.txt", 0);
26675: if( p->out==0 ){
26676: raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
26677: }
26678: if( nArg>=2 ){
26679: sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
26680: }else{
26681: sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
26682: }
26683: }else
1.6.2.1 ! misho 26684: #endif /* !defined(SQLITE_SHELL_FIDDLE) */
1.5 misho 26685:
26686: #ifndef SQLITE_UNTESTABLE
1.6.2.1 ! misho 26687: if( c=='t' && n>=8 && cli_strncmp(azArg[0], "testctrl", n)==0 ){
1.2 misho 26688: static const struct {
26689: const char *zCtrlName; /* Name of a test-control option */
26690: int ctrlCode; /* Integer code for that option */
1.6.2.1 ! misho 26691: int unSafe; /* Not valid unless --unsafe-testing */
1.5 misho 26692: const char *zUsage; /* Usage notes */
1.2 misho 26693: } aCtrl[] = {
1.6.2.1 ! misho 26694: {"always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" },
! 26695: {"assert", SQLITE_TESTCTRL_ASSERT, 1, "BOOLEAN" },
! 26696: /*{"benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, "" },*/
! 26697: /*{"bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "" },*/
! 26698: {"byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" },
! 26699: {"extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" },
! 26700: /*{"fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"" },*/
! 26701: {"imposter", SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"},
! 26702: {"internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,"" },
! 26703: {"localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN" },
! 26704: {"never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" },
! 26705: {"optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" },
1.5 misho 26706: #ifdef YYCOVERAGE
1.6.2.1 ! misho 26707: {"parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE,0,"" },
1.5 misho 26708: #endif
1.6.2.1 ! misho 26709: {"pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET " },
! 26710: {"prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" },
! 26711: {"prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" },
! 26712: {"prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" },
! 26713: {"seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" },
! 26714: {"sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" },
! 26715: {"tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" },
! 26716: {"uselongdouble", SQLITE_TESTCTRL_USELONGDOUBLE,0,"?BOOLEAN|\"default\"?"},
1.2 misho 26717: };
26718: int testctrl = -1;
1.5 misho 26719: int iCtrl = -1;
26720: int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */
26721: int isOk = 0;
1.4 misho 26722: int i, n2;
1.5 misho 26723: const char *zCmd = 0;
26724:
1.4 misho 26725: open_db(p, 0);
1.5 misho 26726: zCmd = nArg>=2 ? azArg[1] : "help";
26727:
26728: /* The argument can optionally begin with "-" or "--" */
26729: if( zCmd[0]=='-' && zCmd[1] ){
26730: zCmd++;
26731: if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
26732: }
26733:
26734: /* --help lists all test-controls */
1.6.2.1 ! misho 26735: if( cli_strcmp(zCmd,"help")==0 ){
1.5 misho 26736: utf8_printf(p->out, "Available test-controls:\n");
26737: for(i=0; i<ArraySize(aCtrl); i++){
1.6.2.1 ! misho 26738: if( aCtrl[i].unSafe && !ShellHasFlag(p,SHFLG_TestingMode) ) continue;
1.5 misho 26739: utf8_printf(p->out, " .testctrl %s %s\n",
26740: aCtrl[i].zCtrlName, aCtrl[i].zUsage);
26741: }
26742: rc = 1;
26743: goto meta_command_exit;
26744: }
1.2 misho 26745:
26746: /* convert testctrl text option to value. allow any unique prefix
26747: ** of the option name, or a numerical value. */
1.5 misho 26748: n2 = strlen30(zCmd);
1.4 misho 26749: for(i=0; i<ArraySize(aCtrl); i++){
1.6.2.1 ! misho 26750: if( aCtrl[i].unSafe && !ShellHasFlag(p,SHFLG_TestingMode) ) continue;
! 26751: if( cli_strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
1.2 misho 26752: if( testctrl<0 ){
26753: testctrl = aCtrl[i].ctrlCode;
1.5 misho 26754: iCtrl = i;
1.2 misho 26755: }else{
1.5 misho 26756: utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
26757: "Use \".testctrl --help\" for help\n", zCmd);
26758: rc = 1;
26759: goto meta_command_exit;
1.2 misho 26760: }
26761: }
26762: }
1.5 misho 26763: if( testctrl<0 ){
26764: utf8_printf(stderr,"Error: unknown test-control: %s\n"
26765: "Use \".testctrl --help\" for help\n", zCmd);
1.2 misho 26766: }else{
26767: switch(testctrl){
26768:
26769: /* sqlite3_test_control(int, db, int) */
26770: case SQLITE_TESTCTRL_OPTIMIZATIONS:
26771: if( nArg==3 ){
1.6 misho 26772: unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
1.4 misho 26773: rc2 = sqlite3_test_control(testctrl, p->db, opt);
1.5 misho 26774: isOk = 3;
1.2 misho 26775: }
26776: break;
26777:
26778: /* sqlite3_test_control(int) */
1.4 misho 26779: case SQLITE_TESTCTRL_PRNG_SAVE:
26780: case SQLITE_TESTCTRL_PRNG_RESTORE:
26781: case SQLITE_TESTCTRL_BYTEORDER:
1.2 misho 26782: if( nArg==2 ){
1.4 misho 26783: rc2 = sqlite3_test_control(testctrl);
1.5 misho 26784: isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
1.2 misho 26785: }
26786: break;
26787:
26788: /* sqlite3_test_control(int, uint) */
1.4 misho 26789: case SQLITE_TESTCTRL_PENDING_BYTE:
1.2 misho 26790: if( nArg==3 ){
1.4 misho 26791: unsigned int opt = (unsigned int)integerValue(azArg[2]);
26792: rc2 = sqlite3_test_control(testctrl, opt);
1.5 misho 26793: isOk = 3;
26794: }
26795: break;
26796:
26797: /* sqlite3_test_control(int, int, sqlite3*) */
26798: case SQLITE_TESTCTRL_PRNG_SEED:
26799: if( nArg==3 || nArg==4 ){
26800: int ii = (int)integerValue(azArg[2]);
26801: sqlite3 *db;
1.6.2.1 ! misho 26802: if( ii==0 && cli_strcmp(azArg[2],"random")==0 ){
1.5 misho 26803: sqlite3_randomness(sizeof(ii),&ii);
26804: printf("-- random seed: %d\n", ii);
26805: }
26806: if( nArg==3 ){
26807: db = 0;
26808: }else{
26809: db = p->db;
26810: /* Make sure the schema has been loaded */
26811: sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);
26812: }
26813: rc2 = sqlite3_test_control(testctrl, ii, db);
26814: isOk = 3;
1.2 misho 26815: }
26816: break;
1.4 misho 26817:
1.2 misho 26818: /* sqlite3_test_control(int, int) */
1.4 misho 26819: case SQLITE_TESTCTRL_ASSERT:
26820: case SQLITE_TESTCTRL_ALWAYS:
1.2 misho 26821: if( nArg==3 ){
1.4 misho 26822: int opt = booleanValue(azArg[2]);
26823: rc2 = sqlite3_test_control(testctrl, opt);
1.5 misho 26824: isOk = 1;
1.2 misho 26825: }
26826: break;
26827:
1.5 misho 26828: /* sqlite3_test_control(int, int) */
26829: case SQLITE_TESTCTRL_LOCALTIME_FAULT:
26830: case SQLITE_TESTCTRL_NEVER_CORRUPT:
1.2 misho 26831: if( nArg==3 ){
1.5 misho 26832: int opt = booleanValue(azArg[2]);
1.4 misho 26833: rc2 = sqlite3_test_control(testctrl, opt);
1.5 misho 26834: isOk = 3;
1.2 misho 26835: }
26836: break;
1.5 misho 26837:
1.6.2.1 ! misho 26838: /* sqlite3_test_control(int, int) */
! 26839: case SQLITE_TESTCTRL_USELONGDOUBLE: {
! 26840: int opt = -1;
! 26841: if( nArg==3 ){
! 26842: if( cli_strcmp(azArg[2],"default")==0 ){
! 26843: opt = 2;
! 26844: }else{
! 26845: opt = booleanValue(azArg[2]);
! 26846: }
! 26847: }
! 26848: rc2 = sqlite3_test_control(testctrl, opt);
! 26849: isOk = 1;
! 26850: break;
! 26851: }
! 26852:
1.5 misho 26853: /* sqlite3_test_control(sqlite3*) */
26854: case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
26855: rc2 = sqlite3_test_control(testctrl, p->db);
26856: isOk = 3;
26857: break;
1.2 misho 26858:
1.4 misho 26859: case SQLITE_TESTCTRL_IMPOSTER:
26860: if( nArg==5 ){
26861: rc2 = sqlite3_test_control(testctrl, p->db,
26862: azArg[2],
26863: integerValue(azArg[3]),
26864: integerValue(azArg[4]));
1.5 misho 26865: isOk = 3;
1.4 misho 26866: }
26867: break;
26868:
1.6 misho 26869: case SQLITE_TESTCTRL_SEEK_COUNT: {
26870: u64 x = 0;
26871: rc2 = sqlite3_test_control(testctrl, p->db, &x);
26872: utf8_printf(p->out, "%llu\n", x);
26873: isOk = 3;
26874: break;
26875: }
26876:
1.5 misho 26877: #ifdef YYCOVERAGE
1.6.2.1 ! misho 26878: case SQLITE_TESTCTRL_PARSER_COVERAGE: {
1.5 misho 26879: if( nArg==2 ){
26880: sqlite3_test_control(testctrl, p->out);
26881: isOk = 3;
26882: }
1.6.2.1 ! misho 26883: break;
! 26884: }
! 26885: #endif
! 26886: #ifdef SQLITE_DEBUG
! 26887: case SQLITE_TESTCTRL_TUNE: {
! 26888: if( nArg==4 ){
! 26889: int id = (int)integerValue(azArg[2]);
! 26890: int val = (int)integerValue(azArg[3]);
! 26891: sqlite3_test_control(testctrl, id, &val);
! 26892: isOk = 3;
! 26893: }else if( nArg==3 ){
! 26894: int id = (int)integerValue(azArg[2]);
! 26895: sqlite3_test_control(testctrl, -id, &rc2);
! 26896: isOk = 1;
! 26897: }else if( nArg==2 ){
! 26898: int id = 1;
! 26899: while(1){
! 26900: int val = 0;
! 26901: rc2 = sqlite3_test_control(testctrl, -id, &val);
! 26902: if( rc2!=SQLITE_OK ) break;
! 26903: if( id>1 ) utf8_printf(p->out, " ");
! 26904: utf8_printf(p->out, "%d: %d", id, val);
! 26905: id++;
! 26906: }
! 26907: if( id>1 ) utf8_printf(p->out, "\n");
! 26908: isOk = 3;
! 26909: }
! 26910: break;
! 26911: }
1.5 misho 26912: #endif
1.6.2.1 ! misho 26913: case SQLITE_TESTCTRL_SORTER_MMAP:
! 26914: if( nArg==3 ){
! 26915: int opt = (unsigned int)integerValue(azArg[2]);
! 26916: rc2 = sqlite3_test_control(testctrl, p->db, opt);
! 26917: isOk = 3;
! 26918: }
! 26919: break;
1.2 misho 26920: }
26921: }
1.5 misho 26922: if( isOk==0 && iCtrl>=0 ){
26923: utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
26924: rc = 1;
26925: }else if( isOk==1 ){
26926: raw_printf(p->out, "%d\n", rc2);
26927: }else if( isOk==2 ){
26928: raw_printf(p->out, "0x%08x\n", rc2);
26929: }
1.2 misho 26930: }else
1.5 misho 26931: #endif /* !defined(SQLITE_UNTESTABLE) */
1.2 misho 26932:
1.6.2.1 ! misho 26933: if( c=='t' && n>4 && cli_strncmp(azArg[0], "timeout", n)==0 ){
1.4 misho 26934: open_db(p, 0);
26935: sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
26936: }else
26937:
1.6.2.1 ! misho 26938: if( c=='t' && n>=5 && cli_strncmp(azArg[0], "timer", n)==0 ){
1.4 misho 26939: if( nArg==2 ){
26940: enableTimer = booleanValue(azArg[1]);
26941: if( enableTimer && !HAS_TIMER ){
26942: raw_printf(stderr, "Error: timer not available on this system.\n");
26943: enableTimer = 0;
26944: }
26945: }else{
26946: raw_printf(stderr, "Usage: .timer on|off\n");
26947: rc = 1;
26948: }
1.2 misho 26949: }else
1.4 misho 26950:
1.5 misho 26951: #ifndef SQLITE_OMIT_TRACE
1.6.2.1 ! misho 26952: if( c=='t' && cli_strncmp(azArg[0], "trace", n)==0 ){
1.5 misho 26953: int mType = 0;
26954: int jj;
1.4 misho 26955: open_db(p, 0);
1.5 misho 26956: for(jj=1; jj<nArg; jj++){
26957: const char *z = azArg[jj];
26958: if( z[0]=='-' ){
26959: if( optionMatch(z, "expanded") ){
26960: p->eTraceType = SHELL_TRACE_EXPANDED;
26961: }
26962: #ifdef SQLITE_ENABLE_NORMALIZE
26963: else if( optionMatch(z, "normalized") ){
26964: p->eTraceType = SHELL_TRACE_NORMALIZED;
26965: }
26966: #endif
26967: else if( optionMatch(z, "plain") ){
26968: p->eTraceType = SHELL_TRACE_PLAIN;
26969: }
26970: else if( optionMatch(z, "profile") ){
26971: mType |= SQLITE_TRACE_PROFILE;
26972: }
26973: else if( optionMatch(z, "row") ){
26974: mType |= SQLITE_TRACE_ROW;
26975: }
26976: else if( optionMatch(z, "stmt") ){
26977: mType |= SQLITE_TRACE_STMT;
26978: }
26979: else if( optionMatch(z, "close") ){
26980: mType |= SQLITE_TRACE_CLOSE;
26981: }
26982: else {
26983: raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
26984: rc = 1;
26985: goto meta_command_exit;
26986: }
26987: }else{
26988: output_file_close(p->traceOut);
1.6.2.1 ! misho 26989: p->traceOut = output_file_open(z, 0);
1.5 misho 26990: }
26991: }
26992: if( p->traceOut==0 ){
26993: sqlite3_trace_v2(p->db, 0, 0, 0);
26994: }else{
26995: if( mType==0 ) mType = SQLITE_TRACE_STMT;
26996: sqlite3_trace_v2(p->db, mType, sql_trace_callback, p);
26997: }
26998: }else
26999: #endif /* !defined(SQLITE_OMIT_TRACE) */
27000:
27001: #if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
1.6.2.1 ! misho 27002: if( c=='u' && cli_strncmp(azArg[0], "unmodule", n)==0 ){
1.5 misho 27003: int ii;
27004: int lenOpt;
27005: char *zOpt;
27006: if( nArg<2 ){
27007: raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
1.4 misho 27008: rc = 1;
27009: goto meta_command_exit;
27010: }
1.5 misho 27011: open_db(p, 0);
27012: zOpt = azArg[1];
27013: if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
27014: lenOpt = (int)strlen(zOpt);
1.6.2.1 ! misho 27015: if( lenOpt>=3 && cli_strncmp(zOpt, "-allexcept",lenOpt)==0 ){
1.5 misho 27016: assert( azArg[nArg]==0 );
27017: sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0);
1.3 misho 27018: }else{
1.5 misho 27019: for(ii=1; ii<nArg; ii++){
27020: sqlite3_create_module(p->db, azArg[ii], 0, 0);
27021: }
1.3 misho 27022: }
1.5 misho 27023: }else
1.3 misho 27024: #endif
27025:
1.4 misho 27026: #if SQLITE_USER_AUTHENTICATION
1.6.2.1 ! misho 27027: if( c=='u' && cli_strncmp(azArg[0], "user", n)==0 ){
1.4 misho 27028: if( nArg<2 ){
27029: raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
27030: rc = 1;
27031: goto meta_command_exit;
27032: }
27033: open_db(p, 0);
1.6.2.1 ! misho 27034: if( cli_strcmp(azArg[1],"login")==0 ){
1.4 misho 27035: if( nArg!=4 ){
27036: raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
27037: rc = 1;
27038: goto meta_command_exit;
27039: }
27040: rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
1.5 misho 27041: strlen30(azArg[3]));
1.4 misho 27042: if( rc ){
27043: utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
27044: rc = 1;
27045: }
1.6.2.1 ! misho 27046: }else if( cli_strcmp(azArg[1],"add")==0 ){
1.4 misho 27047: if( nArg!=5 ){
27048: raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
27049: rc = 1;
27050: goto meta_command_exit;
27051: }
1.5 misho 27052: rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
1.4 misho 27053: booleanValue(azArg[4]));
27054: if( rc ){
27055: raw_printf(stderr, "User-Add failed: %d\n", rc);
27056: rc = 1;
27057: }
1.6.2.1 ! misho 27058: }else if( cli_strcmp(azArg[1],"edit")==0 ){
1.4 misho 27059: if( nArg!=5 ){
27060: raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
27061: rc = 1;
27062: goto meta_command_exit;
27063: }
1.5 misho 27064: rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
1.4 misho 27065: booleanValue(azArg[4]));
27066: if( rc ){
27067: raw_printf(stderr, "User-Edit failed: %d\n", rc);
27068: rc = 1;
27069: }
1.6.2.1 ! misho 27070: }else if( cli_strcmp(azArg[1],"delete")==0 ){
1.4 misho 27071: if( nArg!=3 ){
27072: raw_printf(stderr, "Usage: .user delete USER\n");
27073: rc = 1;
27074: goto meta_command_exit;
27075: }
27076: rc = sqlite3_user_delete(p->db, azArg[2]);
27077: if( rc ){
27078: raw_printf(stderr, "User-Delete failed: %d\n", rc);
27079: rc = 1;
27080: }
27081: }else{
27082: raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
27083: rc = 1;
27084: goto meta_command_exit;
27085: }
27086: }else
27087: #endif /* SQLITE_USER_AUTHENTICATION */
27088:
1.6.2.1 ! misho 27089: if( c=='v' && cli_strncmp(azArg[0], "version", n)==0 ){
! 27090: char *zPtrSz = sizeof(void*)==8 ? "64-bit" : "32-bit";
1.4 misho 27091: utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
1.2 misho 27092: sqlite3_libversion(), sqlite3_sourceid());
1.5 misho 27093: #if SQLITE_HAVE_ZLIB
27094: utf8_printf(p->out, "zlib version %s\n", zlibVersion());
27095: #endif
27096: #define CTIMEOPT_VAL_(opt) #opt
27097: #define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
27098: #if defined(__clang__) && defined(__clang_major__)
27099: utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
27100: CTIMEOPT_VAL(__clang_minor__) "."
1.6.2.1 ! misho 27101: CTIMEOPT_VAL(__clang_patchlevel__) " (%s)\n", zPtrSz);
1.5 misho 27102: #elif defined(_MSC_VER)
1.6.2.1 ! misho 27103: utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) " (%s)\n", zPtrSz);
1.5 misho 27104: #elif defined(__GNUC__) && defined(__VERSION__)
1.6.2.1 ! misho 27105: utf8_printf(p->out, "gcc-" __VERSION__ " (%s)\n", zPtrSz);
1.5 misho 27106: #endif
1.2 misho 27107: }else
27108:
1.6.2.1 ! misho 27109: if( c=='v' && cli_strncmp(azArg[0], "vfsinfo", n)==0 ){
1.4 misho 27110: const char *zDbName = nArg==2 ? azArg[1] : "main";
1.5 misho 27111: sqlite3_vfs *pVfs = 0;
1.4 misho 27112: if( p->db ){
27113: sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
27114: if( pVfs ){
27115: utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
27116: raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
27117: raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
27118: raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
27119: }
27120: }
27121: }else
27122:
1.6.2.1 ! misho 27123: if( c=='v' && cli_strncmp(azArg[0], "vfslist", n)==0 ){
1.4 misho 27124: sqlite3_vfs *pVfs;
27125: sqlite3_vfs *pCurrent = 0;
27126: if( p->db ){
27127: sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
27128: }
27129: for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
27130: utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName,
27131: pVfs==pCurrent ? " <--- CURRENT" : "");
27132: raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
27133: raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
27134: raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
27135: if( pVfs->pNext ){
27136: raw_printf(p->out, "-----------------------------------\n");
27137: }
27138: }
27139: }else
27140:
1.6.2.1 ! misho 27141: if( c=='v' && cli_strncmp(azArg[0], "vfsname", n)==0 ){
1.2 misho 27142: const char *zDbName = nArg==2 ? azArg[1] : "main";
27143: char *zVfsName = 0;
27144: if( p->db ){
27145: sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
27146: if( zVfsName ){
1.4 misho 27147: utf8_printf(p->out, "%s\n", zVfsName);
1.2 misho 27148: sqlite3_free(zVfsName);
27149: }
27150: }
27151: }else
27152:
1.6.2.1 ! misho 27153: if( c=='w' && cli_strncmp(azArg[0], "wheretrace", n)==0 ){
! 27154: unsigned int x = nArg>=2? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
1.6 misho 27155: sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x);
1.3 misho 27156: }else
27157:
1.6.2.1 ! misho 27158: if( c=='w' && cli_strncmp(azArg[0], "width", n)==0 ){
1.2 misho 27159: int j;
27160: assert( nArg<=ArraySize(azArg) );
1.5 misho 27161: p->nWidth = nArg-1;
1.6.2.1 ! misho 27162: p->colWidth = realloc(p->colWidth, (p->nWidth+1)*sizeof(int)*2);
1.5 misho 27163: if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory();
27164: if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
27165: for(j=1; j<nArg; j++){
1.4 misho 27166: p->colWidth[j-1] = (int)integerValue(azArg[j]);
1.2 misho 27167: }
27168: }else
27169:
27170: {
1.4 misho 27171: utf8_printf(stderr, "Error: unknown command or invalid arguments: "
1.2 misho 27172: " \"%s\". Enter \".help\" for help\n", azArg[0]);
27173: rc = 1;
27174: }
27175:
1.4 misho 27176: meta_command_exit:
27177: if( p->outCount ){
27178: p->outCount--;
27179: if( p->outCount==0 ) output_reset(p);
27180: }
1.6.2.1 ! misho 27181: p->bSafeMode = p->bSafeModePersist;
1.2 misho 27182: return rc;
27183: }
27184:
1.6.2.1 ! misho 27185: /* Line scan result and intermediate states (supporting scan resumption)
1.2 misho 27186: */
1.6.2.1 ! misho 27187: #ifndef CHAR_BIT
! 27188: # define CHAR_BIT 8
! 27189: #endif
! 27190: typedef enum {
! 27191: QSS_HasDark = 1<<CHAR_BIT, QSS_EndingSemi = 2<<CHAR_BIT,
! 27192: QSS_CharMask = (1<<CHAR_BIT)-1, QSS_ScanMask = 3<<CHAR_BIT,
! 27193: QSS_Start = 0
! 27194: } QuickScanState;
! 27195: #define QSS_SETV(qss, newst) ((newst) | ((qss) & QSS_ScanMask))
! 27196: #define QSS_INPLAIN(qss) (((qss)&QSS_CharMask)==QSS_Start)
! 27197: #define QSS_PLAINWHITE(qss) (((qss)&~QSS_EndingSemi)==QSS_Start)
! 27198: #define QSS_PLAINDARK(qss) (((qss)&~QSS_EndingSemi)==QSS_HasDark)
! 27199: #define QSS_SEMITERM(qss) (((qss)&~QSS_HasDark)==QSS_EndingSemi)
! 27200:
! 27201: /*
! 27202: ** Scan line for classification to guide shell's handling.
! 27203: ** The scan is resumable for subsequent lines when prior
! 27204: ** return values are passed as the 2nd argument.
! 27205: */
! 27206: static QuickScanState quickscan(char *zLine, QuickScanState qss,
! 27207: SCAN_TRACKER_REFTYPE pst){
! 27208: char cin;
! 27209: char cWait = (char)qss; /* intentional narrowing loss */
! 27210: if( cWait==0 ){
! 27211: PlainScan:
! 27212: assert( cWait==0 );
! 27213: while( (cin = *zLine++)!=0 ){
! 27214: if( IsSpace(cin) )
! 27215: continue;
! 27216: switch (cin){
! 27217: case '-':
! 27218: if( *zLine!='-' )
! 27219: break;
! 27220: while((cin = *++zLine)!=0 )
! 27221: if( cin=='\n')
! 27222: goto PlainScan;
! 27223: return qss;
! 27224: case ';':
! 27225: qss |= QSS_EndingSemi;
! 27226: continue;
! 27227: case '/':
! 27228: if( *zLine=='*' ){
! 27229: ++zLine;
! 27230: cWait = '*';
! 27231: CONTINUE_PROMPT_AWAITS(pst, "/*");
! 27232: qss = QSS_SETV(qss, cWait);
! 27233: goto TermScan;
! 27234: }
! 27235: break;
! 27236: case '[':
! 27237: cin = ']';
! 27238: deliberate_fall_through;
! 27239: case '`': case '\'': case '"':
! 27240: cWait = cin;
! 27241: qss = QSS_HasDark | cWait;
! 27242: CONTINUE_PROMPT_AWAITC(pst, cin);
! 27243: goto TermScan;
! 27244: case '(':
! 27245: CONTINUE_PAREN_INCR(pst, 1);
! 27246: break;
! 27247: case ')':
! 27248: CONTINUE_PAREN_INCR(pst, -1);
! 27249: break;
! 27250: default:
! 27251: break;
! 27252: }
! 27253: qss = (qss & ~QSS_EndingSemi) | QSS_HasDark;
1.2 misho 27254: }
1.6.2.1 ! misho 27255: }else{
! 27256: TermScan:
! 27257: while( (cin = *zLine++)!=0 ){
! 27258: if( cin==cWait ){
! 27259: switch( cWait ){
! 27260: case '*':
! 27261: if( *zLine != '/' )
! 27262: continue;
! 27263: ++zLine;
! 27264: cWait = 0;
! 27265: CONTINUE_PROMPT_AWAITC(pst, 0);
! 27266: qss = QSS_SETV(qss, 0);
! 27267: goto PlainScan;
! 27268: case '`': case '\'': case '"':
! 27269: if(*zLine==cWait){
! 27270: /* Swallow doubled end-delimiter.*/
! 27271: ++zLine;
! 27272: continue;
! 27273: }
! 27274: deliberate_fall_through;
! 27275: case ']':
! 27276: cWait = 0;
! 27277: CONTINUE_PROMPT_AWAITC(pst, 0);
! 27278: qss = QSS_SETV(qss, 0);
! 27279: goto PlainScan;
! 27280: default: assert(0);
! 27281: }
! 27282: }
1.2 misho 27283: }
27284: }
1.6.2.1 ! misho 27285: return qss;
1.2 misho 27286: }
27287:
27288: /*
27289: ** Return TRUE if the line typed in is an SQL command terminator other
27290: ** than a semi-colon. The SQL Server style "go" command is understood
27291: ** as is the Oracle "/".
27292: */
1.6.2.1 ! misho 27293: static int line_is_command_terminator(char *zLine){
1.2 misho 27294: while( IsSpace(zLine[0]) ){ zLine++; };
1.6.2.1 ! misho 27295: if( zLine[0]=='/' )
! 27296: zLine += 1; /* Oracle */
! 27297: else if ( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o' )
! 27298: zLine += 2; /* SQL Server */
! 27299: else
! 27300: return 0;
! 27301: return quickscan(zLine, QSS_Start, 0)==QSS_Start;
1.2 misho 27302: }
27303:
27304: /*
1.6.2.1 ! misho 27305: ** The CLI needs a working sqlite3_complete() to work properly. So error
! 27306: ** out of the build if compiling with SQLITE_OMIT_COMPLETE.
1.5 misho 27307: */
27308: #ifdef SQLITE_OMIT_COMPLETE
1.6.2.1 ! misho 27309: # error the CLI application is imcompatable with SQLITE_OMIT_COMPLETE.
1.5 misho 27310: #endif
27311:
27312: /*
1.2 misho 27313: ** Return true if zSql is a complete SQL statement. Return false if it
27314: ** ends in the middle of a string literal or C-style comment.
27315: */
1.4 misho 27316: static int line_is_complete(char *zSql, int nSql){
1.2 misho 27317: int rc;
27318: if( zSql==0 ) return 1;
27319: zSql[nSql] = ';';
27320: zSql[nSql+1] = 0;
27321: rc = sqlite3_complete(zSql);
27322: zSql[nSql] = 0;
27323: return rc;
27324: }
27325:
27326: /*
1.5 misho 27327: ** Run a single line of SQL. Return the number of errors.
27328: */
27329: static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
27330: int rc;
27331: char *zErrMsg = 0;
27332:
27333: open_db(p, 0);
27334: if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
27335: if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
27336: BEGIN_TIMER;
27337: rc = shell_exec(p, zSql, &zErrMsg);
27338: END_TIMER;
27339: if( rc || zErrMsg ){
27340: char zPrefix[100];
1.6.2.1 ! misho 27341: const char *zErrorTail;
! 27342: const char *zErrorType;
! 27343: if( zErrMsg==0 ){
! 27344: zErrorType = "Error";
! 27345: zErrorTail = sqlite3_errmsg(p->db);
! 27346: }else if( cli_strncmp(zErrMsg, "in prepare, ",12)==0 ){
! 27347: zErrorType = "Parse error";
! 27348: zErrorTail = &zErrMsg[12];
! 27349: }else if( cli_strncmp(zErrMsg, "stepping, ", 10)==0 ){
! 27350: zErrorType = "Runtime error";
! 27351: zErrorTail = &zErrMsg[10];
1.5 misho 27352: }else{
1.6.2.1 ! misho 27353: zErrorType = "Error";
! 27354: zErrorTail = zErrMsg;
1.5 misho 27355: }
1.6.2.1 ! misho 27356: if( in!=0 || !stdin_is_interactive ){
! 27357: sqlite3_snprintf(sizeof(zPrefix), zPrefix,
! 27358: "%s near line %d:", zErrorType, startline);
1.5 misho 27359: }else{
1.6.2.1 ! misho 27360: sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:", zErrorType);
1.5 misho 27361: }
1.6.2.1 ! misho 27362: utf8_printf(stderr, "%s %s\n", zPrefix, zErrorTail);
! 27363: sqlite3_free(zErrMsg);
! 27364: zErrMsg = 0;
1.5 misho 27365: return 1;
27366: }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
1.6.2.1 ! misho 27367: char zLineBuf[2000];
! 27368: sqlite3_snprintf(sizeof(zLineBuf), zLineBuf,
! 27369: "changes: %lld total_changes: %lld",
! 27370: sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
! 27371: raw_printf(p->out, "%s\n", zLineBuf);
1.5 misho 27372: }
27373: return 0;
27374: }
27375:
1.6.2.1 ! misho 27376: static void echo_group_input(ShellState *p, const char *zDo){
! 27377: if( ShellHasFlag(p, SHFLG_Echo) ) utf8_printf(p->out, "%s\n", zDo);
! 27378: }
! 27379:
! 27380: #ifdef SQLITE_SHELL_FIDDLE
! 27381: /*
! 27382: ** Alternate one_input_line() impl for wasm mode. This is not in the primary
! 27383: ** impl because we need the global shellState and cannot access it from that
! 27384: ** function without moving lots of code around (creating a larger/messier diff).
! 27385: */
! 27386: static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
! 27387: /* Parse the next line from shellState.wasm.zInput. */
! 27388: const char *zBegin = shellState.wasm.zPos;
! 27389: const char *z = zBegin;
! 27390: char *zLine = 0;
! 27391: i64 nZ = 0;
! 27392:
! 27393: UNUSED_PARAMETER(in);
! 27394: UNUSED_PARAMETER(isContinuation);
! 27395: if(!z || !*z){
! 27396: return 0;
! 27397: }
! 27398: while(*z && isspace(*z)) ++z;
! 27399: zBegin = z;
! 27400: for(; *z && '\n'!=*z; ++nZ, ++z){}
! 27401: if(nZ>0 && '\r'==zBegin[nZ-1]){
! 27402: --nZ;
! 27403: }
! 27404: shellState.wasm.zPos = z;
! 27405: zLine = realloc(zPrior, nZ+1);
! 27406: shell_check_oom(zLine);
! 27407: memcpy(zLine, zBegin, nZ);
! 27408: zLine[nZ] = 0;
! 27409: return zLine;
! 27410: }
! 27411: #endif /* SQLITE_SHELL_FIDDLE */
1.5 misho 27412:
27413: /*
1.2 misho 27414: ** Read input from *in and process it. If *in==0 then input
27415: ** is interactive - the user is typing it it. Otherwise, input
27416: ** is coming from a file or device. A prompt is issued and history
27417: ** is saved only if input is interactive. An interrupt signal will
27418: ** cause this routine to exit immediately, unless input is interactive.
27419: **
27420: ** Return the number of errors.
27421: */
1.5 misho 27422: static int process_input(ShellState *p){
1.4 misho 27423: char *zLine = 0; /* A single input line */
27424: char *zSql = 0; /* Accumulated SQL text */
1.6.2.1 ! misho 27425: i64 nLine; /* Length of current line */
! 27426: i64 nSql = 0; /* Bytes of zSql[] used */
! 27427: i64 nAlloc = 0; /* Allocated zSql[] space */
1.4 misho 27428: int rc; /* Error code */
27429: int errCnt = 0; /* Number of errors seen */
1.6.2.1 ! misho 27430: i64 startline = 0; /* Line number for start of current input */
! 27431: QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */
1.2 misho 27432:
1.6.2.1 ! misho 27433: if( p->inputNesting==MAX_INPUT_NESTING ){
! 27434: /* This will be more informative in a later version. */
! 27435: utf8_printf(stderr,"Input nesting limit (%d) reached at line %d."
! 27436: " Check recursion.\n", MAX_INPUT_NESTING, p->lineno);
! 27437: return 1;
! 27438: }
! 27439: ++p->inputNesting;
1.5 misho 27440: p->lineno = 0;
1.6.2.1 ! misho 27441: CONTINUE_PROMPT_RESET;
1.5 misho 27442: while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
1.2 misho 27443: fflush(p->out);
1.5 misho 27444: zLine = one_input_line(p->in, zLine, nSql>0);
1.2 misho 27445: if( zLine==0 ){
1.3 misho 27446: /* End of input */
1.5 misho 27447: if( p->in==0 && stdin_is_interactive ) printf("\n");
1.3 misho 27448: break;
1.2 misho 27449: }
27450: if( seenInterrupt ){
1.5 misho 27451: if( p->in!=0 ) break;
1.2 misho 27452: seenInterrupt = 0;
27453: }
1.5 misho 27454: p->lineno++;
1.6.2.1 ! misho 27455: if( QSS_INPLAIN(qss)
! 27456: && line_is_command_terminator(zLine)
! 27457: && line_is_complete(zSql, nSql) ){
! 27458: memcpy(zLine,";",2);
! 27459: }
! 27460: qss = quickscan(zLine, qss, CONTINUE_PROMPT_PSTATE);
! 27461: if( QSS_PLAINWHITE(qss) && nSql==0 ){
! 27462: /* Just swallow single-line whitespace */
! 27463: echo_group_input(p, zLine);
! 27464: qss = QSS_Start;
1.4 misho 27465: continue;
27466: }
1.5 misho 27467: if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
1.6.2.1 ! misho 27468: CONTINUE_PROMPT_RESET;
! 27469: echo_group_input(p, zLine);
1.5 misho 27470: if( zLine[0]=='.' ){
27471: rc = do_meta_command(zLine, p);
27472: if( rc==2 ){ /* exit requested */
27473: break;
27474: }else if( rc ){
27475: errCnt++;
27476: }
1.2 misho 27477: }
1.6.2.1 ! misho 27478: qss = QSS_Start;
1.2 misho 27479: continue;
27480: }
1.6.2.1 ! misho 27481: /* No single-line dispositions remain; accumulate line(s). */
! 27482: nLine = strlen(zLine);
1.4 misho 27483: if( nSql+nLine+2>=nAlloc ){
1.6.2.1 ! misho 27484: /* Grow buffer by half-again increments when big. */
! 27485: nAlloc = nSql+(nSql>>1)+nLine+100;
1.4 misho 27486: zSql = realloc(zSql, nAlloc);
1.6.2.1 ! misho 27487: shell_check_oom(zSql);
1.4 misho 27488: }
27489: if( nSql==0 ){
1.6.2.1 ! misho 27490: i64 i;
1.2 misho 27491: for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
1.4 misho 27492: assert( nAlloc>0 && zSql!=0 );
27493: memcpy(zSql, zLine+i, nLine+1-i);
1.5 misho 27494: startline = p->lineno;
1.4 misho 27495: nSql = nLine-i;
1.2 misho 27496: }else{
27497: zSql[nSql++] = '\n';
1.4 misho 27498: memcpy(zSql+nSql, zLine, nLine+1);
27499: nSql += nLine;
1.2 misho 27500: }
1.6.2.1 ! misho 27501: if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){
! 27502: echo_group_input(p, zSql);
1.5 misho 27503: errCnt += runOneSqlLine(p, zSql, p->in, startline);
1.6.2.1 ! misho 27504: CONTINUE_PROMPT_RESET;
1.4 misho 27505: nSql = 0;
27506: if( p->outCount ){
27507: output_reset(p);
27508: p->outCount = 0;
1.5 misho 27509: }else{
27510: clearTempFile(p);
1.4 misho 27511: }
1.6.2.1 ! misho 27512: p->bSafeMode = p->bSafeModePersist;
! 27513: qss = QSS_Start;
! 27514: }else if( nSql && QSS_PLAINWHITE(qss) ){
! 27515: echo_group_input(p, zSql);
1.2 misho 27516: nSql = 0;
1.6.2.1 ! misho 27517: qss = QSS_Start;
1.2 misho 27518: }
27519: }
1.6.2.1 ! misho 27520: if( nSql ){
! 27521: /* This may be incomplete. Let the SQL parser deal with that. */
! 27522: echo_group_input(p, zSql);
1.5 misho 27523: errCnt += runOneSqlLine(p, zSql, p->in, startline);
1.6.2.1 ! misho 27524: CONTINUE_PROMPT_RESET;
1.2 misho 27525: }
1.4 misho 27526: free(zSql);
1.2 misho 27527: free(zLine);
1.6.2.1 ! misho 27528: --p->inputNesting;
1.3 misho 27529: return errCnt>0;
1.2 misho 27530: }
27531:
27532: /*
27533: ** Return a pathname which is the user's home directory. A
1.3 misho 27534: ** 0 return indicates an error of some kind.
1.2 misho 27535: */
1.5 misho 27536: static char *find_home_dir(int clearFlag){
1.3 misho 27537: static char *home_dir = NULL;
1.5 misho 27538: if( clearFlag ){
27539: free(home_dir);
27540: home_dir = 0;
27541: return 0;
27542: }
1.3 misho 27543: if( home_dir ) return home_dir;
1.2 misho 27544:
1.4 misho 27545: #if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
1.6.2.1 ! misho 27546: && !defined(__RTP__) && !defined(_WRS_KERNEL) && !defined(SQLITE_WASI)
1.3 misho 27547: {
27548: struct passwd *pwent;
27549: uid_t uid = getuid();
27550: if( (pwent=getpwuid(uid)) != NULL) {
27551: home_dir = pwent->pw_dir;
27552: }
1.2 misho 27553: }
27554: #endif
27555:
27556: #if defined(_WIN32_WCE)
27557: /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
27558: */
1.3 misho 27559: home_dir = "/";
1.2 misho 27560: #else
27561:
1.3 misho 27562: #if defined(_WIN32) || defined(WIN32)
1.2 misho 27563: if (!home_dir) {
27564: home_dir = getenv("USERPROFILE");
27565: }
27566: #endif
27567:
27568: if (!home_dir) {
27569: home_dir = getenv("HOME");
27570: }
27571:
1.3 misho 27572: #if defined(_WIN32) || defined(WIN32)
1.2 misho 27573: if (!home_dir) {
27574: char *zDrive, *zPath;
27575: int n;
27576: zDrive = getenv("HOMEDRIVE");
27577: zPath = getenv("HOMEPATH");
27578: if( zDrive && zPath ){
27579: n = strlen30(zDrive) + strlen30(zPath) + 1;
27580: home_dir = malloc( n );
27581: if( home_dir==0 ) return 0;
27582: sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
27583: return home_dir;
27584: }
27585: home_dir = "c:\\";
27586: }
27587: #endif
27588:
27589: #endif /* !_WIN32_WCE */
27590:
27591: if( home_dir ){
1.6.2.1 ! misho 27592: i64 n = strlen(home_dir) + 1;
1.2 misho 27593: char *z = malloc( n );
27594: if( z ) memcpy(z, home_dir, n);
27595: home_dir = z;
27596: }
27597:
27598: return home_dir;
27599: }
27600:
27601: /*
1.6.2.1 ! misho 27602: ** On non-Windows platforms, look for $XDG_CONFIG_HOME.
! 27603: ** If ${XDG_CONFIG_HOME}/sqlite3/sqliterc is found, return
! 27604: ** the path to it, else return 0. The result is cached for
! 27605: ** subsequent calls.
! 27606: */
! 27607: static const char *find_xdg_config(void){
! 27608: #if defined(_WIN32) || defined(WIN32) || defined(_WIN32_WCE) \
! 27609: || defined(__RTP__) || defined(_WRS_KERNEL)
! 27610: return 0;
! 27611: #else
! 27612: static int alreadyTried = 0;
! 27613: static char *zConfig = 0;
! 27614: const char *zXdgHome;
! 27615:
! 27616: if( alreadyTried!=0 ){
! 27617: return zConfig;
! 27618: }
! 27619: alreadyTried = 1;
! 27620: zXdgHome = getenv("XDG_CONFIG_HOME");
! 27621: if( zXdgHome==0 ){
! 27622: return 0;
! 27623: }
! 27624: zConfig = sqlite3_mprintf("%s/sqlite3/sqliterc", zXdgHome);
! 27625: shell_check_oom(zConfig);
! 27626: if( access(zConfig,0)!=0 ){
! 27627: sqlite3_free(zConfig);
! 27628: zConfig = 0;
! 27629: }
! 27630: return zConfig;
! 27631: #endif
! 27632: }
! 27633:
! 27634: /*
1.2 misho 27635: ** Read input from the file given by sqliterc_override. Or if that
1.6.2.1 ! misho 27636: ** parameter is NULL, take input from the first of find_xdg_config()
! 27637: ** or ~/.sqliterc which is found.
1.2 misho 27638: **
27639: ** Returns the number of errors.
27640: */
1.4 misho 27641: static void process_sqliterc(
27642: ShellState *p, /* Configuration data */
1.2 misho 27643: const char *sqliterc_override /* Name of config file. NULL to use default */
27644: ){
27645: char *home_dir = NULL;
27646: const char *sqliterc = sqliterc_override;
27647: char *zBuf = 0;
1.5 misho 27648: FILE *inSaved = p->in;
27649: int savedLineno = p->lineno;
1.2 misho 27650:
1.6.2.1 ! misho 27651: if( sqliterc == NULL ){
! 27652: sqliterc = find_xdg_config();
! 27653: }
! 27654: if( sqliterc == NULL ){
1.5 misho 27655: home_dir = find_home_dir(0);
1.2 misho 27656: if( home_dir==0 ){
1.4 misho 27657: raw_printf(stderr, "-- warning: cannot find home directory;"
27658: " cannot read ~/.sqliterc\n");
27659: return;
1.2 misho 27660: }
1.3 misho 27661: zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
1.6.2.1 ! misho 27662: shell_check_oom(zBuf);
1.3 misho 27663: sqliterc = zBuf;
1.2 misho 27664: }
1.5 misho 27665: p->in = fopen(sqliterc,"rb");
27666: if( p->in ){
1.2 misho 27667: if( stdin_is_interactive ){
1.4 misho 27668: utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
1.2 misho 27669: }
1.6 misho 27670: if( process_input(p) && bail_on_error ) exit(1);
1.5 misho 27671: fclose(p->in);
1.6 misho 27672: }else if( sqliterc_override!=0 ){
27673: utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
27674: if( bail_on_error ) exit(1);
1.2 misho 27675: }
1.5 misho 27676: p->in = inSaved;
27677: p->lineno = savedLineno;
1.3 misho 27678: sqlite3_free(zBuf);
1.2 misho 27679: }
27680:
27681: /*
27682: ** Show available command line options
27683: */
1.4 misho 27684: static const char zOptions[] =
1.6.2.1 ! misho 27685: " -- treat no subsequent arguments as options\n"
1.5 misho 27686: #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
27687: " -A ARGS... run \".archive ARGS\" and exit\n"
27688: #endif
27689: " -append append the database to the end of the file\n"
1.4 misho 27690: " -ascii set output mode to 'ascii'\n"
1.2 misho 27691: " -bail stop after hitting an error\n"
27692: " -batch force batch I/O\n"
1.5 misho 27693: " -box set output mode to 'box'\n"
1.2 misho 27694: " -column set output mode to 'column'\n"
1.3 misho 27695: " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
1.2 misho 27696: " -csv set output mode to 'csv'\n"
1.6.2.1 ! misho 27697: #if !defined(SQLITE_OMIT_DESERIALIZE)
1.5 misho 27698: " -deserialize open the database using sqlite3_deserialize()\n"
27699: #endif
1.6.2.1 ! misho 27700: " -echo print inputs before execution\n"
1.3 misho 27701: " -init FILENAME read/process named file\n"
27702: " -[no]header turn headers on or off\n"
27703: #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
27704: " -heap SIZE Size of heap for memsys3 or memsys5\n"
27705: #endif
27706: " -help show this message\n"
1.2 misho 27707: " -html set output mode to HTML\n"
1.3 misho 27708: " -interactive force interactive I/O\n"
1.5 misho 27709: " -json set output mode to 'json'\n"
1.2 misho 27710: " -line set output mode to 'line'\n"
27711: " -list set output mode to 'list'\n"
1.4 misho 27712: " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
1.5 misho 27713: " -markdown set output mode to 'markdown'\n"
1.6.2.1 ! misho 27714: #if !defined(SQLITE_OMIT_DESERIALIZE)
1.5 misho 27715: " -maxsize N maximum size for a --deserialize database\n"
27716: #endif
27717: " -memtrace trace all memory allocations and deallocations\n"
1.4 misho 27718: " -mmap N default mmap size set to N\n"
1.3 misho 27719: #ifdef SQLITE_ENABLE_MULTIPLEX
27720: " -multiplex enable the multiplexor VFS\n"
27721: #endif
1.4 misho 27722: " -newline SEP set output row separator. Default: '\\n'\n"
1.5 misho 27723: " -nofollow refuse to open symbolic links to database files\n"
1.6.2.1 ! misho 27724: " -nonce STRING set the safe-mode escape nonce\n"
1.3 misho 27725: " -nullvalue TEXT set text string for NULL values. Default ''\n"
1.4 misho 27726: " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
1.6.2.1 ! misho 27727: " -pcachetrace trace all page cache operations\n"
1.5 misho 27728: " -quote set output mode to 'quote'\n"
27729: " -readonly open the database read-only\n"
1.6.2.1 ! misho 27730: " -safe enable safe-mode\n"
1.4 misho 27731: " -separator SEP set output column separator. Default: '|'\n"
1.5 misho 27732: #ifdef SQLITE_ENABLE_SORTER_REFERENCES
27733: " -sorterref SIZE sorter references threshold size\n"
27734: #endif
1.2 misho 27735: " -stats print memory stats before each finalize\n"
1.5 misho 27736: " -table set output mode to 'table'\n"
1.6 misho 27737: " -tabs set output mode to 'tabs'\n"
1.6.2.1 ! misho 27738: " -unsafe-testing allow unsafe commands and modes for testing\n"
! 27739: #if SHELL_WIN_UTF8_OPT
! 27740: " -utf8 setup interactive console code page for UTF-8\n"
! 27741: #endif
1.2 misho 27742: " -version show SQLite version\n"
27743: " -vfs NAME use NAME as the default VFS\n"
27744: #ifdef SQLITE_ENABLE_VFSTRACE
27745: " -vfstrace enable tracing of all VFS calls\n"
27746: #endif
1.5 misho 27747: #ifdef SQLITE_HAVE_ZLIB
27748: " -zip open the file as a ZIP Archive\n"
27749: #endif
1.2 misho 27750: ;
27751: static void usage(int showDetail){
1.4 misho 27752: utf8_printf(stderr,
1.6.2.1 ! misho 27753: "Usage: %s [OPTIONS] [FILENAME [SQL]]\n"
1.2 misho 27754: "FILENAME is the name of an SQLite database. A new database is created\n"
1.6.2.1 ! misho 27755: "if the file does not previously exist. Defaults to :memory:.\n", Argv0);
1.2 misho 27756: if( showDetail ){
1.4 misho 27757: utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
1.2 misho 27758: }else{
1.4 misho 27759: raw_printf(stderr, "Use the -help option for additional information\n");
1.2 misho 27760: }
27761: exit(1);
27762: }
27763:
27764: /*
1.5 misho 27765: ** Internal check: Verify that the SQLite is uninitialized. Print a
27766: ** error message if it is initialized.
27767: */
27768: static void verify_uninitialized(void){
27769: if( sqlite3_config(-1)==SQLITE_MISUSE ){
27770: utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
27771: " initialization.\n");
27772: }
27773: }
27774:
27775: /*
1.2 misho 27776: ** Initialize the state information in data
27777: */
1.4 misho 27778: static void main_init(ShellState *data) {
1.2 misho 27779: memset(data, 0, sizeof(*data));
1.4 misho 27780: data->normalMode = data->cMode = data->mode = MODE_List;
27781: data->autoExplain = 1;
1.6.2.1 ! misho 27782: data->pAuxDb = &data->aAuxDb[0];
1.4 misho 27783: memcpy(data->colSeparator,SEP_Column, 2);
27784: memcpy(data->rowSeparator,SEP_Row, 2);
1.2 misho 27785: data->showHeader = 0;
1.4 misho 27786: data->shellFlgs = SHFLG_Lookaside;
1.6.2.1 ! misho 27787: sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
! 27788: #if !defined(SQLITE_SHELL_FIDDLE)
1.5 misho 27789: verify_uninitialized();
1.6.2.1 ! misho 27790: #endif
1.2 misho 27791: sqlite3_config(SQLITE_CONFIG_URI, 1);
1.4 misho 27792: sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
1.2 misho 27793: sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
27794: sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
27795: }
27796:
1.3 misho 27797: /*
1.4 misho 27798: ** Output text to the console in a font that attracts extra attention.
27799: */
27800: #ifdef _WIN32
27801: static void printBold(const char *zText){
1.5 misho 27802: #if !SQLITE_OS_WINRT
1.4 misho 27803: HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
27804: CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
27805: GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
27806: SetConsoleTextAttribute(out,
27807: FOREGROUND_RED|FOREGROUND_INTENSITY
27808: );
1.5 misho 27809: #endif
1.4 misho 27810: printf("%s", zText);
1.5 misho 27811: #if !SQLITE_OS_WINRT
1.4 misho 27812: SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
1.5 misho 27813: #endif
1.4 misho 27814: }
27815: #else
27816: static void printBold(const char *zText){
27817: printf("\033[1m%s\033[0m", zText);
27818: }
27819: #endif
27820:
27821: /*
1.3 misho 27822: ** Get the argument to an --option. Throw an error and die if no argument
27823: ** is available.
27824: */
27825: static char *cmdline_option_value(int argc, char **argv, int i){
27826: if( i==argc ){
1.4 misho 27827: utf8_printf(stderr, "%s: Error: missing argument to %s\n",
1.3 misho 27828: argv[0], argv[argc-1]);
27829: exit(1);
27830: }
27831: return argv[i];
27832: }
27833:
1.6.2.1 ! misho 27834: static void sayAbnormalExit(void){
! 27835: if( seenInterrupt ) fprintf(stderr, "Program interrupted.\n");
! 27836: }
! 27837:
1.4 misho 27838: #ifndef SQLITE_SHELL_IS_UTF8
1.6 misho 27839: # if (defined(_WIN32) || defined(WIN32)) \
27840: && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
1.4 misho 27841: # define SQLITE_SHELL_IS_UTF8 (0)
27842: # else
27843: # define SQLITE_SHELL_IS_UTF8 (1)
27844: # endif
27845: #endif
27846:
1.6.2.1 ! misho 27847: #ifdef SQLITE_SHELL_FIDDLE
! 27848: # define main fiddle_main
! 27849: #endif
! 27850:
1.4 misho 27851: #if SQLITE_SHELL_IS_UTF8
27852: int SQLITE_CDECL main(int argc, char **argv){
27853: #else
27854: int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
27855: char **argv;
27856: #endif
1.6.2.1 ! misho 27857: #ifdef SQLITE_DEBUG
! 27858: sqlite3_int64 mem_main_enter = 0;
! 27859: #endif
1.2 misho 27860: char *zErrMsg = 0;
1.6.2.1 ! misho 27861: #ifdef SQLITE_SHELL_FIDDLE
! 27862: # define data shellState
! 27863: #else
1.4 misho 27864: ShellState data;
1.6.2.1 ! misho 27865: #endif
1.2 misho 27866: const char *zInitFile = 0;
27867: int i;
27868: int rc = 0;
1.4 misho 27869: int warnInmemoryDb = 0;
27870: int readStdin = 1;
27871: int nCmd = 0;
1.6.2.1 ! misho 27872: int nOptsEnd = argc;
1.4 misho 27873: char **azCmd = 0;
1.5 misho 27874: const char *zVfs = 0; /* Value of -vfs command-line option */
27875: #if !SQLITE_SHELL_IS_UTF8
27876: char **argvToFree = 0;
27877: int argcToFree = 0;
27878: #endif
1.4 misho 27879: setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
1.6.2.1 ! misho 27880:
! 27881: #ifdef SQLITE_SHELL_FIDDLE
! 27882: stdin_is_interactive = 0;
! 27883: stdout_is_console = 1;
! 27884: data.wasm.zDefaultDbName = "/fiddle.sqlite3";
! 27885: #else
1.4 misho 27886: stdin_is_interactive = isatty(0);
27887: stdout_is_console = isatty(1);
1.6.2.1 ! misho 27888: #endif
! 27889: #if SHELL_WIN_UTF8_OPT
! 27890: atexit(console_restore); /* Needs revision for CLI as library call */
! 27891: #endif
! 27892: atexit(sayAbnormalExit);
1.5 misho 27893: #ifdef SQLITE_DEBUG
1.6.2.1 ! misho 27894: mem_main_enter = sqlite3_memory_used();
1.5 misho 27895: #endif
27896: #if !defined(_WIN32_WCE)
27897: if( getenv("SQLITE_DEBUG_BREAK") ){
27898: if( isatty(0) && isatty(2) ){
27899: fprintf(stderr,
27900: "attach debugger to process %d and press any key to continue.\n",
27901: GETPID());
27902: fgetc(stdin);
27903: }else{
27904: #if defined(_WIN32) || defined(WIN32)
27905: #if SQLITE_OS_WINRT
27906: __debugbreak();
27907: #else
27908: DebugBreak();
27909: #endif
27910: #elif defined(SIGTRAP)
27911: raise(SIGTRAP);
27912: #endif
27913: }
27914: }
27915: #endif
1.6.2.1 ! misho 27916: /* Register a valid signal handler early, before much else is done. */
! 27917: #ifdef SIGINT
! 27918: signal(SIGINT, interrupt_handler);
! 27919: #elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
! 27920: if( !SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE) ){
! 27921: fprintf(stderr, "No ^C handler.\n");
! 27922: }
! 27923: #endif
1.5 misho 27924:
1.4 misho 27925: #if USE_SYSTEM_SQLITE+0!=1
1.6.2.1 ! misho 27926: if( cli_strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
1.4 misho 27927: utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
1.2 misho 27928: sqlite3_sourceid(), SQLITE_SOURCE_ID);
27929: exit(1);
27930: }
1.4 misho 27931: #endif
27932: main_init(&data);
1.5 misho 27933:
27934: /* On Windows, we must translate command-line arguments into UTF-8.
27935: ** The SQLite memory allocator subsystem has to be enabled in order to
27936: ** do this. But we want to run an sqlite3_shutdown() afterwards so that
27937: ** subsequent sqlite3_config() calls will work. So copy all results into
27938: ** memory that does not come from the SQLite memory allocator.
27939: */
1.4 misho 27940: #if !SQLITE_SHELL_IS_UTF8
27941: sqlite3_initialize();
1.5 misho 27942: argvToFree = malloc(sizeof(argv[0])*argc*2);
1.6.2.1 ! misho 27943: shell_check_oom(argvToFree);
1.5 misho 27944: argcToFree = argc;
27945: argv = argvToFree + argc;
1.4 misho 27946: for(i=0; i<argc; i++){
1.5 misho 27947: char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
1.6.2.1 ! misho 27948: i64 n;
! 27949: shell_check_oom(z);
! 27950: n = strlen(z);
1.5 misho 27951: argv[i] = malloc( n+1 );
1.6.2.1 ! misho 27952: shell_check_oom(argv[i]);
1.5 misho 27953: memcpy(argv[i], z, n+1);
27954: argvToFree[i] = argv[i];
27955: sqlite3_free(z);
1.4 misho 27956: }
1.5 misho 27957: sqlite3_shutdown();
1.4 misho 27958: #endif
1.5 misho 27959:
1.4 misho 27960: assert( argc>=1 && argv && argv[0] );
1.2 misho 27961: Argv0 = argv[0];
27962:
1.4 misho 27963: #ifdef SQLITE_SHELL_DBNAME_PROC
27964: {
27965: /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
27966: ** of a C-function that will provide the name of the database file. Use
27967: ** this compile-time option to embed this shell program in larger
27968: ** applications. */
27969: extern void SQLITE_SHELL_DBNAME_PROC(const char**);
1.6.2.1 ! misho 27970: SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename);
1.4 misho 27971: warnInmemoryDb = 0;
27972: }
27973: #endif
27974:
1.2 misho 27975: /* Do an initial pass through the command-line argument to locate
27976: ** the name of the database file, the name of the initialization file,
27977: ** the size of the alternative malloc heap,
27978: ** and the first command to execute.
27979: */
1.6.2.1 ! misho 27980: #ifndef SQLITE_SHELL_FIDDLE
1.5 misho 27981: verify_uninitialized();
1.6.2.1 ! misho 27982: #endif
1.3 misho 27983: for(i=1; i<argc; i++){
1.2 misho 27984: char *z;
27985: z = argv[i];
1.6.2.1 ! misho 27986: if( z[0]!='-' || i>nOptsEnd ){
! 27987: if( data.aAuxDb->zDbFilename==0 ){
! 27988: data.aAuxDb->zDbFilename = z;
1.4 misho 27989: }else{
1.6.2.1 ! misho 27990: /* Excess arguments are interpreted as SQL (or dot-commands) and
1.4 misho 27991: ** mean that nothing is read from stdin */
27992: readStdin = 0;
27993: nCmd++;
27994: azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
1.6.2.1 ! misho 27995: shell_check_oom(azCmd);
1.4 misho 27996: azCmd[nCmd-1] = z;
1.3 misho 27997: }
1.6.2.1 ! misho 27998: continue;
1.3 misho 27999: }
28000: if( z[1]=='-' ) z++;
1.6.2.1 ! misho 28001: if( cli_strcmp(z, "-")==0 ){
! 28002: nOptsEnd = i;
! 28003: continue;
! 28004: }else if( cli_strcmp(z,"-separator")==0
! 28005: || cli_strcmp(z,"-nullvalue")==0
! 28006: || cli_strcmp(z,"-newline")==0
! 28007: || cli_strcmp(z,"-cmd")==0
1.3 misho 28008: ){
28009: (void)cmdline_option_value(argc, argv, ++i);
1.6.2.1 ! misho 28010: }else if( cli_strcmp(z,"-init")==0 ){
1.3 misho 28011: zInitFile = cmdline_option_value(argc, argv, ++i);
1.6.2.1 ! misho 28012: }else if( cli_strcmp(z,"-batch")==0 ){
1.3 misho 28013: /* Need to check for batch mode here to so we can avoid printing
1.4 misho 28014: ** informational messages (like from process_sqliterc) before
1.3 misho 28015: ** we do the actual processing of arguments later in a second pass.
28016: */
1.2 misho 28017: stdin_is_interactive = 0;
1.6.2.1 ! misho 28018: }else if( cli_strcmp(z,"-heap")==0 ){
1.2 misho 28019: #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
28020: const char *zSize;
28021: sqlite3_int64 szHeap;
28022:
1.3 misho 28023: zSize = cmdline_option_value(argc, argv, ++i);
1.4 misho 28024: szHeap = integerValue(zSize);
1.2 misho 28025: if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
1.6.2.1 ! misho 28026: verify_uninitialized();
1.2 misho 28027: sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
1.4 misho 28028: #else
28029: (void)cmdline_option_value(argc, argv, ++i);
1.2 misho 28030: #endif
1.6.2.1 ! misho 28031: }else if( cli_strcmp(z,"-pagecache")==0 ){
1.6 misho 28032: sqlite3_int64 n, sz;
28033: sz = integerValue(cmdline_option_value(argc,argv,++i));
1.4 misho 28034: if( sz>70000 ) sz = 70000;
28035: if( sz<0 ) sz = 0;
1.6 misho 28036: n = integerValue(cmdline_option_value(argc,argv,++i));
28037: if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
28038: n = 0xffffffffffffLL/sz;
28039: }
1.6.2.1 ! misho 28040: verify_uninitialized();
1.4 misho 28041: sqlite3_config(SQLITE_CONFIG_PAGECACHE,
28042: (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
28043: data.shellFlgs |= SHFLG_Pagecache;
1.6.2.1 ! misho 28044: }else if( cli_strcmp(z,"-lookaside")==0 ){
1.4 misho 28045: int n, sz;
28046: sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
28047: if( sz<0 ) sz = 0;
28048: n = (int)integerValue(cmdline_option_value(argc,argv,++i));
28049: if( n<0 ) n = 0;
1.6.2.1 ! misho 28050: verify_uninitialized();
1.4 misho 28051: sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
28052: if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
1.6.2.1 ! misho 28053: }else if( cli_strcmp(z,"-threadsafe")==0 ){
! 28054: int n;
! 28055: n = (int)integerValue(cmdline_option_value(argc,argv,++i));
! 28056: verify_uninitialized();
! 28057: switch( n ){
! 28058: case 0: sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); break;
! 28059: case 2: sqlite3_config(SQLITE_CONFIG_MULTITHREAD); break;
! 28060: default: sqlite3_config(SQLITE_CONFIG_SERIALIZED); break;
! 28061: }
1.2 misho 28062: #ifdef SQLITE_ENABLE_VFSTRACE
1.6.2.1 ! misho 28063: }else if( cli_strcmp(z,"-vfstrace")==0 ){
1.2 misho 28064: extern int vfstrace_register(
28065: const char *zTraceName,
28066: const char *zOldVfsName,
28067: int (*xOut)(const char*,void*),
28068: void *pOutArg,
28069: int makeDefault
28070: );
28071: vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
28072: #endif
28073: #ifdef SQLITE_ENABLE_MULTIPLEX
1.6.2.1 ! misho 28074: }else if( cli_strcmp(z,"-multiplex")==0 ){
! 28075: extern int sqlite3_multiplex_initialize(const char*,int);
1.2 misho 28076: sqlite3_multiplex_initialize(0, 1);
28077: #endif
1.6.2.1 ! misho 28078: }else if( cli_strcmp(z,"-mmap")==0 ){
1.4 misho 28079: sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
1.6.2.1 ! misho 28080: verify_uninitialized();
1.4 misho 28081: sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
1.6.2.1 ! misho 28082: #if defined(SQLITE_ENABLE_SORTER_REFERENCES)
! 28083: }else if( cli_strcmp(z,"-sorterref")==0 ){
1.5 misho 28084: sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
1.6.2.1 ! misho 28085: verify_uninitialized();
1.5 misho 28086: sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz);
28087: #endif
1.6.2.1 ! misho 28088: }else if( cli_strcmp(z,"-vfs")==0 ){
1.5 misho 28089: zVfs = cmdline_option_value(argc, argv, ++i);
28090: #ifdef SQLITE_HAVE_ZLIB
1.6.2.1 ! misho 28091: }else if( cli_strcmp(z,"-zip")==0 ){
1.5 misho 28092: data.openMode = SHELL_OPEN_ZIPFILE;
28093: #endif
1.6.2.1 ! misho 28094: }else if( cli_strcmp(z,"-append")==0 ){
1.5 misho 28095: data.openMode = SHELL_OPEN_APPENDVFS;
1.6.2.1 ! misho 28096: #ifndef SQLITE_OMIT_DESERIALIZE
! 28097: }else if( cli_strcmp(z,"-deserialize")==0 ){
1.5 misho 28098: data.openMode = SHELL_OPEN_DESERIALIZE;
1.6.2.1 ! misho 28099: }else if( cli_strcmp(z,"-maxsize")==0 && i+1<argc ){
1.5 misho 28100: data.szMax = integerValue(argv[++i]);
28101: #endif
1.6.2.1 ! misho 28102: }else if( cli_strcmp(z,"-readonly")==0 ){
1.5 misho 28103: data.openMode = SHELL_OPEN_READONLY;
1.6.2.1 ! misho 28104: }else if( cli_strcmp(z,"-nofollow")==0 ){
1.5 misho 28105: data.openFlags = SQLITE_OPEN_NOFOLLOW;
28106: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
1.6.2.1 ! misho 28107: }else if( cli_strncmp(z, "-A",2)==0 ){
1.5 misho 28108: /* All remaining command-line arguments are passed to the ".archive"
28109: ** command, so ignore them */
28110: break;
28111: #endif
1.6.2.1 ! misho 28112: }else if( cli_strcmp(z, "-memtrace")==0 ){
1.5 misho 28113: sqlite3MemTraceActivate(stderr);
1.6.2.1 ! misho 28114: }else if( cli_strcmp(z, "-pcachetrace")==0 ){
! 28115: sqlite3PcacheTraceActivate(stderr);
! 28116: }else if( cli_strcmp(z,"-bail")==0 ){
1.6 misho 28117: bail_on_error = 1;
1.6.2.1 ! misho 28118: }else if( cli_strcmp(z,"-nonce")==0 ){
! 28119: free(data.zNonce);
! 28120: data.zNonce = strdup(cmdline_option_value(argc, argv, ++i));
! 28121: }else if( cli_strcmp(z,"-unsafe-testing")==0 ){
! 28122: ShellSetFlag(&data,SHFLG_TestingMode);
! 28123: }else if( cli_strcmp(z,"-safe")==0 ){
! 28124: /* no-op - catch this on the second pass */
1.5 misho 28125: }
28126: }
1.6.2.1 ! misho 28127: #ifndef SQLITE_SHELL_FIDDLE
1.5 misho 28128: verify_uninitialized();
1.6.2.1 ! misho 28129: #endif
1.5 misho 28130:
28131:
28132: #ifdef SQLITE_SHELL_INIT_PROC
28133: {
28134: /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name
28135: ** of a C-function that will perform initialization actions on SQLite that
28136: ** occur just before or after sqlite3_initialize(). Use this compile-time
28137: ** option to embed this shell program in larger applications. */
28138: extern void SQLITE_SHELL_INIT_PROC(void);
28139: SQLITE_SHELL_INIT_PROC();
28140: }
28141: #else
28142: /* All the sqlite3_config() calls have now been made. So it is safe
28143: ** to call sqlite3_initialize() and process any command line -vfs option. */
28144: sqlite3_initialize();
28145: #endif
28146:
28147: if( zVfs ){
28148: sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
28149: if( pVfs ){
28150: sqlite3_vfs_register(pVfs, 1);
28151: }else{
1.6.2.1 ! misho 28152: utf8_printf(stderr, "no such VFS: \"%s\"\n", zVfs);
1.5 misho 28153: exit(1);
1.2 misho 28154: }
28155: }
1.5 misho 28156:
1.6.2.1 ! misho 28157: if( data.pAuxDb->zDbFilename==0 ){
1.2 misho 28158: #ifndef SQLITE_OMIT_MEMORYDB
1.6.2.1 ! misho 28159: data.pAuxDb->zDbFilename = ":memory:";
1.4 misho 28160: warnInmemoryDb = argc==1;
1.2 misho 28161: #else
1.4 misho 28162: utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
1.3 misho 28163: return 1;
1.2 misho 28164: #endif
28165: }
28166: data.out = stdout;
1.6.2.1 ! misho 28167: #ifndef SQLITE_SHELL_FIDDLE
1.5 misho 28168: sqlite3_appendvfs_init(0,0,0);
1.6.2.1 ! misho 28169: #endif
1.2 misho 28170:
28171: /* Go ahead and open the database file if it already exists. If the
28172: ** file does not exist, delay opening it. This prevents empty database
28173: ** files from being created if a user mistypes the database name argument
28174: ** to the sqlite command-line tool.
28175: */
1.6.2.1 ! misho 28176: if( access(data.pAuxDb->zDbFilename, 0)==0 ){
1.4 misho 28177: open_db(&data, 0);
1.2 misho 28178: }
28179:
28180: /* Process the initialization file if there is one. If no -init option
28181: ** is given on the command line, look for a file named ~/.sqliterc and
28182: ** try to process it.
28183: */
1.4 misho 28184: process_sqliterc(&data,zInitFile);
1.2 misho 28185:
28186: /* Make a second pass through the command-line argument and set
28187: ** options. This second pass is delayed until after the initialization
28188: ** file is processed so that the command-line arguments will override
28189: ** settings in the initialization file.
28190: */
1.3 misho 28191: for(i=1; i<argc; i++){
1.2 misho 28192: char *z = argv[i];
1.6.2.1 ! misho 28193: if( z[0]!='-' || i>=nOptsEnd ) continue;
1.2 misho 28194: if( z[1]=='-' ){ z++; }
1.6.2.1 ! misho 28195: if( cli_strcmp(z,"-init")==0 ){
1.2 misho 28196: i++;
1.6.2.1 ! misho 28197: }else if( cli_strcmp(z,"-html")==0 ){
1.2 misho 28198: data.mode = MODE_Html;
1.6.2.1 ! misho 28199: }else if( cli_strcmp(z,"-list")==0 ){
1.2 misho 28200: data.mode = MODE_List;
1.6.2.1 ! misho 28201: }else if( cli_strcmp(z,"-quote")==0 ){
1.5 misho 28202: data.mode = MODE_Quote;
1.6 misho 28203: sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma);
28204: sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
1.6.2.1 ! misho 28205: }else if( cli_strcmp(z,"-line")==0 ){
1.2 misho 28206: data.mode = MODE_Line;
1.6.2.1 ! misho 28207: }else if( cli_strcmp(z,"-column")==0 ){
1.2 misho 28208: data.mode = MODE_Column;
1.6.2.1 ! misho 28209: }else if( cli_strcmp(z,"-json")==0 ){
1.5 misho 28210: data.mode = MODE_Json;
1.6.2.1 ! misho 28211: }else if( cli_strcmp(z,"-markdown")==0 ){
1.5 misho 28212: data.mode = MODE_Markdown;
1.6.2.1 ! misho 28213: }else if( cli_strcmp(z,"-table")==0 ){
1.5 misho 28214: data.mode = MODE_Table;
1.6.2.1 ! misho 28215: }else if( cli_strcmp(z,"-box")==0 ){
1.5 misho 28216: data.mode = MODE_Box;
1.6.2.1 ! misho 28217: }else if( cli_strcmp(z,"-csv")==0 ){
1.2 misho 28218: data.mode = MODE_Csv;
1.4 misho 28219: memcpy(data.colSeparator,",",2);
1.5 misho 28220: #ifdef SQLITE_HAVE_ZLIB
1.6.2.1 ! misho 28221: }else if( cli_strcmp(z,"-zip")==0 ){
1.5 misho 28222: data.openMode = SHELL_OPEN_ZIPFILE;
28223: #endif
1.6.2.1 ! misho 28224: }else if( cli_strcmp(z,"-append")==0 ){
1.5 misho 28225: data.openMode = SHELL_OPEN_APPENDVFS;
1.6.2.1 ! misho 28226: #ifndef SQLITE_OMIT_DESERIALIZE
! 28227: }else if( cli_strcmp(z,"-deserialize")==0 ){
1.5 misho 28228: data.openMode = SHELL_OPEN_DESERIALIZE;
1.6.2.1 ! misho 28229: }else if( cli_strcmp(z,"-maxsize")==0 && i+1<argc ){
1.5 misho 28230: data.szMax = integerValue(argv[++i]);
28231: #endif
1.6.2.1 ! misho 28232: }else if( cli_strcmp(z,"-readonly")==0 ){
1.5 misho 28233: data.openMode = SHELL_OPEN_READONLY;
1.6.2.1 ! misho 28234: }else if( cli_strcmp(z,"-nofollow")==0 ){
1.5 misho 28235: data.openFlags |= SQLITE_OPEN_NOFOLLOW;
1.6.2.1 ! misho 28236: }else if( cli_strcmp(z,"-ascii")==0 ){
1.4 misho 28237: data.mode = MODE_Ascii;
1.6.2.1 ! misho 28238: sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,SEP_Unit);
! 28239: sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,SEP_Record);
! 28240: }else if( cli_strcmp(z,"-tabs")==0 ){
1.6 misho 28241: data.mode = MODE_List;
1.6.2.1 ! misho 28242: sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,SEP_Tab);
! 28243: sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,SEP_Row);
! 28244: }else if( cli_strcmp(z,"-separator")==0 ){
1.4 misho 28245: sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
28246: "%s",cmdline_option_value(argc,argv,++i));
1.6.2.1 ! misho 28247: }else if( cli_strcmp(z,"-newline")==0 ){
1.4 misho 28248: sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
1.3 misho 28249: "%s",cmdline_option_value(argc,argv,++i));
1.6.2.1 ! misho 28250: }else if( cli_strcmp(z,"-nullvalue")==0 ){
1.4 misho 28251: sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
1.3 misho 28252: "%s",cmdline_option_value(argc,argv,++i));
1.6.2.1 ! misho 28253: }else if( cli_strcmp(z,"-header")==0 ){
1.2 misho 28254: data.showHeader = 1;
1.6.2.1 ! misho 28255: ShellSetFlag(&data, SHFLG_HeaderSet);
! 28256: }else if( cli_strcmp(z,"-noheader")==0 ){
1.2 misho 28257: data.showHeader = 0;
1.6.2.1 ! misho 28258: ShellSetFlag(&data, SHFLG_HeaderSet);
! 28259: }else if( cli_strcmp(z,"-echo")==0 ){
1.5 misho 28260: ShellSetFlag(&data, SHFLG_Echo);
1.6.2.1 ! misho 28261: }else if( cli_strcmp(z,"-eqp")==0 ){
1.5 misho 28262: data.autoEQP = AUTOEQP_on;
1.6.2.1 ! misho 28263: }else if( cli_strcmp(z,"-eqpfull")==0 ){
1.5 misho 28264: data.autoEQP = AUTOEQP_full;
1.6.2.1 ! misho 28265: }else if( cli_strcmp(z,"-stats")==0 ){
1.2 misho 28266: data.statsOn = 1;
1.6.2.1 ! misho 28267: }else if( cli_strcmp(z,"-scanstats")==0 ){
1.4 misho 28268: data.scanstatsOn = 1;
1.6.2.1 ! misho 28269: }else if( cli_strcmp(z,"-backslash")==0 ){
1.4 misho 28270: /* Undocumented command-line option: -backslash
28271: ** Causes C-style backslash escapes to be evaluated in SQL statements
28272: ** prior to sending the SQL into SQLite. Useful for injecting
28273: ** crazy bytes in the middle of SQL statements for testing and debugging.
28274: */
1.5 misho 28275: ShellSetFlag(&data, SHFLG_Backslash);
1.6.2.1 ! misho 28276: }else if( cli_strcmp(z,"-bail")==0 ){
1.6 misho 28277: /* No-op. The bail_on_error flag should already be set. */
1.6.2.1 ! misho 28278: }else if( cli_strcmp(z,"-version")==0 ){
! 28279: printf("%s %s (%d-bit)\n", sqlite3_libversion(), sqlite3_sourceid(),
! 28280: 8*(int)sizeof(char*));
1.2 misho 28281: return 0;
1.6.2.1 ! misho 28282: }else if( cli_strcmp(z,"-interactive")==0 ){
1.2 misho 28283: stdin_is_interactive = 1;
1.6.2.1 ! misho 28284: }else if( cli_strcmp(z,"-batch")==0 ){
1.2 misho 28285: stdin_is_interactive = 0;
1.6.2.1 ! misho 28286: }else if( cli_strcmp(z,"-utf8")==0 ){
! 28287: #if SHELL_WIN_UTF8_OPT
! 28288: console_utf8 = 1;
! 28289: #endif /* SHELL_WIN_UTF8_OPT */
! 28290: }else if( cli_strcmp(z,"-heap")==0 ){
1.2 misho 28291: i++;
1.6.2.1 ! misho 28292: }else if( cli_strcmp(z,"-pagecache")==0 ){
! 28293: i+=2;
! 28294: }else if( cli_strcmp(z,"-lookaside")==0 ){
1.4 misho 28295: i+=2;
1.6.2.1 ! misho 28296: }else if( cli_strcmp(z,"-threadsafe")==0 ){
1.4 misho 28297: i+=2;
1.6.2.1 ! misho 28298: }else if( cli_strcmp(z,"-nonce")==0 ){
! 28299: i += 2;
! 28300: }else if( cli_strcmp(z,"-mmap")==0 ){
1.4 misho 28301: i++;
1.6.2.1 ! misho 28302: }else if( cli_strcmp(z,"-memtrace")==0 ){
! 28303: i++;
! 28304: }else if( cli_strcmp(z,"-pcachetrace")==0 ){
1.5 misho 28305: i++;
28306: #ifdef SQLITE_ENABLE_SORTER_REFERENCES
1.6.2.1 ! misho 28307: }else if( cli_strcmp(z,"-sorterref")==0 ){
1.5 misho 28308: i++;
28309: #endif
1.6.2.1 ! misho 28310: }else if( cli_strcmp(z,"-vfs")==0 ){
1.2 misho 28311: i++;
28312: #ifdef SQLITE_ENABLE_VFSTRACE
1.6.2.1 ! misho 28313: }else if( cli_strcmp(z,"-vfstrace")==0 ){
1.2 misho 28314: i++;
28315: #endif
28316: #ifdef SQLITE_ENABLE_MULTIPLEX
1.6.2.1 ! misho 28317: }else if( cli_strcmp(z,"-multiplex")==0 ){
1.2 misho 28318: i++;
28319: #endif
1.6.2.1 ! misho 28320: }else if( cli_strcmp(z,"-help")==0 ){
1.2 misho 28321: usage(1);
1.6.2.1 ! misho 28322: }else if( cli_strcmp(z,"-cmd")==0 ){
1.4 misho 28323: /* Run commands that follow -cmd first and separately from commands
28324: ** that simply appear on the command-line. This seems goofy. It would
28325: ** be better if all commands ran in the order that they appear. But
28326: ** we retain the goofy behavior for historical compatibility. */
1.3 misho 28327: if( i==argc-1 ) break;
28328: z = cmdline_option_value(argc,argv,++i);
28329: if( z[0]=='.' ){
28330: rc = do_meta_command(z, &data);
1.4 misho 28331: if( rc && bail_on_error ) return rc==2 ? 0 : rc;
1.3 misho 28332: }else{
1.4 misho 28333: open_db(&data, 0);
1.5 misho 28334: rc = shell_exec(&data, z, &zErrMsg);
1.3 misho 28335: if( zErrMsg!=0 ){
1.4 misho 28336: utf8_printf(stderr,"Error: %s\n", zErrMsg);
1.3 misho 28337: if( bail_on_error ) return rc!=0 ? rc : 1;
28338: }else if( rc!=0 ){
1.4 misho 28339: utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
1.3 misho 28340: if( bail_on_error ) return rc;
28341: }
28342: }
1.5 misho 28343: #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
1.6.2.1 ! misho 28344: }else if( cli_strncmp(z, "-A", 2)==0 ){
1.5 misho 28345: if( nCmd>0 ){
28346: utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
28347: " with \"%s\"\n", z);
28348: return 1;
28349: }
28350: open_db(&data, OPEN_DB_ZIPFILE);
28351: if( z[2] ){
28352: argv[i] = &z[2];
28353: arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
28354: }else{
28355: arDotCommand(&data, 1, argv+i, argc-i);
28356: }
28357: readStdin = 0;
28358: break;
28359: #endif
1.6.2.1 ! misho 28360: }else if( cli_strcmp(z,"-safe")==0 ){
! 28361: data.bSafeMode = data.bSafeModePersist = 1;
! 28362: }else if( cli_strcmp(z,"-unsafe-testing")==0 ){
! 28363: /* Acted upon in first pass. */
1.2 misho 28364: }else{
1.4 misho 28365: utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
28366: raw_printf(stderr,"Use -help for a list of options.\n");
1.2 misho 28367: return 1;
28368: }
1.4 misho 28369: data.cMode = data.mode;
1.2 misho 28370: }
1.6.2.1 ! misho 28371: #if SHELL_WIN_UTF8_OPT
! 28372: if( console_utf8 && stdin_is_interactive ){
! 28373: console_prepare();
! 28374: }else{
! 28375: setBinaryMode(stdin, 0);
! 28376: console_utf8 = 0;
! 28377: }
! 28378: #endif
1.2 misho 28379:
1.4 misho 28380: if( !readStdin ){
28381: /* Run all arguments that do not begin with '-' as if they were separate
28382: ** command-line inputs, except for the argToSkip argument which contains
28383: ** the database filename.
1.2 misho 28384: */
1.4 misho 28385: for(i=0; i<nCmd; i++){
28386: if( azCmd[i][0]=='.' ){
28387: rc = do_meta_command(azCmd[i], &data);
1.6 misho 28388: if( rc ){
28389: free(azCmd);
28390: return rc==2 ? 0 : rc;
28391: }
1.4 misho 28392: }else{
28393: open_db(&data, 0);
1.6.2.1 ! misho 28394: echo_group_input(&data, azCmd[i]);
1.5 misho 28395: rc = shell_exec(&data, azCmd[i], &zErrMsg);
1.6 misho 28396: if( zErrMsg || rc ){
28397: if( zErrMsg!=0 ){
28398: utf8_printf(stderr,"Error: %s\n", zErrMsg);
28399: }else{
28400: utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
28401: }
28402: sqlite3_free(zErrMsg);
28403: free(azCmd);
1.4 misho 28404: return rc!=0 ? rc : 1;
28405: }
1.2 misho 28406: }
28407: }
28408: }else{
28409: /* Run commands received from standard input
28410: */
28411: if( stdin_is_interactive ){
28412: char *zHome;
1.5 misho 28413: char *zHistory;
1.2 misho 28414: int nHistory;
28415: printf(
28416: "SQLite version %s %.19s\n" /*extra-version-info*/
1.4 misho 28417: "Enter \".help\" for usage hints.\n",
1.2 misho 28418: sqlite3_libversion(), sqlite3_sourceid()
28419: );
1.4 misho 28420: if( warnInmemoryDb ){
28421: printf("Connected to a ");
28422: printBold("transient in-memory database");
28423: printf(".\nUse \".open FILENAME\" to reopen on a "
28424: "persistent database.\n");
28425: }
1.5 misho 28426: zHistory = getenv("SQLITE_HISTORY");
28427: if( zHistory ){
28428: zHistory = strdup(zHistory);
28429: }else if( (zHome = find_home_dir(0))!=0 ){
1.2 misho 28430: nHistory = strlen30(zHome) + 20;
28431: if( (zHistory = malloc(nHistory))!=0 ){
28432: sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
28433: }
28434: }
1.4 misho 28435: if( zHistory ){ shell_read_history(zHistory); }
1.5 misho 28436: #if HAVE_READLINE || HAVE_EDITLINE
28437: rl_attempted_completion_function = readline_completion;
28438: #elif HAVE_LINENOISE
28439: linenoiseSetCompletionCallback(linenoise_completion);
28440: #endif
28441: data.in = 0;
28442: rc = process_input(&data);
1.2 misho 28443: if( zHistory ){
1.5 misho 28444: shell_stifle_history(2000);
1.4 misho 28445: shell_write_history(zHistory);
1.2 misho 28446: free(zHistory);
28447: }
28448: }else{
1.5 misho 28449: data.in = stdin;
28450: rc = process_input(&data);
1.2 misho 28451: }
28452: }
1.6.2.1 ! misho 28453: #ifndef SQLITE_SHELL_FIDDLE
! 28454: /* In WASM mode we have to leave the db state in place so that
! 28455: ** client code can "push" SQL into it after this call returns. */
1.6 misho 28456: free(azCmd);
1.2 misho 28457: set_table_name(&data, 0);
28458: if( data.db ){
1.6.2.1 ! misho 28459: session_close_all(&data, -1);
1.5 misho 28460: close_db(data.db);
1.2 misho 28461: }
1.6.2.1 ! misho 28462: for(i=0; i<ArraySize(data.aAuxDb); i++){
! 28463: sqlite3_free(data.aAuxDb[i].zFreeOnClose);
! 28464: if( data.aAuxDb[i].db ){
! 28465: session_close_all(&data, i);
! 28466: close_db(data.aAuxDb[i].db);
! 28467: }
! 28468: }
1.5 misho 28469: find_home_dir(1);
28470: output_reset(&data);
28471: data.doXdgOpen = 0;
28472: clearTempFile(&data);
1.4 misho 28473: #if !SQLITE_SHELL_IS_UTF8
1.5 misho 28474: for(i=0; i<argcToFree; i++) free(argvToFree[i]);
28475: free(argvToFree);
1.4 misho 28476: #endif
1.5 misho 28477: free(data.colWidth);
1.6.2.1 ! misho 28478: free(data.zNonce);
1.5 misho 28479: /* Clear the global data structure so that valgrind will detect memory
28480: ** leaks */
28481: memset(&data, 0, sizeof(data));
1.6.2.1 ! misho 28482: #ifdef SQLITE_DEBUG
! 28483: if( sqlite3_memory_used()>mem_main_enter ){
! 28484: utf8_printf(stderr, "Memory leaked: %u bytes\n",
! 28485: (unsigned int)(sqlite3_memory_used()-mem_main_enter));
! 28486: }
! 28487: #endif
! 28488: #endif /* !SQLITE_SHELL_FIDDLE */
! 28489: return rc;
! 28490: }
! 28491:
! 28492:
! 28493: #ifdef SQLITE_SHELL_FIDDLE
! 28494: /* Only for emcc experimentation purposes. */
! 28495: int fiddle_experiment(int a,int b){
! 28496: return a + b;
! 28497: }
! 28498:
! 28499: /*
! 28500: ** Returns a pointer to the current DB handle.
! 28501: */
! 28502: sqlite3 * fiddle_db_handle(){
! 28503: return globalDb;
! 28504: }
! 28505:
! 28506: /*
! 28507: ** Returns a pointer to the given DB name's VFS. If zDbName is 0 then
! 28508: ** "main" is assumed. Returns 0 if no db with the given name is
! 28509: ** open.
! 28510: */
! 28511: sqlite3_vfs * fiddle_db_vfs(const char *zDbName){
! 28512: sqlite3_vfs * pVfs = 0;
! 28513: if(globalDb){
! 28514: sqlite3_file_control(globalDb, zDbName ? zDbName : "main",
! 28515: SQLITE_FCNTL_VFS_POINTER, &pVfs);
! 28516: }
! 28517: return pVfs;
! 28518: }
! 28519:
! 28520: /* Only for emcc experimentation purposes. */
! 28521: sqlite3 * fiddle_db_arg(sqlite3 *arg){
! 28522: printf("fiddle_db_arg(%p)\n", (const void*)arg);
! 28523: return arg;
! 28524: }
! 28525:
! 28526: /*
! 28527: ** Intended to be called via a SharedWorker() while a separate
! 28528: ** SharedWorker() (which manages the wasm module) is performing work
! 28529: ** which should be interrupted. Unfortunately, SharedWorker is not
! 28530: ** portable enough to make real use of.
! 28531: */
! 28532: void fiddle_interrupt(void){
! 28533: if( globalDb ) sqlite3_interrupt(globalDb);
! 28534: }
! 28535:
! 28536: /*
! 28537: ** Returns the filename of the given db name, assuming "main" if
! 28538: ** zDbName is NULL. Returns NULL if globalDb is not opened.
! 28539: */
! 28540: const char * fiddle_db_filename(const char * zDbName){
! 28541: return globalDb
! 28542: ? sqlite3_db_filename(globalDb, zDbName ? zDbName : "main")
! 28543: : NULL;
! 28544: }
! 28545:
! 28546: /*
! 28547: ** Completely wipes out the contents of the currently-opened database
! 28548: ** but leaves its storage intact for reuse.
! 28549: */
! 28550: void fiddle_reset_db(void){
! 28551: if( globalDb ){
! 28552: int rc = sqlite3_db_config(globalDb, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
! 28553: if( 0==rc ) rc = sqlite3_exec(globalDb, "VACUUM", 0, 0, 0);
! 28554: sqlite3_db_config(globalDb, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
! 28555: }
! 28556: }
! 28557:
! 28558: /*
! 28559: ** Uses the current database's VFS xRead to stream the db file's
! 28560: ** contents out to the given callback. The callback gets a single
! 28561: ** chunk of size n (its 2nd argument) on each call and must return 0
! 28562: ** on success, non-0 on error. This function returns 0 on success,
! 28563: ** SQLITE_NOTFOUND if no db is open, or propagates any other non-0
! 28564: ** code from the callback. Note that this is not thread-friendly: it
! 28565: ** expects that it will be the only thread reading the db file and
! 28566: ** takes no measures to ensure that is the case.
! 28567: */
! 28568: int fiddle_export_db( int (*xCallback)(unsigned const char *zOut, int n) ){
! 28569: sqlite3_int64 nSize = 0;
! 28570: sqlite3_int64 nPos = 0;
! 28571: sqlite3_file * pFile = 0;
! 28572: unsigned char buf[1024 * 8];
! 28573: int nBuf = (int)sizeof(buf);
! 28574: int rc = shellState.db
! 28575: ? sqlite3_file_control(shellState.db, "main",
! 28576: SQLITE_FCNTL_FILE_POINTER, &pFile)
! 28577: : SQLITE_NOTFOUND;
! 28578: if( rc ) return rc;
! 28579: rc = pFile->pMethods->xFileSize(pFile, &nSize);
! 28580: if( rc ) return rc;
! 28581: if(nSize % nBuf){
! 28582: /* DB size is not an even multiple of the buffer size. Reduce
! 28583: ** buffer size so that we do not unduly inflate the db size when
! 28584: ** exporting. */
! 28585: if(0 == nSize % 4096) nBuf = 4096;
! 28586: else if(0 == nSize % 2048) nBuf = 2048;
! 28587: else if(0 == nSize % 1024) nBuf = 1024;
! 28588: else nBuf = 512;
! 28589: }
! 28590: for( ; 0==rc && nPos<nSize; nPos += nBuf ){
! 28591: rc = pFile->pMethods->xRead(pFile, buf, nBuf, nPos);
! 28592: if(SQLITE_IOERR_SHORT_READ == rc){
! 28593: rc = (nPos + nBuf) < nSize ? rc : 0/*assume EOF*/;
! 28594: }
! 28595: if( 0==rc ) rc = xCallback(buf, nBuf);
! 28596: }
1.2 misho 28597: return rc;
28598: }
1.6.2.1 ! misho 28599:
! 28600: /*
! 28601: ** Trivial exportable function for emscripten. It processes zSql as if
! 28602: ** it were input to the sqlite3 shell and redirects all output to the
! 28603: ** wasm binding. fiddle_main() must have been called before this
! 28604: ** is called, or results are undefined.
! 28605: */
! 28606: void fiddle_exec(const char * zSql){
! 28607: if(zSql && *zSql){
! 28608: if('.'==*zSql) puts(zSql);
! 28609: shellState.wasm.zInput = zSql;
! 28610: shellState.wasm.zPos = zSql;
! 28611: process_input(&shellState);
! 28612: shellState.wasm.zInput = shellState.wasm.zPos = 0;
! 28613: }
! 28614: }
! 28615: #endif /* SQLITE_SHELL_FIDDLE */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>