1322444Speter/* DO NOT EDIT!
2322444Speter** This file is automatically generated by the script in the canonical
3322444Speter** SQLite source tree at tool/mkshellc.tcl.  That script combines source
4322444Speter** code from various constituent source files of SQLite into this single
5322444Speter** "shell.c" file used to implement the SQLite command-line shell.
6322444Speter**
7322444Speter** Most of the code found below comes from the "src/shell.c.in" file in
8322444Speter** the canonical SQLite source tree.  That main file contains "INCLUDE"
9322444Speter** lines that specify other files in the canonical source tree that are
10322444Speter** inserted to getnerate this complete program source file.
11322444Speter**
12322444Speter** The code from multiple files is combined into this single "shell.c"
13322444Speter** source file to help make the command-line program easier to compile.
14322444Speter**
15322444Speter** To modify this program, get a copy of the canonical SQLite source tree,
16322444Speter** edit the src/shell.c.in" and/or some of the other files that are included
17322444Speter** by "src/shell.c.in", then rerun the tool/mkshellc.tcl script.
18322444Speter*/
19251883Speter/*
20251883Speter** 2001 September 15
21251883Speter**
22251883Speter** The author disclaims copyright to this source code.  In place of
23251883Speter** a legal notice, here is a blessing:
24251883Speter**
25251883Speter**    May you do good and not evil.
26251883Speter**    May you find forgiveness for yourself and forgive others.
27251883Speter**    May you share freely, never taking more than you give.
28251883Speter**
29251883Speter*************************************************************************
30251883Speter** This file contains code to implement the "sqlite" command line
31251883Speter** utility for accessing SQLite databases.
32251883Speter*/
33251883Speter#if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
34251883Speter/* This needs to come before any includes for MSVC compiler */
35251883Speter#define _CRT_SECURE_NO_WARNINGS
36251883Speter#endif
37251883Speter
38251883Speter/*
39362190Scy** Determine if we are dealing with WinRT, which provides only a subset of
40362190Scy** the full Win32 API.
41362190Scy*/
42362190Scy#if !defined(SQLITE_OS_WINRT)
43362190Scy# define SQLITE_OS_WINRT 0
44362190Scy#endif
45362190Scy
46362190Scy/*
47322444Speter** Warning pragmas copied from msvc.h in the core.
48282328Sbapt*/
49322444Speter#if defined(_MSC_VER)
50322444Speter#pragma warning(disable : 4054)
51322444Speter#pragma warning(disable : 4055)
52322444Speter#pragma warning(disable : 4100)
53322444Speter#pragma warning(disable : 4127)
54322444Speter#pragma warning(disable : 4130)
55322444Speter#pragma warning(disable : 4152)
56322444Speter#pragma warning(disable : 4189)
57322444Speter#pragma warning(disable : 4206)
58322444Speter#pragma warning(disable : 4210)
59322444Speter#pragma warning(disable : 4232)
60322444Speter#pragma warning(disable : 4244)
61322444Speter#pragma warning(disable : 4305)
62322444Speter#pragma warning(disable : 4306)
63322444Speter#pragma warning(disable : 4702)
64322444Speter#pragma warning(disable : 4706)
65322444Speter#endif /* defined(_MSC_VER) */
66282328Sbapt
67282328Sbapt/*
68282328Sbapt** No support for loadable extensions in VxWorks.
69282328Sbapt*/
70282328Sbapt#if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION
71282328Sbapt# define SQLITE_OMIT_LOAD_EXTENSION 1
72282328Sbapt#endif
73282328Sbapt
74282328Sbapt/*
75251883Speter** Enable large-file support for fopen() and friends on unix.
76251883Speter*/
77251883Speter#ifndef SQLITE_DISABLE_LFS
78251883Speter# define _LARGE_FILE       1
79251883Speter# ifndef _FILE_OFFSET_BITS
80251883Speter#   define _FILE_OFFSET_BITS 64
81251883Speter# endif
82251883Speter# define _LARGEFILE_SOURCE 1
83251883Speter#endif
84251883Speter
85251883Speter#include <stdlib.h>
86251883Speter#include <string.h>
87251883Speter#include <stdio.h>
88251883Speter#include <assert.h>
89251883Speter#include "sqlite3.h"
90342292Scytypedef sqlite3_int64 i64;
91342292Scytypedef sqlite3_uint64 u64;
92342292Scytypedef unsigned char u8;
93274884Sbapt#if SQLITE_USER_AUTHENTICATION
94274884Sbapt# include "sqlite3userauth.h"
95274884Sbapt#endif
96251883Speter#include <ctype.h>
97251883Speter#include <stdarg.h>
98251883Speter
99251883Speter#if !defined(_WIN32) && !defined(WIN32)
100251883Speter# include <signal.h>
101251883Speter# if !defined(__RTP__) && !defined(_WRS_KERNEL)
102251883Speter#  include <pwd.h>
103251883Speter# endif
104342292Scy#endif
105342292Scy#if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__)
106251883Speter# include <unistd.h>
107342292Scy# include <dirent.h>
108342292Scy# define GETPID getpid
109342292Scy# if defined(__MINGW32__)
110342292Scy#  define DIRENT dirent
111342292Scy#  ifndef S_ISLNK
112342292Scy#   define S_ISLNK(mode) (0)
113342292Scy#  endif
114342292Scy# endif
115342292Scy#else
116342292Scy# define GETPID (int)GetCurrentProcessId
117251883Speter#endif
118342292Scy#include <sys/types.h>
119342292Scy#include <sys/stat.h>
120251883Speter
121282328Sbapt#if HAVE_READLINE
122251883Speter# include <readline/readline.h>
123251883Speter# include <readline/history.h>
124251883Speter#endif
125282328Sbapt
126282328Sbapt#if HAVE_EDITLINE
127269851Speter# include <editline/readline.h>
128269851Speter#endif
129282328Sbapt
130282328Sbapt#if HAVE_EDITLINE || HAVE_READLINE
131282328Sbapt
132282328Sbapt# define shell_add_history(X) add_history(X)
133282328Sbapt# define shell_read_history(X) read_history(X)
134282328Sbapt# define shell_write_history(X) write_history(X)
135282328Sbapt# define shell_stifle_history(X) stifle_history(X)
136282328Sbapt# define shell_readline(X) readline(X)
137282328Sbapt
138282328Sbapt#elif HAVE_LINENOISE
139282328Sbapt
140282328Sbapt# include "linenoise.h"
141282328Sbapt# define shell_add_history(X) linenoiseHistoryAdd(X)
142282328Sbapt# define shell_read_history(X) linenoiseHistoryLoad(X)
143282328Sbapt# define shell_write_history(X) linenoiseHistorySave(X)
144282328Sbapt# define shell_stifle_history(X) linenoiseHistorySetMaxLen(X)
145282328Sbapt# define shell_readline(X) linenoise(X)
146282328Sbapt
147282328Sbapt#else
148282328Sbapt
149305002Scy# define shell_read_history(X)
150282328Sbapt# define shell_write_history(X)
151282328Sbapt# define shell_stifle_history(X)
152282328Sbapt
153282328Sbapt# define SHELL_USE_LOCAL_GETLINE 1
154251883Speter#endif
155251883Speter
156282328Sbapt
157251883Speter#if defined(_WIN32) || defined(WIN32)
158362190Scy# if SQLITE_OS_WINRT
159362190Scy#  define SQLITE_OMIT_POPEN 1
160362190Scy# else
161362190Scy#  include <io.h>
162362190Scy#  include <fcntl.h>
163362190Scy#  define isatty(h) _isatty(h)
164362190Scy#  ifndef access
165362190Scy#   define access(f,m) _access((f),(m))
166362190Scy#  endif
167362190Scy#  ifndef unlink
168362190Scy#   define unlink _unlink
169362190Scy#  endif
170362190Scy#  ifndef strdup
171362190Scy#   define strdup _strdup
172362190Scy#  endif
173362190Scy#  undef popen
174362190Scy#  define popen _popen
175362190Scy#  undef pclose
176362190Scy#  define pclose _pclose
177286510Speter# endif
178251883Speter#else
179286510Speter /* Make sure isatty() has a prototype. */
180286510Speter extern int isatty(int);
181269851Speter
182286510Speter# if !defined(__RTP__) && !defined(_WRS_KERNEL)
183286510Speter  /* popen and pclose are not C89 functions and so are
184286510Speter  ** sometimes omitted from the <stdio.h> header */
185286510Speter   extern FILE *popen(const char*,const char*);
186286510Speter   extern int pclose(FILE*);
187286510Speter# else
188286510Speter#  define SQLITE_OMIT_POPEN 1
189286510Speter# endif
190251883Speter#endif
191251883Speter
192251883Speter#if defined(_WIN32_WCE)
193251883Speter/* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty()
194251883Speter * thus we always assume that we have a console. That can be
195251883Speter * overridden with the -batch command line option.
196251883Speter */
197251883Speter#define isatty(x) 1
198251883Speter#endif
199251883Speter
200251883Speter/* ctype macros that work with signed characters */
201251883Speter#define IsSpace(X)  isspace((unsigned char)X)
202251883Speter#define IsDigit(X)  isdigit((unsigned char)X)
203251883Speter#define ToLower(X)  (char)tolower((unsigned char)X)
204251883Speter
205305002Scy#if defined(_WIN32) || defined(WIN32)
206362190Scy#if SQLITE_OS_WINRT
207362190Scy#include <intrin.h>
208362190Scy#endif
209305002Scy#include <windows.h>
210305002Scy
211305002Scy/* string conversion routines only needed on Win32 */
212305002Scyextern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
213305002Scyextern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int);
214305002Scyextern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int);
215322444Speterextern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
216305002Scy#endif
217305002Scy
218282328Sbapt/* On Windows, we normally run with output mode of TEXT so that \n characters
219282328Sbapt** are automatically translated into \r\n.  However, this behavior needs
220282328Sbapt** to be disabled in some cases (ex: when generating CSV output and when
221282328Sbapt** rendering quoted strings that contain \n characters).  The following
222282328Sbapt** routines take care of that.
223282328Sbapt*/
224362190Scy#if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
225305002Scystatic void setBinaryMode(FILE *file, int isOutput){
226305002Scy  if( isOutput ) fflush(file);
227305002Scy  _setmode(_fileno(file), _O_BINARY);
228282328Sbapt}
229305002Scystatic void setTextMode(FILE *file, int isOutput){
230305002Scy  if( isOutput ) fflush(file);
231305002Scy  _setmode(_fileno(file), _O_TEXT);
232282328Sbapt}
233282328Sbapt#else
234305002Scy# define setBinaryMode(X,Y)
235305002Scy# define setTextMode(X,Y)
236282328Sbapt#endif
237269851Speter
238282328Sbapt
239269851Speter/* True if the timer is enabled */
240269851Speterstatic int enableTimer = 0;
241269851Speter
242269851Speter/* Return the current wall-clock time */
243269851Speterstatic sqlite3_int64 timeOfDay(void){
244269851Speter  static sqlite3_vfs *clockVfs = 0;
245269851Speter  sqlite3_int64 t;
246269851Speter  if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
247298161Sbapt  if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
248269851Speter    clockVfs->xCurrentTimeInt64(clockVfs, &t);
249269851Speter  }else{
250269851Speter    double r;
251269851Speter    clockVfs->xCurrentTime(clockVfs, &r);
252269851Speter    t = (sqlite3_int64)(r*86400000.0);
253269851Speter  }
254269851Speter  return t;
255269851Speter}
256269851Speter
257282328Sbapt#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
258251883Speter#include <sys/time.h>
259251883Speter#include <sys/resource.h>
260251883Speter
261282328Sbapt/* VxWorks does not support getrusage() as far as we can determine */
262282328Sbapt#if defined(_WRS_KERNEL) || defined(__RTP__)
263282328Sbaptstruct rusage {
264282328Sbapt  struct timeval ru_utime; /* user CPU time used */
265282328Sbapt  struct timeval ru_stime; /* system CPU time used */
266282328Sbapt};
267282328Sbapt#define getrusage(A,B) memset(B,0,sizeof(*B))
268282328Sbapt#endif
269282328Sbapt
270251883Speter/* Saved resource information for the beginning of an operation */
271269851Speterstatic struct rusage sBegin;  /* CPU time at start */
272269851Speterstatic sqlite3_int64 iBegin;  /* Wall-clock time at start */
273251883Speter
274251883Speter/*
275251883Speter** Begin timing an operation
276251883Speter*/
277251883Speterstatic void beginTimer(void){
278251883Speter  if( enableTimer ){
279251883Speter    getrusage(RUSAGE_SELF, &sBegin);
280269851Speter    iBegin = timeOfDay();
281251883Speter  }
282251883Speter}
283251883Speter
284251883Speter/* Return the difference of two time_structs in seconds */
285251883Speterstatic double timeDiff(struct timeval *pStart, struct timeval *pEnd){
286305002Scy  return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
287251883Speter         (double)(pEnd->tv_sec - pStart->tv_sec);
288251883Speter}
289251883Speter
290251883Speter/*
291251883Speter** Print the timing results.
292251883Speter*/
293251883Speterstatic void endTimer(void){
294251883Speter  if( enableTimer ){
295282328Sbapt    sqlite3_int64 iEnd = timeOfDay();
296251883Speter    struct rusage sEnd;
297251883Speter    getrusage(RUSAGE_SELF, &sEnd);
298269851Speter    printf("Run Time: real %.3f user %f sys %f\n",
299269851Speter       (iEnd - iBegin)*0.001,
300251883Speter       timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
301251883Speter       timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
302251883Speter  }
303251883Speter}
304251883Speter
305251883Speter#define BEGIN_TIMER beginTimer()
306251883Speter#define END_TIMER endTimer()
307251883Speter#define HAS_TIMER 1
308251883Speter
309251883Speter#elif (defined(_WIN32) || defined(WIN32))
310251883Speter
311251883Speter/* Saved resource information for the beginning of an operation */
312251883Speterstatic HANDLE hProcess;
313251883Speterstatic FILETIME ftKernelBegin;
314251883Speterstatic FILETIME ftUserBegin;
315269851Speterstatic sqlite3_int64 ftWallBegin;
316282328Sbapttypedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
317282328Sbapt                                    LPFILETIME, LPFILETIME);
318251883Speterstatic GETPROCTIMES getProcessTimesAddr = NULL;
319251883Speter
320251883Speter/*
321251883Speter** Check to see if we have timer support.  Return 1 if necessary
322251883Speter** support found (or found previously).
323251883Speter*/
324251883Speterstatic int hasTimer(void){
325251883Speter  if( getProcessTimesAddr ){
326251883Speter    return 1;
327251883Speter  } else {
328362190Scy#if !SQLITE_OS_WINRT
329282328Sbapt    /* GetProcessTimes() isn't supported in WIN95 and some other Windows
330282328Sbapt    ** versions. See if the version we are running on has it, and if it
331282328Sbapt    ** does, save off a pointer to it and the current process handle.
332251883Speter    */
333251883Speter    hProcess = GetCurrentProcess();
334251883Speter    if( hProcess ){
335251883Speter      HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
336251883Speter      if( NULL != hinstLib ){
337282328Sbapt        getProcessTimesAddr =
338282328Sbapt            (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
339251883Speter        if( NULL != getProcessTimesAddr ){
340251883Speter          return 1;
341251883Speter        }
342305002Scy        FreeLibrary(hinstLib);
343251883Speter      }
344251883Speter    }
345362190Scy#endif
346251883Speter  }
347251883Speter  return 0;
348251883Speter}
349251883Speter
350251883Speter/*
351251883Speter** Begin timing an operation
352251883Speter*/
353251883Speterstatic void beginTimer(void){
354251883Speter  if( enableTimer && getProcessTimesAddr ){
355251883Speter    FILETIME ftCreation, ftExit;
356282328Sbapt    getProcessTimesAddr(hProcess,&ftCreation,&ftExit,
357282328Sbapt                        &ftKernelBegin,&ftUserBegin);
358269851Speter    ftWallBegin = timeOfDay();
359251883Speter  }
360251883Speter}
361251883Speter
362251883Speter/* Return the difference of two FILETIME structs in seconds */
363251883Speterstatic double timeDiff(FILETIME *pStart, FILETIME *pEnd){
364251883Speter  sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
365251883Speter  sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
366251883Speter  return (double) ((i64End - i64Start) / 10000000.0);
367251883Speter}
368251883Speter
369251883Speter/*
370251883Speter** Print the timing results.
371251883Speter*/
372251883Speterstatic void endTimer(void){
373251883Speter  if( enableTimer && getProcessTimesAddr){
374251883Speter    FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
375269851Speter    sqlite3_int64 ftWallEnd = timeOfDay();
376282328Sbapt    getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
377269851Speter    printf("Run Time: real %.3f user %f sys %f\n",
378269851Speter       (ftWallEnd - ftWallBegin)*0.001,
379251883Speter       timeDiff(&ftUserBegin, &ftUserEnd),
380251883Speter       timeDiff(&ftKernelBegin, &ftKernelEnd));
381251883Speter  }
382251883Speter}
383251883Speter
384251883Speter#define BEGIN_TIMER beginTimer()
385251883Speter#define END_TIMER endTimer()
386251883Speter#define HAS_TIMER hasTimer()
387251883Speter
388251883Speter#else
389305002Scy#define BEGIN_TIMER
390251883Speter#define END_TIMER
391251883Speter#define HAS_TIMER 0
392251883Speter#endif
393251883Speter
394251883Speter/*
395251883Speter** Used to prevent warnings about unused parameters
396251883Speter*/
397251883Speter#define UNUSED_PARAMETER(x) (void)(x)
398251883Speter
399251883Speter/*
400342292Scy** Number of elements in an array
401342292Scy*/
402342292Scy#define ArraySize(X)  (int)(sizeof(X)/sizeof(X[0]))
403342292Scy
404342292Scy/*
405251883Speter** If the following flag is set, then command execution stops
406251883Speter** at an error if we are not interactive.
407251883Speter*/
408251883Speterstatic int bail_on_error = 0;
409251883Speter
410251883Speter/*
411251883Speter** Threat stdin as an interactive input if the following variable
412251883Speter** is true.  Otherwise, assume stdin is connected to a file or pipe.
413251883Speter*/
414251883Speterstatic int stdin_is_interactive = 1;
415251883Speter
416251883Speter/*
417298161Sbapt** On Windows systems we have to know if standard output is a console
418298161Sbapt** in order to translate UTF-8 into MBCS.  The following variable is
419298161Sbapt** true if translation is required.
420298161Sbapt*/
421298161Sbaptstatic int stdout_is_console = 1;
422298161Sbapt
423298161Sbapt/*
424251883Speter** The following is the open SQLite database.  We make a pointer
425251883Speter** to this database a static variable so that it can be accessed
426251883Speter** by the SIGINT handler to interrupt database processing.
427251883Speter*/
428286510Speterstatic sqlite3 *globalDb = 0;
429251883Speter
430251883Speter/*
431251883Speter** True if an interrupt (Control-C) has been received.
432251883Speter*/
433251883Speterstatic volatile int seenInterrupt = 0;
434251883Speter
435362190Scy#ifdef SQLITE_DEBUG
436251883Speter/*
437362190Scy** Out-of-memory simulator variables
438362190Scy*/
439362190Scystatic unsigned int oomCounter = 0;    /* Simulate OOM when equals 1 */
440362190Scystatic unsigned int oomRepeat = 0;     /* Number of OOMs in a row */
441362190Scystatic void*(*defaultMalloc)(int) = 0; /* The low-level malloc routine */
442362190Scy#endif /* SQLITE_DEBUG */
443362190Scy
444362190Scy/*
445251883Speter** This is the name of our program. It is set in main(), used
446251883Speter** in a number of other places, mostly for error messages.
447251883Speter*/
448251883Speterstatic char *Argv0;
449251883Speter
450251883Speter/*
451251883Speter** Prompt strings. Initialized in main. Settable with
452251883Speter**   .prompt main continue
453251883Speter*/
454251883Speterstatic char mainPrompt[20];     /* First line prompt. default: "sqlite> "*/
455251883Speterstatic char continuePrompt[20]; /* Continuation prompt. default: "   ...> " */
456251883Speter
457251883Speter/*
458305002Scy** Render output like fprintf().  Except, if the output is going to the
459305002Scy** console and if this is running on a Windows machine, translate the
460305002Scy** output from UTF-8 into MBCS.
461305002Scy*/
462305002Scy#if defined(_WIN32) || defined(WIN32)
463305002Scyvoid utf8_printf(FILE *out, const char *zFormat, ...){
464305002Scy  va_list ap;
465305002Scy  va_start(ap, zFormat);
466305002Scy  if( stdout_is_console && (out==stdout || out==stderr) ){
467305002Scy    char *z1 = sqlite3_vmprintf(zFormat, ap);
468305002Scy    char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0);
469305002Scy    sqlite3_free(z1);
470305002Scy    fputs(z2, out);
471305002Scy    sqlite3_free(z2);
472305002Scy  }else{
473305002Scy    vfprintf(out, zFormat, ap);
474305002Scy  }
475305002Scy  va_end(ap);
476305002Scy}
477305002Scy#elif !defined(utf8_printf)
478305002Scy# define utf8_printf fprintf
479305002Scy#endif
480305002Scy
481305002Scy/*
482305002Scy** Render output like fprintf().  This should not be used on anything that
483305002Scy** includes string formatting (e.g. "%s").
484305002Scy*/
485305002Scy#if !defined(raw_printf)
486305002Scy# define raw_printf fprintf
487305002Scy#endif
488305002Scy
489342292Scy/* Indicate out-of-memory and exit. */
490342292Scystatic void shell_out_of_memory(void){
491342292Scy  raw_printf(stderr,"Error: out of memory\n");
492342292Scy  exit(1);
493342292Scy}
494342292Scy
495362190Scy#ifdef SQLITE_DEBUG
496362190Scy/* This routine is called when a simulated OOM occurs.  It is broken
497362190Scy** out as a separate routine to make it easy to set a breakpoint on
498362190Scy** the OOM
499362190Scy*/
500362190Scyvoid shellOomFault(void){
501362190Scy  if( oomRepeat>0 ){
502362190Scy    oomRepeat--;
503362190Scy  }else{
504362190Scy    oomCounter--;
505362190Scy  }
506362190Scy}
507362190Scy#endif /* SQLITE_DEBUG */
508362190Scy
509362190Scy#ifdef SQLITE_DEBUG
510362190Scy/* This routine is a replacement malloc() that is used to simulate
511362190Scy** Out-Of-Memory (OOM) errors for testing purposes.
512362190Scy*/
513362190Scystatic void *oomMalloc(int nByte){
514362190Scy  if( oomCounter ){
515362190Scy    if( oomCounter==1 ){
516362190Scy      shellOomFault();
517362190Scy      return 0;
518362190Scy    }else{
519362190Scy      oomCounter--;
520362190Scy    }
521362190Scy  }
522362190Scy  return defaultMalloc(nByte);
523362190Scy}
524362190Scy#endif /* SQLITE_DEBUG */
525362190Scy
526362190Scy#ifdef SQLITE_DEBUG
527362190Scy/* Register the OOM simulator.  This must occur before any memory
528362190Scy** allocations */
529362190Scystatic void registerOomSimulator(void){
530362190Scy  sqlite3_mem_methods mem;
531362190Scy  sqlite3_config(SQLITE_CONFIG_GETMALLOC, &mem);
532362190Scy  defaultMalloc = mem.xMalloc;
533362190Scy  mem.xMalloc = oomMalloc;
534362190Scy  sqlite3_config(SQLITE_CONFIG_MALLOC, &mem);
535362190Scy}
536362190Scy#endif
537362190Scy
538305002Scy/*
539251883Speter** Write I/O traces to the following stream.
540251883Speter*/
541251883Speter#ifdef SQLITE_ENABLE_IOTRACE
542251883Speterstatic FILE *iotrace = 0;
543251883Speter#endif
544251883Speter
545251883Speter/*
546251883Speter** This routine works like printf in that its first argument is a
547251883Speter** format string and subsequent arguments are values to be substituted
548251883Speter** in place of % fields.  The result of formatting this string
549251883Speter** is written to iotrace.
550251883Speter*/
551251883Speter#ifdef SQLITE_ENABLE_IOTRACE
552282328Sbaptstatic void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
553251883Speter  va_list ap;
554251883Speter  char *z;
555251883Speter  if( iotrace==0 ) return;
556251883Speter  va_start(ap, zFormat);
557251883Speter  z = sqlite3_vmprintf(zFormat, ap);
558251883Speter  va_end(ap);
559305002Scy  utf8_printf(iotrace, "%s", z);
560251883Speter  sqlite3_free(z);
561251883Speter}
562251883Speter#endif
563251883Speter
564322444Speter/*
565322444Speter** Output string zUtf to stream pOut as w characters.  If w is negative,
566322444Speter** then right-justify the text.  W is the width in UTF-8 characters, not
567322444Speter** in bytes.  This is different from the %*.*s specification in printf
568322444Speter** since with %*.*s the width is measured in bytes, not characters.
569322444Speter*/
570322444Speterstatic void utf8_width_print(FILE *pOut, int w, const char *zUtf){
571322444Speter  int i;
572322444Speter  int n;
573322444Speter  int aw = w<0 ? -w : w;
574322444Speter  for(i=n=0; zUtf[i]; i++){
575322444Speter    if( (zUtf[i]&0xc0)!=0x80 ){
576322444Speter      n++;
577322444Speter      if( n==aw ){
578322444Speter        do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
579322444Speter        break;
580322444Speter      }
581322444Speter    }
582322444Speter  }
583322444Speter  if( n>=aw ){
584322444Speter    utf8_printf(pOut, "%.*s", i, zUtf);
585322444Speter  }else if( w<0 ){
586322444Speter    utf8_printf(pOut, "%*s%s", aw-n, "", zUtf);
587322444Speter  }else{
588322444Speter    utf8_printf(pOut, "%s%*s", zUtf, aw-n, "");
589322444Speter  }
590322444Speter}
591251883Speter
592322444Speter
593251883Speter/*
594251883Speter** Determines if a string is a number of not.
595251883Speter*/
596251883Speterstatic int isNumber(const char *z, int *realnum){
597251883Speter  if( *z=='-' || *z=='+' ) z++;
598251883Speter  if( !IsDigit(*z) ){
599251883Speter    return 0;
600251883Speter  }
601251883Speter  z++;
602251883Speter  if( realnum ) *realnum = 0;
603251883Speter  while( IsDigit(*z) ){ z++; }
604251883Speter  if( *z=='.' ){
605251883Speter    z++;
606251883Speter    if( !IsDigit(*z) ) return 0;
607251883Speter    while( IsDigit(*z) ){ z++; }
608251883Speter    if( realnum ) *realnum = 1;
609251883Speter  }
610251883Speter  if( *z=='e' || *z=='E' ){
611251883Speter    z++;
612251883Speter    if( *z=='+' || *z=='-' ) z++;
613251883Speter    if( !IsDigit(*z) ) return 0;
614251883Speter    while( IsDigit(*z) ){ z++; }
615251883Speter    if( realnum ) *realnum = 1;
616251883Speter  }
617251883Speter  return *z==0;
618251883Speter}
619251883Speter
620251883Speter/*
621298161Sbapt** Compute a string length that is limited to what can be stored in
622298161Sbapt** lower 30 bits of a 32-bit signed integer.
623298161Sbapt*/
624298161Sbaptstatic int strlen30(const char *z){
625298161Sbapt  const char *z2 = z;
626298161Sbapt  while( *z2 ){ z2++; }
627298161Sbapt  return 0x3fffffff & (int)(z2 - z);
628298161Sbapt}
629298161Sbapt
630298161Sbapt/*
631322444Speter** Return the length of a string in characters.  Multibyte UTF8 characters
632322444Speter** count as a single character.
633322444Speter*/
634322444Speterstatic int strlenChar(const char *z){
635322444Speter  int n = 0;
636322444Speter  while( *z ){
637322444Speter    if( (0xc0&*(z++))!=0x80 ) n++;
638322444Speter  }
639322444Speter  return n;
640322444Speter}
641322444Speter
642322444Speter/*
643366076Scy** Return true if zFile does not exist or if it is not an ordinary file.
644366076Scy*/
645366076Scy#ifdef _WIN32
646366076Scy# define notNormalFile(X) 0
647366076Scy#else
648366076Scystatic int notNormalFile(const char *zFile){
649366076Scy  struct stat x;
650366076Scy  int rc;
651366076Scy  memset(&x, 0, sizeof(x));
652366076Scy  rc = stat(zFile, &x);
653366076Scy  return rc || !S_ISREG(x.st_mode);
654366076Scy}
655366076Scy#endif
656366076Scy
657366076Scy/*
658251883Speter** This routine reads a line of text from FILE in, stores
659251883Speter** the text in memory obtained from malloc() and returns a pointer
660251883Speter** to the text.  NULL is returned at end of file, or if malloc()
661251883Speter** fails.
662251883Speter**
663269851Speter** If zLine is not NULL then it is a malloced buffer returned from
664269851Speter** a previous call to this routine that may be reused.
665251883Speter*/
666269851Speterstatic char *local_getline(char *zLine, FILE *in){
667269851Speter  int nLine = zLine==0 ? 0 : 100;
668269851Speter  int n = 0;
669251883Speter
670251883Speter  while( 1 ){
671251883Speter    if( n+100>nLine ){
672251883Speter      nLine = nLine*2 + 100;
673251883Speter      zLine = realloc(zLine, nLine);
674342292Scy      if( zLine==0 ) shell_out_of_memory();
675251883Speter    }
676251883Speter    if( fgets(&zLine[n], nLine - n, in)==0 ){
677251883Speter      if( n==0 ){
678251883Speter        free(zLine);
679251883Speter        return 0;
680251883Speter      }
681251883Speter      zLine[n] = 0;
682251883Speter      break;
683251883Speter    }
684269851Speter    while( zLine[n] ) n++;
685269851Speter    if( n>0 && zLine[n-1]=='\n' ){
686251883Speter      n--;
687251883Speter      if( n>0 && zLine[n-1]=='\r' ) n--;
688251883Speter      zLine[n] = 0;
689251883Speter      break;
690251883Speter    }
691251883Speter  }
692298161Sbapt#if defined(_WIN32) || defined(WIN32)
693305002Scy  /* For interactive input on Windows systems, translate the
694298161Sbapt  ** multi-byte characterset characters into UTF-8. */
695322444Speter  if( stdin_is_interactive && in==stdin ){
696305002Scy    char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
697298161Sbapt    if( zTrans ){
698298161Sbapt      int nTrans = strlen30(zTrans)+1;
699298161Sbapt      if( nTrans>nLine ){
700298161Sbapt        zLine = realloc(zLine, nTrans);
701342292Scy        if( zLine==0 ) shell_out_of_memory();
702298161Sbapt      }
703298161Sbapt      memcpy(zLine, zTrans, nTrans);
704298161Sbapt      sqlite3_free(zTrans);
705298161Sbapt    }
706298161Sbapt  }
707298161Sbapt#endif /* defined(_WIN32) || defined(WIN32) */
708251883Speter  return zLine;
709251883Speter}
710251883Speter
711251883Speter/*
712251883Speter** Retrieve a single line of input text.
713251883Speter**
714269851Speter** If in==0 then read from standard input and prompt before each line.
715269851Speter** If isContinuation is true, then a continuation prompt is appropriate.
716269851Speter** If isContinuation is zero, then the main prompt should be used.
717269851Speter**
718269851Speter** If zPrior is not NULL then it is a buffer from a prior call to this
719269851Speter** routine that can be reused.
720269851Speter**
721269851Speter** The result is stored in space obtained from malloc() and must either
722269851Speter** be freed by the caller or else passed back into this routine via the
723269851Speter** zPrior argument for reuse.
724251883Speter*/
725269851Speterstatic char *one_input_line(FILE *in, char *zPrior, int isContinuation){
726251883Speter  char *zPrompt;
727251883Speter  char *zResult;
728251883Speter  if( in!=0 ){
729269851Speter    zResult = local_getline(zPrior, in);
730251883Speter  }else{
731269851Speter    zPrompt = isContinuation ? continuePrompt : mainPrompt;
732282328Sbapt#if SHELL_USE_LOCAL_GETLINE
733269851Speter    printf("%s", zPrompt);
734269851Speter    fflush(stdout);
735269851Speter    zResult = local_getline(zPrior, stdin);
736282328Sbapt#else
737282328Sbapt    free(zPrior);
738282328Sbapt    zResult = shell_readline(zPrompt);
739282328Sbapt    if( zResult && *zResult ) shell_add_history(zResult);
740269851Speter#endif
741251883Speter  }
742251883Speter  return zResult;
743251883Speter}
744342292Scy
745342292Scy
746322444Speter/*
747342292Scy** Return the value of a hexadecimal digit.  Return -1 if the input
748342292Scy** is not a hex digit.
749342292Scy*/
750342292Scystatic int hexDigitValue(char c){
751342292Scy  if( c>='0' && c<='9' ) return c - '0';
752342292Scy  if( c>='a' && c<='f' ) return c - 'a' + 10;
753342292Scy  if( c>='A' && c<='F' ) return c - 'A' + 10;
754342292Scy  return -1;
755342292Scy}
756342292Scy
757342292Scy/*
758342292Scy** Interpret zArg as an integer value, possibly with suffixes.
759342292Scy*/
760342292Scystatic sqlite3_int64 integerValue(const char *zArg){
761342292Scy  sqlite3_int64 v = 0;
762342292Scy  static const struct { char *zSuffix; int iMult; } aMult[] = {
763342292Scy    { "KiB", 1024 },
764342292Scy    { "MiB", 1024*1024 },
765342292Scy    { "GiB", 1024*1024*1024 },
766342292Scy    { "KB",  1000 },
767342292Scy    { "MB",  1000000 },
768342292Scy    { "GB",  1000000000 },
769342292Scy    { "K",   1000 },
770342292Scy    { "M",   1000000 },
771342292Scy    { "G",   1000000000 },
772342292Scy  };
773342292Scy  int i;
774342292Scy  int isNeg = 0;
775342292Scy  if( zArg[0]=='-' ){
776342292Scy    isNeg = 1;
777342292Scy    zArg++;
778342292Scy  }else if( zArg[0]=='+' ){
779342292Scy    zArg++;
780342292Scy  }
781342292Scy  if( zArg[0]=='0' && zArg[1]=='x' ){
782342292Scy    int x;
783342292Scy    zArg += 2;
784342292Scy    while( (x = hexDigitValue(zArg[0]))>=0 ){
785342292Scy      v = (v<<4) + x;
786342292Scy      zArg++;
787342292Scy    }
788342292Scy  }else{
789342292Scy    while( IsDigit(zArg[0]) ){
790342292Scy      v = v*10 + zArg[0] - '0';
791342292Scy      zArg++;
792342292Scy    }
793342292Scy  }
794342292Scy  for(i=0; i<ArraySize(aMult); i++){
795342292Scy    if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
796342292Scy      v *= aMult[i].iMult;
797342292Scy      break;
798342292Scy    }
799342292Scy  }
800342292Scy  return isNeg? -v : v;
801342292Scy}
802342292Scy
803342292Scy/*
804322444Speter** A variable length string to which one can append text.
805322444Speter*/
806322444Spetertypedef struct ShellText ShellText;
807322444Speterstruct ShellText {
808322444Speter  char *z;
809322444Speter  int n;
810322444Speter  int nAlloc;
811322444Speter};
812251883Speter
813322444Speter/*
814322444Speter** Initialize and destroy a ShellText object
815322444Speter*/
816322444Speterstatic void initText(ShellText *p){
817322444Speter  memset(p, 0, sizeof(*p));
818322444Speter}
819322444Speterstatic void freeText(ShellText *p){
820322444Speter  free(p->z);
821322444Speter  initText(p);
822322444Speter}
823322444Speter
824322444Speter/* zIn is either a pointer to a NULL-terminated string in memory obtained
825322444Speter** from malloc(), or a NULL pointer. The string pointed to by zAppend is
826322444Speter** added to zIn, and the result returned in memory obtained from malloc().
827322444Speter** zIn, if it was not NULL, is freed.
828322444Speter**
829322444Speter** If the third argument, quote, is not '\0', then it is used as a
830322444Speter** quote character for zAppend.
831322444Speter*/
832322444Speterstatic void appendText(ShellText *p, char const *zAppend, char quote){
833322444Speter  int len;
834322444Speter  int i;
835322444Speter  int nAppend = strlen30(zAppend);
836322444Speter
837322444Speter  len = nAppend+p->n+1;
838322444Speter  if( quote ){
839322444Speter    len += 2;
840322444Speter    for(i=0; i<nAppend; i++){
841322444Speter      if( zAppend[i]==quote ) len++;
842322444Speter    }
843322444Speter  }
844322444Speter
845322444Speter  if( p->n+len>=p->nAlloc ){
846322444Speter    p->nAlloc = p->nAlloc*2 + len + 20;
847322444Speter    p->z = realloc(p->z, p->nAlloc);
848342292Scy    if( p->z==0 ) shell_out_of_memory();
849322444Speter  }
850322444Speter
851322444Speter  if( quote ){
852322444Speter    char *zCsr = p->z+p->n;
853322444Speter    *zCsr++ = quote;
854322444Speter    for(i=0; i<nAppend; i++){
855322444Speter      *zCsr++ = zAppend[i];
856322444Speter      if( zAppend[i]==quote ) *zCsr++ = quote;
857322444Speter    }
858322444Speter    *zCsr++ = quote;
859322444Speter    p->n = (int)(zCsr - p->z);
860322444Speter    *zCsr = '\0';
861322444Speter  }else{
862322444Speter    memcpy(p->z+p->n, zAppend, nAppend);
863322444Speter    p->n += nAppend;
864322444Speter    p->z[p->n] = '\0';
865322444Speter  }
866322444Speter}
867322444Speter
868322444Speter/*
869322444Speter** Attempt to determine if identifier zName needs to be quoted, either
870322444Speter** because it contains non-alphanumeric characters, or because it is an
871322444Speter** SQLite keyword.  Be conservative in this estimate:  When in doubt assume
872322444Speter** that quoting is required.
873322444Speter**
874322444Speter** Return '"' if quoting is required.  Return 0 if no quoting is required.
875322444Speter*/
876322444Speterstatic char quoteChar(const char *zName){
877342292Scy  int i;
878322444Speter  if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
879322444Speter  for(i=0; zName[i]; i++){
880322444Speter    if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
881322444Speter  }
882342292Scy  return sqlite3_keyword_check(zName, i) ? '"' : 0;
883342292Scy}
884342292Scy
885342292Scy/*
886342292Scy** Construct a fake object name and column list to describe the structure
887342292Scy** of the view, virtual table, or table valued function zSchema.zName.
888342292Scy*/
889342292Scystatic char *shellFakeSchema(
890342292Scy  sqlite3 *db,            /* The database connection containing the vtab */
891342292Scy  const char *zSchema,    /* Schema of the database holding the vtab */
892342292Scy  const char *zName       /* The name of the virtual table */
893342292Scy){
894342292Scy  sqlite3_stmt *pStmt = 0;
895342292Scy  char *zSql;
896342292Scy  ShellText s;
897342292Scy  char cQuote;
898342292Scy  char *zDiv = "(";
899342292Scy  int nRow = 0;
900342292Scy
901342292Scy  zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
902342292Scy                         zSchema ? zSchema : "main", zName);
903342292Scy  sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
904342292Scy  sqlite3_free(zSql);
905342292Scy  initText(&s);
906342292Scy  if( zSchema ){
907342292Scy    cQuote = quoteChar(zSchema);
908342292Scy    if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0;
909342292Scy    appendText(&s, zSchema, cQuote);
910342292Scy    appendText(&s, ".", 0);
911322444Speter  }
912342292Scy  cQuote = quoteChar(zName);
913342292Scy  appendText(&s, zName, cQuote);
914342292Scy  while( sqlite3_step(pStmt)==SQLITE_ROW ){
915342292Scy    const char *zCol = (const char*)sqlite3_column_text(pStmt, 1);
916342292Scy    nRow++;
917342292Scy    appendText(&s, zDiv, 0);
918342292Scy    zDiv = ",";
919342292Scy    cQuote = quoteChar(zCol);
920342292Scy    appendText(&s, zCol, cQuote);
921342292Scy  }
922342292Scy  appendText(&s, ")", 0);
923342292Scy  sqlite3_finalize(pStmt);
924342292Scy  if( nRow==0 ){
925342292Scy    freeText(&s);
926342292Scy    s.z = 0;
927342292Scy  }
928342292Scy  return s.z;
929322444Speter}
930322444Speter
931322444Speter/*
932342292Scy** SQL function:  shell_module_schema(X)
933342292Scy**
934342292Scy** Return a fake schema for the table-valued function or eponymous virtual
935342292Scy** table X.
936342292Scy*/
937342292Scystatic void shellModuleSchema(
938342292Scy  sqlite3_context *pCtx,
939342292Scy  int nVal,
940342292Scy  sqlite3_value **apVal
941342292Scy){
942342292Scy  const char *zName = (const char*)sqlite3_value_text(apVal[0]);
943342292Scy  char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName);
944342292Scy  UNUSED_PARAMETER(nVal);
945342292Scy  if( zFake ){
946342292Scy    sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
947342292Scy                        -1, sqlite3_free);
948342292Scy    free(zFake);
949342292Scy  }
950342292Scy}
951342292Scy
952342292Scy/*
953322444Speter** SQL function:  shell_add_schema(S,X)
954322444Speter**
955322444Speter** Add the schema name X to the CREATE statement in S and return the result.
956322444Speter** Examples:
957322444Speter**
958322444Speter**    CREATE TABLE t1(x)   ->   CREATE TABLE xyz.t1(x);
959322444Speter**
960322444Speter** Also works on
961322444Speter**
962322444Speter**    CREATE INDEX
963322444Speter**    CREATE UNIQUE INDEX
964322444Speter**    CREATE VIEW
965322444Speter**    CREATE TRIGGER
966322444Speter**    CREATE VIRTUAL TABLE
967322444Speter**
968322444Speter** This UDF is used by the .schema command to insert the schema name of
969366076Scy** attached databases into the middle of the sqlite_schema.sql field.
970322444Speter*/
971322444Speterstatic void shellAddSchemaName(
972322444Speter  sqlite3_context *pCtx,
973322444Speter  int nVal,
974322444Speter  sqlite3_value **apVal
975322444Speter){
976322444Speter  static const char *aPrefix[] = {
977322444Speter     "TABLE",
978322444Speter     "INDEX",
979322444Speter     "UNIQUE INDEX",
980322444Speter     "VIEW",
981322444Speter     "TRIGGER",
982322444Speter     "VIRTUAL TABLE"
983322444Speter  };
984322444Speter  int i = 0;
985322444Speter  const char *zIn = (const char*)sqlite3_value_text(apVal[0]);
986322444Speter  const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
987342292Scy  const char *zName = (const char*)sqlite3_value_text(apVal[2]);
988342292Scy  sqlite3 *db = sqlite3_context_db_handle(pCtx);
989342292Scy  UNUSED_PARAMETER(nVal);
990322444Speter  if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
991322444Speter    for(i=0; i<(int)(sizeof(aPrefix)/sizeof(aPrefix[0])); i++){
992322444Speter      int n = strlen30(aPrefix[i]);
993322444Speter      if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
994342292Scy        char *z = 0;
995342292Scy        char *zFake = 0;
996342292Scy        if( zSchema ){
997342292Scy          char cQuote = quoteChar(zSchema);
998342292Scy          if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){
999342292Scy            z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8);
1000342292Scy          }else{
1001342292Scy            z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8);
1002342292Scy          }
1003322444Speter        }
1004342292Scy        if( zName
1005342292Scy         && aPrefix[i][0]=='V'
1006342292Scy         && (zFake = shellFakeSchema(db, zSchema, zName))!=0
1007342292Scy        ){
1008342292Scy          if( z==0 ){
1009342292Scy            z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake);
1010342292Scy          }else{
1011342292Scy            z = sqlite3_mprintf("%z\n/* %s */", z, zFake);
1012342292Scy          }
1013342292Scy          free(zFake);
1014342292Scy        }
1015342292Scy        if( z ){
1016342292Scy          sqlite3_result_text(pCtx, z, -1, sqlite3_free);
1017342292Scy          return;
1018342292Scy        }
1019322444Speter      }
1020322444Speter    }
1021322444Speter  }
1022322444Speter  sqlite3_result_value(pCtx, apVal[0]);
1023322444Speter}
1024322444Speter
1025322444Speter/*
1026322444Speter** The source code for several run-time loadable extensions is inserted
1027322444Speter** below by the ../tool/mkshellc.tcl script.  Before processing that included
1028322444Speter** code, we need to override some macros to make the included program code
1029322444Speter** work here in the middle of this regular program.
1030322444Speter*/
1031322444Speter#define SQLITE_EXTENSION_INIT1
1032322444Speter#define SQLITE_EXTENSION_INIT2(X) (void)(X)
1033322444Speter
1034342292Scy#if defined(_WIN32) && defined(_MSC_VER)
1035342292Scy/************************* Begin test_windirent.h ******************/
1036342292Scy/*
1037342292Scy** 2015 November 30
1038342292Scy**
1039342292Scy** The author disclaims copyright to this source code.  In place of
1040342292Scy** a legal notice, here is a blessing:
1041342292Scy**
1042342292Scy**    May you do good and not evil.
1043342292Scy**    May you find forgiveness for yourself and forgive others.
1044342292Scy**    May you share freely, never taking more than you give.
1045342292Scy**
1046342292Scy*************************************************************************
1047342292Scy** This file contains declarations for most of the opendir() family of
1048342292Scy** POSIX functions on Win32 using the MSVCRT.
1049342292Scy*/
1050342292Scy
1051342292Scy#if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H)
1052342292Scy#define SQLITE_WINDIRENT_H
1053342292Scy
1054342292Scy/*
1055342292Scy** We need several data types from the Windows SDK header.
1056342292Scy*/
1057342292Scy
1058342292Scy#ifndef WIN32_LEAN_AND_MEAN
1059342292Scy#define WIN32_LEAN_AND_MEAN
1060342292Scy#endif
1061342292Scy
1062342292Scy#include "windows.h"
1063342292Scy
1064342292Scy/*
1065342292Scy** We need several support functions from the SQLite core.
1066342292Scy*/
1067342292Scy
1068351633Scy/* #include "sqlite3.h" */
1069342292Scy
1070342292Scy/*
1071342292Scy** We need several things from the ANSI and MSVCRT headers.
1072342292Scy*/
1073342292Scy
1074342292Scy#include <stdio.h>
1075342292Scy#include <stdlib.h>
1076342292Scy#include <errno.h>
1077342292Scy#include <io.h>
1078342292Scy#include <limits.h>
1079342292Scy#include <sys/types.h>
1080342292Scy#include <sys/stat.h>
1081342292Scy
1082342292Scy/*
1083342292Scy** We may need several defines that should have been in "sys/stat.h".
1084342292Scy*/
1085342292Scy
1086342292Scy#ifndef S_ISREG
1087342292Scy#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
1088342292Scy#endif
1089342292Scy
1090342292Scy#ifndef S_ISDIR
1091342292Scy#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
1092342292Scy#endif
1093342292Scy
1094342292Scy#ifndef S_ISLNK
1095342292Scy#define S_ISLNK(mode) (0)
1096342292Scy#endif
1097342292Scy
1098342292Scy/*
1099342292Scy** We may need to provide the "mode_t" type.
1100342292Scy*/
1101342292Scy
1102342292Scy#ifndef MODE_T_DEFINED
1103342292Scy  #define MODE_T_DEFINED
1104342292Scy  typedef unsigned short mode_t;
1105342292Scy#endif
1106342292Scy
1107342292Scy/*
1108342292Scy** We may need to provide the "ino_t" type.
1109342292Scy*/
1110342292Scy
1111342292Scy#ifndef INO_T_DEFINED
1112342292Scy  #define INO_T_DEFINED
1113342292Scy  typedef unsigned short ino_t;
1114342292Scy#endif
1115342292Scy
1116342292Scy/*
1117342292Scy** We need to define "NAME_MAX" if it was not present in "limits.h".
1118342292Scy*/
1119342292Scy
1120342292Scy#ifndef NAME_MAX
1121342292Scy#  ifdef FILENAME_MAX
1122342292Scy#    define NAME_MAX (FILENAME_MAX)
1123342292Scy#  else
1124342292Scy#    define NAME_MAX (260)
1125342292Scy#  endif
1126342292Scy#endif
1127342292Scy
1128342292Scy/*
1129342292Scy** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T".
1130342292Scy*/
1131342292Scy
1132342292Scy#ifndef NULL_INTPTR_T
1133342292Scy#  define NULL_INTPTR_T ((intptr_t)(0))
1134342292Scy#endif
1135342292Scy
1136342292Scy#ifndef BAD_INTPTR_T
1137342292Scy#  define BAD_INTPTR_T ((intptr_t)(-1))
1138342292Scy#endif
1139342292Scy
1140342292Scy/*
1141342292Scy** We need to provide the necessary structures and related types.
1142342292Scy*/
1143342292Scy
1144342292Scy#ifndef DIRENT_DEFINED
1145342292Scy#define DIRENT_DEFINED
1146342292Scytypedef struct DIRENT DIRENT;
1147342292Scytypedef DIRENT *LPDIRENT;
1148342292Scystruct DIRENT {
1149342292Scy  ino_t d_ino;               /* Sequence number, do not use. */
1150342292Scy  unsigned d_attributes;     /* Win32 file attributes. */
1151342292Scy  char d_name[NAME_MAX + 1]; /* Name within the directory. */
1152342292Scy};
1153342292Scy#endif
1154342292Scy
1155342292Scy#ifndef DIR_DEFINED
1156342292Scy#define DIR_DEFINED
1157342292Scytypedef struct DIR DIR;
1158342292Scytypedef DIR *LPDIR;
1159342292Scystruct DIR {
1160342292Scy  intptr_t d_handle; /* Value returned by "_findfirst". */
1161342292Scy  DIRENT d_first;    /* DIRENT constructed based on "_findfirst". */
1162342292Scy  DIRENT d_next;     /* DIRENT constructed based on "_findnext". */
1163342292Scy};
1164342292Scy#endif
1165342292Scy
1166342292Scy/*
1167342292Scy** Provide a macro, for use by the implementation, to determine if a
1168342292Scy** particular directory entry should be skipped over when searching for
1169342292Scy** the next directory entry that should be returned by the readdir() or
1170342292Scy** readdir_r() functions.
1171342292Scy*/
1172342292Scy
1173342292Scy#ifndef is_filtered
1174342292Scy#  define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM))
1175342292Scy#endif
1176342292Scy
1177342292Scy/*
1178342292Scy** Provide the function prototype for the POSIX compatiable getenv()
1179342292Scy** function.  This function is not thread-safe.
1180342292Scy*/
1181342292Scy
1182342292Scyextern const char *windirent_getenv(const char *name);
1183342292Scy
1184342292Scy/*
1185342292Scy** Finally, we can provide the function prototypes for the opendir(),
1186342292Scy** readdir(), readdir_r(), and closedir() POSIX functions.
1187342292Scy*/
1188342292Scy
1189342292Scyextern LPDIR opendir(const char *dirname);
1190342292Scyextern LPDIRENT readdir(LPDIR dirp);
1191342292Scyextern INT readdir_r(LPDIR dirp, LPDIRENT entry, LPDIRENT *result);
1192342292Scyextern INT closedir(LPDIR dirp);
1193342292Scy
1194342292Scy#endif /* defined(WIN32) && defined(_MSC_VER) */
1195342292Scy
1196342292Scy/************************* End test_windirent.h ********************/
1197342292Scy/************************* Begin test_windirent.c ******************/
1198342292Scy/*
1199342292Scy** 2015 November 30
1200342292Scy**
1201342292Scy** The author disclaims copyright to this source code.  In place of
1202342292Scy** a legal notice, here is a blessing:
1203342292Scy**
1204342292Scy**    May you do good and not evil.
1205342292Scy**    May you find forgiveness for yourself and forgive others.
1206342292Scy**    May you share freely, never taking more than you give.
1207342292Scy**
1208342292Scy*************************************************************************
1209342292Scy** This file contains code to implement most of the opendir() family of
1210342292Scy** POSIX functions on Win32 using the MSVCRT.
1211342292Scy*/
1212342292Scy
1213342292Scy#if defined(_WIN32) && defined(_MSC_VER)
1214342292Scy/* #include "test_windirent.h" */
1215342292Scy
1216342292Scy/*
1217342292Scy** Implementation of the POSIX getenv() function using the Win32 API.
1218342292Scy** This function is not thread-safe.
1219342292Scy*/
1220342292Scyconst char *windirent_getenv(
1221342292Scy  const char *name
1222342292Scy){
1223342292Scy  static char value[32768]; /* Maximum length, per MSDN */
1224342292Scy  DWORD dwSize = sizeof(value) / sizeof(char); /* Size in chars */
1225342292Scy  DWORD dwRet; /* Value returned by GetEnvironmentVariableA() */
1226342292Scy
1227342292Scy  memset(value, 0, sizeof(value));
1228342292Scy  dwRet = GetEnvironmentVariableA(name, value, dwSize);
1229342292Scy  if( dwRet==0 || dwRet>dwSize ){
1230342292Scy    /*
1231342292Scy    ** The function call to GetEnvironmentVariableA() failed -OR-
1232342292Scy    ** the buffer is not large enough.  Either way, return NULL.
1233342292Scy    */
1234342292Scy    return 0;
1235342292Scy  }else{
1236342292Scy    /*
1237342292Scy    ** The function call to GetEnvironmentVariableA() succeeded
1238342292Scy    ** -AND- the buffer contains the entire value.
1239342292Scy    */
1240342292Scy    return value;
1241342292Scy  }
1242342292Scy}
1243342292Scy
1244342292Scy/*
1245342292Scy** Implementation of the POSIX opendir() function using the MSVCRT.
1246342292Scy*/
1247342292ScyLPDIR opendir(
1248342292Scy  const char *dirname
1249342292Scy){
1250342292Scy  struct _finddata_t data;
1251342292Scy  LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR));
1252342292Scy  SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]);
1253342292Scy
1254342292Scy  if( dirp==NULL ) return NULL;
1255342292Scy  memset(dirp, 0, sizeof(DIR));
1256342292Scy
1257342292Scy  /* TODO: Remove this if Unix-style root paths are not used. */
1258342292Scy  if( sqlite3_stricmp(dirname, "/")==0 ){
1259342292Scy    dirname = windirent_getenv("SystemDrive");
1260342292Scy  }
1261342292Scy
1262342292Scy  memset(&data, 0, sizeof(struct _finddata_t));
1263342292Scy  _snprintf(data.name, namesize, "%s\\*", dirname);
1264342292Scy  dirp->d_handle = _findfirst(data.name, &data);
1265342292Scy
1266342292Scy  if( dirp->d_handle==BAD_INTPTR_T ){
1267342292Scy    closedir(dirp);
1268342292Scy    return NULL;
1269342292Scy  }
1270342292Scy
1271342292Scy  /* TODO: Remove this block to allow hidden and/or system files. */
1272342292Scy  if( is_filtered(data) ){
1273342292Scynext:
1274342292Scy
1275342292Scy    memset(&data, 0, sizeof(struct _finddata_t));
1276342292Scy    if( _findnext(dirp->d_handle, &data)==-1 ){
1277342292Scy      closedir(dirp);
1278342292Scy      return NULL;
1279342292Scy    }
1280342292Scy
1281342292Scy    /* TODO: Remove this block to allow hidden and/or system files. */
1282342292Scy    if( is_filtered(data) ) goto next;
1283342292Scy  }
1284342292Scy
1285342292Scy  dirp->d_first.d_attributes = data.attrib;
1286342292Scy  strncpy(dirp->d_first.d_name, data.name, NAME_MAX);
1287342292Scy  dirp->d_first.d_name[NAME_MAX] = '\0';
1288342292Scy
1289342292Scy  return dirp;
1290342292Scy}
1291342292Scy
1292342292Scy/*
1293342292Scy** Implementation of the POSIX readdir() function using the MSVCRT.
1294342292Scy*/
1295342292ScyLPDIRENT readdir(
1296342292Scy  LPDIR dirp
1297342292Scy){
1298342292Scy  struct _finddata_t data;
1299342292Scy
1300342292Scy  if( dirp==NULL ) return NULL;
1301342292Scy
1302342292Scy  if( dirp->d_first.d_ino==0 ){
1303342292Scy    dirp->d_first.d_ino++;
1304342292Scy    dirp->d_next.d_ino++;
1305342292Scy
1306342292Scy    return &dirp->d_first;
1307342292Scy  }
1308342292Scy
1309342292Scynext:
1310342292Scy
1311342292Scy  memset(&data, 0, sizeof(struct _finddata_t));
1312342292Scy  if( _findnext(dirp->d_handle, &data)==-1 ) return NULL;
1313342292Scy
1314342292Scy  /* TODO: Remove this block to allow hidden and/or system files. */
1315342292Scy  if( is_filtered(data) ) goto next;
1316342292Scy
1317342292Scy  dirp->d_next.d_ino++;
1318342292Scy  dirp->d_next.d_attributes = data.attrib;
1319342292Scy  strncpy(dirp->d_next.d_name, data.name, NAME_MAX);
1320342292Scy  dirp->d_next.d_name[NAME_MAX] = '\0';
1321342292Scy
1322342292Scy  return &dirp->d_next;
1323342292Scy}
1324342292Scy
1325342292Scy/*
1326342292Scy** Implementation of the POSIX readdir_r() function using the MSVCRT.
1327342292Scy*/
1328342292ScyINT readdir_r(
1329342292Scy  LPDIR dirp,
1330342292Scy  LPDIRENT entry,
1331342292Scy  LPDIRENT *result
1332342292Scy){
1333342292Scy  struct _finddata_t data;
1334342292Scy
1335342292Scy  if( dirp==NULL ) return EBADF;
1336342292Scy
1337342292Scy  if( dirp->d_first.d_ino==0 ){
1338342292Scy    dirp->d_first.d_ino++;
1339342292Scy    dirp->d_next.d_ino++;
1340342292Scy
1341342292Scy    entry->d_ino = dirp->d_first.d_ino;
1342342292Scy    entry->d_attributes = dirp->d_first.d_attributes;
1343342292Scy    strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX);
1344342292Scy    entry->d_name[NAME_MAX] = '\0';
1345342292Scy
1346342292Scy    *result = entry;
1347342292Scy    return 0;
1348342292Scy  }
1349342292Scy
1350342292Scynext:
1351342292Scy
1352342292Scy  memset(&data, 0, sizeof(struct _finddata_t));
1353342292Scy  if( _findnext(dirp->d_handle, &data)==-1 ){
1354342292Scy    *result = NULL;
1355342292Scy    return ENOENT;
1356342292Scy  }
1357342292Scy
1358342292Scy  /* TODO: Remove this block to allow hidden and/or system files. */
1359342292Scy  if( is_filtered(data) ) goto next;
1360342292Scy
1361342292Scy  entry->d_ino = (ino_t)-1; /* not available */
1362342292Scy  entry->d_attributes = data.attrib;
1363342292Scy  strncpy(entry->d_name, data.name, NAME_MAX);
1364342292Scy  entry->d_name[NAME_MAX] = '\0';
1365342292Scy
1366342292Scy  *result = entry;
1367342292Scy  return 0;
1368342292Scy}
1369342292Scy
1370342292Scy/*
1371342292Scy** Implementation of the POSIX closedir() function using the MSVCRT.
1372342292Scy*/
1373342292ScyINT closedir(
1374342292Scy  LPDIR dirp
1375342292Scy){
1376342292Scy  INT result = 0;
1377342292Scy
1378342292Scy  if( dirp==NULL ) return EINVAL;
1379342292Scy
1380342292Scy  if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){
1381342292Scy    result = _findclose(dirp->d_handle);
1382342292Scy  }
1383342292Scy
1384342292Scy  sqlite3_free(dirp);
1385342292Scy  return result;
1386342292Scy}
1387342292Scy
1388342292Scy#endif /* defined(WIN32) && defined(_MSC_VER) */
1389342292Scy
1390342292Scy/************************* End test_windirent.c ********************/
1391342292Scy#define dirent DIRENT
1392342292Scy#endif
1393322444Speter/************************* Begin ../ext/misc/shathree.c ******************/
1394322444Speter/*
1395322444Speter** 2017-03-08
1396322444Speter**
1397322444Speter** The author disclaims copyright to this source code.  In place of
1398322444Speter** a legal notice, here is a blessing:
1399322444Speter**
1400322444Speter**    May you do good and not evil.
1401322444Speter**    May you find forgiveness for yourself and forgive others.
1402322444Speter**    May you share freely, never taking more than you give.
1403322444Speter**
1404322444Speter******************************************************************************
1405322444Speter**
1406342292Scy** This SQLite extension implements functions that compute SHA3 hashes.
1407322444Speter** Two SQL functions are implemented:
1408322444Speter**
1409322444Speter**     sha3(X,SIZE)
1410322444Speter**     sha3_query(Y,SIZE)
1411322444Speter**
1412322444Speter** The sha3(X) function computes the SHA3 hash of the input X, or NULL if
1413322444Speter** X is NULL.
1414322444Speter**
1415322444Speter** The sha3_query(Y) function evalutes all queries in the SQL statements of Y
1416322444Speter** and returns a hash of their results.
1417322444Speter**
1418322444Speter** The SIZE argument is optional.  If omitted, the SHA3-256 hash algorithm
1419322444Speter** is used.  If SIZE is included it must be one of the integers 224, 256,
1420322444Speter** 384, or 512, to determine SHA3 hash variant that is computed.
1421322444Speter*/
1422351633Scy/* #include "sqlite3ext.h" */
1423322444SpeterSQLITE_EXTENSION_INIT1
1424322444Speter#include <assert.h>
1425322444Speter#include <string.h>
1426322444Speter#include <stdarg.h>
1427369951Scy
1428369951Scy#ifndef SQLITE_AMALGAMATION
1429342292Scy/* typedef sqlite3_uint64 u64; */
1430369951Scy#endif /* SQLITE_AMALGAMATION */
1431322444Speter
1432322444Speter/******************************************************************************
1433322444Speter** The Hash Engine
1434322444Speter*/
1435322444Speter/*
1436322444Speter** Macros to determine whether the machine is big or little endian,
1437322444Speter** and whether or not that determination is run-time or compile-time.
1438322444Speter**
1439322444Speter** For best performance, an attempt is made to guess at the byte-order
1440322444Speter** using C-preprocessor macros.  If that is unsuccessful, or if
1441322444Speter** -DSHA3_BYTEORDER=0 is set, then byte-order is determined
1442322444Speter** at run-time.
1443322444Speter*/
1444322444Speter#ifndef SHA3_BYTEORDER
1445322444Speter# if defined(i386)     || defined(__i386__)   || defined(_M_IX86) ||    \
1446322444Speter     defined(__x86_64) || defined(__x86_64__) || defined(_M_X64)  ||    \
1447322444Speter     defined(_M_AMD64) || defined(_M_ARM)     || defined(__x86)   ||    \
1448322444Speter     defined(__arm__)
1449322444Speter#   define SHA3_BYTEORDER    1234
1450322444Speter# elif defined(sparc)    || defined(__ppc__)
1451322444Speter#   define SHA3_BYTEORDER    4321
1452322444Speter# else
1453322444Speter#   define SHA3_BYTEORDER 0
1454322444Speter# endif
1455322444Speter#endif
1456322444Speter
1457322444Speter
1458322444Speter/*
1459322444Speter** State structure for a SHA3 hash in progress
1460322444Speter*/
1461322444Spetertypedef struct SHA3Context SHA3Context;
1462322444Speterstruct SHA3Context {
1463322444Speter  union {
1464322444Speter    u64 s[25];                /* Keccak state. 5x5 lines of 64 bits each */
1465322444Speter    unsigned char x[1600];    /* ... or 1600 bytes */
1466322444Speter  } u;
1467322444Speter  unsigned nRate;        /* Bytes of input accepted per Keccak iteration */
1468322444Speter  unsigned nLoaded;      /* Input bytes loaded into u.x[] so far this cycle */
1469322444Speter  unsigned ixMask;       /* Insert next input into u.x[nLoaded^ixMask]. */
1470322444Speter};
1471322444Speter
1472322444Speter/*
1473322444Speter** A single step of the Keccak mixing function for a 1600-bit state
1474322444Speter*/
1475322444Speterstatic void KeccakF1600Step(SHA3Context *p){
1476322444Speter  int i;
1477342292Scy  u64 b0, b1, b2, b3, b4;
1478342292Scy  u64 c0, c1, c2, c3, c4;
1479342292Scy  u64 d0, d1, d2, d3, d4;
1480322444Speter  static const u64 RC[] = {
1481322444Speter    0x0000000000000001ULL,  0x0000000000008082ULL,
1482322444Speter    0x800000000000808aULL,  0x8000000080008000ULL,
1483322444Speter    0x000000000000808bULL,  0x0000000080000001ULL,
1484322444Speter    0x8000000080008081ULL,  0x8000000000008009ULL,
1485322444Speter    0x000000000000008aULL,  0x0000000000000088ULL,
1486322444Speter    0x0000000080008009ULL,  0x000000008000000aULL,
1487322444Speter    0x000000008000808bULL,  0x800000000000008bULL,
1488322444Speter    0x8000000000008089ULL,  0x8000000000008003ULL,
1489322444Speter    0x8000000000008002ULL,  0x8000000000000080ULL,
1490322444Speter    0x000000000000800aULL,  0x800000008000000aULL,
1491322444Speter    0x8000000080008081ULL,  0x8000000000008080ULL,
1492322444Speter    0x0000000080000001ULL,  0x8000000080008008ULL
1493322444Speter  };
1494342292Scy# define a00 (p->u.s[0])
1495342292Scy# define a01 (p->u.s[1])
1496342292Scy# define a02 (p->u.s[2])
1497342292Scy# define a03 (p->u.s[3])
1498342292Scy# define a04 (p->u.s[4])
1499342292Scy# define a10 (p->u.s[5])
1500342292Scy# define a11 (p->u.s[6])
1501342292Scy# define a12 (p->u.s[7])
1502342292Scy# define a13 (p->u.s[8])
1503342292Scy# define a14 (p->u.s[9])
1504342292Scy# define a20 (p->u.s[10])
1505342292Scy# define a21 (p->u.s[11])
1506342292Scy# define a22 (p->u.s[12])
1507342292Scy# define a23 (p->u.s[13])
1508342292Scy# define a24 (p->u.s[14])
1509342292Scy# define a30 (p->u.s[15])
1510342292Scy# define a31 (p->u.s[16])
1511342292Scy# define a32 (p->u.s[17])
1512342292Scy# define a33 (p->u.s[18])
1513342292Scy# define a34 (p->u.s[19])
1514342292Scy# define a40 (p->u.s[20])
1515342292Scy# define a41 (p->u.s[21])
1516342292Scy# define a42 (p->u.s[22])
1517342292Scy# define a43 (p->u.s[23])
1518342292Scy# define a44 (p->u.s[24])
1519322444Speter# define ROL64(a,x) ((a<<x)|(a>>(64-x)))
1520322444Speter
1521322444Speter  for(i=0; i<24; i+=4){
1522342292Scy    c0 = a00^a10^a20^a30^a40;
1523342292Scy    c1 = a01^a11^a21^a31^a41;
1524342292Scy    c2 = a02^a12^a22^a32^a42;
1525342292Scy    c3 = a03^a13^a23^a33^a43;
1526342292Scy    c4 = a04^a14^a24^a34^a44;
1527342292Scy    d0 = c4^ROL64(c1, 1);
1528342292Scy    d1 = c0^ROL64(c2, 1);
1529342292Scy    d2 = c1^ROL64(c3, 1);
1530342292Scy    d3 = c2^ROL64(c4, 1);
1531342292Scy    d4 = c3^ROL64(c0, 1);
1532322444Speter
1533342292Scy    b0 = (a00^d0);
1534342292Scy    b1 = ROL64((a11^d1), 44);
1535342292Scy    b2 = ROL64((a22^d2), 43);
1536342292Scy    b3 = ROL64((a33^d3), 21);
1537342292Scy    b4 = ROL64((a44^d4), 14);
1538342292Scy    a00 =   b0 ^((~b1)&  b2 );
1539342292Scy    a00 ^= RC[i];
1540342292Scy    a11 =   b1 ^((~b2)&  b3 );
1541342292Scy    a22 =   b2 ^((~b3)&  b4 );
1542342292Scy    a33 =   b3 ^((~b4)&  b0 );
1543342292Scy    a44 =   b4 ^((~b0)&  b1 );
1544322444Speter
1545342292Scy    b2 = ROL64((a20^d0), 3);
1546342292Scy    b3 = ROL64((a31^d1), 45);
1547342292Scy    b4 = ROL64((a42^d2), 61);
1548342292Scy    b0 = ROL64((a03^d3), 28);
1549342292Scy    b1 = ROL64((a14^d4), 20);
1550342292Scy    a20 =   b0 ^((~b1)&  b2 );
1551342292Scy    a31 =   b1 ^((~b2)&  b3 );
1552342292Scy    a42 =   b2 ^((~b3)&  b4 );
1553342292Scy    a03 =   b3 ^((~b4)&  b0 );
1554342292Scy    a14 =   b4 ^((~b0)&  b1 );
1555322444Speter
1556342292Scy    b4 = ROL64((a40^d0), 18);
1557342292Scy    b0 = ROL64((a01^d1), 1);
1558342292Scy    b1 = ROL64((a12^d2), 6);
1559342292Scy    b2 = ROL64((a23^d3), 25);
1560342292Scy    b3 = ROL64((a34^d4), 8);
1561342292Scy    a40 =   b0 ^((~b1)&  b2 );
1562342292Scy    a01 =   b1 ^((~b2)&  b3 );
1563342292Scy    a12 =   b2 ^((~b3)&  b4 );
1564342292Scy    a23 =   b3 ^((~b4)&  b0 );
1565342292Scy    a34 =   b4 ^((~b0)&  b1 );
1566322444Speter
1567342292Scy    b1 = ROL64((a10^d0), 36);
1568342292Scy    b2 = ROL64((a21^d1), 10);
1569342292Scy    b3 = ROL64((a32^d2), 15);
1570342292Scy    b4 = ROL64((a43^d3), 56);
1571342292Scy    b0 = ROL64((a04^d4), 27);
1572342292Scy    a10 =   b0 ^((~b1)&  b2 );
1573342292Scy    a21 =   b1 ^((~b2)&  b3 );
1574342292Scy    a32 =   b2 ^((~b3)&  b4 );
1575342292Scy    a43 =   b3 ^((~b4)&  b0 );
1576342292Scy    a04 =   b4 ^((~b0)&  b1 );
1577322444Speter
1578342292Scy    b3 = ROL64((a30^d0), 41);
1579342292Scy    b4 = ROL64((a41^d1), 2);
1580342292Scy    b0 = ROL64((a02^d2), 62);
1581342292Scy    b1 = ROL64((a13^d3), 55);
1582342292Scy    b2 = ROL64((a24^d4), 39);
1583342292Scy    a30 =   b0 ^((~b1)&  b2 );
1584342292Scy    a41 =   b1 ^((~b2)&  b3 );
1585342292Scy    a02 =   b2 ^((~b3)&  b4 );
1586342292Scy    a13 =   b3 ^((~b4)&  b0 );
1587342292Scy    a24 =   b4 ^((~b0)&  b1 );
1588322444Speter
1589342292Scy    c0 = a00^a20^a40^a10^a30;
1590342292Scy    c1 = a11^a31^a01^a21^a41;
1591342292Scy    c2 = a22^a42^a12^a32^a02;
1592342292Scy    c3 = a33^a03^a23^a43^a13;
1593342292Scy    c4 = a44^a14^a34^a04^a24;
1594342292Scy    d0 = c4^ROL64(c1, 1);
1595342292Scy    d1 = c0^ROL64(c2, 1);
1596342292Scy    d2 = c1^ROL64(c3, 1);
1597342292Scy    d3 = c2^ROL64(c4, 1);
1598342292Scy    d4 = c3^ROL64(c0, 1);
1599322444Speter
1600342292Scy    b0 = (a00^d0);
1601342292Scy    b1 = ROL64((a31^d1), 44);
1602342292Scy    b2 = ROL64((a12^d2), 43);
1603342292Scy    b3 = ROL64((a43^d3), 21);
1604342292Scy    b4 = ROL64((a24^d4), 14);
1605342292Scy    a00 =   b0 ^((~b1)&  b2 );
1606342292Scy    a00 ^= RC[i+1];
1607342292Scy    a31 =   b1 ^((~b2)&  b3 );
1608342292Scy    a12 =   b2 ^((~b3)&  b4 );
1609342292Scy    a43 =   b3 ^((~b4)&  b0 );
1610342292Scy    a24 =   b4 ^((~b0)&  b1 );
1611322444Speter
1612342292Scy    b2 = ROL64((a40^d0), 3);
1613342292Scy    b3 = ROL64((a21^d1), 45);
1614342292Scy    b4 = ROL64((a02^d2), 61);
1615342292Scy    b0 = ROL64((a33^d3), 28);
1616342292Scy    b1 = ROL64((a14^d4), 20);
1617342292Scy    a40 =   b0 ^((~b1)&  b2 );
1618342292Scy    a21 =   b1 ^((~b2)&  b3 );
1619342292Scy    a02 =   b2 ^((~b3)&  b4 );
1620342292Scy    a33 =   b3 ^((~b4)&  b0 );
1621342292Scy    a14 =   b4 ^((~b0)&  b1 );
1622322444Speter
1623342292Scy    b4 = ROL64((a30^d0), 18);
1624342292Scy    b0 = ROL64((a11^d1), 1);
1625342292Scy    b1 = ROL64((a42^d2), 6);
1626342292Scy    b2 = ROL64((a23^d3), 25);
1627342292Scy    b3 = ROL64((a04^d4), 8);
1628342292Scy    a30 =   b0 ^((~b1)&  b2 );
1629342292Scy    a11 =   b1 ^((~b2)&  b3 );
1630342292Scy    a42 =   b2 ^((~b3)&  b4 );
1631342292Scy    a23 =   b3 ^((~b4)&  b0 );
1632342292Scy    a04 =   b4 ^((~b0)&  b1 );
1633322444Speter
1634342292Scy    b1 = ROL64((a20^d0), 36);
1635342292Scy    b2 = ROL64((a01^d1), 10);
1636342292Scy    b3 = ROL64((a32^d2), 15);
1637342292Scy    b4 = ROL64((a13^d3), 56);
1638342292Scy    b0 = ROL64((a44^d4), 27);
1639342292Scy    a20 =   b0 ^((~b1)&  b2 );
1640342292Scy    a01 =   b1 ^((~b2)&  b3 );
1641342292Scy    a32 =   b2 ^((~b3)&  b4 );
1642342292Scy    a13 =   b3 ^((~b4)&  b0 );
1643342292Scy    a44 =   b4 ^((~b0)&  b1 );
1644322444Speter
1645342292Scy    b3 = ROL64((a10^d0), 41);
1646342292Scy    b4 = ROL64((a41^d1), 2);
1647342292Scy    b0 = ROL64((a22^d2), 62);
1648342292Scy    b1 = ROL64((a03^d3), 55);
1649342292Scy    b2 = ROL64((a34^d4), 39);
1650342292Scy    a10 =   b0 ^((~b1)&  b2 );
1651342292Scy    a41 =   b1 ^((~b2)&  b3 );
1652342292Scy    a22 =   b2 ^((~b3)&  b4 );
1653342292Scy    a03 =   b3 ^((~b4)&  b0 );
1654342292Scy    a34 =   b4 ^((~b0)&  b1 );
1655322444Speter
1656342292Scy    c0 = a00^a40^a30^a20^a10;
1657342292Scy    c1 = a31^a21^a11^a01^a41;
1658342292Scy    c2 = a12^a02^a42^a32^a22;
1659342292Scy    c3 = a43^a33^a23^a13^a03;
1660342292Scy    c4 = a24^a14^a04^a44^a34;
1661342292Scy    d0 = c4^ROL64(c1, 1);
1662342292Scy    d1 = c0^ROL64(c2, 1);
1663342292Scy    d2 = c1^ROL64(c3, 1);
1664342292Scy    d3 = c2^ROL64(c4, 1);
1665342292Scy    d4 = c3^ROL64(c0, 1);
1666322444Speter
1667342292Scy    b0 = (a00^d0);
1668342292Scy    b1 = ROL64((a21^d1), 44);
1669342292Scy    b2 = ROL64((a42^d2), 43);
1670342292Scy    b3 = ROL64((a13^d3), 21);
1671342292Scy    b4 = ROL64((a34^d4), 14);
1672342292Scy    a00 =   b0 ^((~b1)&  b2 );
1673342292Scy    a00 ^= RC[i+2];
1674342292Scy    a21 =   b1 ^((~b2)&  b3 );
1675342292Scy    a42 =   b2 ^((~b3)&  b4 );
1676342292Scy    a13 =   b3 ^((~b4)&  b0 );
1677342292Scy    a34 =   b4 ^((~b0)&  b1 );
1678322444Speter
1679342292Scy    b2 = ROL64((a30^d0), 3);
1680342292Scy    b3 = ROL64((a01^d1), 45);
1681342292Scy    b4 = ROL64((a22^d2), 61);
1682342292Scy    b0 = ROL64((a43^d3), 28);
1683342292Scy    b1 = ROL64((a14^d4), 20);
1684342292Scy    a30 =   b0 ^((~b1)&  b2 );
1685342292Scy    a01 =   b1 ^((~b2)&  b3 );
1686342292Scy    a22 =   b2 ^((~b3)&  b4 );
1687342292Scy    a43 =   b3 ^((~b4)&  b0 );
1688342292Scy    a14 =   b4 ^((~b0)&  b1 );
1689322444Speter
1690342292Scy    b4 = ROL64((a10^d0), 18);
1691342292Scy    b0 = ROL64((a31^d1), 1);
1692342292Scy    b1 = ROL64((a02^d2), 6);
1693342292Scy    b2 = ROL64((a23^d3), 25);
1694342292Scy    b3 = ROL64((a44^d4), 8);
1695342292Scy    a10 =   b0 ^((~b1)&  b2 );
1696342292Scy    a31 =   b1 ^((~b2)&  b3 );
1697342292Scy    a02 =   b2 ^((~b3)&  b4 );
1698342292Scy    a23 =   b3 ^((~b4)&  b0 );
1699342292Scy    a44 =   b4 ^((~b0)&  b1 );
1700322444Speter
1701342292Scy    b1 = ROL64((a40^d0), 36);
1702342292Scy    b2 = ROL64((a11^d1), 10);
1703342292Scy    b3 = ROL64((a32^d2), 15);
1704342292Scy    b4 = ROL64((a03^d3), 56);
1705342292Scy    b0 = ROL64((a24^d4), 27);
1706342292Scy    a40 =   b0 ^((~b1)&  b2 );
1707342292Scy    a11 =   b1 ^((~b2)&  b3 );
1708342292Scy    a32 =   b2 ^((~b3)&  b4 );
1709342292Scy    a03 =   b3 ^((~b4)&  b0 );
1710342292Scy    a24 =   b4 ^((~b0)&  b1 );
1711322444Speter
1712342292Scy    b3 = ROL64((a20^d0), 41);
1713342292Scy    b4 = ROL64((a41^d1), 2);
1714342292Scy    b0 = ROL64((a12^d2), 62);
1715342292Scy    b1 = ROL64((a33^d3), 55);
1716342292Scy    b2 = ROL64((a04^d4), 39);
1717342292Scy    a20 =   b0 ^((~b1)&  b2 );
1718342292Scy    a41 =   b1 ^((~b2)&  b3 );
1719342292Scy    a12 =   b2 ^((~b3)&  b4 );
1720342292Scy    a33 =   b3 ^((~b4)&  b0 );
1721342292Scy    a04 =   b4 ^((~b0)&  b1 );
1722322444Speter
1723342292Scy    c0 = a00^a30^a10^a40^a20;
1724342292Scy    c1 = a21^a01^a31^a11^a41;
1725342292Scy    c2 = a42^a22^a02^a32^a12;
1726342292Scy    c3 = a13^a43^a23^a03^a33;
1727342292Scy    c4 = a34^a14^a44^a24^a04;
1728342292Scy    d0 = c4^ROL64(c1, 1);
1729342292Scy    d1 = c0^ROL64(c2, 1);
1730342292Scy    d2 = c1^ROL64(c3, 1);
1731342292Scy    d3 = c2^ROL64(c4, 1);
1732342292Scy    d4 = c3^ROL64(c0, 1);
1733322444Speter
1734342292Scy    b0 = (a00^d0);
1735342292Scy    b1 = ROL64((a01^d1), 44);
1736342292Scy    b2 = ROL64((a02^d2), 43);
1737342292Scy    b3 = ROL64((a03^d3), 21);
1738342292Scy    b4 = ROL64((a04^d4), 14);
1739342292Scy    a00 =   b0 ^((~b1)&  b2 );
1740342292Scy    a00 ^= RC[i+3];
1741342292Scy    a01 =   b1 ^((~b2)&  b3 );
1742342292Scy    a02 =   b2 ^((~b3)&  b4 );
1743342292Scy    a03 =   b3 ^((~b4)&  b0 );
1744342292Scy    a04 =   b4 ^((~b0)&  b1 );
1745322444Speter
1746342292Scy    b2 = ROL64((a10^d0), 3);
1747342292Scy    b3 = ROL64((a11^d1), 45);
1748342292Scy    b4 = ROL64((a12^d2), 61);
1749342292Scy    b0 = ROL64((a13^d3), 28);
1750342292Scy    b1 = ROL64((a14^d4), 20);
1751342292Scy    a10 =   b0 ^((~b1)&  b2 );
1752342292Scy    a11 =   b1 ^((~b2)&  b3 );
1753342292Scy    a12 =   b2 ^((~b3)&  b4 );
1754342292Scy    a13 =   b3 ^((~b4)&  b0 );
1755342292Scy    a14 =   b4 ^((~b0)&  b1 );
1756322444Speter
1757342292Scy    b4 = ROL64((a20^d0), 18);
1758342292Scy    b0 = ROL64((a21^d1), 1);
1759342292Scy    b1 = ROL64((a22^d2), 6);
1760342292Scy    b2 = ROL64((a23^d3), 25);
1761342292Scy    b3 = ROL64((a24^d4), 8);
1762342292Scy    a20 =   b0 ^((~b1)&  b2 );
1763342292Scy    a21 =   b1 ^((~b2)&  b3 );
1764342292Scy    a22 =   b2 ^((~b3)&  b4 );
1765342292Scy    a23 =   b3 ^((~b4)&  b0 );
1766342292Scy    a24 =   b4 ^((~b0)&  b1 );
1767322444Speter
1768342292Scy    b1 = ROL64((a30^d0), 36);
1769342292Scy    b2 = ROL64((a31^d1), 10);
1770342292Scy    b3 = ROL64((a32^d2), 15);
1771342292Scy    b4 = ROL64((a33^d3), 56);
1772342292Scy    b0 = ROL64((a34^d4), 27);
1773342292Scy    a30 =   b0 ^((~b1)&  b2 );
1774342292Scy    a31 =   b1 ^((~b2)&  b3 );
1775342292Scy    a32 =   b2 ^((~b3)&  b4 );
1776342292Scy    a33 =   b3 ^((~b4)&  b0 );
1777342292Scy    a34 =   b4 ^((~b0)&  b1 );
1778322444Speter
1779342292Scy    b3 = ROL64((a40^d0), 41);
1780342292Scy    b4 = ROL64((a41^d1), 2);
1781342292Scy    b0 = ROL64((a42^d2), 62);
1782342292Scy    b1 = ROL64((a43^d3), 55);
1783342292Scy    b2 = ROL64((a44^d4), 39);
1784342292Scy    a40 =   b0 ^((~b1)&  b2 );
1785342292Scy    a41 =   b1 ^((~b2)&  b3 );
1786342292Scy    a42 =   b2 ^((~b3)&  b4 );
1787342292Scy    a43 =   b3 ^((~b4)&  b0 );
1788342292Scy    a44 =   b4 ^((~b0)&  b1 );
1789322444Speter  }
1790322444Speter}
1791322444Speter
1792322444Speter/*
1793322444Speter** Initialize a new hash.  iSize determines the size of the hash
1794322444Speter** in bits and should be one of 224, 256, 384, or 512.  Or iSize
1795322444Speter** can be zero to use the default hash size of 256 bits.
1796322444Speter*/
1797322444Speterstatic void SHA3Init(SHA3Context *p, int iSize){
1798322444Speter  memset(p, 0, sizeof(*p));
1799322444Speter  if( iSize>=128 && iSize<=512 ){
1800322444Speter    p->nRate = (1600 - ((iSize + 31)&~31)*2)/8;
1801322444Speter  }else{
1802322444Speter    p->nRate = (1600 - 2*256)/8;
1803322444Speter  }
1804322444Speter#if SHA3_BYTEORDER==1234
1805322444Speter  /* Known to be little-endian at compile-time. No-op */
1806322444Speter#elif SHA3_BYTEORDER==4321
1807322444Speter  p->ixMask = 7;  /* Big-endian */
1808322444Speter#else
1809322444Speter  {
1810322444Speter    static unsigned int one = 1;
1811322444Speter    if( 1==*(unsigned char*)&one ){
1812322444Speter      /* Little endian.  No byte swapping. */
1813322444Speter      p->ixMask = 0;
1814322444Speter    }else{
1815322444Speter      /* Big endian.  Byte swap. */
1816322444Speter      p->ixMask = 7;
1817322444Speter    }
1818322444Speter  }
1819322444Speter#endif
1820322444Speter}
1821322444Speter
1822322444Speter/*
1823322444Speter** Make consecutive calls to the SHA3Update function to add new content
1824322444Speter** to the hash
1825322444Speter*/
1826322444Speterstatic void SHA3Update(
1827322444Speter  SHA3Context *p,
1828322444Speter  const unsigned char *aData,
1829322444Speter  unsigned int nData
1830322444Speter){
1831322444Speter  unsigned int i = 0;
1832322444Speter#if SHA3_BYTEORDER==1234
1833322444Speter  if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
1834322444Speter    for(; i+7<nData; i+=8){
1835322444Speter      p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i];
1836322444Speter      p->nLoaded += 8;
1837322444Speter      if( p->nLoaded>=p->nRate ){
1838322444Speter        KeccakF1600Step(p);
1839322444Speter        p->nLoaded = 0;
1840322444Speter      }
1841322444Speter    }
1842322444Speter  }
1843322444Speter#endif
1844322444Speter  for(; i<nData; i++){
1845322444Speter#if SHA3_BYTEORDER==1234
1846322444Speter    p->u.x[p->nLoaded] ^= aData[i];
1847322444Speter#elif SHA3_BYTEORDER==4321
1848322444Speter    p->u.x[p->nLoaded^0x07] ^= aData[i];
1849322444Speter#else
1850322444Speter    p->u.x[p->nLoaded^p->ixMask] ^= aData[i];
1851322444Speter#endif
1852322444Speter    p->nLoaded++;
1853322444Speter    if( p->nLoaded==p->nRate ){
1854322444Speter      KeccakF1600Step(p);
1855322444Speter      p->nLoaded = 0;
1856322444Speter    }
1857322444Speter  }
1858322444Speter}
1859322444Speter
1860322444Speter/*
1861322444Speter** After all content has been added, invoke SHA3Final() to compute
1862322444Speter** the final hash.  The function returns a pointer to the binary
1863322444Speter** hash value.
1864322444Speter*/
1865322444Speterstatic unsigned char *SHA3Final(SHA3Context *p){
1866322444Speter  unsigned int i;
1867322444Speter  if( p->nLoaded==p->nRate-1 ){
1868322444Speter    const unsigned char c1 = 0x86;
1869322444Speter    SHA3Update(p, &c1, 1);
1870322444Speter  }else{
1871322444Speter    const unsigned char c2 = 0x06;
1872322444Speter    const unsigned char c3 = 0x80;
1873322444Speter    SHA3Update(p, &c2, 1);
1874322444Speter    p->nLoaded = p->nRate - 1;
1875322444Speter    SHA3Update(p, &c3, 1);
1876322444Speter  }
1877322444Speter  for(i=0; i<p->nRate; i++){
1878322444Speter    p->u.x[i+p->nRate] = p->u.x[i^p->ixMask];
1879322444Speter  }
1880322444Speter  return &p->u.x[p->nRate];
1881322444Speter}
1882322444Speter/* End of the hashing logic
1883322444Speter*****************************************************************************/
1884322444Speter
1885322444Speter/*
1886322444Speter** Implementation of the sha3(X,SIZE) function.
1887322444Speter**
1888322444Speter** Return a BLOB which is the SIZE-bit SHA3 hash of X.  The default
1889322444Speter** size is 256.  If X is a BLOB, it is hashed as is.
1890322444Speter** For all other non-NULL types of input, X is converted into a UTF-8 string
1891322444Speter** and the string is hashed without the trailing 0x00 terminator.  The hash
1892322444Speter** of a NULL value is NULL.
1893322444Speter*/
1894322444Speterstatic void sha3Func(
1895322444Speter  sqlite3_context *context,
1896322444Speter  int argc,
1897322444Speter  sqlite3_value **argv
1898322444Speter){
1899322444Speter  SHA3Context cx;
1900322444Speter  int eType = sqlite3_value_type(argv[0]);
1901322444Speter  int nByte = sqlite3_value_bytes(argv[0]);
1902322444Speter  int iSize;
1903322444Speter  if( argc==1 ){
1904322444Speter    iSize = 256;
1905322444Speter  }else{
1906322444Speter    iSize = sqlite3_value_int(argv[1]);
1907322444Speter    if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
1908322444Speter      sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
1909322444Speter                                    "384 512", -1);
1910322444Speter      return;
1911322444Speter    }
1912322444Speter  }
1913322444Speter  if( eType==SQLITE_NULL ) return;
1914322444Speter  SHA3Init(&cx, iSize);
1915322444Speter  if( eType==SQLITE_BLOB ){
1916322444Speter    SHA3Update(&cx, sqlite3_value_blob(argv[0]), nByte);
1917322444Speter  }else{
1918322444Speter    SHA3Update(&cx, sqlite3_value_text(argv[0]), nByte);
1919322444Speter  }
1920322444Speter  sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
1921322444Speter}
1922322444Speter
1923322444Speter/* Compute a string using sqlite3_vsnprintf() with a maximum length
1924322444Speter** of 50 bytes and add it to the hash.
1925322444Speter*/
1926322444Speterstatic void hash_step_vformat(
1927322444Speter  SHA3Context *p,                 /* Add content to this context */
1928322444Speter  const char *zFormat,
1929322444Speter  ...
1930322444Speter){
1931322444Speter  va_list ap;
1932322444Speter  int n;
1933322444Speter  char zBuf[50];
1934322444Speter  va_start(ap, zFormat);
1935322444Speter  sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
1936322444Speter  va_end(ap);
1937322444Speter  n = (int)strlen(zBuf);
1938322444Speter  SHA3Update(p, (unsigned char*)zBuf, n);
1939322444Speter}
1940322444Speter
1941322444Speter/*
1942322444Speter** Implementation of the sha3_query(SQL,SIZE) function.
1943322444Speter**
1944322444Speter** This function compiles and runs the SQL statement(s) given in the
1945322444Speter** argument. The results are hashed using a SIZE-bit SHA3.  The default
1946322444Speter** size is 256.
1947322444Speter**
1948322444Speter** The format of the byte stream that is hashed is summarized as follows:
1949322444Speter**
1950322444Speter**       S<n>:<sql>
1951322444Speter**       R
1952322444Speter**       N
1953322444Speter**       I<int>
1954322444Speter**       F<ieee-float>
1955322444Speter**       B<size>:<bytes>
1956322444Speter**       T<size>:<text>
1957322444Speter**
1958322444Speter** <sql> is the original SQL text for each statement run and <n> is
1959322444Speter** the size of that text.  The SQL text is UTF-8.  A single R character
1960322444Speter** occurs before the start of each row.  N means a NULL value.
1961322444Speter** I mean an 8-byte little-endian integer <int>.  F is a floating point
1962322444Speter** number with an 8-byte little-endian IEEE floating point value <ieee-float>.
1963322444Speter** B means blobs of <size> bytes.  T means text rendered as <size>
1964322444Speter** bytes of UTF-8.  The <n> and <size> values are expressed as an ASCII
1965322444Speter** text integers.
1966322444Speter**
1967322444Speter** For each SQL statement in the X input, there is one S segment.  Each
1968322444Speter** S segment is followed by zero or more R segments, one for each row in the
1969322444Speter** result set.  After each R, there are one or more N, I, F, B, or T segments,
1970322444Speter** one for each column in the result set.  Segments are concatentated directly
1971322444Speter** with no delimiters of any kind.
1972322444Speter*/
1973322444Speterstatic void sha3QueryFunc(
1974322444Speter  sqlite3_context *context,
1975322444Speter  int argc,
1976322444Speter  sqlite3_value **argv
1977322444Speter){
1978322444Speter  sqlite3 *db = sqlite3_context_db_handle(context);
1979322444Speter  const char *zSql = (const char*)sqlite3_value_text(argv[0]);
1980322444Speter  sqlite3_stmt *pStmt = 0;
1981322444Speter  int nCol;                   /* Number of columns in the result set */
1982322444Speter  int i;                      /* Loop counter */
1983322444Speter  int rc;
1984322444Speter  int n;
1985322444Speter  const char *z;
1986322444Speter  SHA3Context cx;
1987322444Speter  int iSize;
1988322444Speter
1989322444Speter  if( argc==1 ){
1990322444Speter    iSize = 256;
1991322444Speter  }else{
1992322444Speter    iSize = sqlite3_value_int(argv[1]);
1993322444Speter    if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
1994322444Speter      sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
1995322444Speter                                    "384 512", -1);
1996322444Speter      return;
1997322444Speter    }
1998322444Speter  }
1999322444Speter  if( zSql==0 ) return;
2000322444Speter  SHA3Init(&cx, iSize);
2001322444Speter  while( zSql[0] ){
2002322444Speter    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
2003322444Speter    if( rc ){
2004322444Speter      char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s",
2005322444Speter                                   zSql, sqlite3_errmsg(db));
2006322444Speter      sqlite3_finalize(pStmt);
2007322444Speter      sqlite3_result_error(context, zMsg, -1);
2008322444Speter      sqlite3_free(zMsg);
2009322444Speter      return;
2010322444Speter    }
2011322444Speter    if( !sqlite3_stmt_readonly(pStmt) ){
2012322444Speter      char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt));
2013322444Speter      sqlite3_finalize(pStmt);
2014322444Speter      sqlite3_result_error(context, zMsg, -1);
2015322444Speter      sqlite3_free(zMsg);
2016322444Speter      return;
2017322444Speter    }
2018322444Speter    nCol = sqlite3_column_count(pStmt);
2019322444Speter    z = sqlite3_sql(pStmt);
2020369950Scy    if( z ){
2021369950Scy      n = (int)strlen(z);
2022369950Scy      hash_step_vformat(&cx,"S%d:",n);
2023369950Scy      SHA3Update(&cx,(unsigned char*)z,n);
2024369950Scy    }
2025322444Speter
2026322444Speter    /* Compute a hash over the result of the query */
2027322444Speter    while( SQLITE_ROW==sqlite3_step(pStmt) ){
2028322444Speter      SHA3Update(&cx,(const unsigned char*)"R",1);
2029322444Speter      for(i=0; i<nCol; i++){
2030322444Speter        switch( sqlite3_column_type(pStmt,i) ){
2031322444Speter          case SQLITE_NULL: {
2032322444Speter            SHA3Update(&cx, (const unsigned char*)"N",1);
2033322444Speter            break;
2034322444Speter          }
2035322444Speter          case SQLITE_INTEGER: {
2036322444Speter            sqlite3_uint64 u;
2037322444Speter            int j;
2038322444Speter            unsigned char x[9];
2039322444Speter            sqlite3_int64 v = sqlite3_column_int64(pStmt,i);
2040322444Speter            memcpy(&u, &v, 8);
2041322444Speter            for(j=8; j>=1; j--){
2042322444Speter              x[j] = u & 0xff;
2043322444Speter              u >>= 8;
2044322444Speter            }
2045322444Speter            x[0] = 'I';
2046322444Speter            SHA3Update(&cx, x, 9);
2047322444Speter            break;
2048322444Speter          }
2049322444Speter          case SQLITE_FLOAT: {
2050322444Speter            sqlite3_uint64 u;
2051322444Speter            int j;
2052322444Speter            unsigned char x[9];
2053322444Speter            double r = sqlite3_column_double(pStmt,i);
2054322444Speter            memcpy(&u, &r, 8);
2055322444Speter            for(j=8; j>=1; j--){
2056322444Speter              x[j] = u & 0xff;
2057322444Speter              u >>= 8;
2058322444Speter            }
2059322444Speter            x[0] = 'F';
2060322444Speter            SHA3Update(&cx,x,9);
2061322444Speter            break;
2062322444Speter          }
2063322444Speter          case SQLITE_TEXT: {
2064322444Speter            int n2 = sqlite3_column_bytes(pStmt, i);
2065322444Speter            const unsigned char *z2 = sqlite3_column_text(pStmt, i);
2066322444Speter            hash_step_vformat(&cx,"T%d:",n2);
2067322444Speter            SHA3Update(&cx, z2, n2);
2068322444Speter            break;
2069322444Speter          }
2070322444Speter          case SQLITE_BLOB: {
2071322444Speter            int n2 = sqlite3_column_bytes(pStmt, i);
2072322444Speter            const unsigned char *z2 = sqlite3_column_blob(pStmt, i);
2073322444Speter            hash_step_vformat(&cx,"B%d:",n2);
2074322444Speter            SHA3Update(&cx, z2, n2);
2075322444Speter            break;
2076322444Speter          }
2077322444Speter        }
2078322444Speter      }
2079322444Speter    }
2080322444Speter    sqlite3_finalize(pStmt);
2081322444Speter  }
2082322444Speter  sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
2083322444Speter}
2084322444Speter
2085322444Speter
2086322444Speter#ifdef _WIN32
2087342292Scy
2088322444Speter#endif
2089322444Speterint sqlite3_shathree_init(
2090322444Speter  sqlite3 *db,
2091322444Speter  char **pzErrMsg,
2092322444Speter  const sqlite3_api_routines *pApi
2093322444Speter){
2094322444Speter  int rc = SQLITE_OK;
2095322444Speter  SQLITE_EXTENSION_INIT2(pApi);
2096322444Speter  (void)pzErrMsg;  /* Unused parameter */
2097361456Scy  rc = sqlite3_create_function(db, "sha3", 1,
2098361456Scy                      SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
2099361456Scy                      0, sha3Func, 0, 0);
2100322444Speter  if( rc==SQLITE_OK ){
2101361456Scy    rc = sqlite3_create_function(db, "sha3", 2,
2102361456Scy                      SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
2103361456Scy                      0, sha3Func, 0, 0);
2104322444Speter  }
2105322444Speter  if( rc==SQLITE_OK ){
2106361456Scy    rc = sqlite3_create_function(db, "sha3_query", 1,
2107361456Scy                      SQLITE_UTF8 | SQLITE_DIRECTONLY,
2108361456Scy                      0, sha3QueryFunc, 0, 0);
2109322444Speter  }
2110322444Speter  if( rc==SQLITE_OK ){
2111361456Scy    rc = sqlite3_create_function(db, "sha3_query", 2,
2112361456Scy                      SQLITE_UTF8 | SQLITE_DIRECTONLY,
2113361456Scy                      0, sha3QueryFunc, 0, 0);
2114322444Speter  }
2115322444Speter  return rc;
2116322444Speter}
2117322444Speter
2118322444Speter/************************* End ../ext/misc/shathree.c ********************/
2119322444Speter/************************* Begin ../ext/misc/fileio.c ******************/
2120322444Speter/*
2121322444Speter** 2014-06-13
2122322444Speter**
2123322444Speter** The author disclaims copyright to this source code.  In place of
2124322444Speter** a legal notice, here is a blessing:
2125322444Speter**
2126322444Speter**    May you do good and not evil.
2127322444Speter**    May you find forgiveness for yourself and forgive others.
2128322444Speter**    May you share freely, never taking more than you give.
2129322444Speter**
2130322444Speter******************************************************************************
2131322444Speter**
2132322444Speter** This SQLite extension implements SQL functions readfile() and
2133342292Scy** writefile(), and eponymous virtual type "fsdir".
2134342292Scy**
2135342292Scy** WRITEFILE(FILE, DATA [, MODE [, MTIME]]):
2136342292Scy**
2137342292Scy**   If neither of the optional arguments is present, then this UDF
2138342292Scy**   function writes blob DATA to file FILE. If successful, the number
2139342292Scy**   of bytes written is returned. If an error occurs, NULL is returned.
2140342292Scy**
2141342292Scy**   If the first option argument - MODE - is present, then it must
2142342292Scy**   be passed an integer value that corresponds to a POSIX mode
2143342292Scy**   value (file type + permissions, as returned in the stat.st_mode
2144342292Scy**   field by the stat() system call). Three types of files may
2145342292Scy**   be written/created:
2146342292Scy**
2147342292Scy**     regular files:  (mode & 0170000)==0100000
2148342292Scy**     symbolic links: (mode & 0170000)==0120000
2149342292Scy**     directories:    (mode & 0170000)==0040000
2150342292Scy**
2151342292Scy**   For a directory, the DATA is ignored. For a symbolic link, it is
2152342292Scy**   interpreted as text and used as the target of the link. For a
2153342292Scy**   regular file, it is interpreted as a blob and written into the
2154342292Scy**   named file. Regardless of the type of file, its permissions are
2155342292Scy**   set to (mode & 0777) before returning.
2156342292Scy**
2157342292Scy**   If the optional MTIME argument is present, then it is interpreted
2158342292Scy**   as an integer - the number of seconds since the unix epoch. The
2159342292Scy**   modification-time of the target file is set to this value before
2160342292Scy**   returning.
2161342292Scy**
2162342292Scy**   If three or more arguments are passed to this function and an
2163342292Scy**   error is encountered, an exception is raised.
2164342292Scy**
2165342292Scy** READFILE(FILE):
2166342292Scy**
2167342292Scy**   Read and return the contents of file FILE (type blob) from disk.
2168342292Scy**
2169342292Scy** FSDIR:
2170342292Scy**
2171342292Scy**   Used as follows:
2172342292Scy**
2173342292Scy**     SELECT * FROM fsdir($path [, $dir]);
2174342292Scy**
2175342292Scy**   Parameter $path is an absolute or relative pathname. If the file that it
2176342292Scy**   refers to does not exist, it is an error. If the path refers to a regular
2177342292Scy**   file or symbolic link, it returns a single row. Or, if the path refers
2178342292Scy**   to a directory, it returns one row for the directory, and one row for each
2179342292Scy**   file within the hierarchy rooted at $path.
2180342292Scy**
2181342292Scy**   Each row has the following columns:
2182342292Scy**
2183342292Scy**     name:  Path to file or directory (text value).
2184342292Scy**     mode:  Value of stat.st_mode for directory entry (an integer).
2185342292Scy**     mtime: Value of stat.st_mtime for directory entry (an integer).
2186342292Scy**     data:  For a regular file, a blob containing the file data. For a
2187342292Scy**            symlink, a text value containing the text of the link. For a
2188342292Scy**            directory, NULL.
2189342292Scy**
2190342292Scy**   If a non-NULL value is specified for the optional $dir parameter and
2191342292Scy**   $path is a relative path, then $path is interpreted relative to $dir.
2192342292Scy**   And the paths returned in the "name" column of the table are also
2193342292Scy**   relative to directory $dir.
2194322444Speter*/
2195351633Scy/* #include "sqlite3ext.h" */
2196322444SpeterSQLITE_EXTENSION_INIT1
2197322444Speter#include <stdio.h>
2198342292Scy#include <string.h>
2199342292Scy#include <assert.h>
2200322444Speter
2201342292Scy#include <sys/types.h>
2202342292Scy#include <sys/stat.h>
2203342292Scy#include <fcntl.h>
2204342292Scy#if !defined(_WIN32) && !defined(WIN32)
2205342292Scy#  include <unistd.h>
2206342292Scy#  include <dirent.h>
2207342292Scy#  include <utime.h>
2208342292Scy#  include <sys/time.h>
2209342292Scy#else
2210342292Scy#  include "windows.h"
2211342292Scy#  include <io.h>
2212342292Scy#  include <direct.h>
2213342292Scy/* #  include "test_windirent.h" */
2214342292Scy#  define dirent DIRENT
2215342292Scy#  ifndef chmod
2216342292Scy#    define chmod _chmod
2217342292Scy#  endif
2218342292Scy#  ifndef stat
2219342292Scy#    define stat _stat
2220342292Scy#  endif
2221342292Scy#  define mkdir(path,mode) _mkdir(path)
2222342292Scy#  define lstat(path,buf) stat(path,buf)
2223342292Scy#endif
2224342292Scy#include <time.h>
2225342292Scy#include <errno.h>
2226342292Scy
2227342292Scy
2228322444Speter/*
2229342292Scy** Structure of the fsdir() table-valued function
2230322444Speter*/
2231342292Scy                 /*    0    1    2     3    4           5             */
2232342292Scy#define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)"
2233342292Scy#define FSDIR_COLUMN_NAME     0     /* Name of the file */
2234342292Scy#define FSDIR_COLUMN_MODE     1     /* Access mode */
2235342292Scy#define FSDIR_COLUMN_MTIME    2     /* Last modification time */
2236342292Scy#define FSDIR_COLUMN_DATA     3     /* File content */
2237342292Scy#define FSDIR_COLUMN_PATH     4     /* Path to top of search */
2238342292Scy#define FSDIR_COLUMN_DIR      5     /* Path is relative to this directory */
2239342292Scy
2240342292Scy
2241342292Scy/*
2242342292Scy** Set the result stored by context ctx to a blob containing the
2243346442Scy** contents of file zName.  Or, leave the result unchanged (NULL)
2244346442Scy** if the file does not exist or is unreadable.
2245346442Scy**
2246346442Scy** If the file exceeds the SQLite blob size limit, through an
2247346442Scy** SQLITE_TOOBIG error.
2248346442Scy**
2249346442Scy** Throw an SQLITE_IOERR if there are difficulties pulling the file
2250346442Scy** off of disk.
2251342292Scy*/
2252342292Scystatic void readFileContents(sqlite3_context *ctx, const char *zName){
2253322444Speter  FILE *in;
2254346442Scy  sqlite3_int64 nIn;
2255322444Speter  void *pBuf;
2256346442Scy  sqlite3 *db;
2257346442Scy  int mxBlob;
2258322444Speter
2259322444Speter  in = fopen(zName, "rb");
2260346442Scy  if( in==0 ){
2261346442Scy    /* File does not exist or is unreadable. Leave the result set to NULL. */
2262346442Scy    return;
2263346442Scy  }
2264322444Speter  fseek(in, 0, SEEK_END);
2265322444Speter  nIn = ftell(in);
2266322444Speter  rewind(in);
2267346442Scy  db = sqlite3_context_db_handle(ctx);
2268346442Scy  mxBlob = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1);
2269346442Scy  if( nIn>mxBlob ){
2270346442Scy    sqlite3_result_error_code(ctx, SQLITE_TOOBIG);
2271346442Scy    fclose(in);
2272346442Scy    return;
2273346442Scy  }
2274347347Scy  pBuf = sqlite3_malloc64( nIn ? nIn : 1 );
2275346442Scy  if( pBuf==0 ){
2276346442Scy    sqlite3_result_error_nomem(ctx);
2277346442Scy    fclose(in);
2278346442Scy    return;
2279346442Scy  }
2280347347Scy  if( nIn==(sqlite3_int64)fread(pBuf, 1, (size_t)nIn, in) ){
2281346442Scy    sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
2282322444Speter  }else{
2283346442Scy    sqlite3_result_error_code(ctx, SQLITE_IOERR);
2284322444Speter    sqlite3_free(pBuf);
2285322444Speter  }
2286322444Speter  fclose(in);
2287322444Speter}
2288322444Speter
2289322444Speter/*
2290342292Scy** Implementation of the "readfile(X)" SQL function.  The entire content
2291342292Scy** of the file named X is read and returned as a BLOB.  NULL is returned
2292342292Scy** if the file does not exist or is unreadable.
2293322444Speter*/
2294342292Scystatic void readfileFunc(
2295342292Scy  sqlite3_context *context,
2296342292Scy  int argc,
2297342292Scy  sqlite3_value **argv
2298342292Scy){
2299342292Scy  const char *zName;
2300342292Scy  (void)(argc);  /* Unused parameter */
2301342292Scy  zName = (const char*)sqlite3_value_text(argv[0]);
2302342292Scy  if( zName==0 ) return;
2303342292Scy  readFileContents(context, zName);
2304342292Scy}
2305342292Scy
2306342292Scy/*
2307342292Scy** Set the error message contained in context ctx to the results of
2308342292Scy** vprintf(zFmt, ...).
2309342292Scy*/
2310342292Scystatic void ctxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
2311342292Scy  char *zMsg = 0;
2312342292Scy  va_list ap;
2313342292Scy  va_start(ap, zFmt);
2314342292Scy  zMsg = sqlite3_vmprintf(zFmt, ap);
2315342292Scy  sqlite3_result_error(ctx, zMsg, -1);
2316342292Scy  sqlite3_free(zMsg);
2317342292Scy  va_end(ap);
2318342292Scy}
2319342292Scy
2320342292Scy#if defined(_WIN32)
2321342292Scy/*
2322342292Scy** This function is designed to convert a Win32 FILETIME structure into the
2323342292Scy** number of seconds since the Unix Epoch (1970-01-01 00:00:00 UTC).
2324342292Scy*/
2325342292Scystatic sqlite3_uint64 fileTimeToUnixTime(
2326342292Scy  LPFILETIME pFileTime
2327342292Scy){
2328342292Scy  SYSTEMTIME epochSystemTime;
2329342292Scy  ULARGE_INTEGER epochIntervals;
2330342292Scy  FILETIME epochFileTime;
2331342292Scy  ULARGE_INTEGER fileIntervals;
2332342292Scy
2333342292Scy  memset(&epochSystemTime, 0, sizeof(SYSTEMTIME));
2334342292Scy  epochSystemTime.wYear = 1970;
2335342292Scy  epochSystemTime.wMonth = 1;
2336342292Scy  epochSystemTime.wDay = 1;
2337342292Scy  SystemTimeToFileTime(&epochSystemTime, &epochFileTime);
2338342292Scy  epochIntervals.LowPart = epochFileTime.dwLowDateTime;
2339342292Scy  epochIntervals.HighPart = epochFileTime.dwHighDateTime;
2340342292Scy
2341342292Scy  fileIntervals.LowPart = pFileTime->dwLowDateTime;
2342342292Scy  fileIntervals.HighPart = pFileTime->dwHighDateTime;
2343342292Scy
2344342292Scy  return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000;
2345342292Scy}
2346342292Scy
2347342292Scy/*
2348342292Scy** This function attempts to normalize the time values found in the stat()
2349342292Scy** buffer to UTC.  This is necessary on Win32, where the runtime library
2350342292Scy** appears to return these values as local times.
2351342292Scy*/
2352342292Scystatic void statTimesToUtc(
2353342292Scy  const char *zPath,
2354342292Scy  struct stat *pStatBuf
2355342292Scy){
2356342292Scy  HANDLE hFindFile;
2357342292Scy  WIN32_FIND_DATAW fd;
2358342292Scy  LPWSTR zUnicodeName;
2359342292Scy  extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
2360342292Scy  zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath);
2361342292Scy  if( zUnicodeName ){
2362342292Scy    memset(&fd, 0, sizeof(WIN32_FIND_DATAW));
2363342292Scy    hFindFile = FindFirstFileW(zUnicodeName, &fd);
2364342292Scy    if( hFindFile!=NULL ){
2365342292Scy      pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime);
2366342292Scy      pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime);
2367342292Scy      pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime);
2368342292Scy      FindClose(hFindFile);
2369342292Scy    }
2370342292Scy    sqlite3_free(zUnicodeName);
2371342292Scy  }
2372342292Scy}
2373342292Scy#endif
2374342292Scy
2375342292Scy/*
2376342292Scy** This function is used in place of stat().  On Windows, special handling
2377342292Scy** is required in order for the included time to be returned as UTC.  On all
2378342292Scy** other systems, this function simply calls stat().
2379342292Scy*/
2380342292Scystatic int fileStat(
2381342292Scy  const char *zPath,
2382342292Scy  struct stat *pStatBuf
2383342292Scy){
2384342292Scy#if defined(_WIN32)
2385342292Scy  int rc = stat(zPath, pStatBuf);
2386342292Scy  if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
2387342292Scy  return rc;
2388342292Scy#else
2389342292Scy  return stat(zPath, pStatBuf);
2390342292Scy#endif
2391342292Scy}
2392342292Scy
2393342292Scy/*
2394342292Scy** This function is used in place of lstat().  On Windows, special handling
2395342292Scy** is required in order for the included time to be returned as UTC.  On all
2396342292Scy** other systems, this function simply calls lstat().
2397342292Scy*/
2398342292Scystatic int fileLinkStat(
2399342292Scy  const char *zPath,
2400342292Scy  struct stat *pStatBuf
2401342292Scy){
2402342292Scy#if defined(_WIN32)
2403342292Scy  int rc = lstat(zPath, pStatBuf);
2404342292Scy  if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
2405342292Scy  return rc;
2406342292Scy#else
2407342292Scy  return lstat(zPath, pStatBuf);
2408342292Scy#endif
2409342292Scy}
2410342292Scy
2411342292Scy/*
2412342292Scy** Argument zFile is the name of a file that will be created and/or written
2413342292Scy** by SQL function writefile(). This function ensures that the directory
2414342292Scy** zFile will be written to exists, creating it if required. The permissions
2415347347Scy** for any path components created by this function are set in accordance
2416347347Scy** with the current umask.
2417342292Scy**
2418342292Scy** If an OOM condition is encountered, SQLITE_NOMEM is returned. Otherwise,
2419342292Scy** SQLITE_OK is returned if the directory is successfully created, or
2420342292Scy** SQLITE_ERROR otherwise.
2421342292Scy*/
2422342292Scystatic int makeDirectory(
2423347347Scy  const char *zFile
2424342292Scy){
2425342292Scy  char *zCopy = sqlite3_mprintf("%s", zFile);
2426342292Scy  int rc = SQLITE_OK;
2427342292Scy
2428342292Scy  if( zCopy==0 ){
2429342292Scy    rc = SQLITE_NOMEM;
2430342292Scy  }else{
2431342292Scy    int nCopy = (int)strlen(zCopy);
2432342292Scy    int i = 1;
2433342292Scy
2434342292Scy    while( rc==SQLITE_OK ){
2435342292Scy      struct stat sStat;
2436342292Scy      int rc2;
2437342292Scy
2438342292Scy      for(; zCopy[i]!='/' && i<nCopy; i++);
2439342292Scy      if( i==nCopy ) break;
2440342292Scy      zCopy[i] = '\0';
2441342292Scy
2442342292Scy      rc2 = fileStat(zCopy, &sStat);
2443342292Scy      if( rc2!=0 ){
2444347347Scy        if( mkdir(zCopy, 0777) ) rc = SQLITE_ERROR;
2445342292Scy      }else{
2446342292Scy        if( !S_ISDIR(sStat.st_mode) ) rc = SQLITE_ERROR;
2447342292Scy      }
2448342292Scy      zCopy[i] = '/';
2449342292Scy      i++;
2450342292Scy    }
2451342292Scy
2452342292Scy    sqlite3_free(zCopy);
2453342292Scy  }
2454342292Scy
2455342292Scy  return rc;
2456342292Scy}
2457342292Scy
2458342292Scy/*
2459342292Scy** This function does the work for the writefile() UDF. Refer to
2460342292Scy** header comments at the top of this file for details.
2461342292Scy*/
2462342292Scystatic int writeFile(
2463342292Scy  sqlite3_context *pCtx,          /* Context to return bytes written in */
2464342292Scy  const char *zFile,              /* File to write */
2465342292Scy  sqlite3_value *pData,           /* Data to write */
2466342292Scy  mode_t mode,                    /* MODE parameter passed to writefile() */
2467342292Scy  sqlite3_int64 mtime             /* MTIME parameter (or -1 to not set time) */
2468342292Scy){
2469342292Scy#if !defined(_WIN32) && !defined(WIN32)
2470342292Scy  if( S_ISLNK(mode) ){
2471342292Scy    const char *zTo = (const char*)sqlite3_value_text(pData);
2472342292Scy    if( symlink(zTo, zFile)<0 ) return 1;
2473342292Scy  }else
2474342292Scy#endif
2475342292Scy  {
2476342292Scy    if( S_ISDIR(mode) ){
2477342292Scy      if( mkdir(zFile, mode) ){
2478342292Scy        /* The mkdir() call to create the directory failed. This might not
2479342292Scy        ** be an error though - if there is already a directory at the same
2480342292Scy        ** path and either the permissions already match or can be changed
2481342292Scy        ** to do so using chmod(), it is not an error.  */
2482342292Scy        struct stat sStat;
2483342292Scy        if( errno!=EEXIST
2484342292Scy         || 0!=fileStat(zFile, &sStat)
2485342292Scy         || !S_ISDIR(sStat.st_mode)
2486342292Scy         || ((sStat.st_mode&0777)!=(mode&0777) && 0!=chmod(zFile, mode&0777))
2487342292Scy        ){
2488342292Scy          return 1;
2489342292Scy        }
2490342292Scy      }
2491342292Scy    }else{
2492342292Scy      sqlite3_int64 nWrite = 0;
2493342292Scy      const char *z;
2494342292Scy      int rc = 0;
2495342292Scy      FILE *out = fopen(zFile, "wb");
2496342292Scy      if( out==0 ) return 1;
2497342292Scy      z = (const char*)sqlite3_value_blob(pData);
2498342292Scy      if( z ){
2499342292Scy        sqlite3_int64 n = fwrite(z, 1, sqlite3_value_bytes(pData), out);
2500342292Scy        nWrite = sqlite3_value_bytes(pData);
2501342292Scy        if( nWrite!=n ){
2502342292Scy          rc = 1;
2503342292Scy        }
2504342292Scy      }
2505342292Scy      fclose(out);
2506342292Scy      if( rc==0 && mode && chmod(zFile, mode & 0777) ){
2507342292Scy        rc = 1;
2508342292Scy      }
2509342292Scy      if( rc ) return 2;
2510342292Scy      sqlite3_result_int64(pCtx, nWrite);
2511342292Scy    }
2512342292Scy  }
2513342292Scy
2514342292Scy  if( mtime>=0 ){
2515342292Scy#if defined(_WIN32)
2516362190Scy#if !SQLITE_OS_WINRT
2517342292Scy    /* Windows */
2518342292Scy    FILETIME lastAccess;
2519342292Scy    FILETIME lastWrite;
2520342292Scy    SYSTEMTIME currentTime;
2521342292Scy    LONGLONG intervals;
2522342292Scy    HANDLE hFile;
2523342292Scy    LPWSTR zUnicodeName;
2524342292Scy    extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
2525342292Scy
2526342292Scy    GetSystemTime(&currentTime);
2527342292Scy    SystemTimeToFileTime(&currentTime, &lastAccess);
2528342292Scy    intervals = Int32x32To64(mtime, 10000000) + 116444736000000000;
2529342292Scy    lastWrite.dwLowDateTime = (DWORD)intervals;
2530342292Scy    lastWrite.dwHighDateTime = intervals >> 32;
2531342292Scy    zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile);
2532342292Scy    if( zUnicodeName==0 ){
2533342292Scy      return 1;
2534342292Scy    }
2535342292Scy    hFile = CreateFileW(
2536342292Scy      zUnicodeName, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
2537342292Scy      FILE_FLAG_BACKUP_SEMANTICS, NULL
2538342292Scy    );
2539342292Scy    sqlite3_free(zUnicodeName);
2540342292Scy    if( hFile!=INVALID_HANDLE_VALUE ){
2541342292Scy      BOOL bResult = SetFileTime(hFile, NULL, &lastAccess, &lastWrite);
2542342292Scy      CloseHandle(hFile);
2543342292Scy      return !bResult;
2544342292Scy    }else{
2545342292Scy      return 1;
2546342292Scy    }
2547362190Scy#endif
2548342292Scy#elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
2549342292Scy    /* Recent unix */
2550342292Scy    struct timespec times[2];
2551342292Scy    times[0].tv_nsec = times[1].tv_nsec = 0;
2552342292Scy    times[0].tv_sec = time(0);
2553342292Scy    times[1].tv_sec = mtime;
2554342292Scy    if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){
2555342292Scy      return 1;
2556342292Scy    }
2557342292Scy#else
2558342292Scy    /* Legacy unix */
2559342292Scy    struct timeval times[2];
2560342292Scy    times[0].tv_usec = times[1].tv_usec = 0;
2561342292Scy    times[0].tv_sec = time(0);
2562342292Scy    times[1].tv_sec = mtime;
2563342292Scy    if( utimes(zFile, times) ){
2564342292Scy      return 1;
2565342292Scy    }
2566342292Scy#endif
2567342292Scy  }
2568342292Scy
2569342292Scy  return 0;
2570342292Scy}
2571342292Scy
2572342292Scy/*
2573342292Scy** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function.
2574342292Scy** Refer to header comments at the top of this file for details.
2575342292Scy*/
2576322444Speterstatic void writefileFunc(
2577322444Speter  sqlite3_context *context,
2578322444Speter  int argc,
2579322444Speter  sqlite3_value **argv
2580322444Speter){
2581322444Speter  const char *zFile;
2582342292Scy  mode_t mode = 0;
2583342292Scy  int res;
2584342292Scy  sqlite3_int64 mtime = -1;
2585322444Speter
2586342292Scy  if( argc<2 || argc>4 ){
2587342292Scy    sqlite3_result_error(context,
2588342292Scy        "wrong number of arguments to function writefile()", -1
2589342292Scy    );
2590342292Scy    return;
2591342292Scy  }
2592342292Scy
2593322444Speter  zFile = (const char*)sqlite3_value_text(argv[0]);
2594322444Speter  if( zFile==0 ) return;
2595342292Scy  if( argc>=3 ){
2596342292Scy    mode = (mode_t)sqlite3_value_int(argv[2]);
2597342292Scy  }
2598342292Scy  if( argc==4 ){
2599342292Scy    mtime = sqlite3_value_int64(argv[3]);
2600342292Scy  }
2601342292Scy
2602342292Scy  res = writeFile(context, zFile, argv[1], mode, mtime);
2603342292Scy  if( res==1 && errno==ENOENT ){
2604347347Scy    if( makeDirectory(zFile)==SQLITE_OK ){
2605342292Scy      res = writeFile(context, zFile, argv[1], mode, mtime);
2606342292Scy    }
2607342292Scy  }
2608342292Scy
2609342292Scy  if( argc>2 && res!=0 ){
2610342292Scy    if( S_ISLNK(mode) ){
2611342292Scy      ctxErrorMsg(context, "failed to create symlink: %s", zFile);
2612342292Scy    }else if( S_ISDIR(mode) ){
2613342292Scy      ctxErrorMsg(context, "failed to create directory: %s", zFile);
2614342292Scy    }else{
2615342292Scy      ctxErrorMsg(context, "failed to write file: %s", zFile);
2616342292Scy    }
2617342292Scy  }
2618342292Scy}
2619342292Scy
2620342292Scy/*
2621342292Scy** SQL function:   lsmode(MODE)
2622342292Scy**
2623342292Scy** Given a numberic st_mode from stat(), convert it into a human-readable
2624342292Scy** text string in the style of "ls -l".
2625342292Scy*/
2626342292Scystatic void lsModeFunc(
2627342292Scy  sqlite3_context *context,
2628342292Scy  int argc,
2629342292Scy  sqlite3_value **argv
2630342292Scy){
2631342292Scy  int i;
2632342292Scy  int iMode = sqlite3_value_int(argv[0]);
2633342292Scy  char z[16];
2634342292Scy  (void)argc;
2635342292Scy  if( S_ISLNK(iMode) ){
2636342292Scy    z[0] = 'l';
2637342292Scy  }else if( S_ISREG(iMode) ){
2638342292Scy    z[0] = '-';
2639342292Scy  }else if( S_ISDIR(iMode) ){
2640342292Scy    z[0] = 'd';
2641322444Speter  }else{
2642342292Scy    z[0] = '?';
2643322444Speter  }
2644342292Scy  for(i=0; i<3; i++){
2645342292Scy    int m = (iMode >> ((2-i)*3));
2646342292Scy    char *a = &z[1 + i*3];
2647342292Scy    a[0] = (m & 0x4) ? 'r' : '-';
2648342292Scy    a[1] = (m & 0x2) ? 'w' : '-';
2649342292Scy    a[2] = (m & 0x1) ? 'x' : '-';
2650342292Scy  }
2651342292Scy  z[10] = '\0';
2652342292Scy  sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
2653322444Speter}
2654322444Speter
2655342292Scy#ifndef SQLITE_OMIT_VIRTUALTABLE
2656322444Speter
2657342292Scy/*
2658342292Scy** Cursor type for recursively iterating through a directory structure.
2659342292Scy*/
2660342292Scytypedef struct fsdir_cursor fsdir_cursor;
2661342292Scytypedef struct FsdirLevel FsdirLevel;
2662342292Scy
2663342292Scystruct FsdirLevel {
2664342292Scy  DIR *pDir;                 /* From opendir() */
2665342292Scy  char *zDir;                /* Name of directory (nul-terminated) */
2666342292Scy};
2667342292Scy
2668342292Scystruct fsdir_cursor {
2669342292Scy  sqlite3_vtab_cursor base;  /* Base class - must be first */
2670342292Scy
2671342292Scy  int nLvl;                  /* Number of entries in aLvl[] array */
2672342292Scy  int iLvl;                  /* Index of current entry */
2673342292Scy  FsdirLevel *aLvl;          /* Hierarchy of directories being traversed */
2674342292Scy
2675342292Scy  const char *zBase;
2676342292Scy  int nBase;
2677342292Scy
2678342292Scy  struct stat sStat;         /* Current lstat() results */
2679342292Scy  char *zPath;               /* Path to current entry */
2680342292Scy  sqlite3_int64 iRowid;      /* Current rowid */
2681342292Scy};
2682342292Scy
2683342292Scytypedef struct fsdir_tab fsdir_tab;
2684342292Scystruct fsdir_tab {
2685342292Scy  sqlite3_vtab base;         /* Base class - must be first */
2686342292Scy};
2687342292Scy
2688342292Scy/*
2689342292Scy** Construct a new fsdir virtual table object.
2690342292Scy*/
2691342292Scystatic int fsdirConnect(
2692342292Scy  sqlite3 *db,
2693342292Scy  void *pAux,
2694342292Scy  int argc, const char *const*argv,
2695342292Scy  sqlite3_vtab **ppVtab,
2696342292Scy  char **pzErr
2697342292Scy){
2698342292Scy  fsdir_tab *pNew = 0;
2699342292Scy  int rc;
2700342292Scy  (void)pAux;
2701342292Scy  (void)argc;
2702342292Scy  (void)argv;
2703342292Scy  (void)pzErr;
2704342292Scy  rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA);
2705342292Scy  if( rc==SQLITE_OK ){
2706342292Scy    pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) );
2707342292Scy    if( pNew==0 ) return SQLITE_NOMEM;
2708342292Scy    memset(pNew, 0, sizeof(*pNew));
2709361456Scy    sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
2710342292Scy  }
2711342292Scy  *ppVtab = (sqlite3_vtab*)pNew;
2712342292Scy  return rc;
2713342292Scy}
2714342292Scy
2715342292Scy/*
2716342292Scy** This method is the destructor for fsdir vtab objects.
2717342292Scy*/
2718342292Scystatic int fsdirDisconnect(sqlite3_vtab *pVtab){
2719342292Scy  sqlite3_free(pVtab);
2720342292Scy  return SQLITE_OK;
2721342292Scy}
2722342292Scy
2723342292Scy/*
2724342292Scy** Constructor for a new fsdir_cursor object.
2725342292Scy*/
2726342292Scystatic int fsdirOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
2727342292Scy  fsdir_cursor *pCur;
2728342292Scy  (void)p;
2729342292Scy  pCur = sqlite3_malloc( sizeof(*pCur) );
2730342292Scy  if( pCur==0 ) return SQLITE_NOMEM;
2731342292Scy  memset(pCur, 0, sizeof(*pCur));
2732342292Scy  pCur->iLvl = -1;
2733342292Scy  *ppCursor = &pCur->base;
2734342292Scy  return SQLITE_OK;
2735342292Scy}
2736342292Scy
2737342292Scy/*
2738342292Scy** Reset a cursor back to the state it was in when first returned
2739342292Scy** by fsdirOpen().
2740342292Scy*/
2741342292Scystatic void fsdirResetCursor(fsdir_cursor *pCur){
2742342292Scy  int i;
2743342292Scy  for(i=0; i<=pCur->iLvl; i++){
2744342292Scy    FsdirLevel *pLvl = &pCur->aLvl[i];
2745342292Scy    if( pLvl->pDir ) closedir(pLvl->pDir);
2746342292Scy    sqlite3_free(pLvl->zDir);
2747342292Scy  }
2748342292Scy  sqlite3_free(pCur->zPath);
2749342292Scy  sqlite3_free(pCur->aLvl);
2750342292Scy  pCur->aLvl = 0;
2751342292Scy  pCur->zPath = 0;
2752342292Scy  pCur->zBase = 0;
2753342292Scy  pCur->nBase = 0;
2754342292Scy  pCur->nLvl = 0;
2755342292Scy  pCur->iLvl = -1;
2756342292Scy  pCur->iRowid = 1;
2757342292Scy}
2758342292Scy
2759342292Scy/*
2760342292Scy** Destructor for an fsdir_cursor.
2761342292Scy*/
2762342292Scystatic int fsdirClose(sqlite3_vtab_cursor *cur){
2763342292Scy  fsdir_cursor *pCur = (fsdir_cursor*)cur;
2764342292Scy
2765342292Scy  fsdirResetCursor(pCur);
2766342292Scy  sqlite3_free(pCur);
2767342292Scy  return SQLITE_OK;
2768342292Scy}
2769342292Scy
2770342292Scy/*
2771342292Scy** Set the error message for the virtual table associated with cursor
2772342292Scy** pCur to the results of vprintf(zFmt, ...).
2773342292Scy*/
2774342292Scystatic void fsdirSetErrmsg(fsdir_cursor *pCur, const char *zFmt, ...){
2775342292Scy  va_list ap;
2776342292Scy  va_start(ap, zFmt);
2777342292Scy  pCur->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
2778342292Scy  va_end(ap);
2779342292Scy}
2780342292Scy
2781342292Scy
2782342292Scy/*
2783342292Scy** Advance an fsdir_cursor to its next row of output.
2784342292Scy*/
2785342292Scystatic int fsdirNext(sqlite3_vtab_cursor *cur){
2786342292Scy  fsdir_cursor *pCur = (fsdir_cursor*)cur;
2787342292Scy  mode_t m = pCur->sStat.st_mode;
2788342292Scy
2789342292Scy  pCur->iRowid++;
2790342292Scy  if( S_ISDIR(m) ){
2791342292Scy    /* Descend into this directory */
2792342292Scy    int iNew = pCur->iLvl + 1;
2793342292Scy    FsdirLevel *pLvl;
2794342292Scy    if( iNew>=pCur->nLvl ){
2795342292Scy      int nNew = iNew+1;
2796346442Scy      sqlite3_int64 nByte = nNew*sizeof(FsdirLevel);
2797346442Scy      FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc64(pCur->aLvl, nByte);
2798342292Scy      if( aNew==0 ) return SQLITE_NOMEM;
2799342292Scy      memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl));
2800342292Scy      pCur->aLvl = aNew;
2801342292Scy      pCur->nLvl = nNew;
2802342292Scy    }
2803342292Scy    pCur->iLvl = iNew;
2804342292Scy    pLvl = &pCur->aLvl[iNew];
2805342292Scy
2806342292Scy    pLvl->zDir = pCur->zPath;
2807342292Scy    pCur->zPath = 0;
2808342292Scy    pLvl->pDir = opendir(pLvl->zDir);
2809342292Scy    if( pLvl->pDir==0 ){
2810342292Scy      fsdirSetErrmsg(pCur, "cannot read directory: %s", pCur->zPath);
2811342292Scy      return SQLITE_ERROR;
2812342292Scy    }
2813342292Scy  }
2814342292Scy
2815342292Scy  while( pCur->iLvl>=0 ){
2816342292Scy    FsdirLevel *pLvl = &pCur->aLvl[pCur->iLvl];
2817342292Scy    struct dirent *pEntry = readdir(pLvl->pDir);
2818342292Scy    if( pEntry ){
2819342292Scy      if( pEntry->d_name[0]=='.' ){
2820342292Scy       if( pEntry->d_name[1]=='.' && pEntry->d_name[2]=='\0' ) continue;
2821342292Scy       if( pEntry->d_name[1]=='\0' ) continue;
2822342292Scy      }
2823342292Scy      sqlite3_free(pCur->zPath);
2824342292Scy      pCur->zPath = sqlite3_mprintf("%s/%s", pLvl->zDir, pEntry->d_name);
2825342292Scy      if( pCur->zPath==0 ) return SQLITE_NOMEM;
2826342292Scy      if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
2827342292Scy        fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
2828342292Scy        return SQLITE_ERROR;
2829342292Scy      }
2830342292Scy      return SQLITE_OK;
2831342292Scy    }
2832342292Scy    closedir(pLvl->pDir);
2833342292Scy    sqlite3_free(pLvl->zDir);
2834342292Scy    pLvl->pDir = 0;
2835342292Scy    pLvl->zDir = 0;
2836342292Scy    pCur->iLvl--;
2837342292Scy  }
2838342292Scy
2839342292Scy  /* EOF */
2840342292Scy  sqlite3_free(pCur->zPath);
2841342292Scy  pCur->zPath = 0;
2842342292Scy  return SQLITE_OK;
2843342292Scy}
2844342292Scy
2845342292Scy/*
2846342292Scy** Return values of columns for the row at which the series_cursor
2847342292Scy** is currently pointing.
2848342292Scy*/
2849342292Scystatic int fsdirColumn(
2850342292Scy  sqlite3_vtab_cursor *cur,   /* The cursor */
2851342292Scy  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
2852342292Scy  int i                       /* Which column to return */
2853342292Scy){
2854342292Scy  fsdir_cursor *pCur = (fsdir_cursor*)cur;
2855342292Scy  switch( i ){
2856342292Scy    case FSDIR_COLUMN_NAME: {
2857342292Scy      sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT);
2858342292Scy      break;
2859342292Scy    }
2860342292Scy
2861342292Scy    case FSDIR_COLUMN_MODE:
2862342292Scy      sqlite3_result_int64(ctx, pCur->sStat.st_mode);
2863342292Scy      break;
2864342292Scy
2865342292Scy    case FSDIR_COLUMN_MTIME:
2866342292Scy      sqlite3_result_int64(ctx, pCur->sStat.st_mtime);
2867342292Scy      break;
2868342292Scy
2869342292Scy    case FSDIR_COLUMN_DATA: {
2870342292Scy      mode_t m = pCur->sStat.st_mode;
2871342292Scy      if( S_ISDIR(m) ){
2872342292Scy        sqlite3_result_null(ctx);
2873342292Scy#if !defined(_WIN32) && !defined(WIN32)
2874342292Scy      }else if( S_ISLNK(m) ){
2875342292Scy        char aStatic[64];
2876342292Scy        char *aBuf = aStatic;
2877346442Scy        sqlite3_int64 nBuf = 64;
2878342292Scy        int n;
2879342292Scy
2880342292Scy        while( 1 ){
2881342292Scy          n = readlink(pCur->zPath, aBuf, nBuf);
2882342292Scy          if( n<nBuf ) break;
2883342292Scy          if( aBuf!=aStatic ) sqlite3_free(aBuf);
2884342292Scy          nBuf = nBuf*2;
2885346442Scy          aBuf = sqlite3_malloc64(nBuf);
2886342292Scy          if( aBuf==0 ){
2887342292Scy            sqlite3_result_error_nomem(ctx);
2888342292Scy            return SQLITE_NOMEM;
2889342292Scy          }
2890342292Scy        }
2891342292Scy
2892342292Scy        sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT);
2893342292Scy        if( aBuf!=aStatic ) sqlite3_free(aBuf);
2894342292Scy#endif
2895342292Scy      }else{
2896342292Scy        readFileContents(ctx, pCur->zPath);
2897342292Scy      }
2898342292Scy    }
2899342292Scy    case FSDIR_COLUMN_PATH:
2900342292Scy    default: {
2901342292Scy      /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters.
2902342292Scy      ** always return their values as NULL */
2903342292Scy      break;
2904342292Scy    }
2905342292Scy  }
2906342292Scy  return SQLITE_OK;
2907342292Scy}
2908342292Scy
2909342292Scy/*
2910342292Scy** Return the rowid for the current row. In this implementation, the
2911342292Scy** first row returned is assigned rowid value 1, and each subsequent
2912342292Scy** row a value 1 more than that of the previous.
2913342292Scy*/
2914342292Scystatic int fsdirRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
2915342292Scy  fsdir_cursor *pCur = (fsdir_cursor*)cur;
2916342292Scy  *pRowid = pCur->iRowid;
2917342292Scy  return SQLITE_OK;
2918342292Scy}
2919342292Scy
2920342292Scy/*
2921342292Scy** Return TRUE if the cursor has been moved off of the last
2922342292Scy** row of output.
2923342292Scy*/
2924342292Scystatic int fsdirEof(sqlite3_vtab_cursor *cur){
2925342292Scy  fsdir_cursor *pCur = (fsdir_cursor*)cur;
2926342292Scy  return (pCur->zPath==0);
2927342292Scy}
2928342292Scy
2929342292Scy/*
2930342292Scy** xFilter callback.
2931342292Scy**
2932342292Scy** idxNum==1   PATH parameter only
2933342292Scy** idxNum==2   Both PATH and DIR supplied
2934342292Scy*/
2935342292Scystatic int fsdirFilter(
2936342292Scy  sqlite3_vtab_cursor *cur,
2937342292Scy  int idxNum, const char *idxStr,
2938342292Scy  int argc, sqlite3_value **argv
2939342292Scy){
2940342292Scy  const char *zDir = 0;
2941342292Scy  fsdir_cursor *pCur = (fsdir_cursor*)cur;
2942342292Scy  (void)idxStr;
2943342292Scy  fsdirResetCursor(pCur);
2944342292Scy
2945342292Scy  if( idxNum==0 ){
2946342292Scy    fsdirSetErrmsg(pCur, "table function fsdir requires an argument");
2947342292Scy    return SQLITE_ERROR;
2948342292Scy  }
2949342292Scy
2950342292Scy  assert( argc==idxNum && (argc==1 || argc==2) );
2951342292Scy  zDir = (const char*)sqlite3_value_text(argv[0]);
2952342292Scy  if( zDir==0 ){
2953342292Scy    fsdirSetErrmsg(pCur, "table function fsdir requires a non-NULL argument");
2954342292Scy    return SQLITE_ERROR;
2955342292Scy  }
2956342292Scy  if( argc==2 ){
2957342292Scy    pCur->zBase = (const char*)sqlite3_value_text(argv[1]);
2958342292Scy  }
2959342292Scy  if( pCur->zBase ){
2960342292Scy    pCur->nBase = (int)strlen(pCur->zBase)+1;
2961342292Scy    pCur->zPath = sqlite3_mprintf("%s/%s", pCur->zBase, zDir);
2962342292Scy  }else{
2963342292Scy    pCur->zPath = sqlite3_mprintf("%s", zDir);
2964342292Scy  }
2965342292Scy
2966342292Scy  if( pCur->zPath==0 ){
2967342292Scy    return SQLITE_NOMEM;
2968342292Scy  }
2969342292Scy  if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
2970342292Scy    fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
2971342292Scy    return SQLITE_ERROR;
2972342292Scy  }
2973342292Scy
2974342292Scy  return SQLITE_OK;
2975342292Scy}
2976342292Scy
2977342292Scy/*
2978342292Scy** SQLite will invoke this method one or more times while planning a query
2979342292Scy** that uses the generate_series virtual table.  This routine needs to create
2980342292Scy** a query plan for each invocation and compute an estimated cost for that
2981342292Scy** plan.
2982342292Scy**
2983342292Scy** In this implementation idxNum is used to represent the
2984342292Scy** query plan.  idxStr is unused.
2985342292Scy**
2986342292Scy** The query plan is represented by values of idxNum:
2987342292Scy**
2988342292Scy**  (1)  The path value is supplied by argv[0]
2989342292Scy**  (2)  Path is in argv[0] and dir is in argv[1]
2990342292Scy*/
2991342292Scystatic int fsdirBestIndex(
2992342292Scy  sqlite3_vtab *tab,
2993342292Scy  sqlite3_index_info *pIdxInfo
2994342292Scy){
2995342292Scy  int i;                 /* Loop over constraints */
2996342292Scy  int idxPath = -1;      /* Index in pIdxInfo->aConstraint of PATH= */
2997342292Scy  int idxDir = -1;       /* Index in pIdxInfo->aConstraint of DIR= */
2998342292Scy  int seenPath = 0;      /* True if an unusable PATH= constraint is seen */
2999342292Scy  int seenDir = 0;       /* True if an unusable DIR= constraint is seen */
3000342292Scy  const struct sqlite3_index_constraint *pConstraint;
3001342292Scy
3002342292Scy  (void)tab;
3003342292Scy  pConstraint = pIdxInfo->aConstraint;
3004342292Scy  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
3005342292Scy    if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
3006342292Scy    switch( pConstraint->iColumn ){
3007342292Scy      case FSDIR_COLUMN_PATH: {
3008342292Scy        if( pConstraint->usable ){
3009342292Scy          idxPath = i;
3010342292Scy          seenPath = 0;
3011342292Scy        }else if( idxPath<0 ){
3012342292Scy          seenPath = 1;
3013342292Scy        }
3014342292Scy        break;
3015342292Scy      }
3016342292Scy      case FSDIR_COLUMN_DIR: {
3017342292Scy        if( pConstraint->usable ){
3018342292Scy          idxDir = i;
3019342292Scy          seenDir = 0;
3020342292Scy        }else if( idxDir<0 ){
3021342292Scy          seenDir = 1;
3022342292Scy        }
3023342292Scy        break;
3024342292Scy      }
3025342292Scy    }
3026342292Scy  }
3027342292Scy  if( seenPath || seenDir ){
3028342292Scy    /* If input parameters are unusable, disallow this plan */
3029342292Scy    return SQLITE_CONSTRAINT;
3030342292Scy  }
3031342292Scy
3032342292Scy  if( idxPath<0 ){
3033342292Scy    pIdxInfo->idxNum = 0;
3034342292Scy    /* The pIdxInfo->estimatedCost should have been initialized to a huge
3035342292Scy    ** number.  Leave it unchanged. */
3036342292Scy    pIdxInfo->estimatedRows = 0x7fffffff;
3037342292Scy  }else{
3038342292Scy    pIdxInfo->aConstraintUsage[idxPath].omit = 1;
3039342292Scy    pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1;
3040342292Scy    if( idxDir>=0 ){
3041342292Scy      pIdxInfo->aConstraintUsage[idxDir].omit = 1;
3042342292Scy      pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2;
3043342292Scy      pIdxInfo->idxNum = 2;
3044342292Scy      pIdxInfo->estimatedCost = 10.0;
3045342292Scy    }else{
3046342292Scy      pIdxInfo->idxNum = 1;
3047342292Scy      pIdxInfo->estimatedCost = 100.0;
3048342292Scy    }
3049342292Scy  }
3050342292Scy
3051342292Scy  return SQLITE_OK;
3052342292Scy}
3053342292Scy
3054342292Scy/*
3055342292Scy** Register the "fsdir" virtual table.
3056342292Scy*/
3057342292Scystatic int fsdirRegister(sqlite3 *db){
3058342292Scy  static sqlite3_module fsdirModule = {
3059342292Scy    0,                         /* iVersion */
3060342292Scy    0,                         /* xCreate */
3061342292Scy    fsdirConnect,              /* xConnect */
3062342292Scy    fsdirBestIndex,            /* xBestIndex */
3063342292Scy    fsdirDisconnect,           /* xDisconnect */
3064342292Scy    0,                         /* xDestroy */
3065342292Scy    fsdirOpen,                 /* xOpen - open a cursor */
3066342292Scy    fsdirClose,                /* xClose - close a cursor */
3067342292Scy    fsdirFilter,               /* xFilter - configure scan constraints */
3068342292Scy    fsdirNext,                 /* xNext - advance a cursor */
3069342292Scy    fsdirEof,                  /* xEof - check for end of scan */
3070342292Scy    fsdirColumn,               /* xColumn - read data */
3071342292Scy    fsdirRowid,                /* xRowid - read data */
3072342292Scy    0,                         /* xUpdate */
3073342292Scy    0,                         /* xBegin */
3074342292Scy    0,                         /* xSync */
3075342292Scy    0,                         /* xCommit */
3076342292Scy    0,                         /* xRollback */
3077342292Scy    0,                         /* xFindMethod */
3078342292Scy    0,                         /* xRename */
3079342292Scy    0,                         /* xSavepoint */
3080342292Scy    0,                         /* xRelease */
3081342292Scy    0,                         /* xRollbackTo */
3082342292Scy    0,                         /* xShadowName */
3083342292Scy  };
3084342292Scy
3085342292Scy  int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
3086342292Scy  return rc;
3087342292Scy}
3088342292Scy#else         /* SQLITE_OMIT_VIRTUALTABLE */
3089342292Scy# define fsdirRegister(x) SQLITE_OK
3090342292Scy#endif
3091342292Scy
3092322444Speter#ifdef _WIN32
3093342292Scy
3094322444Speter#endif
3095322444Speterint sqlite3_fileio_init(
3096322444Speter  sqlite3 *db,
3097322444Speter  char **pzErrMsg,
3098322444Speter  const sqlite3_api_routines *pApi
3099322444Speter){
3100322444Speter  int rc = SQLITE_OK;
3101322444Speter  SQLITE_EXTENSION_INIT2(pApi);
3102322444Speter  (void)pzErrMsg;  /* Unused parameter */
3103361456Scy  rc = sqlite3_create_function(db, "readfile", 1,
3104361456Scy                               SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
3105322444Speter                               readfileFunc, 0, 0);
3106322444Speter  if( rc==SQLITE_OK ){
3107361456Scy    rc = sqlite3_create_function(db, "writefile", -1,
3108361456Scy                                 SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
3109322444Speter                                 writefileFunc, 0, 0);
3110322444Speter  }
3111342292Scy  if( rc==SQLITE_OK ){
3112342292Scy    rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0,
3113342292Scy                                 lsModeFunc, 0, 0);
3114342292Scy  }
3115342292Scy  if( rc==SQLITE_OK ){
3116342292Scy    rc = fsdirRegister(db);
3117342292Scy  }
3118322444Speter  return rc;
3119322444Speter}
3120322444Speter
3121322444Speter/************************* End ../ext/misc/fileio.c ********************/
3122322444Speter/************************* Begin ../ext/misc/completion.c ******************/
3123322444Speter/*
3124322444Speter** 2017-07-10
3125322444Speter**
3126322444Speter** The author disclaims copyright to this source code.  In place of
3127322444Speter** a legal notice, here is a blessing:
3128322444Speter**
3129322444Speter**    May you do good and not evil.
3130322444Speter**    May you find forgiveness for yourself and forgive others.
3131322444Speter**    May you share freely, never taking more than you give.
3132322444Speter**
3133322444Speter*************************************************************************
3134322444Speter**
3135322444Speter** This file implements an eponymous virtual table that returns suggested
3136322444Speter** completions for a partial SQL input.
3137322444Speter**
3138322444Speter** Suggested usage:
3139322444Speter**
3140322444Speter**     SELECT DISTINCT candidate COLLATE nocase
3141322444Speter**       FROM completion($prefix,$wholeline)
3142322444Speter**      ORDER BY 1;
3143322444Speter**
3144322444Speter** The two query parameters are optional.  $prefix is the text of the
3145322444Speter** current word being typed and that is to be completed.  $wholeline is
3146322444Speter** the complete input line, used for context.
3147322444Speter**
3148322444Speter** The raw completion() table might return the same candidate multiple
3149322444Speter** times, for example if the same column name is used to two or more
3150322444Speter** tables.  And the candidates are returned in an arbitrary order.  Hence,
3151322444Speter** the DISTINCT and ORDER BY are recommended.
3152322444Speter**
3153322444Speter** This virtual table operates at the speed of human typing, and so there
3154322444Speter** is no attempt to make it fast.  Even a slow implementation will be much
3155322444Speter** faster than any human can type.
3156322444Speter**
3157322444Speter*/
3158351633Scy/* #include "sqlite3ext.h" */
3159322444SpeterSQLITE_EXTENSION_INIT1
3160322444Speter#include <assert.h>
3161322444Speter#include <string.h>
3162322444Speter#include <ctype.h>
3163322444Speter
3164322444Speter#ifndef SQLITE_OMIT_VIRTUALTABLE
3165322444Speter
3166322444Speter/* completion_vtab is a subclass of sqlite3_vtab which will
3167322444Speter** serve as the underlying representation of a completion virtual table
3168322444Speter*/
3169322444Spetertypedef struct completion_vtab completion_vtab;
3170322444Speterstruct completion_vtab {
3171322444Speter  sqlite3_vtab base;  /* Base class - must be first */
3172322444Speter  sqlite3 *db;        /* Database connection for this completion vtab */
3173322444Speter};
3174322444Speter
3175322444Speter/* completion_cursor is a subclass of sqlite3_vtab_cursor which will
3176322444Speter** serve as the underlying representation of a cursor that scans
3177322444Speter** over rows of the result
3178322444Speter*/
3179322444Spetertypedef struct completion_cursor completion_cursor;
3180322444Speterstruct completion_cursor {
3181322444Speter  sqlite3_vtab_cursor base;  /* Base class - must be first */
3182322444Speter  sqlite3 *db;               /* Database connection for this cursor */
3183322444Speter  int nPrefix, nLine;        /* Number of bytes in zPrefix and zLine */
3184322444Speter  char *zPrefix;             /* The prefix for the word we want to complete */
3185322444Speter  char *zLine;               /* The whole that we want to complete */
3186322444Speter  const char *zCurrentRow;   /* Current output row */
3187342292Scy  int szRow;                 /* Length of the zCurrentRow string */
3188322444Speter  sqlite3_stmt *pStmt;       /* Current statement */
3189322444Speter  sqlite3_int64 iRowid;      /* The rowid */
3190322444Speter  int ePhase;                /* Current phase */
3191322444Speter  int j;                     /* inter-phase counter */
3192322444Speter};
3193322444Speter
3194322444Speter/* Values for ePhase:
3195322444Speter*/
3196322444Speter#define COMPLETION_FIRST_PHASE   1
3197322444Speter#define COMPLETION_KEYWORDS      1
3198322444Speter#define COMPLETION_PRAGMAS       2
3199322444Speter#define COMPLETION_FUNCTIONS     3
3200322444Speter#define COMPLETION_COLLATIONS    4
3201322444Speter#define COMPLETION_INDEXES       5
3202322444Speter#define COMPLETION_TRIGGERS      6
3203322444Speter#define COMPLETION_DATABASES     7
3204342292Scy#define COMPLETION_TABLES        8    /* Also VIEWs and TRIGGERs */
3205322444Speter#define COMPLETION_COLUMNS       9
3206322444Speter#define COMPLETION_MODULES       10
3207322444Speter#define COMPLETION_EOF           11
3208322444Speter
3209322444Speter/*
3210322444Speter** The completionConnect() method is invoked to create a new
3211322444Speter** completion_vtab that describes the completion virtual table.
3212322444Speter**
3213322444Speter** Think of this routine as the constructor for completion_vtab objects.
3214322444Speter**
3215322444Speter** All this routine needs to do is:
3216322444Speter**
3217322444Speter**    (1) Allocate the completion_vtab object and initialize all fields.
3218322444Speter**
3219322444Speter**    (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
3220322444Speter**        result set of queries against completion will look like.
3221322444Speter*/
3222322444Speterstatic int completionConnect(
3223322444Speter  sqlite3 *db,
3224322444Speter  void *pAux,
3225322444Speter  int argc, const char *const*argv,
3226322444Speter  sqlite3_vtab **ppVtab,
3227322444Speter  char **pzErr
3228322444Speter){
3229322444Speter  completion_vtab *pNew;
3230322444Speter  int rc;
3231322444Speter
3232322444Speter  (void)(pAux);    /* Unused parameter */
3233322444Speter  (void)(argc);    /* Unused parameter */
3234322444Speter  (void)(argv);    /* Unused parameter */
3235322444Speter  (void)(pzErr);   /* Unused parameter */
3236322444Speter
3237322444Speter/* Column numbers */
3238322444Speter#define COMPLETION_COLUMN_CANDIDATE 0  /* Suggested completion of the input */
3239322444Speter#define COMPLETION_COLUMN_PREFIX    1  /* Prefix of the word to be completed */
3240322444Speter#define COMPLETION_COLUMN_WHOLELINE 2  /* Entire line seen so far */
3241322444Speter#define COMPLETION_COLUMN_PHASE     3  /* ePhase - used for debugging only */
3242322444Speter
3243361456Scy  sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
3244322444Speter  rc = sqlite3_declare_vtab(db,
3245322444Speter      "CREATE TABLE x("
3246322444Speter      "  candidate TEXT,"
3247322444Speter      "  prefix TEXT HIDDEN,"
3248322444Speter      "  wholeline TEXT HIDDEN,"
3249322444Speter      "  phase INT HIDDEN"        /* Used for debugging only */
3250322444Speter      ")");
3251322444Speter  if( rc==SQLITE_OK ){
3252322444Speter    pNew = sqlite3_malloc( sizeof(*pNew) );
3253322444Speter    *ppVtab = (sqlite3_vtab*)pNew;
3254322444Speter    if( pNew==0 ) return SQLITE_NOMEM;
3255322444Speter    memset(pNew, 0, sizeof(*pNew));
3256322444Speter    pNew->db = db;
3257322444Speter  }
3258322444Speter  return rc;
3259322444Speter}
3260322444Speter
3261322444Speter/*
3262322444Speter** This method is the destructor for completion_cursor objects.
3263322444Speter*/
3264322444Speterstatic int completionDisconnect(sqlite3_vtab *pVtab){
3265322444Speter  sqlite3_free(pVtab);
3266322444Speter  return SQLITE_OK;
3267322444Speter}
3268322444Speter
3269322444Speter/*
3270322444Speter** Constructor for a new completion_cursor object.
3271322444Speter*/
3272322444Speterstatic int completionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
3273322444Speter  completion_cursor *pCur;
3274322444Speter  pCur = sqlite3_malloc( sizeof(*pCur) );
3275322444Speter  if( pCur==0 ) return SQLITE_NOMEM;
3276322444Speter  memset(pCur, 0, sizeof(*pCur));
3277322444Speter  pCur->db = ((completion_vtab*)p)->db;
3278322444Speter  *ppCursor = &pCur->base;
3279322444Speter  return SQLITE_OK;
3280322444Speter}
3281322444Speter
3282322444Speter/*
3283322444Speter** Reset the completion_cursor.
3284322444Speter*/
3285322444Speterstatic void completionCursorReset(completion_cursor *pCur){
3286322444Speter  sqlite3_free(pCur->zPrefix);   pCur->zPrefix = 0;  pCur->nPrefix = 0;
3287322444Speter  sqlite3_free(pCur->zLine);     pCur->zLine = 0;    pCur->nLine = 0;
3288322444Speter  sqlite3_finalize(pCur->pStmt); pCur->pStmt = 0;
3289322444Speter  pCur->j = 0;
3290322444Speter}
3291322444Speter
3292322444Speter/*
3293322444Speter** Destructor for a completion_cursor.
3294322444Speter*/
3295322444Speterstatic int completionClose(sqlite3_vtab_cursor *cur){
3296322444Speter  completionCursorReset((completion_cursor*)cur);
3297322444Speter  sqlite3_free(cur);
3298322444Speter  return SQLITE_OK;
3299322444Speter}
3300322444Speter
3301322444Speter/*
3302322444Speter** Advance a completion_cursor to its next row of output.
3303322444Speter**
3304322444Speter** The ->ePhase, ->j, and ->pStmt fields of the completion_cursor object
3305322444Speter** record the current state of the scan.  This routine sets ->zCurrentRow
3306322444Speter** to the current row of output and then returns.  If no more rows remain,
3307322444Speter** then ->ePhase is set to COMPLETION_EOF which will signal the virtual
3308322444Speter** table that has reached the end of its scan.
3309322444Speter**
3310322444Speter** The current implementation just lists potential identifiers and
3311322444Speter** keywords and filters them by zPrefix.  Future enhancements should
3312322444Speter** take zLine into account to try to restrict the set of identifiers and
3313322444Speter** keywords based on what would be legal at the current point of input.
3314322444Speter*/
3315322444Speterstatic int completionNext(sqlite3_vtab_cursor *cur){
3316322444Speter  completion_cursor *pCur = (completion_cursor*)cur;
3317322444Speter  int eNextPhase = 0;  /* Next phase to try if current phase reaches end */
3318322444Speter  int iCol = -1;       /* If >=0, step pCur->pStmt and use the i-th column */
3319322444Speter  pCur->iRowid++;
3320322444Speter  while( pCur->ePhase!=COMPLETION_EOF ){
3321322444Speter    switch( pCur->ePhase ){
3322322444Speter      case COMPLETION_KEYWORDS: {
3323342292Scy        if( pCur->j >= sqlite3_keyword_count() ){
3324322444Speter          pCur->zCurrentRow = 0;
3325322444Speter          pCur->ePhase = COMPLETION_DATABASES;
3326322444Speter        }else{
3327342292Scy          sqlite3_keyword_name(pCur->j++, &pCur->zCurrentRow, &pCur->szRow);
3328322444Speter        }
3329322444Speter        iCol = -1;
3330322444Speter        break;
3331322444Speter      }
3332322444Speter      case COMPLETION_DATABASES: {
3333322444Speter        if( pCur->pStmt==0 ){
3334322444Speter          sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1,
3335322444Speter                             &pCur->pStmt, 0);
3336322444Speter        }
3337322444Speter        iCol = 1;
3338322444Speter        eNextPhase = COMPLETION_TABLES;
3339322444Speter        break;
3340322444Speter      }
3341322444Speter      case COMPLETION_TABLES: {
3342322444Speter        if( pCur->pStmt==0 ){
3343322444Speter          sqlite3_stmt *pS2;
3344322444Speter          char *zSql = 0;
3345322444Speter          const char *zSep = "";
3346322444Speter          sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
3347322444Speter          while( sqlite3_step(pS2)==SQLITE_ROW ){
3348322444Speter            const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
3349322444Speter            zSql = sqlite3_mprintf(
3350322444Speter               "%z%s"
3351366076Scy               "SELECT name FROM \"%w\".sqlite_schema",
3352322444Speter               zSql, zSep, zDb
3353322444Speter            );
3354322444Speter            if( zSql==0 ) return SQLITE_NOMEM;
3355322444Speter            zSep = " UNION ";
3356322444Speter          }
3357322444Speter          sqlite3_finalize(pS2);
3358322444Speter          sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
3359322444Speter          sqlite3_free(zSql);
3360322444Speter        }
3361322444Speter        iCol = 0;
3362322444Speter        eNextPhase = COMPLETION_COLUMNS;
3363322444Speter        break;
3364322444Speter      }
3365322444Speter      case COMPLETION_COLUMNS: {
3366322444Speter        if( pCur->pStmt==0 ){
3367322444Speter          sqlite3_stmt *pS2;
3368322444Speter          char *zSql = 0;
3369322444Speter          const char *zSep = "";
3370322444Speter          sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
3371322444Speter          while( sqlite3_step(pS2)==SQLITE_ROW ){
3372322444Speter            const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
3373322444Speter            zSql = sqlite3_mprintf(
3374322444Speter               "%z%s"
3375366076Scy               "SELECT pti.name FROM \"%w\".sqlite_schema AS sm"
3376322444Speter                       " JOIN pragma_table_info(sm.name,%Q) AS pti"
3377322444Speter               " WHERE sm.type='table'",
3378322444Speter               zSql, zSep, zDb, zDb
3379322444Speter            );
3380322444Speter            if( zSql==0 ) return SQLITE_NOMEM;
3381322444Speter            zSep = " UNION ";
3382322444Speter          }
3383322444Speter          sqlite3_finalize(pS2);
3384322444Speter          sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
3385322444Speter          sqlite3_free(zSql);
3386322444Speter        }
3387322444Speter        iCol = 0;
3388322444Speter        eNextPhase = COMPLETION_EOF;
3389322444Speter        break;
3390322444Speter      }
3391322444Speter    }
3392322444Speter    if( iCol<0 ){
3393322444Speter      /* This case is when the phase presets zCurrentRow */
3394322444Speter      if( pCur->zCurrentRow==0 ) continue;
3395322444Speter    }else{
3396322444Speter      if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){
3397322444Speter        /* Extract the next row of content */
3398322444Speter        pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol);
3399342292Scy        pCur->szRow = sqlite3_column_bytes(pCur->pStmt, iCol);
3400322444Speter      }else{
3401322444Speter        /* When all rows are finished, advance to the next phase */
3402322444Speter        sqlite3_finalize(pCur->pStmt);
3403322444Speter        pCur->pStmt = 0;
3404322444Speter        pCur->ePhase = eNextPhase;
3405322444Speter        continue;
3406322444Speter      }
3407322444Speter    }
3408322444Speter    if( pCur->nPrefix==0 ) break;
3409342292Scy    if( pCur->nPrefix<=pCur->szRow
3410342292Scy     && sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0
3411342292Scy    ){
3412322444Speter      break;
3413322444Speter    }
3414322444Speter  }
3415322444Speter
3416322444Speter  return SQLITE_OK;
3417322444Speter}
3418322444Speter
3419322444Speter/*
3420322444Speter** Return values of columns for the row at which the completion_cursor
3421322444Speter** is currently pointing.
3422322444Speter*/
3423322444Speterstatic int completionColumn(
3424322444Speter  sqlite3_vtab_cursor *cur,   /* The cursor */
3425322444Speter  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
3426322444Speter  int i                       /* Which column to return */
3427322444Speter){
3428322444Speter  completion_cursor *pCur = (completion_cursor*)cur;
3429322444Speter  switch( i ){
3430322444Speter    case COMPLETION_COLUMN_CANDIDATE: {
3431342292Scy      sqlite3_result_text(ctx, pCur->zCurrentRow, pCur->szRow,SQLITE_TRANSIENT);
3432322444Speter      break;
3433322444Speter    }
3434322444Speter    case COMPLETION_COLUMN_PREFIX: {
3435322444Speter      sqlite3_result_text(ctx, pCur->zPrefix, -1, SQLITE_TRANSIENT);
3436322444Speter      break;
3437322444Speter    }
3438322444Speter    case COMPLETION_COLUMN_WHOLELINE: {
3439322444Speter      sqlite3_result_text(ctx, pCur->zLine, -1, SQLITE_TRANSIENT);
3440322444Speter      break;
3441322444Speter    }
3442322444Speter    case COMPLETION_COLUMN_PHASE: {
3443322444Speter      sqlite3_result_int(ctx, pCur->ePhase);
3444322444Speter      break;
3445322444Speter    }
3446322444Speter  }
3447322444Speter  return SQLITE_OK;
3448322444Speter}
3449322444Speter
3450322444Speter/*
3451322444Speter** Return the rowid for the current row.  In this implementation, the
3452322444Speter** rowid is the same as the output value.
3453322444Speter*/
3454322444Speterstatic int completionRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
3455322444Speter  completion_cursor *pCur = (completion_cursor*)cur;
3456322444Speter  *pRowid = pCur->iRowid;
3457322444Speter  return SQLITE_OK;
3458322444Speter}
3459322444Speter
3460322444Speter/*
3461322444Speter** Return TRUE if the cursor has been moved off of the last
3462322444Speter** row of output.
3463322444Speter*/
3464322444Speterstatic int completionEof(sqlite3_vtab_cursor *cur){
3465322444Speter  completion_cursor *pCur = (completion_cursor*)cur;
3466322444Speter  return pCur->ePhase >= COMPLETION_EOF;
3467322444Speter}
3468322444Speter
3469322444Speter/*
3470322444Speter** This method is called to "rewind" the completion_cursor object back
3471322444Speter** to the first row of output.  This method is always called at least
3472322444Speter** once prior to any call to completionColumn() or completionRowid() or
3473322444Speter** completionEof().
3474322444Speter*/
3475322444Speterstatic int completionFilter(
3476322444Speter  sqlite3_vtab_cursor *pVtabCursor,
3477322444Speter  int idxNum, const char *idxStr,
3478322444Speter  int argc, sqlite3_value **argv
3479322444Speter){
3480322444Speter  completion_cursor *pCur = (completion_cursor *)pVtabCursor;
3481322444Speter  int iArg = 0;
3482322444Speter  (void)(idxStr);   /* Unused parameter */
3483322444Speter  (void)(argc);     /* Unused parameter */
3484322444Speter  completionCursorReset(pCur);
3485322444Speter  if( idxNum & 1 ){
3486322444Speter    pCur->nPrefix = sqlite3_value_bytes(argv[iArg]);
3487322444Speter    if( pCur->nPrefix>0 ){
3488322444Speter      pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
3489322444Speter      if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
3490322444Speter    }
3491342292Scy    iArg = 1;
3492322444Speter  }
3493322444Speter  if( idxNum & 2 ){
3494322444Speter    pCur->nLine = sqlite3_value_bytes(argv[iArg]);
3495322444Speter    if( pCur->nLine>0 ){
3496322444Speter      pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
3497322444Speter      if( pCur->zLine==0 ) return SQLITE_NOMEM;
3498322444Speter    }
3499322444Speter  }
3500322444Speter  if( pCur->zLine!=0 && pCur->zPrefix==0 ){
3501322444Speter    int i = pCur->nLine;
3502322444Speter    while( i>0 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
3503322444Speter      i--;
3504322444Speter    }
3505322444Speter    pCur->nPrefix = pCur->nLine - i;
3506322444Speter    if( pCur->nPrefix>0 ){
3507322444Speter      pCur->zPrefix = sqlite3_mprintf("%.*s", pCur->nPrefix, pCur->zLine + i);
3508322444Speter      if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
3509322444Speter    }
3510322444Speter  }
3511322444Speter  pCur->iRowid = 0;
3512322444Speter  pCur->ePhase = COMPLETION_FIRST_PHASE;
3513322444Speter  return completionNext(pVtabCursor);
3514322444Speter}
3515322444Speter
3516322444Speter/*
3517322444Speter** SQLite will invoke this method one or more times while planning a query
3518322444Speter** that uses the completion virtual table.  This routine needs to create
3519322444Speter** a query plan for each invocation and compute an estimated cost for that
3520322444Speter** plan.
3521322444Speter**
3522322444Speter** There are two hidden parameters that act as arguments to the table-valued
3523322444Speter** function:  "prefix" and "wholeline".  Bit 0 of idxNum is set if "prefix"
3524322444Speter** is available and bit 1 is set if "wholeline" is available.
3525322444Speter*/
3526322444Speterstatic int completionBestIndex(
3527322444Speter  sqlite3_vtab *tab,
3528322444Speter  sqlite3_index_info *pIdxInfo
3529322444Speter){
3530322444Speter  int i;                 /* Loop over constraints */
3531322444Speter  int idxNum = 0;        /* The query plan bitmask */
3532322444Speter  int prefixIdx = -1;    /* Index of the start= constraint, or -1 if none */
3533322444Speter  int wholelineIdx = -1; /* Index of the stop= constraint, or -1 if none */
3534322444Speter  int nArg = 0;          /* Number of arguments that completeFilter() expects */
3535322444Speter  const struct sqlite3_index_constraint *pConstraint;
3536322444Speter
3537322444Speter  (void)(tab);    /* Unused parameter */
3538322444Speter  pConstraint = pIdxInfo->aConstraint;
3539322444Speter  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
3540322444Speter    if( pConstraint->usable==0 ) continue;
3541322444Speter    if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
3542322444Speter    switch( pConstraint->iColumn ){
3543322444Speter      case COMPLETION_COLUMN_PREFIX:
3544322444Speter        prefixIdx = i;
3545322444Speter        idxNum |= 1;
3546322444Speter        break;
3547322444Speter      case COMPLETION_COLUMN_WHOLELINE:
3548322444Speter        wholelineIdx = i;
3549322444Speter        idxNum |= 2;
3550322444Speter        break;
3551322444Speter    }
3552322444Speter  }
3553322444Speter  if( prefixIdx>=0 ){
3554322444Speter    pIdxInfo->aConstraintUsage[prefixIdx].argvIndex = ++nArg;
3555322444Speter    pIdxInfo->aConstraintUsage[prefixIdx].omit = 1;
3556322444Speter  }
3557322444Speter  if( wholelineIdx>=0 ){
3558322444Speter    pIdxInfo->aConstraintUsage[wholelineIdx].argvIndex = ++nArg;
3559322444Speter    pIdxInfo->aConstraintUsage[wholelineIdx].omit = 1;
3560322444Speter  }
3561322444Speter  pIdxInfo->idxNum = idxNum;
3562322444Speter  pIdxInfo->estimatedCost = (double)5000 - 1000*nArg;
3563322444Speter  pIdxInfo->estimatedRows = 500 - 100*nArg;
3564322444Speter  return SQLITE_OK;
3565322444Speter}
3566322444Speter
3567322444Speter/*
3568322444Speter** This following structure defines all the methods for the
3569322444Speter** completion virtual table.
3570322444Speter*/
3571322444Speterstatic sqlite3_module completionModule = {
3572322444Speter  0,                         /* iVersion */
3573322444Speter  0,                         /* xCreate */
3574322444Speter  completionConnect,         /* xConnect */
3575322444Speter  completionBestIndex,       /* xBestIndex */
3576322444Speter  completionDisconnect,      /* xDisconnect */
3577322444Speter  0,                         /* xDestroy */
3578322444Speter  completionOpen,            /* xOpen - open a cursor */
3579322444Speter  completionClose,           /* xClose - close a cursor */
3580322444Speter  completionFilter,          /* xFilter - configure scan constraints */
3581322444Speter  completionNext,            /* xNext - advance a cursor */
3582322444Speter  completionEof,             /* xEof - check for end of scan */
3583322444Speter  completionColumn,          /* xColumn - read data */
3584322444Speter  completionRowid,           /* xRowid - read data */
3585322444Speter  0,                         /* xUpdate */
3586322444Speter  0,                         /* xBegin */
3587322444Speter  0,                         /* xSync */
3588322444Speter  0,                         /* xCommit */
3589322444Speter  0,                         /* xRollback */
3590322444Speter  0,                         /* xFindMethod */
3591322444Speter  0,                         /* xRename */
3592322444Speter  0,                         /* xSavepoint */
3593322444Speter  0,                         /* xRelease */
3594342292Scy  0,                         /* xRollbackTo */
3595342292Scy  0                          /* xShadowName */
3596322444Speter};
3597322444Speter
3598322444Speter#endif /* SQLITE_OMIT_VIRTUALTABLE */
3599322444Speter
3600322444Speterint sqlite3CompletionVtabInit(sqlite3 *db){
3601322444Speter  int rc = SQLITE_OK;
3602322444Speter#ifndef SQLITE_OMIT_VIRTUALTABLE
3603322444Speter  rc = sqlite3_create_module(db, "completion", &completionModule, 0);
3604322444Speter#endif
3605322444Speter  return rc;
3606322444Speter}
3607322444Speter
3608322444Speter#ifdef _WIN32
3609342292Scy
3610322444Speter#endif
3611322444Speterint sqlite3_completion_init(
3612322444Speter  sqlite3 *db,
3613322444Speter  char **pzErrMsg,
3614322444Speter  const sqlite3_api_routines *pApi
3615322444Speter){
3616322444Speter  int rc = SQLITE_OK;
3617322444Speter  SQLITE_EXTENSION_INIT2(pApi);
3618322444Speter  (void)(pzErrMsg);  /* Unused parameter */
3619322444Speter#ifndef SQLITE_OMIT_VIRTUALTABLE
3620322444Speter  rc = sqlite3CompletionVtabInit(db);
3621322444Speter#endif
3622322444Speter  return rc;
3623322444Speter}
3624322444Speter
3625322444Speter/************************* End ../ext/misc/completion.c ********************/
3626342292Scy/************************* Begin ../ext/misc/appendvfs.c ******************/
3627342292Scy/*
3628342292Scy** 2017-10-20
3629342292Scy**
3630342292Scy** The author disclaims copyright to this source code.  In place of
3631342292Scy** a legal notice, here is a blessing:
3632342292Scy**
3633342292Scy**    May you do good and not evil.
3634342292Scy**    May you find forgiveness for yourself and forgive others.
3635342292Scy**    May you share freely, never taking more than you give.
3636342292Scy**
3637342292Scy******************************************************************************
3638342292Scy**
3639342292Scy** This file implements a VFS shim that allows an SQLite database to be
3640342292Scy** appended onto the end of some other file, such as an executable.
3641342292Scy**
3642342292Scy** A special record must appear at the end of the file that identifies the
3643369951Scy** file as an appended database and provides the offset to the first page
3644369951Scy** of the exposed content. (Or, it is the length of the content prefix.)
3645369951Scy** For best performance page 1 should be located at a disk page boundary,
3646369951Scy** though that is not required.
3647342292Scy**
3648342292Scy** When opening a database using this VFS, the connection might treat
3649369951Scy** the file as an ordinary SQLite database, or it might treat it as a
3650369951Scy** database appended onto some other file.  The decision is made by
3651369951Scy** applying the following rules in order:
3652342292Scy**
3653369951Scy**  (1)  An empty file is an ordinary database.
3654342292Scy**
3655369951Scy**  (2)  If the file ends with the appendvfs trailer string
3656369951Scy**       "Start-Of-SQLite3-NNNNNNNN" that file is an appended database.
3657342292Scy**
3658369951Scy**  (3)  If the file begins with the standard SQLite prefix string
3659369951Scy**       "SQLite format 3", that file is an ordinary database.
3660342292Scy**
3661342292Scy**  (4)  If none of the above apply and the SQLITE_OPEN_CREATE flag is
3662342292Scy**       set, then a new database is appended to the already existing file.
3663342292Scy**
3664342292Scy**  (5)  Otherwise, SQLITE_CANTOPEN is returned.
3665342292Scy**
3666342292Scy** To avoid unnecessary complications with the PENDING_BYTE, the size of
3667369951Scy** the file containing the database is limited to 1GiB. (1073741824 bytes)
3668369951Scy** This VFS will not read or write past the 1GiB mark.  This restriction
3669369951Scy** might be lifted in future versions.  For now, if you need a larger
3670369951Scy** database, then keep it in a separate file.
3671342292Scy**
3672369951Scy** If the file being opened is a plain database (not an appended one), then
3673369951Scy** this shim is a pass-through into the default underlying VFS. (rule 3)
3674342292Scy**/
3675351633Scy/* #include "sqlite3ext.h" */
3676342292ScySQLITE_EXTENSION_INIT1
3677342292Scy#include <string.h>
3678342292Scy#include <assert.h>
3679322444Speter
3680342292Scy/* The append mark at the end of the database is:
3681342292Scy**
3682342292Scy**     Start-Of-SQLite3-NNNNNNNN
3683342292Scy**     123456789 123456789 12345
3684342292Scy**
3685342292Scy** The NNNNNNNN represents a 64-bit big-endian unsigned integer which is
3686369951Scy** the offset to page 1, and also the length of the prefix content.
3687342292Scy*/
3688342292Scy#define APND_MARK_PREFIX     "Start-Of-SQLite3-"
3689342292Scy#define APND_MARK_PREFIX_SZ  17
3690369951Scy#define APND_MARK_FOS_SZ      8
3691369951Scy#define APND_MARK_SIZE       (APND_MARK_PREFIX_SZ+APND_MARK_FOS_SZ)
3692342292Scy
3693342292Scy/*
3694342292Scy** Maximum size of the combined prefix + database + append-mark.  This
3695342292Scy** must be less than 0x40000000 to avoid locking issues on Windows.
3696342292Scy*/
3697369951Scy#define APND_MAX_SIZE  (0x40000000)
3698342292Scy
3699342292Scy/*
3700369951Scy** Try to align the database to an even multiple of APND_ROUNDUP bytes.
3701369951Scy*/
3702369951Scy#ifndef APND_ROUNDUP
3703369951Scy#define APND_ROUNDUP 4096
3704369951Scy#endif
3705369951Scy#define APND_ALIGN_MASK         ((sqlite3_int64)(APND_ROUNDUP-1))
3706369951Scy#define APND_START_ROUNDUP(fsz) (((fsz)+APND_ALIGN_MASK) & ~APND_ALIGN_MASK)
3707369951Scy
3708369951Scy/*
3709342292Scy** Forward declaration of objects used by this utility
3710342292Scy*/
3711342292Scytypedef struct sqlite3_vfs ApndVfs;
3712342292Scytypedef struct ApndFile ApndFile;
3713342292Scy
3714342292Scy/* Access to a lower-level VFS that (might) implement dynamic loading,
3715342292Scy** access to randomness, etc.
3716342292Scy*/
3717342292Scy#define ORIGVFS(p)  ((sqlite3_vfs*)((p)->pAppData))
3718342292Scy#define ORIGFILE(p) ((sqlite3_file*)(((ApndFile*)(p))+1))
3719342292Scy
3720369951Scy/* An open appendvfs file
3721369951Scy**
3722369951Scy** An instance of this structure describes the appended database file.
3723369951Scy** A separate sqlite3_file object is always appended. The appended
3724369951Scy** sqlite3_file object (which can be accessed using ORIGFILE()) describes
3725369951Scy** the entire file, including the prefix, the database, and the
3726369951Scy** append-mark.
3727369951Scy**
3728369951Scy** The structure of an AppendVFS database is like this:
3729369951Scy**
3730369951Scy**   +-------------+---------+----------+-------------+
3731369951Scy**   | prefix-file | padding | database | append-mark |
3732369951Scy**   +-------------+---------+----------+-------------+
3733369951Scy**                           ^          ^
3734369951Scy**                           |          |
3735369951Scy**                         iPgOne      iMark
3736369951Scy**
3737369951Scy**
3738369951Scy** "prefix file" -  file onto which the database has been appended.
3739369951Scy** "padding"     -  zero or more bytes inserted so that "database"
3740369951Scy**                  starts on an APND_ROUNDUP boundary
3741369951Scy** "database"    -  The SQLite database file
3742369951Scy** "append-mark" -  The 25-byte "Start-Of-SQLite3-NNNNNNNN" that indicates
3743369951Scy**                  the offset from the start of prefix-file to the start
3744369951Scy**                  of "database".
3745369951Scy**
3746369951Scy** The size of the database is iMark - iPgOne.
3747369951Scy**
3748369951Scy** The NNNNNNNN in the "Start-Of-SQLite3-NNNNNNNN" suffix is the value
3749369951Scy** of iPgOne stored as a big-ending 64-bit integer.
3750369951Scy**
3751369951Scy** iMark will be the size of the underlying file minus 25 (APND_MARKSIZE).
3752369951Scy** Or, iMark is -1 to indicate that it has not yet been written.
3753369951Scy*/
3754342292Scystruct ApndFile {
3755369951Scy  sqlite3_file base;        /* Subclass.  MUST BE FIRST! */
3756369951Scy  sqlite3_int64 iPgOne;     /* Offset to the start of the database */
3757369951Scy  sqlite3_int64 iMark;      /* Offset of the append mark.  -1 if unwritten */
3758369951Scy  /* Always followed by another sqlite3_file that describes the whole file */
3759342292Scy};
3760342292Scy
3761342292Scy/*
3762342292Scy** Methods for ApndFile
3763342292Scy*/
3764342292Scystatic int apndClose(sqlite3_file*);
3765342292Scystatic int apndRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
3766342292Scystatic int apndWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
3767342292Scystatic int apndTruncate(sqlite3_file*, sqlite3_int64 size);
3768342292Scystatic int apndSync(sqlite3_file*, int flags);
3769342292Scystatic int apndFileSize(sqlite3_file*, sqlite3_int64 *pSize);
3770342292Scystatic int apndLock(sqlite3_file*, int);
3771342292Scystatic int apndUnlock(sqlite3_file*, int);
3772342292Scystatic int apndCheckReservedLock(sqlite3_file*, int *pResOut);
3773342292Scystatic int apndFileControl(sqlite3_file*, int op, void *pArg);
3774342292Scystatic int apndSectorSize(sqlite3_file*);
3775342292Scystatic int apndDeviceCharacteristics(sqlite3_file*);
3776342292Scystatic int apndShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
3777342292Scystatic int apndShmLock(sqlite3_file*, int offset, int n, int flags);
3778342292Scystatic void apndShmBarrier(sqlite3_file*);
3779342292Scystatic int apndShmUnmap(sqlite3_file*, int deleteFlag);
3780342292Scystatic int apndFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
3781342292Scystatic int apndUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
3782342292Scy
3783342292Scy/*
3784342292Scy** Methods for ApndVfs
3785342292Scy*/
3786342292Scystatic int apndOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
3787342292Scystatic int apndDelete(sqlite3_vfs*, const char *zName, int syncDir);
3788342292Scystatic int apndAccess(sqlite3_vfs*, const char *zName, int flags, int *);
3789342292Scystatic int apndFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
3790342292Scystatic void *apndDlOpen(sqlite3_vfs*, const char *zFilename);
3791342292Scystatic void apndDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
3792342292Scystatic void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
3793342292Scystatic void apndDlClose(sqlite3_vfs*, void*);
3794342292Scystatic int apndRandomness(sqlite3_vfs*, int nByte, char *zOut);
3795342292Scystatic int apndSleep(sqlite3_vfs*, int microseconds);
3796342292Scystatic int apndCurrentTime(sqlite3_vfs*, double*);
3797342292Scystatic int apndGetLastError(sqlite3_vfs*, int, char *);
3798342292Scystatic int apndCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
3799342292Scystatic int apndSetSystemCall(sqlite3_vfs*, const char*,sqlite3_syscall_ptr);
3800342292Scystatic sqlite3_syscall_ptr apndGetSystemCall(sqlite3_vfs*, const char *z);
3801342292Scystatic const char *apndNextSystemCall(sqlite3_vfs*, const char *zName);
3802342292Scy
3803342292Scystatic sqlite3_vfs apnd_vfs = {
3804342292Scy  3,                            /* iVersion (set when registered) */
3805342292Scy  0,                            /* szOsFile (set when registered) */
3806342292Scy  1024,                         /* mxPathname */
3807342292Scy  0,                            /* pNext */
3808342292Scy  "apndvfs",                    /* zName */
3809342292Scy  0,                            /* pAppData (set when registered) */
3810342292Scy  apndOpen,                     /* xOpen */
3811342292Scy  apndDelete,                   /* xDelete */
3812342292Scy  apndAccess,                   /* xAccess */
3813342292Scy  apndFullPathname,             /* xFullPathname */
3814342292Scy  apndDlOpen,                   /* xDlOpen */
3815342292Scy  apndDlError,                  /* xDlError */
3816342292Scy  apndDlSym,                    /* xDlSym */
3817342292Scy  apndDlClose,                  /* xDlClose */
3818342292Scy  apndRandomness,               /* xRandomness */
3819342292Scy  apndSleep,                    /* xSleep */
3820342292Scy  apndCurrentTime,              /* xCurrentTime */
3821342292Scy  apndGetLastError,             /* xGetLastError */
3822342292Scy  apndCurrentTimeInt64,         /* xCurrentTimeInt64 */
3823342292Scy  apndSetSystemCall,            /* xSetSystemCall */
3824342292Scy  apndGetSystemCall,            /* xGetSystemCall */
3825342292Scy  apndNextSystemCall            /* xNextSystemCall */
3826342292Scy};
3827342292Scy
3828342292Scystatic const sqlite3_io_methods apnd_io_methods = {
3829342292Scy  3,                              /* iVersion */
3830342292Scy  apndClose,                      /* xClose */
3831342292Scy  apndRead,                       /* xRead */
3832342292Scy  apndWrite,                      /* xWrite */
3833342292Scy  apndTruncate,                   /* xTruncate */
3834342292Scy  apndSync,                       /* xSync */
3835342292Scy  apndFileSize,                   /* xFileSize */
3836342292Scy  apndLock,                       /* xLock */
3837342292Scy  apndUnlock,                     /* xUnlock */
3838342292Scy  apndCheckReservedLock,          /* xCheckReservedLock */
3839342292Scy  apndFileControl,                /* xFileControl */
3840342292Scy  apndSectorSize,                 /* xSectorSize */
3841342292Scy  apndDeviceCharacteristics,      /* xDeviceCharacteristics */
3842342292Scy  apndShmMap,                     /* xShmMap */
3843342292Scy  apndShmLock,                    /* xShmLock */
3844342292Scy  apndShmBarrier,                 /* xShmBarrier */
3845342292Scy  apndShmUnmap,                   /* xShmUnmap */
3846342292Scy  apndFetch,                      /* xFetch */
3847342292Scy  apndUnfetch                     /* xUnfetch */
3848342292Scy};
3849342292Scy
3850342292Scy/*
3851342292Scy** Close an apnd-file.
3852342292Scy*/
3853342292Scystatic int apndClose(sqlite3_file *pFile){
3854342292Scy  pFile = ORIGFILE(pFile);
3855342292Scy  return pFile->pMethods->xClose(pFile);
3856342292Scy}
3857342292Scy
3858342292Scy/*
3859342292Scy** Read data from an apnd-file.
3860342292Scy*/
3861342292Scystatic int apndRead(
3862342292Scy  sqlite3_file *pFile,
3863342292Scy  void *zBuf,
3864342292Scy  int iAmt,
3865342292Scy  sqlite_int64 iOfst
3866342292Scy){
3867369951Scy  ApndFile *paf = (ApndFile *)pFile;
3868342292Scy  pFile = ORIGFILE(pFile);
3869369951Scy  return pFile->pMethods->xRead(pFile, zBuf, iAmt, paf->iPgOne+iOfst);
3870342292Scy}
3871342292Scy
3872342292Scy/*
3873369951Scy** Add the append-mark onto what should become the end of the file.
3874369951Scy*  If and only if this succeeds, internal ApndFile.iMark is updated.
3875369951Scy*  Parameter iWriteEnd is the appendvfs-relative offset of the new mark.
3876342292Scy*/
3877369951Scystatic int apndWriteMark(
3878369951Scy  ApndFile *paf,
3879369951Scy  sqlite3_file *pFile,
3880369951Scy  sqlite_int64 iWriteEnd
3881369951Scy){
3882369951Scy  sqlite_int64 iPgOne = paf->iPgOne;
3883342292Scy  unsigned char a[APND_MARK_SIZE];
3884369951Scy  int i = APND_MARK_FOS_SZ;
3885369951Scy  int rc;
3886369951Scy  assert(pFile == ORIGFILE(paf));
3887342292Scy  memcpy(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ);
3888369951Scy  while( --i >= 0 ){
3889369951Scy    a[APND_MARK_PREFIX_SZ+i] = (unsigned char)(iPgOne & 0xff);
3890369951Scy    iPgOne >>= 8;
3891342292Scy  }
3892369951Scy  iWriteEnd += paf->iPgOne;
3893369951Scy  if( SQLITE_OK==(rc = pFile->pMethods->xWrite
3894369951Scy                  (pFile, a, APND_MARK_SIZE, iWriteEnd)) ){
3895369951Scy    paf->iMark = iWriteEnd;
3896369951Scy  }
3897369951Scy  return rc;
3898342292Scy}
3899342292Scy
3900342292Scy/*
3901342292Scy** Write data to an apnd-file.
3902342292Scy*/
3903342292Scystatic int apndWrite(
3904342292Scy  sqlite3_file *pFile,
3905342292Scy  const void *zBuf,
3906342292Scy  int iAmt,
3907342292Scy  sqlite_int64 iOfst
3908342292Scy){
3909369951Scy  ApndFile *paf = (ApndFile *)pFile;
3910369951Scy  sqlite_int64 iWriteEnd = iOfst + iAmt;
3911369951Scy  if( iWriteEnd>=APND_MAX_SIZE ) return SQLITE_FULL;
3912342292Scy  pFile = ORIGFILE(pFile);
3913369951Scy  /* If append-mark is absent or will be overwritten, write it. */
3914369951Scy  if( paf->iMark < 0 || paf->iPgOne + iWriteEnd > paf->iMark ){
3915369951Scy    int rc = apndWriteMark(paf, pFile, iWriteEnd);
3916369951Scy    if( SQLITE_OK!=rc ) return rc;
3917342292Scy  }
3918369951Scy  return pFile->pMethods->xWrite(pFile, zBuf, iAmt, paf->iPgOne+iOfst);
3919342292Scy}
3920342292Scy
3921342292Scy/*
3922342292Scy** Truncate an apnd-file.
3923342292Scy*/
3924342292Scystatic int apndTruncate(sqlite3_file *pFile, sqlite_int64 size){
3925369951Scy  ApndFile *paf = (ApndFile *)pFile;
3926342292Scy  pFile = ORIGFILE(pFile);
3927369951Scy  /* The append mark goes out first so truncate failure does not lose it. */
3928369951Scy  if( SQLITE_OK!=apndWriteMark(paf, pFile, size) ) return SQLITE_IOERR;
3929369951Scy  /* Truncate underlying file just past append mark */
3930369951Scy  return pFile->pMethods->xTruncate(pFile, paf->iMark+APND_MARK_SIZE);
3931342292Scy}
3932342292Scy
3933342292Scy/*
3934342292Scy** Sync an apnd-file.
3935342292Scy*/
3936342292Scystatic int apndSync(sqlite3_file *pFile, int flags){
3937342292Scy  pFile = ORIGFILE(pFile);
3938342292Scy  return pFile->pMethods->xSync(pFile, flags);
3939342292Scy}
3940342292Scy
3941342292Scy/*
3942342292Scy** Return the current file-size of an apnd-file.
3943369951Scy** If the append mark is not yet there, the file-size is 0.
3944342292Scy*/
3945342292Scystatic int apndFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
3946369951Scy  ApndFile *paf = (ApndFile *)pFile;
3947369951Scy  *pSize = ( paf->iMark >= 0 )? (paf->iMark - paf->iPgOne) : 0;
3948369951Scy  return SQLITE_OK;
3949342292Scy}
3950342292Scy
3951342292Scy/*
3952342292Scy** Lock an apnd-file.
3953342292Scy*/
3954342292Scystatic int apndLock(sqlite3_file *pFile, int eLock){
3955342292Scy  pFile = ORIGFILE(pFile);
3956342292Scy  return pFile->pMethods->xLock(pFile, eLock);
3957342292Scy}
3958342292Scy
3959342292Scy/*
3960342292Scy** Unlock an apnd-file.
3961342292Scy*/
3962342292Scystatic int apndUnlock(sqlite3_file *pFile, int eLock){
3963342292Scy  pFile = ORIGFILE(pFile);
3964342292Scy  return pFile->pMethods->xUnlock(pFile, eLock);
3965342292Scy}
3966342292Scy
3967342292Scy/*
3968342292Scy** Check if another file-handle holds a RESERVED lock on an apnd-file.
3969342292Scy*/
3970342292Scystatic int apndCheckReservedLock(sqlite3_file *pFile, int *pResOut){
3971342292Scy  pFile = ORIGFILE(pFile);
3972342292Scy  return pFile->pMethods->xCheckReservedLock(pFile, pResOut);
3973342292Scy}
3974342292Scy
3975342292Scy/*
3976342292Scy** File control method. For custom operations on an apnd-file.
3977342292Scy*/
3978342292Scystatic int apndFileControl(sqlite3_file *pFile, int op, void *pArg){
3979369951Scy  ApndFile *paf = (ApndFile *)pFile;
3980342292Scy  int rc;
3981342292Scy  pFile = ORIGFILE(pFile);
3982369951Scy  if( op==SQLITE_FCNTL_SIZE_HINT ) *(sqlite3_int64*)pArg += paf->iPgOne;
3983342292Scy  rc = pFile->pMethods->xFileControl(pFile, op, pArg);
3984342292Scy  if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
3985369951Scy    *(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", paf->iPgOne,*(char**)pArg);
3986342292Scy  }
3987342292Scy  return rc;
3988342292Scy}
3989342292Scy
3990342292Scy/*
3991342292Scy** Return the sector-size in bytes for an apnd-file.
3992342292Scy*/
3993342292Scystatic int apndSectorSize(sqlite3_file *pFile){
3994342292Scy  pFile = ORIGFILE(pFile);
3995342292Scy  return pFile->pMethods->xSectorSize(pFile);
3996342292Scy}
3997342292Scy
3998342292Scy/*
3999342292Scy** Return the device characteristic flags supported by an apnd-file.
4000342292Scy*/
4001342292Scystatic int apndDeviceCharacteristics(sqlite3_file *pFile){
4002342292Scy  pFile = ORIGFILE(pFile);
4003342292Scy  return pFile->pMethods->xDeviceCharacteristics(pFile);
4004342292Scy}
4005342292Scy
4006342292Scy/* Create a shared memory file mapping */
4007342292Scystatic int apndShmMap(
4008342292Scy  sqlite3_file *pFile,
4009342292Scy  int iPg,
4010342292Scy  int pgsz,
4011342292Scy  int bExtend,
4012342292Scy  void volatile **pp
4013342292Scy){
4014342292Scy  pFile = ORIGFILE(pFile);
4015342292Scy  return pFile->pMethods->xShmMap(pFile,iPg,pgsz,bExtend,pp);
4016342292Scy}
4017342292Scy
4018342292Scy/* Perform locking on a shared-memory segment */
4019342292Scystatic int apndShmLock(sqlite3_file *pFile, int offset, int n, int flags){
4020342292Scy  pFile = ORIGFILE(pFile);
4021342292Scy  return pFile->pMethods->xShmLock(pFile,offset,n,flags);
4022342292Scy}
4023342292Scy
4024342292Scy/* Memory barrier operation on shared memory */
4025342292Scystatic void apndShmBarrier(sqlite3_file *pFile){
4026342292Scy  pFile = ORIGFILE(pFile);
4027342292Scy  pFile->pMethods->xShmBarrier(pFile);
4028342292Scy}
4029342292Scy
4030342292Scy/* Unmap a shared memory segment */
4031342292Scystatic int apndShmUnmap(sqlite3_file *pFile, int deleteFlag){
4032342292Scy  pFile = ORIGFILE(pFile);
4033342292Scy  return pFile->pMethods->xShmUnmap(pFile,deleteFlag);
4034342292Scy}
4035342292Scy
4036342292Scy/* Fetch a page of a memory-mapped file */
4037342292Scystatic int apndFetch(
4038342292Scy  sqlite3_file *pFile,
4039342292Scy  sqlite3_int64 iOfst,
4040342292Scy  int iAmt,
4041342292Scy  void **pp
4042342292Scy){
4043342292Scy  ApndFile *p = (ApndFile *)pFile;
4044369951Scy  if( p->iMark < 0 || iOfst+iAmt > p->iMark ){
4045369951Scy    return SQLITE_IOERR; /* Cannot read what is not yet there. */
4046369951Scy  }
4047342292Scy  pFile = ORIGFILE(pFile);
4048342292Scy  return pFile->pMethods->xFetch(pFile, iOfst+p->iPgOne, iAmt, pp);
4049342292Scy}
4050342292Scy
4051342292Scy/* Release a memory-mapped page */
4052342292Scystatic int apndUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
4053342292Scy  ApndFile *p = (ApndFile *)pFile;
4054342292Scy  pFile = ORIGFILE(pFile);
4055342292Scy  return pFile->pMethods->xUnfetch(pFile, iOfst+p->iPgOne, pPage);
4056342292Scy}
4057342292Scy
4058342292Scy/*
4059342292Scy** Try to read the append-mark off the end of a file.  Return the
4060369951Scy** start of the appended database if the append-mark is present.
4061369951Scy** If there is no valid append-mark, return -1;
4062369951Scy**
4063369951Scy** An append-mark is only valid if the NNNNNNNN start-of-database offset
4064369951Scy** indicates that the appended database contains at least one page.  The
4065369951Scy** start-of-database value must be a multiple of 512.
4066342292Scy*/
4067342292Scystatic sqlite3_int64 apndReadMark(sqlite3_int64 sz, sqlite3_file *pFile){
4068342292Scy  int rc, i;
4069342292Scy  sqlite3_int64 iMark;
4070369951Scy  int msbs = 8 * (APND_MARK_FOS_SZ-1);
4071342292Scy  unsigned char a[APND_MARK_SIZE];
4072342292Scy
4073369951Scy  if( APND_MARK_SIZE!=(sz & 0x1ff) ) return -1;
4074342292Scy  rc = pFile->pMethods->xRead(pFile, a, APND_MARK_SIZE, sz-APND_MARK_SIZE);
4075342292Scy  if( rc ) return -1;
4076342292Scy  if( memcmp(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ)!=0 ) return -1;
4077369951Scy  iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ] & 0x7f)) << msbs;
4078369951Scy  for(i=1; i<8; i++){
4079369951Scy    msbs -= 8;
4080369951Scy    iMark |= (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]<<msbs;
4081342292Scy  }
4082369951Scy  if( iMark > (sz - APND_MARK_SIZE - 512) ) return -1;
4083369951Scy  if( iMark & 0x1ff ) return -1;
4084342292Scy  return iMark;
4085342292Scy}
4086342292Scy
4087369951Scystatic const char apvfsSqliteHdr[] = "SQLite format 3";
4088342292Scy/*
4089369951Scy** Check to see if the file is an appendvfs SQLite database file.
4090369951Scy** Return true iff it is such. Parameter sz is the file's size.
4091369951Scy*/
4092369951Scystatic int apndIsAppendvfsDatabase(sqlite3_int64 sz, sqlite3_file *pFile){
4093369951Scy  int rc;
4094369951Scy  char zHdr[16];
4095369951Scy  sqlite3_int64 iMark = apndReadMark(sz, pFile);
4096369951Scy  if( iMark>=0 ){
4097369951Scy    /* If file has the correct end-marker, the expected odd size, and the
4098369951Scy    ** SQLite DB type marker where the end-marker puts it, then it
4099369951Scy    ** is an appendvfs database.
4100369951Scy    */
4101369951Scy    rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), iMark);
4102369951Scy    if( SQLITE_OK==rc
4103369951Scy     && memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))==0
4104369951Scy     && (sz & 0x1ff) == APND_MARK_SIZE
4105369951Scy     && sz>=512+APND_MARK_SIZE
4106369951Scy    ){
4107369951Scy      return 1; /* It's an appendvfs database */
4108369951Scy    }
4109369951Scy  }
4110369951Scy  return 0;
4111369951Scy}
4112369951Scy
4113369951Scy/*
4114369951Scy** Check to see if the file is an ordinary SQLite database file.
4115369951Scy** Return true iff so. Parameter sz is the file's size.
4116369951Scy*/
4117369951Scystatic int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){
4118369951Scy  char zHdr[16];
4119369951Scy  if( apndIsAppendvfsDatabase(sz, pFile) /* rule 2 */
4120369951Scy   || (sz & 0x1ff) != 0
4121369951Scy   || SQLITE_OK!=pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0)
4122369951Scy   || memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))!=0
4123369951Scy  ){
4124369951Scy    return 0;
4125369951Scy  }else{
4126369951Scy    return 1;
4127369951Scy  }
4128369951Scy}
4129369951Scy
4130369951Scy/*
4131342292Scy** Open an apnd file handle.
4132342292Scy*/
4133342292Scystatic int apndOpen(
4134369951Scy  sqlite3_vfs *pApndVfs,
4135342292Scy  const char *zName,
4136342292Scy  sqlite3_file *pFile,
4137342292Scy  int flags,
4138342292Scy  int *pOutFlags
4139342292Scy){
4140369951Scy  ApndFile *pApndFile = (ApndFile*)pFile;
4141369951Scy  sqlite3_file *pBaseFile = ORIGFILE(pFile);
4142369951Scy  sqlite3_vfs *pBaseVfs = ORIGVFS(pApndVfs);
4143342292Scy  int rc;
4144369951Scy  sqlite3_int64 sz = 0;
4145342292Scy  if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
4146369951Scy    /* The appendvfs is not to be used for transient or temporary databases.
4147369951Scy    ** Just use the base VFS open to initialize the given file object and
4148369951Scy    ** open the underlying file. (Appendvfs is then unused for this file.)
4149369951Scy    */
4150369951Scy    return pBaseVfs->xOpen(pBaseVfs, zName, pFile, flags, pOutFlags);
4151342292Scy  }
4152369951Scy  memset(pApndFile, 0, sizeof(ApndFile));
4153366076Scy  pFile->pMethods = &apnd_io_methods;
4154369951Scy  pApndFile->iMark = -1;    /* Append mark not yet written */
4155369951Scy
4156369951Scy  rc = pBaseVfs->xOpen(pBaseVfs, zName, pBaseFile, flags, pOutFlags);
4157369951Scy  if( rc==SQLITE_OK ){
4158369951Scy    rc = pBaseFile->pMethods->xFileSize(pBaseFile, &sz);
4159369951Scy  }
4160342292Scy  if( rc ){
4161369951Scy    pBaseFile->pMethods->xClose(pBaseFile);
4162369951Scy    pFile->pMethods = 0;
4163369951Scy    return rc;
4164342292Scy  }
4165369951Scy  if( apndIsOrdinaryDatabaseFile(sz, pBaseFile) ){
4166369951Scy    /* The file being opened appears to be just an ordinary DB. Copy
4167369951Scy    ** the base dispatch-table so this instance mimics the base VFS.
4168369951Scy    */
4169369951Scy    memmove(pApndFile, pBaseFile, pBaseVfs->szOsFile);
4170342292Scy    return SQLITE_OK;
4171342292Scy  }
4172369951Scy  pApndFile->iPgOne = apndReadMark(sz, pFile);
4173369951Scy  if( pApndFile->iPgOne>=0 ){
4174369951Scy    pApndFile->iMark = sz - APND_MARK_SIZE; /* Append mark found */
4175342292Scy    return SQLITE_OK;
4176342292Scy  }
4177342292Scy  if( (flags & SQLITE_OPEN_CREATE)==0 ){
4178369951Scy    pBaseFile->pMethods->xClose(pBaseFile);
4179342292Scy    rc = SQLITE_CANTOPEN;
4180369951Scy    pFile->pMethods = 0;
4181369951Scy  }else{
4182369951Scy    /* Round newly added appendvfs location to #define'd page boundary.
4183369951Scy    ** Note that nothing has yet been written to the underlying file.
4184369951Scy    ** The append mark will be written along with first content write.
4185369951Scy    ** Until then, paf->iMark value indicates it is not yet written.
4186369951Scy    */
4187369951Scy    pApndFile->iPgOne = APND_START_ROUNDUP(sz);
4188342292Scy  }
4189342292Scy  return rc;
4190342292Scy}
4191342292Scy
4192342292Scy/*
4193369951Scy** Delete an apnd file.
4194369951Scy** For an appendvfs, this could mean delete the appendvfs portion,
4195369951Scy** leaving the appendee as it was before it gained an appendvfs.
4196369951Scy** For now, this code deletes the underlying file too.
4197342292Scy*/
4198342292Scystatic int apndDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
4199342292Scy  return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync);
4200342292Scy}
4201369951Scy
4202369951Scy/*
4203369951Scy** All other VFS methods are pass-thrus.
4204369951Scy*/
4205342292Scystatic int apndAccess(
4206342292Scy  sqlite3_vfs *pVfs,
4207342292Scy  const char *zPath,
4208342292Scy  int flags,
4209342292Scy  int *pResOut
4210342292Scy){
4211342292Scy  return ORIGVFS(pVfs)->xAccess(ORIGVFS(pVfs), zPath, flags, pResOut);
4212342292Scy}
4213342292Scystatic int apndFullPathname(
4214342292Scy  sqlite3_vfs *pVfs,
4215342292Scy  const char *zPath,
4216342292Scy  int nOut,
4217342292Scy  char *zOut
4218342292Scy){
4219342292Scy  return ORIGVFS(pVfs)->xFullPathname(ORIGVFS(pVfs),zPath,nOut,zOut);
4220342292Scy}
4221342292Scystatic void *apndDlOpen(sqlite3_vfs *pVfs, const char *zPath){
4222342292Scy  return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
4223342292Scy}
4224342292Scystatic void apndDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
4225342292Scy  ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
4226342292Scy}
4227342292Scystatic void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
4228342292Scy  return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
4229342292Scy}
4230342292Scystatic void apndDlClose(sqlite3_vfs *pVfs, void *pHandle){
4231342292Scy  ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
4232342292Scy}
4233342292Scystatic int apndRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
4234342292Scy  return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
4235342292Scy}
4236342292Scystatic int apndSleep(sqlite3_vfs *pVfs, int nMicro){
4237342292Scy  return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
4238342292Scy}
4239342292Scystatic int apndCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
4240342292Scy  return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
4241342292Scy}
4242342292Scystatic int apndGetLastError(sqlite3_vfs *pVfs, int a, char *b){
4243342292Scy  return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
4244342292Scy}
4245342292Scystatic int apndCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
4246342292Scy  return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
4247342292Scy}
4248342292Scystatic int apndSetSystemCall(
4249342292Scy  sqlite3_vfs *pVfs,
4250342292Scy  const char *zName,
4251342292Scy  sqlite3_syscall_ptr pCall
4252342292Scy){
4253342292Scy  return ORIGVFS(pVfs)->xSetSystemCall(ORIGVFS(pVfs),zName,pCall);
4254342292Scy}
4255342292Scystatic sqlite3_syscall_ptr apndGetSystemCall(
4256342292Scy  sqlite3_vfs *pVfs,
4257342292Scy  const char *zName
4258342292Scy){
4259342292Scy  return ORIGVFS(pVfs)->xGetSystemCall(ORIGVFS(pVfs),zName);
4260342292Scy}
4261342292Scystatic const char *apndNextSystemCall(sqlite3_vfs *pVfs, const char *zName){
4262342292Scy  return ORIGVFS(pVfs)->xNextSystemCall(ORIGVFS(pVfs), zName);
4263342292Scy}
4264342292Scy
4265342292Scy
4266342292Scy#ifdef _WIN32
4267342292Scy
4268342292Scy#endif
4269342292Scy/*
4270342292Scy** This routine is called when the extension is loaded.
4271342292Scy** Register the new VFS.
4272342292Scy*/
4273342292Scyint sqlite3_appendvfs_init(
4274342292Scy  sqlite3 *db,
4275342292Scy  char **pzErrMsg,
4276342292Scy  const sqlite3_api_routines *pApi
4277342292Scy){
4278342292Scy  int rc = SQLITE_OK;
4279342292Scy  sqlite3_vfs *pOrig;
4280342292Scy  SQLITE_EXTENSION_INIT2(pApi);
4281342292Scy  (void)pzErrMsg;
4282342292Scy  (void)db;
4283342292Scy  pOrig = sqlite3_vfs_find(0);
4284342292Scy  apnd_vfs.iVersion = pOrig->iVersion;
4285342292Scy  apnd_vfs.pAppData = pOrig;
4286342292Scy  apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile);
4287342292Scy  rc = sqlite3_vfs_register(&apnd_vfs, 0);
4288342292Scy#ifdef APPENDVFS_TEST
4289342292Scy  if( rc==SQLITE_OK ){
4290342292Scy    rc = sqlite3_auto_extension((void(*)(void))apndvfsRegister);
4291342292Scy  }
4292342292Scy#endif
4293342292Scy  if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
4294342292Scy  return rc;
4295342292Scy}
4296342292Scy
4297342292Scy/************************* End ../ext/misc/appendvfs.c ********************/
4298346442Scy/************************* Begin ../ext/misc/memtrace.c ******************/
4299346442Scy/*
4300346442Scy** 2019-01-21
4301346442Scy**
4302346442Scy** The author disclaims copyright to this source code.  In place of
4303346442Scy** a legal notice, here is a blessing:
4304346442Scy**
4305346442Scy**    May you do good and not evil.
4306346442Scy**    May you find forgiveness for yourself and forgive others.
4307346442Scy**    May you share freely, never taking more than you give.
4308346442Scy**
4309346442Scy*************************************************************************
4310346442Scy**
4311346442Scy** This file implements an extension that uses the SQLITE_CONFIG_MALLOC
4312346442Scy** mechanism to add a tracing layer on top of SQLite.  If this extension
4313346442Scy** is registered prior to sqlite3_initialize(), it will cause all memory
4314346442Scy** allocation activities to be logged on standard output, or to some other
4315346442Scy** FILE specified by the initializer.
4316346442Scy**
4317346442Scy** This file needs to be compiled into the application that uses it.
4318346442Scy**
4319346442Scy** This extension is used to implement the --memtrace option of the
4320346442Scy** command-line shell.
4321346442Scy*/
4322346442Scy#include <assert.h>
4323346442Scy#include <string.h>
4324346442Scy#include <stdio.h>
4325346442Scy
4326346442Scy/* The original memory allocation routines */
4327346442Scystatic sqlite3_mem_methods memtraceBase;
4328346442Scystatic FILE *memtraceOut;
4329346442Scy
4330346442Scy/* Methods that trace memory allocations */
4331346442Scystatic void *memtraceMalloc(int n){
4332346442Scy  if( memtraceOut ){
4333346442Scy    fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n",
4334346442Scy            memtraceBase.xRoundup(n));
4335346442Scy  }
4336346442Scy  return memtraceBase.xMalloc(n);
4337346442Scy}
4338346442Scystatic void memtraceFree(void *p){
4339346442Scy  if( p==0 ) return;
4340346442Scy  if( memtraceOut ){
4341346442Scy    fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p));
4342346442Scy  }
4343346442Scy  memtraceBase.xFree(p);
4344346442Scy}
4345346442Scystatic void *memtraceRealloc(void *p, int n){
4346346442Scy  if( p==0 ) return memtraceMalloc(n);
4347346442Scy  if( n==0 ){
4348346442Scy    memtraceFree(p);
4349346442Scy    return 0;
4350346442Scy  }
4351346442Scy  if( memtraceOut ){
4352346442Scy    fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n",
4353346442Scy            memtraceBase.xSize(p), memtraceBase.xRoundup(n));
4354346442Scy  }
4355346442Scy  return memtraceBase.xRealloc(p, n);
4356346442Scy}
4357346442Scystatic int memtraceSize(void *p){
4358346442Scy  return memtraceBase.xSize(p);
4359346442Scy}
4360346442Scystatic int memtraceRoundup(int n){
4361346442Scy  return memtraceBase.xRoundup(n);
4362346442Scy}
4363346442Scystatic int memtraceInit(void *p){
4364346442Scy  return memtraceBase.xInit(p);
4365346442Scy}
4366346442Scystatic void memtraceShutdown(void *p){
4367346442Scy  memtraceBase.xShutdown(p);
4368346442Scy}
4369346442Scy
4370346442Scy/* The substitute memory allocator */
4371346442Scystatic sqlite3_mem_methods ersaztMethods = {
4372346442Scy  memtraceMalloc,
4373346442Scy  memtraceFree,
4374346442Scy  memtraceRealloc,
4375346442Scy  memtraceSize,
4376346442Scy  memtraceRoundup,
4377346442Scy  memtraceInit,
4378346442Scy  memtraceShutdown,
4379346442Scy  0
4380346442Scy};
4381346442Scy
4382346442Scy/* Begin tracing memory allocations to out. */
4383346442Scyint sqlite3MemTraceActivate(FILE *out){
4384346442Scy  int rc = SQLITE_OK;
4385346442Scy  if( memtraceBase.xMalloc==0 ){
4386346442Scy    rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase);
4387346442Scy    if( rc==SQLITE_OK ){
4388346442Scy      rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods);
4389346442Scy    }
4390346442Scy  }
4391346442Scy  memtraceOut = out;
4392346442Scy  return rc;
4393346442Scy}
4394346442Scy
4395346442Scy/* Deactivate memory tracing */
4396346442Scyint sqlite3MemTraceDeactivate(void){
4397346442Scy  int rc = SQLITE_OK;
4398346442Scy  if( memtraceBase.xMalloc!=0 ){
4399346442Scy    rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase);
4400346442Scy    if( rc==SQLITE_OK ){
4401346442Scy      memset(&memtraceBase, 0, sizeof(memtraceBase));
4402346442Scy    }
4403346442Scy  }
4404346442Scy  memtraceOut = 0;
4405346442Scy  return rc;
4406346442Scy}
4407346442Scy
4408346442Scy/************************* End ../ext/misc/memtrace.c ********************/
4409362190Scy/************************* Begin ../ext/misc/uint.c ******************/
4410362190Scy/*
4411362190Scy** 2020-04-14
4412362190Scy**
4413362190Scy** The author disclaims copyright to this source code.  In place of
4414362190Scy** a legal notice, here is a blessing:
4415362190Scy**
4416362190Scy**    May you do good and not evil.
4417362190Scy**    May you find forgiveness for yourself and forgive others.
4418362190Scy**    May you share freely, never taking more than you give.
4419362190Scy**
4420362190Scy******************************************************************************
4421362190Scy**
4422362190Scy** This SQLite extension implements the UINT collating sequence.
4423362190Scy**
4424362190Scy** UINT works like BINARY for text, except that embedded strings
4425362190Scy** of digits compare in numeric order.
4426362190Scy**
4427362190Scy**     *   Leading zeros are handled properly, in the sense that
4428362190Scy**         they do not mess of the maginitude comparison of embedded
4429362190Scy**         strings of digits.  "x00123y" is equal to "x123y".
4430362190Scy**
4431362190Scy**     *   Only unsigned integers are recognized.  Plus and minus
4432362190Scy**         signs are ignored.  Decimal points and exponential notation
4433362190Scy**         are ignored.
4434362190Scy**
4435362190Scy**     *   Embedded integers can be of arbitrary length.  Comparison
4436362190Scy**         is *not* limited integers that can be expressed as a
4437362190Scy**         64-bit machine integer.
4438362190Scy*/
4439362190Scy/* #include "sqlite3ext.h" */
4440362190ScySQLITE_EXTENSION_INIT1
4441362190Scy#include <assert.h>
4442362190Scy#include <string.h>
4443362190Scy#include <ctype.h>
4444362190Scy
4445362190Scy/*
4446362190Scy** Compare text in lexicographic order, except strings of digits
4447362190Scy** compare in numeric order.
4448362190Scy*/
4449362190Scystatic int uintCollFunc(
4450362190Scy  void *notUsed,
4451362190Scy  int nKey1, const void *pKey1,
4452362190Scy  int nKey2, const void *pKey2
4453362190Scy){
4454362190Scy  const unsigned char *zA = (const unsigned char*)pKey1;
4455362190Scy  const unsigned char *zB = (const unsigned char*)pKey2;
4456362190Scy  int i=0, j=0, x;
4457362190Scy  (void)notUsed;
4458362190Scy  while( i<nKey1 && j<nKey2 ){
4459362190Scy    x = zA[i] - zB[j];
4460362190Scy    if( isdigit(zA[i]) ){
4461362190Scy      int k;
4462362190Scy      if( !isdigit(zB[j]) ) return x;
4463362190Scy      while( i<nKey1 && zA[i]=='0' ){ i++; }
4464362190Scy      while( j<nKey2 && zB[j]=='0' ){ j++; }
4465362190Scy      k = 0;
4466362190Scy      while( i+k<nKey1 && isdigit(zA[i+k])
4467362190Scy             && j+k<nKey2 && isdigit(zB[j+k]) ){
4468362190Scy        k++;
4469362190Scy      }
4470362190Scy      if( i+k<nKey1 && isdigit(zA[i+k]) ){
4471362190Scy        return +1;
4472362190Scy      }else if( j+k<nKey2 && isdigit(zB[j+k]) ){
4473362190Scy        return -1;
4474362190Scy      }else{
4475362190Scy        x = memcmp(zA+i, zB+j, k);
4476362190Scy        if( x ) return x;
4477362190Scy        i += k;
4478362190Scy        j += k;
4479362190Scy      }
4480362190Scy    }else if( x ){
4481362190Scy      return x;
4482362190Scy    }else{
4483362190Scy      i++;
4484362190Scy      j++;
4485362190Scy    }
4486362190Scy  }
4487362190Scy  return (nKey1 - i) - (nKey2 - j);
4488362190Scy}
4489362190Scy
4490362190Scy#ifdef _WIN32
4491362190Scy
4492362190Scy#endif
4493362190Scyint sqlite3_uint_init(
4494362190Scy  sqlite3 *db,
4495362190Scy  char **pzErrMsg,
4496362190Scy  const sqlite3_api_routines *pApi
4497362190Scy){
4498362190Scy  SQLITE_EXTENSION_INIT2(pApi);
4499362190Scy  (void)pzErrMsg;  /* Unused parameter */
4500362190Scy  return sqlite3_create_collation(db, "uint", SQLITE_UTF8, 0, uintCollFunc);
4501362190Scy}
4502362190Scy
4503362190Scy/************************* End ../ext/misc/uint.c ********************/
4504366076Scy/************************* Begin ../ext/misc/decimal.c ******************/
4505366076Scy/*
4506366076Scy** 2020-06-22
4507366076Scy**
4508366076Scy** The author disclaims copyright to this source code.  In place of
4509366076Scy** a legal notice, here is a blessing:
4510366076Scy**
4511366076Scy**    May you do good and not evil.
4512366076Scy**    May you find forgiveness for yourself and forgive others.
4513366076Scy**    May you share freely, never taking more than you give.
4514366076Scy**
4515366076Scy******************************************************************************
4516366076Scy**
4517366076Scy** Routines to implement arbitrary-precision decimal math.
4518366076Scy**
4519366076Scy** The focus here is on simplicity and correctness, not performance.
4520366076Scy*/
4521366076Scy/* #include "sqlite3ext.h" */
4522366076ScySQLITE_EXTENSION_INIT1
4523366076Scy#include <assert.h>
4524366076Scy#include <string.h>
4525366076Scy#include <ctype.h>
4526366076Scy#include <stdlib.h>
4527366076Scy
4528366076Scy/* Mark a function parameter as unused, to suppress nuisance compiler
4529366076Scy** warnings. */
4530366076Scy#ifndef UNUSED_PARAMETER
4531366076Scy# define UNUSED_PARAMETER(X)  (void)(X)
4532366076Scy#endif
4533366076Scy
4534366076Scy
4535366076Scy/* A decimal object */
4536366076Scytypedef struct Decimal Decimal;
4537366076Scystruct Decimal {
4538366076Scy  char sign;        /* 0 for positive, 1 for negative */
4539366076Scy  char oom;         /* True if an OOM is encountered */
4540366076Scy  char isNull;      /* True if holds a NULL rather than a number */
4541366076Scy  char isInit;      /* True upon initialization */
4542366076Scy  int nDigit;       /* Total number of digits */
4543366076Scy  int nFrac;        /* Number of digits to the right of the decimal point */
4544366076Scy  signed char *a;   /* Array of digits.  Most significant first. */
4545366076Scy};
4546366076Scy
4547366076Scy/*
4548366076Scy** Release memory held by a Decimal, but do not free the object itself.
4549366076Scy*/
4550366076Scystatic void decimal_clear(Decimal *p){
4551366076Scy  sqlite3_free(p->a);
4552366076Scy}
4553366076Scy
4554366076Scy/*
4555366076Scy** Destroy a Decimal object
4556366076Scy*/
4557366076Scystatic void decimal_free(Decimal *p){
4558366076Scy  if( p ){
4559366076Scy    decimal_clear(p);
4560366076Scy    sqlite3_free(p);
4561366076Scy  }
4562366076Scy}
4563366076Scy
4564366076Scy/*
4565366076Scy** Allocate a new Decimal object.  Initialize it to the number given
4566366076Scy** by the input string.
4567366076Scy*/
4568366076Scystatic Decimal *decimal_new(
4569366076Scy  sqlite3_context *pCtx,
4570366076Scy  sqlite3_value *pIn,
4571366076Scy  int nAlt,
4572366076Scy  const unsigned char *zAlt
4573366076Scy){
4574366076Scy  Decimal *p;
4575366076Scy  int n, i;
4576366076Scy  const unsigned char *zIn;
4577366076Scy  int iExp = 0;
4578366076Scy  p = sqlite3_malloc( sizeof(*p) );
4579366076Scy  if( p==0 ) goto new_no_mem;
4580366076Scy  p->sign = 0;
4581366076Scy  p->oom = 0;
4582366076Scy  p->isInit = 1;
4583366076Scy  p->isNull = 0;
4584366076Scy  p->nDigit = 0;
4585366076Scy  p->nFrac = 0;
4586366076Scy  if( zAlt ){
4587366076Scy    n = nAlt,
4588366076Scy    zIn = zAlt;
4589366076Scy  }else{
4590366076Scy    if( sqlite3_value_type(pIn)==SQLITE_NULL ){
4591366076Scy      p->a = 0;
4592366076Scy      p->isNull = 1;
4593366076Scy      return p;
4594366076Scy    }
4595366076Scy    n = sqlite3_value_bytes(pIn);
4596366076Scy    zIn = sqlite3_value_text(pIn);
4597366076Scy  }
4598366076Scy  p->a = sqlite3_malloc64( n+1 );
4599366076Scy  if( p->a==0 ) goto new_no_mem;
4600366076Scy  for(i=0; isspace(zIn[i]); i++){}
4601366076Scy  if( zIn[i]=='-' ){
4602366076Scy    p->sign = 1;
4603366076Scy    i++;
4604366076Scy  }else if( zIn[i]=='+' ){
4605366076Scy    i++;
4606366076Scy  }
4607366076Scy  while( i<n && zIn[i]=='0' ) i++;
4608366076Scy  while( i<n ){
4609366076Scy    char c = zIn[i];
4610366076Scy    if( c>='0' && c<='9' ){
4611366076Scy      p->a[p->nDigit++] = c - '0';
4612366076Scy    }else if( c=='.' ){
4613366076Scy      p->nFrac = p->nDigit + 1;
4614366076Scy    }else if( c=='e' || c=='E' ){
4615366076Scy      int j = i+1;
4616366076Scy      int neg = 0;
4617366076Scy      if( j>=n ) break;
4618366076Scy      if( zIn[j]=='-' ){
4619366076Scy        neg = 1;
4620366076Scy        j++;
4621366076Scy      }else if( zIn[j]=='+' ){
4622366076Scy        j++;
4623366076Scy      }
4624366076Scy      while( j<n && iExp<1000000 ){
4625366076Scy        if( zIn[j]>='0' && zIn[j]<='9' ){
4626366076Scy          iExp = iExp*10 + zIn[j] - '0';
4627366076Scy        }
4628366076Scy        j++;
4629366076Scy      }
4630366076Scy      if( neg ) iExp = -iExp;
4631366076Scy      break;
4632366076Scy    }
4633366076Scy    i++;
4634366076Scy  }
4635366076Scy  if( p->nFrac ){
4636366076Scy    p->nFrac = p->nDigit - (p->nFrac - 1);
4637366076Scy  }
4638366076Scy  if( iExp>0 ){
4639366076Scy    if( p->nFrac>0 ){
4640366076Scy      if( iExp<=p->nFrac ){
4641366076Scy        p->nFrac -= iExp;
4642366076Scy        iExp = 0;
4643366076Scy      }else{
4644366076Scy        iExp -= p->nFrac;
4645366076Scy        p->nFrac = 0;
4646366076Scy      }
4647366076Scy    }
4648366076Scy    if( iExp>0 ){
4649366076Scy      p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 );
4650366076Scy      if( p->a==0 ) goto new_no_mem;
4651366076Scy      memset(p->a+p->nDigit, 0, iExp);
4652366076Scy      p->nDigit += iExp;
4653366076Scy    }
4654366076Scy  }else if( iExp<0 ){
4655366076Scy    int nExtra;
4656366076Scy    iExp = -iExp;
4657366076Scy    nExtra = p->nDigit - p->nFrac - 1;
4658366076Scy    if( nExtra ){
4659366076Scy      if( nExtra>=iExp ){
4660366076Scy        p->nFrac += iExp;
4661366076Scy        iExp  = 0;
4662366076Scy      }else{
4663366076Scy        iExp -= nExtra;
4664366076Scy        p->nFrac = p->nDigit - 1;
4665366076Scy      }
4666366076Scy    }
4667366076Scy    if( iExp>0 ){
4668366076Scy      p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 );
4669366076Scy      if( p->a==0 ) goto new_no_mem;
4670366076Scy      memmove(p->a+iExp, p->a, p->nDigit);
4671366076Scy      memset(p->a, 0, iExp);
4672366076Scy      p->nDigit += iExp;
4673366076Scy      p->nFrac += iExp;
4674366076Scy    }
4675366076Scy  }
4676366076Scy  return p;
4677366076Scy
4678366076Scynew_no_mem:
4679366076Scy  if( pCtx ) sqlite3_result_error_nomem(pCtx);
4680366076Scy  sqlite3_free(p);
4681366076Scy  return 0;
4682366076Scy}
4683366076Scy
4684366076Scy/*
4685366076Scy** Make the given Decimal the result.
4686366076Scy*/
4687366076Scystatic void decimal_result(sqlite3_context *pCtx, Decimal *p){
4688366076Scy  char *z;
4689366076Scy  int i, j;
4690366076Scy  int n;
4691366076Scy  if( p==0 || p->oom ){
4692366076Scy    sqlite3_result_error_nomem(pCtx);
4693366076Scy    return;
4694366076Scy  }
4695366076Scy  if( p->isNull ){
4696366076Scy    sqlite3_result_null(pCtx);
4697366076Scy    return;
4698366076Scy  }
4699366076Scy  z = sqlite3_malloc( p->nDigit+4 );
4700366076Scy  if( z==0 ){
4701366076Scy    sqlite3_result_error_nomem(pCtx);
4702366076Scy    return;
4703366076Scy  }
4704366076Scy  i = 0;
4705366076Scy  if( p->nDigit==0 || (p->nDigit==1 && p->a[0]==0) ){
4706366076Scy    p->sign = 0;
4707366076Scy  }
4708366076Scy  if( p->sign ){
4709366076Scy    z[0] = '-';
4710366076Scy    i = 1;
4711366076Scy  }
4712366076Scy  n = p->nDigit - p->nFrac;
4713366076Scy  if( n<=0 ){
4714366076Scy    z[i++] = '0';
4715366076Scy  }
4716366076Scy  j = 0;
4717366076Scy  while( n>1 && p->a[j]==0 ){
4718366076Scy    j++;
4719366076Scy    n--;
4720366076Scy  }
4721366076Scy  while( n>0  ){
4722366076Scy    z[i++] = p->a[j] + '0';
4723366076Scy    j++;
4724366076Scy    n--;
4725366076Scy  }
4726366076Scy  if( p->nFrac ){
4727366076Scy    z[i++] = '.';
4728366076Scy    do{
4729366076Scy      z[i++] = p->a[j] + '0';
4730366076Scy      j++;
4731366076Scy    }while( j<p->nDigit );
4732366076Scy  }
4733366076Scy  z[i] = 0;
4734366076Scy  sqlite3_result_text(pCtx, z, i, sqlite3_free);
4735366076Scy}
4736366076Scy
4737366076Scy/*
4738366076Scy** SQL Function:   decimal(X)
4739366076Scy**
4740366076Scy** Convert input X into decimal and then back into text
4741366076Scy*/
4742366076Scystatic void decimalFunc(
4743366076Scy  sqlite3_context *context,
4744366076Scy  int argc,
4745366076Scy  sqlite3_value **argv
4746366076Scy){
4747366076Scy  Decimal *p = decimal_new(context, argv[0], 0, 0);
4748366076Scy  UNUSED_PARAMETER(argc);
4749366076Scy  decimal_result(context, p);
4750366076Scy  decimal_free(p);
4751366076Scy}
4752366076Scy
4753366076Scy/*
4754366076Scy** Compare to Decimal objects.  Return negative, 0, or positive if the
4755366076Scy** first object is less than, equal to, or greater than the second.
4756366076Scy**
4757366076Scy** Preconditions for this routine:
4758366076Scy**
4759366076Scy**    pA!=0
4760366076Scy**    pA->isNull==0
4761366076Scy**    pB!=0
4762366076Scy**    pB->isNull==0
4763366076Scy*/
4764366076Scystatic int decimal_cmp(const Decimal *pA, const Decimal *pB){
4765366076Scy  int nASig, nBSig, rc, n;
4766366076Scy  if( pA->sign!=pB->sign ){
4767366076Scy    return pA->sign ? -1 : +1;
4768366076Scy  }
4769366076Scy  if( pA->sign ){
4770366076Scy    const Decimal *pTemp = pA;
4771366076Scy    pA = pB;
4772366076Scy    pB = pTemp;
4773366076Scy  }
4774366076Scy  nASig = pA->nDigit - pA->nFrac;
4775366076Scy  nBSig = pB->nDigit - pB->nFrac;
4776366076Scy  if( nASig!=nBSig ){
4777366076Scy    return nASig - nBSig;
4778366076Scy  }
4779366076Scy  n = pA->nDigit;
4780366076Scy  if( n>pB->nDigit ) n = pB->nDigit;
4781366076Scy  rc = memcmp(pA->a, pB->a, n);
4782366076Scy  if( rc==0 ){
4783366076Scy    rc = pA->nDigit - pB->nDigit;
4784366076Scy  }
4785366076Scy  return rc;
4786366076Scy}
4787366076Scy
4788366076Scy/*
4789366076Scy** SQL Function:   decimal_cmp(X, Y)
4790366076Scy**
4791366076Scy** Return negative, zero, or positive if X is less then, equal to, or
4792366076Scy** greater than Y.
4793366076Scy*/
4794366076Scystatic void decimalCmpFunc(
4795366076Scy  sqlite3_context *context,
4796366076Scy  int argc,
4797366076Scy  sqlite3_value **argv
4798366076Scy){
4799366076Scy  Decimal *pA = 0, *pB = 0;
4800366076Scy  int rc;
4801366076Scy
4802366076Scy  UNUSED_PARAMETER(argc);
4803366076Scy  pA = decimal_new(context, argv[0], 0, 0);
4804366076Scy  if( pA==0 || pA->isNull ) goto cmp_done;
4805366076Scy  pB = decimal_new(context, argv[1], 0, 0);
4806366076Scy  if( pB==0 || pB->isNull ) goto cmp_done;
4807366076Scy  rc = decimal_cmp(pA, pB);
4808366076Scy  if( rc<0 ) rc = -1;
4809366076Scy  else if( rc>0 ) rc = +1;
4810366076Scy  sqlite3_result_int(context, rc);
4811366076Scycmp_done:
4812366076Scy  decimal_free(pA);
4813366076Scy  decimal_free(pB);
4814366076Scy}
4815366076Scy
4816366076Scy/*
4817366076Scy** Expand the Decimal so that it has a least nDigit digits and nFrac
4818366076Scy** digits to the right of the decimal point.
4819366076Scy*/
4820366076Scystatic void decimal_expand(Decimal *p, int nDigit, int nFrac){
4821366076Scy  int nAddSig;
4822366076Scy  int nAddFrac;
4823366076Scy  if( p==0 ) return;
4824366076Scy  nAddFrac = nFrac - p->nFrac;
4825366076Scy  nAddSig = (nDigit - p->nDigit) - nAddFrac;
4826366076Scy  if( nAddFrac==0 && nAddSig==0 ) return;
4827366076Scy  p->a = sqlite3_realloc64(p->a, nDigit+1);
4828366076Scy  if( p->a==0 ){
4829366076Scy    p->oom = 1;
4830366076Scy    return;
4831366076Scy  }
4832366076Scy  if( nAddSig ){
4833366076Scy    memmove(p->a+nAddSig, p->a, p->nDigit);
4834366076Scy    memset(p->a, 0, nAddSig);
4835366076Scy    p->nDigit += nAddSig;
4836366076Scy  }
4837366076Scy  if( nAddFrac ){
4838366076Scy    memset(p->a+p->nDigit, 0, nAddFrac);
4839366076Scy    p->nDigit += nAddFrac;
4840366076Scy    p->nFrac += nAddFrac;
4841366076Scy  }
4842366076Scy}
4843366076Scy
4844366076Scy/*
4845366076Scy** Add the value pB into pA.
4846366076Scy**
4847366076Scy** Both pA and pB might become denormalized by this routine.
4848366076Scy*/
4849366076Scystatic void decimal_add(Decimal *pA, Decimal *pB){
4850366076Scy  int nSig, nFrac, nDigit;
4851366076Scy  int i, rc;
4852366076Scy  if( pA==0 ){
4853366076Scy    return;
4854366076Scy  }
4855366076Scy  if( pA->oom || pB==0 || pB->oom ){
4856366076Scy    pA->oom = 1;
4857366076Scy    return;
4858366076Scy  }
4859366076Scy  if( pA->isNull || pB->isNull ){
4860366076Scy    pA->isNull = 1;
4861366076Scy    return;
4862366076Scy  }
4863366076Scy  nSig = pA->nDigit - pA->nFrac;
4864366076Scy  if( nSig && pA->a[0]==0 ) nSig--;
4865366076Scy  if( nSig<pB->nDigit-pB->nFrac ){
4866366076Scy    nSig = pB->nDigit - pB->nFrac;
4867366076Scy  }
4868366076Scy  nFrac = pA->nFrac;
4869366076Scy  if( nFrac<pB->nFrac ) nFrac = pB->nFrac;
4870366076Scy  nDigit = nSig + nFrac + 1;
4871366076Scy  decimal_expand(pA, nDigit, nFrac);
4872366076Scy  decimal_expand(pB, nDigit, nFrac);
4873366076Scy  if( pA->oom || pB->oom ){
4874366076Scy    pA->oom = 1;
4875366076Scy  }else{
4876366076Scy    if( pA->sign==pB->sign ){
4877366076Scy      int carry = 0;
4878366076Scy      for(i=nDigit-1; i>=0; i--){
4879366076Scy        int x = pA->a[i] + pB->a[i] + carry;
4880366076Scy        if( x>=10 ){
4881366076Scy          carry = 1;
4882366076Scy          pA->a[i] = x - 10;
4883366076Scy        }else{
4884366076Scy          carry = 0;
4885366076Scy          pA->a[i] = x;
4886366076Scy        }
4887366076Scy      }
4888366076Scy    }else{
4889366076Scy      signed char *aA, *aB;
4890366076Scy      int borrow = 0;
4891366076Scy      rc = memcmp(pA->a, pB->a, nDigit);
4892366076Scy      if( rc<0 ){
4893366076Scy        aA = pB->a;
4894366076Scy        aB = pA->a;
4895366076Scy        pA->sign = !pA->sign;
4896366076Scy      }else{
4897366076Scy        aA = pA->a;
4898366076Scy        aB = pB->a;
4899366076Scy      }
4900366076Scy      for(i=nDigit-1; i>=0; i--){
4901366076Scy        int x = aA[i] - aB[i] - borrow;
4902366076Scy        if( x<0 ){
4903366076Scy          pA->a[i] = x+10;
4904366076Scy          borrow = 1;
4905366076Scy        }else{
4906366076Scy          pA->a[i] = x;
4907366076Scy          borrow = 0;
4908366076Scy        }
4909366076Scy      }
4910366076Scy    }
4911366076Scy  }
4912366076Scy}
4913366076Scy
4914366076Scy/*
4915366076Scy** Compare text in decimal order.
4916366076Scy*/
4917366076Scystatic int decimalCollFunc(
4918366076Scy  void *notUsed,
4919366076Scy  int nKey1, const void *pKey1,
4920366076Scy  int nKey2, const void *pKey2
4921366076Scy){
4922366076Scy  const unsigned char *zA = (const unsigned char*)pKey1;
4923366076Scy  const unsigned char *zB = (const unsigned char*)pKey2;
4924366076Scy  Decimal *pA = decimal_new(0, 0, nKey1, zA);
4925366076Scy  Decimal *pB = decimal_new(0, 0, nKey2, zB);
4926366076Scy  int rc;
4927366076Scy  UNUSED_PARAMETER(notUsed);
4928366076Scy  if( pA==0 || pB==0 ){
4929366076Scy    rc = 0;
4930366076Scy  }else{
4931366076Scy    rc = decimal_cmp(pA, pB);
4932366076Scy  }
4933366076Scy  decimal_free(pA);
4934366076Scy  decimal_free(pB);
4935366076Scy  return rc;
4936366076Scy}
4937366076Scy
4938366076Scy
4939366076Scy/*
4940366076Scy** SQL Function:   decimal_add(X, Y)
4941366076Scy**                 decimal_sub(X, Y)
4942366076Scy**
4943366076Scy** Return the sum or difference of X and Y.
4944366076Scy*/
4945366076Scystatic void decimalAddFunc(
4946366076Scy  sqlite3_context *context,
4947366076Scy  int argc,
4948366076Scy  sqlite3_value **argv
4949366076Scy){
4950366076Scy  Decimal *pA = decimal_new(context, argv[0], 0, 0);
4951366076Scy  Decimal *pB = decimal_new(context, argv[1], 0, 0);
4952366076Scy  UNUSED_PARAMETER(argc);
4953366076Scy  decimal_add(pA, pB);
4954366076Scy  decimal_result(context, pA);
4955366076Scy  decimal_free(pA);
4956366076Scy  decimal_free(pB);
4957366076Scy}
4958366076Scystatic void decimalSubFunc(
4959366076Scy  sqlite3_context *context,
4960366076Scy  int argc,
4961366076Scy  sqlite3_value **argv
4962366076Scy){
4963366076Scy  Decimal *pA = decimal_new(context, argv[0], 0, 0);
4964366076Scy  Decimal *pB = decimal_new(context, argv[1], 0, 0);
4965366076Scy  UNUSED_PARAMETER(argc);
4966366076Scy  if( pB==0 ) return;
4967366076Scy  pB->sign = !pB->sign;
4968366076Scy  decimal_add(pA, pB);
4969366076Scy  decimal_result(context, pA);
4970366076Scy  decimal_free(pA);
4971366076Scy  decimal_free(pB);
4972366076Scy}
4973366076Scy
4974366076Scy/* Aggregate funcion:   decimal_sum(X)
4975366076Scy**
4976366076Scy** Works like sum() except that it uses decimal arithmetic for unlimited
4977366076Scy** precision.
4978366076Scy*/
4979366076Scystatic void decimalSumStep(
4980366076Scy  sqlite3_context *context,
4981366076Scy  int argc,
4982366076Scy  sqlite3_value **argv
4983366076Scy){
4984366076Scy  Decimal *p;
4985366076Scy  Decimal *pArg;
4986366076Scy  UNUSED_PARAMETER(argc);
4987366076Scy  p = sqlite3_aggregate_context(context, sizeof(*p));
4988366076Scy  if( p==0 ) return;
4989366076Scy  if( !p->isInit ){
4990366076Scy    p->isInit = 1;
4991366076Scy    p->a = sqlite3_malloc(2);
4992366076Scy    if( p->a==0 ){
4993366076Scy      p->oom = 1;
4994366076Scy    }else{
4995366076Scy      p->a[0] = 0;
4996366076Scy    }
4997366076Scy    p->nDigit = 1;
4998366076Scy    p->nFrac = 0;
4999366076Scy  }
5000366076Scy  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
5001366076Scy  pArg = decimal_new(context, argv[0], 0, 0);
5002366076Scy  decimal_add(p, pArg);
5003366076Scy  decimal_free(pArg);
5004366076Scy}
5005366076Scystatic void decimalSumInverse(
5006366076Scy  sqlite3_context *context,
5007366076Scy  int argc,
5008366076Scy  sqlite3_value **argv
5009366076Scy){
5010366076Scy  Decimal *p;
5011366076Scy  Decimal *pArg;
5012366076Scy  UNUSED_PARAMETER(argc);
5013366076Scy  p = sqlite3_aggregate_context(context, sizeof(*p));
5014366076Scy  if( p==0 ) return;
5015366076Scy  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
5016366076Scy  pArg = decimal_new(context, argv[0], 0, 0);
5017366076Scy  if( pArg ) pArg->sign = !pArg->sign;
5018366076Scy  decimal_add(p, pArg);
5019366076Scy  decimal_free(pArg);
5020366076Scy}
5021366076Scystatic void decimalSumValue(sqlite3_context *context){
5022366076Scy  Decimal *p = sqlite3_aggregate_context(context, 0);
5023366076Scy  if( p==0 ) return;
5024366076Scy  decimal_result(context, p);
5025366076Scy}
5026366076Scystatic void decimalSumFinalize(sqlite3_context *context){
5027366076Scy  Decimal *p = sqlite3_aggregate_context(context, 0);
5028366076Scy  if( p==0 ) return;
5029366076Scy  decimal_result(context, p);
5030366076Scy  decimal_clear(p);
5031366076Scy}
5032366076Scy
5033366076Scy/*
5034366076Scy** SQL Function:   decimal_mul(X, Y)
5035366076Scy**
5036366076Scy** Return the product of X and Y.
5037366076Scy**
5038366076Scy** All significant digits after the decimal point are retained.
5039366076Scy** Trailing zeros after the decimal point are omitted as long as
5040366076Scy** the number of digits after the decimal point is no less than
5041366076Scy** either the number of digits in either input.
5042366076Scy*/
5043366076Scystatic void decimalMulFunc(
5044366076Scy  sqlite3_context *context,
5045366076Scy  int argc,
5046366076Scy  sqlite3_value **argv
5047366076Scy){
5048366076Scy  Decimal *pA = decimal_new(context, argv[0], 0, 0);
5049366076Scy  Decimal *pB = decimal_new(context, argv[1], 0, 0);
5050366076Scy  signed char *acc = 0;
5051366076Scy  int i, j, k;
5052366076Scy  int minFrac;
5053366076Scy  UNUSED_PARAMETER(argc);
5054366076Scy  if( pA==0 || pA->oom || pA->isNull
5055366076Scy   || pB==0 || pB->oom || pB->isNull
5056366076Scy  ){
5057366076Scy    goto mul_end;
5058366076Scy  }
5059366076Scy  acc = sqlite3_malloc64( pA->nDigit + pB->nDigit + 2 );
5060366076Scy  if( acc==0 ){
5061366076Scy    sqlite3_result_error_nomem(context);
5062366076Scy    goto mul_end;
5063366076Scy  }
5064366076Scy  memset(acc, 0, pA->nDigit + pB->nDigit + 2);
5065366076Scy  minFrac = pA->nFrac;
5066366076Scy  if( pB->nFrac<minFrac ) minFrac = pB->nFrac;
5067366076Scy  for(i=pA->nDigit-1; i>=0; i--){
5068366076Scy    signed char f = pA->a[i];
5069366076Scy    int carry = 0, x;
5070366076Scy    for(j=pB->nDigit-1, k=i+j+3; j>=0; j--, k--){
5071366076Scy      x = acc[k] + f*pB->a[j] + carry;
5072366076Scy      acc[k] = x%10;
5073366076Scy      carry = x/10;
5074366076Scy    }
5075366076Scy    x = acc[k] + carry;
5076366076Scy    acc[k] = x%10;
5077366076Scy    acc[k-1] += x/10;
5078366076Scy  }
5079366076Scy  sqlite3_free(pA->a);
5080366076Scy  pA->a = acc;
5081366076Scy  acc = 0;
5082366076Scy  pA->nDigit += pB->nDigit + 2;
5083366076Scy  pA->nFrac += pB->nFrac;
5084366076Scy  pA->sign ^= pB->sign;
5085366076Scy  while( pA->nFrac>minFrac && pA->a[pA->nDigit-1]==0 ){
5086366076Scy    pA->nFrac--;
5087366076Scy    pA->nDigit--;
5088366076Scy  }
5089366076Scy  decimal_result(context, pA);
5090366076Scy
5091366076Scymul_end:
5092366076Scy  sqlite3_free(acc);
5093366076Scy  decimal_free(pA);
5094366076Scy  decimal_free(pB);
5095366076Scy}
5096366076Scy
5097366076Scy#ifdef _WIN32
5098366076Scy
5099366076Scy#endif
5100366076Scyint sqlite3_decimal_init(
5101366076Scy  sqlite3 *db,
5102366076Scy  char **pzErrMsg,
5103366076Scy  const sqlite3_api_routines *pApi
5104366076Scy){
5105366076Scy  int rc = SQLITE_OK;
5106366076Scy  static const struct {
5107366076Scy    const char *zFuncName;
5108366076Scy    int nArg;
5109366076Scy    void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
5110366076Scy  } aFunc[] = {
5111366076Scy    { "decimal",       1,   decimalFunc        },
5112366076Scy    { "decimal_cmp",   2,   decimalCmpFunc     },
5113366076Scy    { "decimal_add",   2,   decimalAddFunc     },
5114366076Scy    { "decimal_sub",   2,   decimalSubFunc     },
5115366076Scy    { "decimal_mul",   2,   decimalMulFunc     },
5116366076Scy  };
5117366076Scy  unsigned int i;
5118366076Scy  (void)pzErrMsg;  /* Unused parameter */
5119366076Scy
5120366076Scy  SQLITE_EXTENSION_INIT2(pApi);
5121366076Scy
5122366076Scy  for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
5123366076Scy    rc = sqlite3_create_function(db, aFunc[i].zFuncName, aFunc[i].nArg,
5124366076Scy                   SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
5125366076Scy                   0, aFunc[i].xFunc, 0, 0);
5126366076Scy  }
5127366076Scy  if( rc==SQLITE_OK ){
5128366076Scy    rc = sqlite3_create_window_function(db, "decimal_sum", 1,
5129366076Scy                   SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, 0,
5130366076Scy                   decimalSumStep, decimalSumFinalize,
5131366076Scy                   decimalSumValue, decimalSumInverse, 0);
5132366076Scy  }
5133366076Scy  if( rc==SQLITE_OK ){
5134366076Scy    rc = sqlite3_create_collation(db, "decimal", SQLITE_UTF8,
5135366076Scy                                  0, decimalCollFunc);
5136366076Scy  }
5137366076Scy  return rc;
5138366076Scy}
5139366076Scy
5140366076Scy/************************* End ../ext/misc/decimal.c ********************/
5141366076Scy/************************* Begin ../ext/misc/ieee754.c ******************/
5142366076Scy/*
5143366076Scy** 2013-04-17
5144366076Scy**
5145366076Scy** The author disclaims copyright to this source code.  In place of
5146366076Scy** a legal notice, here is a blessing:
5147366076Scy**
5148366076Scy**    May you do good and not evil.
5149366076Scy**    May you find forgiveness for yourself and forgive others.
5150366076Scy**    May you share freely, never taking more than you give.
5151366076Scy**
5152366076Scy******************************************************************************
5153366076Scy**
5154366076Scy** This SQLite extension implements functions for the exact display
5155366076Scy** and input of IEEE754 Binary64 floating-point numbers.
5156366076Scy**
5157366076Scy**   ieee754(X)
5158366076Scy**   ieee754(Y,Z)
5159366076Scy**
5160366076Scy** In the first form, the value X should be a floating-point number.
5161366076Scy** The function will return a string of the form 'ieee754(Y,Z)' where
5162366076Scy** Y and Z are integers such that X==Y*pow(2,Z).
5163366076Scy**
5164366076Scy** In the second form, Y and Z are integers which are the mantissa and
5165366076Scy** base-2 exponent of a new floating point number.  The function returns
5166366076Scy** a floating-point value equal to Y*pow(2,Z).
5167366076Scy**
5168366076Scy** Examples:
5169366076Scy**
5170366076Scy**     ieee754(2.0)             ->     'ieee754(2,0)'
5171366076Scy**     ieee754(45.25)           ->     'ieee754(181,-2)'
5172366076Scy**     ieee754(2, 0)            ->     2.0
5173366076Scy**     ieee754(181, -2)         ->     45.25
5174366076Scy**
5175366076Scy** Two additional functions break apart the one-argument ieee754()
5176366076Scy** result into separate integer values:
5177366076Scy**
5178366076Scy**     ieee754_mantissa(45.25)  ->     181
5179366076Scy**     ieee754_exponent(45.25)  ->     -2
5180366076Scy**
5181366076Scy** These functions convert binary64 numbers into blobs and back again.
5182366076Scy**
5183366076Scy**     ieee754_from_blob(x'3ff0000000000000')  ->  1.0
5184366076Scy**     ieee754_to_blob(1.0)                    ->  x'3ff0000000000000'
5185366076Scy**
5186366076Scy** In all single-argument functions, if the argument is an 8-byte blob
5187366076Scy** then that blob is interpreted as a big-endian binary64 value.
5188366076Scy**
5189366076Scy**
5190366076Scy** EXACT DECIMAL REPRESENTATION OF BINARY64 VALUES
5191366076Scy** -----------------------------------------------
5192366076Scy**
5193366076Scy** This extension in combination with the separate 'decimal' extension
5194366076Scy** can be used to compute the exact decimal representation of binary64
5195366076Scy** values.  To begin, first compute a table of exponent values:
5196366076Scy**
5197366076Scy**    CREATE TABLE pow2(x INTEGER PRIMARY KEY, v TEXT);
5198366076Scy**    WITH RECURSIVE c(x,v) AS (
5199366076Scy**      VALUES(0,'1')
5200366076Scy**      UNION ALL
5201366076Scy**      SELECT x+1, decimal_mul(v,'2') FROM c WHERE x+1<=971
5202366076Scy**    ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
5203366076Scy**    WITH RECURSIVE c(x,v) AS (
5204366076Scy**      VALUES(-1,'0.5')
5205366076Scy**      UNION ALL
5206366076Scy**      SELECT x-1, decimal_mul(v,'0.5') FROM c WHERE x-1>=-1075
5207366076Scy**    ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
5208366076Scy**
5209366076Scy** Then, to compute the exact decimal representation of a floating
5210366076Scy** point value (the value 47.49 is used in the example) do:
5211366076Scy**
5212366076Scy**    WITH c(n) AS (VALUES(47.49))
5213366076Scy**          ---------------^^^^^---- Replace with whatever you want
5214366076Scy**    SELECT decimal_mul(ieee754_mantissa(c.n),pow2.v)
5215366076Scy**      FROM pow2, c WHERE pow2.x=ieee754_exponent(c.n);
5216366076Scy**
5217366076Scy** Here is a query to show various boundry values for the binary64
5218366076Scy** number format:
5219366076Scy**
5220366076Scy**    WITH c(name,bin) AS (VALUES
5221366076Scy**       ('minimum positive value',        x'0000000000000001'),
5222366076Scy**       ('maximum subnormal value',       x'000fffffffffffff'),
5223366076Scy**       ('mininum positive nornal value', x'0010000000000000'),
5224366076Scy**       ('maximum value',                 x'7fefffffffffffff'))
5225366076Scy**    SELECT c.name, decimal_mul(ieee754_mantissa(c.bin),pow2.v)
5226366076Scy**      FROM pow2, c WHERE pow2.x=ieee754_exponent(c.bin);
5227366076Scy**
5228366076Scy*/
5229366076Scy/* #include "sqlite3ext.h" */
5230366076ScySQLITE_EXTENSION_INIT1
5231366076Scy#include <assert.h>
5232366076Scy#include <string.h>
5233366076Scy
5234366076Scy/* Mark a function parameter as unused, to suppress nuisance compiler
5235366076Scy** warnings. */
5236366076Scy#ifndef UNUSED_PARAMETER
5237366076Scy# define UNUSED_PARAMETER(X)  (void)(X)
5238366076Scy#endif
5239366076Scy
5240366076Scy/*
5241366076Scy** Implementation of the ieee754() function
5242366076Scy*/
5243366076Scystatic void ieee754func(
5244366076Scy  sqlite3_context *context,
5245366076Scy  int argc,
5246366076Scy  sqlite3_value **argv
5247366076Scy){
5248366076Scy  if( argc==1 ){
5249366076Scy    sqlite3_int64 m, a;
5250366076Scy    double r;
5251366076Scy    int e;
5252366076Scy    int isNeg;
5253366076Scy    char zResult[100];
5254366076Scy    assert( sizeof(m)==sizeof(r) );
5255366076Scy    if( sqlite3_value_type(argv[0])==SQLITE_BLOB
5256366076Scy     && sqlite3_value_bytes(argv[0])==sizeof(r)
5257366076Scy    ){
5258366076Scy      const unsigned char *x = sqlite3_value_blob(argv[0]);
5259366076Scy      unsigned int i;
5260366076Scy      sqlite3_uint64 v = 0;
5261366076Scy      for(i=0; i<sizeof(r); i++){
5262366076Scy        v = (v<<8) | x[i];
5263366076Scy      }
5264366076Scy      memcpy(&r, &v, sizeof(r));
5265366076Scy    }else{
5266366076Scy      r = sqlite3_value_double(argv[0]);
5267366076Scy    }
5268366076Scy    if( r<0.0 ){
5269366076Scy      isNeg = 1;
5270366076Scy      r = -r;
5271366076Scy    }else{
5272366076Scy      isNeg = 0;
5273366076Scy    }
5274366076Scy    memcpy(&a,&r,sizeof(a));
5275366076Scy    if( a==0 ){
5276366076Scy      e = 0;
5277366076Scy      m = 0;
5278366076Scy    }else{
5279366076Scy      e = a>>52;
5280366076Scy      m = a & ((((sqlite3_int64)1)<<52)-1);
5281366076Scy      if( e==0 ){
5282366076Scy        m <<= 1;
5283366076Scy      }else{
5284366076Scy        m |= ((sqlite3_int64)1)<<52;
5285366076Scy      }
5286366076Scy      while( e<1075 && m>0 && (m&1)==0 ){
5287366076Scy        m >>= 1;
5288366076Scy        e++;
5289366076Scy      }
5290366076Scy      if( isNeg ) m = -m;
5291366076Scy    }
5292366076Scy    switch( *(int*)sqlite3_user_data(context) ){
5293366076Scy      case 0:
5294366076Scy        sqlite3_snprintf(sizeof(zResult), zResult, "ieee754(%lld,%d)",
5295366076Scy                         m, e-1075);
5296366076Scy        sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT);
5297366076Scy        break;
5298366076Scy      case 1:
5299366076Scy        sqlite3_result_int64(context, m);
5300366076Scy        break;
5301366076Scy      case 2:
5302366076Scy        sqlite3_result_int(context, e-1075);
5303366076Scy        break;
5304366076Scy    }
5305366076Scy  }else{
5306366076Scy    sqlite3_int64 m, e, a;
5307366076Scy    double r;
5308366076Scy    int isNeg = 0;
5309366076Scy    m = sqlite3_value_int64(argv[0]);
5310366076Scy    e = sqlite3_value_int64(argv[1]);
5311369951Scy
5312369951Scy    /* Limit the range of e.  Ticket 22dea1cfdb9151e4 2021-03-02 */
5313369951Scy    if( e>10000 ){
5314369951Scy      e = 10000;
5315369951Scy    }else if( e<-10000 ){
5316369951Scy      e = -10000;
5317369951Scy    }
5318369951Scy
5319366076Scy    if( m<0 ){
5320366076Scy      isNeg = 1;
5321366076Scy      m = -m;
5322366076Scy      if( m<0 ) return;
5323366076Scy    }else if( m==0 && e>-1000 && e<1000 ){
5324366076Scy      sqlite3_result_double(context, 0.0);
5325366076Scy      return;
5326366076Scy    }
5327366076Scy    while( (m>>32)&0xffe00000 ){
5328366076Scy      m >>= 1;
5329366076Scy      e++;
5330366076Scy    }
5331366076Scy    while( m!=0 && ((m>>32)&0xfff00000)==0 ){
5332366076Scy      m <<= 1;
5333366076Scy      e--;
5334366076Scy    }
5335366076Scy    e += 1075;
5336366076Scy    if( e<=0 ){
5337366076Scy      /* Subnormal */
5338366076Scy      m >>= 1-e;
5339366076Scy      e = 0;
5340366076Scy    }else if( e>0x7ff ){
5341366076Scy      e = 0x7ff;
5342366076Scy    }
5343366076Scy    a = m & ((((sqlite3_int64)1)<<52)-1);
5344366076Scy    a |= e<<52;
5345366076Scy    if( isNeg ) a |= ((sqlite3_uint64)1)<<63;
5346366076Scy    memcpy(&r, &a, sizeof(r));
5347366076Scy    sqlite3_result_double(context, r);
5348366076Scy  }
5349366076Scy}
5350366076Scy
5351366076Scy/*
5352366076Scy** Functions to convert between blobs and floats.
5353366076Scy*/
5354366076Scystatic void ieee754func_from_blob(
5355366076Scy  sqlite3_context *context,
5356366076Scy  int argc,
5357366076Scy  sqlite3_value **argv
5358366076Scy){
5359366076Scy  UNUSED_PARAMETER(argc);
5360366076Scy  if( sqlite3_value_type(argv[0])==SQLITE_BLOB
5361366076Scy   && sqlite3_value_bytes(argv[0])==sizeof(double)
5362366076Scy  ){
5363366076Scy    double r;
5364366076Scy    const unsigned char *x = sqlite3_value_blob(argv[0]);
5365366076Scy    unsigned int i;
5366366076Scy    sqlite3_uint64 v = 0;
5367366076Scy    for(i=0; i<sizeof(r); i++){
5368366076Scy      v = (v<<8) | x[i];
5369366076Scy    }
5370366076Scy    memcpy(&r, &v, sizeof(r));
5371366076Scy    sqlite3_result_double(context, r);
5372366076Scy  }
5373366076Scy}
5374366076Scystatic void ieee754func_to_blob(
5375366076Scy  sqlite3_context *context,
5376366076Scy  int argc,
5377366076Scy  sqlite3_value **argv
5378366076Scy){
5379366076Scy  UNUSED_PARAMETER(argc);
5380366076Scy  if( sqlite3_value_type(argv[0])==SQLITE_FLOAT
5381366076Scy   || sqlite3_value_type(argv[0])==SQLITE_INTEGER
5382366076Scy  ){
5383366076Scy    double r = sqlite3_value_double(argv[0]);
5384366076Scy    sqlite3_uint64 v;
5385366076Scy    unsigned char a[sizeof(r)];
5386366076Scy    unsigned int i;
5387366076Scy    memcpy(&v, &r, sizeof(r));
5388366076Scy    for(i=1; i<=sizeof(r); i++){
5389366076Scy      a[sizeof(r)-i] = v&0xff;
5390366076Scy      v >>= 8;
5391366076Scy    }
5392366076Scy    sqlite3_result_blob(context, a, sizeof(r), SQLITE_TRANSIENT);
5393366076Scy  }
5394366076Scy}
5395366076Scy
5396366076Scy
5397366076Scy#ifdef _WIN32
5398366076Scy
5399366076Scy#endif
5400366076Scyint sqlite3_ieee_init(
5401366076Scy  sqlite3 *db,
5402366076Scy  char **pzErrMsg,
5403366076Scy  const sqlite3_api_routines *pApi
5404366076Scy){
5405366076Scy  static const struct {
5406366076Scy    char *zFName;
5407366076Scy    int nArg;
5408366076Scy    int iAux;
5409366076Scy    void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
5410366076Scy  } aFunc[] = {
5411366076Scy    { "ieee754",           1,   0, ieee754func },
5412366076Scy    { "ieee754",           2,   0, ieee754func },
5413366076Scy    { "ieee754_mantissa",  1,   1, ieee754func },
5414366076Scy    { "ieee754_exponent",  1,   2, ieee754func },
5415366076Scy    { "ieee754_to_blob",   1,   0, ieee754func_to_blob },
5416366076Scy    { "ieee754_from_blob", 1,   0, ieee754func_from_blob },
5417366076Scy
5418366076Scy  };
5419366076Scy  unsigned int i;
5420366076Scy  int rc = SQLITE_OK;
5421366076Scy  SQLITE_EXTENSION_INIT2(pApi);
5422366076Scy  (void)pzErrMsg;  /* Unused parameter */
5423366076Scy  for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
5424366076Scy    rc = sqlite3_create_function(db, aFunc[i].zFName, aFunc[i].nArg,
5425366076Scy                               SQLITE_UTF8|SQLITE_INNOCUOUS,
5426366076Scy                               (void*)&aFunc[i].iAux,
5427366076Scy                               aFunc[i].xFunc, 0, 0);
5428366076Scy  }
5429366076Scy  return rc;
5430366076Scy}
5431366076Scy
5432366076Scy/************************* End ../ext/misc/ieee754.c ********************/
5433369950Scy/************************* Begin ../ext/misc/series.c ******************/
5434369950Scy/*
5435369950Scy** 2015-08-18
5436369950Scy**
5437369950Scy** The author disclaims copyright to this source code.  In place of
5438369950Scy** a legal notice, here is a blessing:
5439369950Scy**
5440369950Scy**    May you do good and not evil.
5441369950Scy**    May you find forgiveness for yourself and forgive others.
5442369950Scy**    May you share freely, never taking more than you give.
5443369950Scy**
5444369950Scy*************************************************************************
5445369950Scy**
5446369950Scy** This file demonstrates how to create a table-valued-function using
5447369950Scy** a virtual table.  This demo implements the generate_series() function
5448369950Scy** which gives similar results to the eponymous function in PostgreSQL.
5449369950Scy** Examples:
5450369950Scy**
5451369950Scy**      SELECT * FROM generate_series(0,100,5);
5452369950Scy**
5453369950Scy** The query above returns integers from 0 through 100 counting by steps
5454369950Scy** of 5.
5455369950Scy**
5456369950Scy**      SELECT * FROM generate_series(0,100);
5457369950Scy**
5458369950Scy** Integers from 0 through 100 with a step size of 1.
5459369950Scy**
5460369950Scy**      SELECT * FROM generate_series(20) LIMIT 10;
5461369950Scy**
5462369950Scy** Integers 20 through 29.
5463369950Scy**
5464369950Scy** HOW IT WORKS
5465369950Scy**
5466369950Scy** The generate_series "function" is really a virtual table with the
5467369950Scy** following schema:
5468369950Scy**
5469369950Scy**     CREATE TABLE generate_series(
5470369950Scy**       value,
5471369950Scy**       start HIDDEN,
5472369950Scy**       stop HIDDEN,
5473369950Scy**       step HIDDEN
5474369950Scy**     );
5475369950Scy**
5476369950Scy** Function arguments in queries against this virtual table are translated
5477369950Scy** into equality constraints against successive hidden columns.  In other
5478369950Scy** words, the following pairs of queries are equivalent to each other:
5479369950Scy**
5480369950Scy**    SELECT * FROM generate_series(0,100,5);
5481369950Scy**    SELECT * FROM generate_series WHERE start=0 AND stop=100 AND step=5;
5482369950Scy**
5483369950Scy**    SELECT * FROM generate_series(0,100);
5484369950Scy**    SELECT * FROM generate_series WHERE start=0 AND stop=100;
5485369950Scy**
5486369950Scy**    SELECT * FROM generate_series(20) LIMIT 10;
5487369950Scy**    SELECT * FROM generate_series WHERE start=20 LIMIT 10;
5488369950Scy**
5489369950Scy** The generate_series virtual table implementation leaves the xCreate method
5490369950Scy** set to NULL.  This means that it is not possible to do a CREATE VIRTUAL
5491369950Scy** TABLE command with "generate_series" as the USING argument.  Instead, there
5492369950Scy** is a single generate_series virtual table that is always available without
5493369950Scy** having to be created first.
5494369950Scy**
5495369950Scy** The xBestIndex method looks for equality constraints against the hidden
5496369950Scy** start, stop, and step columns, and if present, it uses those constraints
5497369950Scy** to bound the sequence of generated values.  If the equality constraints
5498369950Scy** are missing, it uses 0 for start, 4294967295 for stop, and 1 for step.
5499369950Scy** xBestIndex returns a small cost when both start and stop are available,
5500369950Scy** and a very large cost if either start or stop are unavailable.  This
5501369950Scy** encourages the query planner to order joins such that the bounds of the
5502369950Scy** series are well-defined.
5503369950Scy*/
5504369950Scy/* #include "sqlite3ext.h" */
5505369950ScySQLITE_EXTENSION_INIT1
5506369950Scy#include <assert.h>
5507369950Scy#include <string.h>
5508369950Scy
5509369950Scy#ifndef SQLITE_OMIT_VIRTUALTABLE
5510369950Scy
5511369950Scy
5512369950Scy/* series_cursor is a subclass of sqlite3_vtab_cursor which will
5513369950Scy** serve as the underlying representation of a cursor that scans
5514369950Scy** over rows of the result
5515369950Scy*/
5516369950Scytypedef struct series_cursor series_cursor;
5517369950Scystruct series_cursor {
5518369950Scy  sqlite3_vtab_cursor base;  /* Base class - must be first */
5519369950Scy  int isDesc;                /* True to count down rather than up */
5520369950Scy  sqlite3_int64 iRowid;      /* The rowid */
5521369950Scy  sqlite3_int64 iValue;      /* Current value ("value") */
5522369950Scy  sqlite3_int64 mnValue;     /* Mimimum value ("start") */
5523369950Scy  sqlite3_int64 mxValue;     /* Maximum value ("stop") */
5524369950Scy  sqlite3_int64 iStep;       /* Increment ("step") */
5525369950Scy};
5526369950Scy
5527369950Scy/*
5528369950Scy** The seriesConnect() method is invoked to create a new
5529369950Scy** series_vtab that describes the generate_series virtual table.
5530369950Scy**
5531369950Scy** Think of this routine as the constructor for series_vtab objects.
5532369950Scy**
5533369950Scy** All this routine needs to do is:
5534369950Scy**
5535369950Scy**    (1) Allocate the series_vtab object and initialize all fields.
5536369950Scy**
5537369950Scy**    (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
5538369950Scy**        result set of queries against generate_series will look like.
5539369950Scy*/
5540369950Scystatic int seriesConnect(
5541369950Scy  sqlite3 *db,
5542369950Scy  void *pUnused,
5543369950Scy  int argcUnused, const char *const*argvUnused,
5544369950Scy  sqlite3_vtab **ppVtab,
5545369950Scy  char **pzErrUnused
5546369950Scy){
5547369950Scy  sqlite3_vtab *pNew;
5548369950Scy  int rc;
5549369950Scy
5550369950Scy/* Column numbers */
5551369950Scy#define SERIES_COLUMN_VALUE 0
5552369950Scy#define SERIES_COLUMN_START 1
5553369950Scy#define SERIES_COLUMN_STOP  2
5554369950Scy#define SERIES_COLUMN_STEP  3
5555369950Scy
5556369950Scy  (void)pUnused;
5557369950Scy  (void)argcUnused;
5558369950Scy  (void)argvUnused;
5559369950Scy  (void)pzErrUnused;
5560369950Scy  rc = sqlite3_declare_vtab(db,
5561369950Scy     "CREATE TABLE x(value,start hidden,stop hidden,step hidden)");
5562369950Scy  if( rc==SQLITE_OK ){
5563369950Scy    pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
5564369950Scy    if( pNew==0 ) return SQLITE_NOMEM;
5565369950Scy    memset(pNew, 0, sizeof(*pNew));
5566369950Scy    sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
5567369950Scy  }
5568369950Scy  return rc;
5569369950Scy}
5570369950Scy
5571369950Scy/*
5572369950Scy** This method is the destructor for series_cursor objects.
5573369950Scy*/
5574369950Scystatic int seriesDisconnect(sqlite3_vtab *pVtab){
5575369950Scy  sqlite3_free(pVtab);
5576369950Scy  return SQLITE_OK;
5577369950Scy}
5578369950Scy
5579369950Scy/*
5580369950Scy** Constructor for a new series_cursor object.
5581369950Scy*/
5582369950Scystatic int seriesOpen(sqlite3_vtab *pUnused, sqlite3_vtab_cursor **ppCursor){
5583369950Scy  series_cursor *pCur;
5584369950Scy  (void)pUnused;
5585369950Scy  pCur = sqlite3_malloc( sizeof(*pCur) );
5586369950Scy  if( pCur==0 ) return SQLITE_NOMEM;
5587369950Scy  memset(pCur, 0, sizeof(*pCur));
5588369950Scy  *ppCursor = &pCur->base;
5589369950Scy  return SQLITE_OK;
5590369950Scy}
5591369950Scy
5592369950Scy/*
5593369950Scy** Destructor for a series_cursor.
5594369950Scy*/
5595369950Scystatic int seriesClose(sqlite3_vtab_cursor *cur){
5596369950Scy  sqlite3_free(cur);
5597369950Scy  return SQLITE_OK;
5598369950Scy}
5599369950Scy
5600369950Scy
5601369950Scy/*
5602369950Scy** Advance a series_cursor to its next row of output.
5603369950Scy*/
5604369950Scystatic int seriesNext(sqlite3_vtab_cursor *cur){
5605369950Scy  series_cursor *pCur = (series_cursor*)cur;
5606369950Scy  if( pCur->isDesc ){
5607369950Scy    pCur->iValue -= pCur->iStep;
5608369950Scy  }else{
5609369950Scy    pCur->iValue += pCur->iStep;
5610369950Scy  }
5611369950Scy  pCur->iRowid++;
5612369950Scy  return SQLITE_OK;
5613369950Scy}
5614369950Scy
5615369950Scy/*
5616369950Scy** Return values of columns for the row at which the series_cursor
5617369950Scy** is currently pointing.
5618369950Scy*/
5619369950Scystatic int seriesColumn(
5620369950Scy  sqlite3_vtab_cursor *cur,   /* The cursor */
5621369950Scy  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
5622369950Scy  int i                       /* Which column to return */
5623369950Scy){
5624369950Scy  series_cursor *pCur = (series_cursor*)cur;
5625369950Scy  sqlite3_int64 x = 0;
5626369950Scy  switch( i ){
5627369950Scy    case SERIES_COLUMN_START:  x = pCur->mnValue; break;
5628369950Scy    case SERIES_COLUMN_STOP:   x = pCur->mxValue; break;
5629369950Scy    case SERIES_COLUMN_STEP:   x = pCur->iStep;   break;
5630369950Scy    default:                   x = pCur->iValue;  break;
5631369950Scy  }
5632369950Scy  sqlite3_result_int64(ctx, x);
5633369950Scy  return SQLITE_OK;
5634369950Scy}
5635369950Scy
5636369950Scy/*
5637369950Scy** Return the rowid for the current row. In this implementation, the
5638369950Scy** first row returned is assigned rowid value 1, and each subsequent
5639369950Scy** row a value 1 more than that of the previous.
5640369950Scy*/
5641369950Scystatic int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
5642369950Scy  series_cursor *pCur = (series_cursor*)cur;
5643369950Scy  *pRowid = pCur->iRowid;
5644369950Scy  return SQLITE_OK;
5645369950Scy}
5646369950Scy
5647369950Scy/*
5648369950Scy** Return TRUE if the cursor has been moved off of the last
5649369950Scy** row of output.
5650369950Scy*/
5651369950Scystatic int seriesEof(sqlite3_vtab_cursor *cur){
5652369950Scy  series_cursor *pCur = (series_cursor*)cur;
5653369950Scy  if( pCur->isDesc ){
5654369950Scy    return pCur->iValue < pCur->mnValue;
5655369950Scy  }else{
5656369950Scy    return pCur->iValue > pCur->mxValue;
5657369950Scy  }
5658369950Scy}
5659369950Scy
5660369950Scy/* True to cause run-time checking of the start=, stop=, and/or step=
5661369950Scy** parameters.  The only reason to do this is for testing the
5662369950Scy** constraint checking logic for virtual tables in the SQLite core.
5663369950Scy*/
5664369950Scy#ifndef SQLITE_SERIES_CONSTRAINT_VERIFY
5665369950Scy# define SQLITE_SERIES_CONSTRAINT_VERIFY 0
5666369950Scy#endif
5667369950Scy
5668369950Scy/*
5669369950Scy** This method is called to "rewind" the series_cursor object back
5670369950Scy** to the first row of output.  This method is always called at least
5671369950Scy** once prior to any call to seriesColumn() or seriesRowid() or
5672369950Scy** seriesEof().
5673369950Scy**
5674369950Scy** The query plan selected by seriesBestIndex is passed in the idxNum
5675369950Scy** parameter.  (idxStr is not used in this implementation.)  idxNum
5676369950Scy** is a bitmask showing which constraints are available:
5677369950Scy**
5678369950Scy**    1:    start=VALUE
5679369950Scy**    2:    stop=VALUE
5680369950Scy**    4:    step=VALUE
5681369950Scy**
5682369950Scy** Also, if bit 8 is set, that means that the series should be output
5683369951Scy** in descending order rather than in ascending order.  If bit 16 is
5684369951Scy** set, then output must appear in ascending order.
5685369950Scy**
5686369950Scy** This routine should initialize the cursor and position it so that it
5687369950Scy** is pointing at the first row, or pointing off the end of the table
5688369950Scy** (so that seriesEof() will return true) if the table is empty.
5689369950Scy*/
5690369950Scystatic int seriesFilter(
5691369950Scy  sqlite3_vtab_cursor *pVtabCursor,
5692369950Scy  int idxNum, const char *idxStrUnused,
5693369950Scy  int argc, sqlite3_value **argv
5694369950Scy){
5695369950Scy  series_cursor *pCur = (series_cursor *)pVtabCursor;
5696369950Scy  int i = 0;
5697369950Scy  (void)idxStrUnused;
5698369950Scy  if( idxNum & 1 ){
5699369950Scy    pCur->mnValue = sqlite3_value_int64(argv[i++]);
5700369950Scy  }else{
5701369950Scy    pCur->mnValue = 0;
5702369950Scy  }
5703369950Scy  if( idxNum & 2 ){
5704369950Scy    pCur->mxValue = sqlite3_value_int64(argv[i++]);
5705369950Scy  }else{
5706369950Scy    pCur->mxValue = 0xffffffff;
5707369950Scy  }
5708369950Scy  if( idxNum & 4 ){
5709369950Scy    pCur->iStep = sqlite3_value_int64(argv[i++]);
5710369951Scy    if( pCur->iStep==0 ){
5711369951Scy      pCur->iStep = 1;
5712369951Scy    }else if( pCur->iStep<0 ){
5713369951Scy      pCur->iStep = -pCur->iStep;
5714369951Scy      if( (idxNum & 16)==0 ) idxNum |= 8;
5715369951Scy    }
5716369950Scy  }else{
5717369950Scy    pCur->iStep = 1;
5718369950Scy  }
5719369950Scy  for(i=0; i<argc; i++){
5720369950Scy    if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
5721369950Scy      /* If any of the constraints have a NULL value, then return no rows.
5722369950Scy      ** See ticket https://www.sqlite.org/src/info/fac496b61722daf2 */
5723369950Scy      pCur->mnValue = 1;
5724369950Scy      pCur->mxValue = 0;
5725369950Scy      break;
5726369950Scy    }
5727369950Scy  }
5728369950Scy  if( idxNum & 8 ){
5729369950Scy    pCur->isDesc = 1;
5730369950Scy    pCur->iValue = pCur->mxValue;
5731369950Scy    if( pCur->iStep>0 ){
5732369950Scy      pCur->iValue -= (pCur->mxValue - pCur->mnValue)%pCur->iStep;
5733369950Scy    }
5734369950Scy  }else{
5735369950Scy    pCur->isDesc = 0;
5736369950Scy    pCur->iValue = pCur->mnValue;
5737369950Scy  }
5738369950Scy  pCur->iRowid = 1;
5739369950Scy  return SQLITE_OK;
5740369950Scy}
5741369950Scy
5742369950Scy/*
5743369950Scy** SQLite will invoke this method one or more times while planning a query
5744369950Scy** that uses the generate_series virtual table.  This routine needs to create
5745369950Scy** a query plan for each invocation and compute an estimated cost for that
5746369950Scy** plan.
5747369950Scy**
5748369950Scy** In this implementation idxNum is used to represent the
5749369950Scy** query plan.  idxStr is unused.
5750369950Scy**
5751369950Scy** The query plan is represented by bits in idxNum:
5752369950Scy**
5753369950Scy**  (1)  start = $value  -- constraint exists
5754369950Scy**  (2)  stop = $value   -- constraint exists
5755369950Scy**  (4)  step = $value   -- constraint exists
5756369950Scy**  (8)  output in descending order
5757369950Scy*/
5758369950Scystatic int seriesBestIndex(
5759369950Scy  sqlite3_vtab *tabUnused,
5760369950Scy  sqlite3_index_info *pIdxInfo
5761369950Scy){
5762369950Scy  int i, j;              /* Loop over constraints */
5763369950Scy  int idxNum = 0;        /* The query plan bitmask */
5764369950Scy  int unusableMask = 0;  /* Mask of unusable constraints */
5765369950Scy  int nArg = 0;          /* Number of arguments that seriesFilter() expects */
5766369950Scy  int aIdx[3];           /* Constraints on start, stop, and step */
5767369950Scy  const struct sqlite3_index_constraint *pConstraint;
5768369950Scy
5769369950Scy  /* This implementation assumes that the start, stop, and step columns
5770369950Scy  ** are the last three columns in the virtual table. */
5771369950Scy  assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
5772369950Scy  assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
5773369950Scy  (void)tabUnused;
5774369950Scy  aIdx[0] = aIdx[1] = aIdx[2] = -1;
5775369950Scy  pConstraint = pIdxInfo->aConstraint;
5776369950Scy  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
5777369950Scy    int iCol;    /* 0 for start, 1 for stop, 2 for step */
5778369950Scy    int iMask;   /* bitmask for those column */
5779369950Scy    if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
5780369950Scy    iCol = pConstraint->iColumn - SERIES_COLUMN_START;
5781369950Scy    assert( iCol>=0 && iCol<=2 );
5782369950Scy    iMask = 1 << iCol;
5783369950Scy    if( pConstraint->usable==0 ){
5784369950Scy      unusableMask |=  iMask;
5785369950Scy      continue;
5786369950Scy    }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
5787369950Scy      idxNum |= iMask;
5788369950Scy      aIdx[iCol] = i;
5789369950Scy    }
5790369950Scy  }
5791369950Scy  for(i=0; i<3; i++){
5792369950Scy    if( (j = aIdx[i])>=0 ){
5793369950Scy      pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
5794369950Scy      pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
5795369950Scy    }
5796369950Scy  }
5797369950Scy  if( (unusableMask & ~idxNum)!=0 ){
5798369950Scy    /* The start, stop, and step columns are inputs.  Therefore if there
5799369950Scy    ** are unusable constraints on any of start, stop, or step then
5800369950Scy    ** this plan is unusable */
5801369950Scy    return SQLITE_CONSTRAINT;
5802369950Scy  }
5803369950Scy  if( (idxNum & 3)==3 ){
5804369950Scy    /* Both start= and stop= boundaries are available.  This is the
5805369950Scy    ** the preferred case */
5806369950Scy    pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
5807369950Scy    pIdxInfo->estimatedRows = 1000;
5808369950Scy    if( pIdxInfo->nOrderBy==1 ){
5809369951Scy      if( pIdxInfo->aOrderBy[0].desc ){
5810369951Scy        idxNum |= 8;
5811369951Scy      }else{
5812369951Scy        idxNum |= 16;
5813369951Scy      }
5814369950Scy      pIdxInfo->orderByConsumed = 1;
5815369950Scy    }
5816369950Scy  }else{
5817369950Scy    /* If either boundary is missing, we have to generate a huge span
5818369950Scy    ** of numbers.  Make this case very expensive so that the query
5819369950Scy    ** planner will work hard to avoid it. */
5820369950Scy    pIdxInfo->estimatedRows = 2147483647;
5821369950Scy  }
5822369950Scy  pIdxInfo->idxNum = idxNum;
5823369950Scy  return SQLITE_OK;
5824369950Scy}
5825369950Scy
5826369950Scy/*
5827369950Scy** This following structure defines all the methods for the
5828369950Scy** generate_series virtual table.
5829369950Scy*/
5830369950Scystatic sqlite3_module seriesModule = {
5831369950Scy  0,                         /* iVersion */
5832369950Scy  0,                         /* xCreate */
5833369950Scy  seriesConnect,             /* xConnect */
5834369950Scy  seriesBestIndex,           /* xBestIndex */
5835369950Scy  seriesDisconnect,          /* xDisconnect */
5836369950Scy  0,                         /* xDestroy */
5837369950Scy  seriesOpen,                /* xOpen - open a cursor */
5838369950Scy  seriesClose,               /* xClose - close a cursor */
5839369950Scy  seriesFilter,              /* xFilter - configure scan constraints */
5840369950Scy  seriesNext,                /* xNext - advance a cursor */
5841369950Scy  seriesEof,                 /* xEof - check for end of scan */
5842369950Scy  seriesColumn,              /* xColumn - read data */
5843369950Scy  seriesRowid,               /* xRowid - read data */
5844369950Scy  0,                         /* xUpdate */
5845369950Scy  0,                         /* xBegin */
5846369950Scy  0,                         /* xSync */
5847369950Scy  0,                         /* xCommit */
5848369950Scy  0,                         /* xRollback */
5849369950Scy  0,                         /* xFindMethod */
5850369950Scy  0,                         /* xRename */
5851369950Scy  0,                         /* xSavepoint */
5852369950Scy  0,                         /* xRelease */
5853369950Scy  0,                         /* xRollbackTo */
5854369950Scy  0                          /* xShadowName */
5855369950Scy};
5856369950Scy
5857369950Scy#endif /* SQLITE_OMIT_VIRTUALTABLE */
5858369950Scy
5859369950Scy#ifdef _WIN32
5860369950Scy
5861369950Scy#endif
5862369950Scyint sqlite3_series_init(
5863369950Scy  sqlite3 *db,
5864369950Scy  char **pzErrMsg,
5865369950Scy  const sqlite3_api_routines *pApi
5866369950Scy){
5867369950Scy  int rc = SQLITE_OK;
5868369950Scy  SQLITE_EXTENSION_INIT2(pApi);
5869369950Scy#ifndef SQLITE_OMIT_VIRTUALTABLE
5870369950Scy  if( sqlite3_libversion_number()<3008012 ){
5871369950Scy    *pzErrMsg = sqlite3_mprintf(
5872369950Scy        "generate_series() requires SQLite 3.8.12 or later");
5873369950Scy    return SQLITE_ERROR;
5874369950Scy  }
5875369950Scy  rc = sqlite3_create_module(db, "generate_series", &seriesModule, 0);
5876369950Scy#endif
5877369950Scy  return rc;
5878369950Scy}
5879369950Scy
5880369950Scy/************************* End ../ext/misc/series.c ********************/
5881342292Scy#ifdef SQLITE_HAVE_ZLIB
5882342292Scy/************************* Begin ../ext/misc/zipfile.c ******************/
5883342292Scy/*
5884342292Scy** 2017-12-26
5885342292Scy**
5886342292Scy** The author disclaims copyright to this source code.  In place of
5887342292Scy** a legal notice, here is a blessing:
5888342292Scy**
5889342292Scy**    May you do good and not evil.
5890342292Scy**    May you find forgiveness for yourself and forgive others.
5891342292Scy**    May you share freely, never taking more than you give.
5892342292Scy**
5893342292Scy******************************************************************************
5894342292Scy**
5895342292Scy** This file implements a virtual table for reading and writing ZIP archive
5896342292Scy** files.
5897342292Scy**
5898342292Scy** Usage example:
5899342292Scy**
5900342292Scy**     SELECT name, sz, datetime(mtime,'unixepoch') FROM zipfile($filename);
5901342292Scy**
5902342292Scy** Current limitations:
5903342292Scy**
5904342292Scy**    *  No support for encryption
5905342292Scy**    *  No support for ZIP archives spanning multiple files
5906342292Scy**    *  No support for zip64 extensions
5907342292Scy**    *  Only the "inflate/deflate" (zlib) compression method is supported
5908342292Scy*/
5909351633Scy/* #include "sqlite3ext.h" */
5910342292ScySQLITE_EXTENSION_INIT1
5911342292Scy#include <stdio.h>
5912342292Scy#include <string.h>
5913342292Scy#include <assert.h>
5914342292Scy
5915342292Scy#include <zlib.h>
5916342292Scy
5917342292Scy#ifndef SQLITE_OMIT_VIRTUALTABLE
5918342292Scy
5919342292Scy#ifndef SQLITE_AMALGAMATION
5920342292Scy
5921342292Scy/* typedef sqlite3_int64 i64; */
5922342292Scy/* typedef unsigned char u8; */
5923342292Scytypedef unsigned short u16;
5924342292Scytypedef unsigned long u32;
5925342292Scy#define MIN(a,b) ((a)<(b) ? (a) : (b))
5926342292Scy
5927342292Scy#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
5928342292Scy# define ALWAYS(X)      (1)
5929342292Scy# define NEVER(X)       (0)
5930342292Scy#elif !defined(NDEBUG)
5931342292Scy# define ALWAYS(X)      ((X)?1:(assert(0),0))
5932342292Scy# define NEVER(X)       ((X)?(assert(0),1):0)
5933342292Scy#else
5934342292Scy# define ALWAYS(X)      (X)
5935342292Scy# define NEVER(X)       (X)
5936342292Scy#endif
5937342292Scy
5938342292Scy#endif   /* SQLITE_AMALGAMATION */
5939342292Scy
5940342292Scy/*
5941342292Scy** Definitions for mode bitmasks S_IFDIR, S_IFREG and S_IFLNK.
5942342292Scy**
5943342292Scy** In some ways it would be better to obtain these values from system
5944342292Scy** header files. But, the dependency is undesirable and (a) these
5945342292Scy** have been stable for decades, (b) the values are part of POSIX and
5946342292Scy** are also made explicit in [man stat], and (c) are part of the
5947342292Scy** file format for zip archives.
5948342292Scy*/
5949342292Scy#ifndef S_IFDIR
5950342292Scy# define S_IFDIR 0040000
5951342292Scy#endif
5952342292Scy#ifndef S_IFREG
5953342292Scy# define S_IFREG 0100000
5954342292Scy#endif
5955342292Scy#ifndef S_IFLNK
5956342292Scy# define S_IFLNK 0120000
5957342292Scy#endif
5958342292Scy
5959342292Scystatic const char ZIPFILE_SCHEMA[] =
5960342292Scy  "CREATE TABLE y("
5961342292Scy    "name PRIMARY KEY,"  /* 0: Name of file in zip archive */
5962342292Scy    "mode,"              /* 1: POSIX mode for file */
5963342292Scy    "mtime,"             /* 2: Last modification time (secs since 1970)*/
5964342292Scy    "sz,"                /* 3: Size of object */
5965342292Scy    "rawdata,"           /* 4: Raw data */
5966342292Scy    "data,"              /* 5: Uncompressed data */
5967342292Scy    "method,"            /* 6: Compression method (integer) */
5968342292Scy    "z HIDDEN"           /* 7: Name of zip file */
5969342292Scy  ") WITHOUT ROWID;";
5970342292Scy
5971342292Scy#define ZIPFILE_F_COLUMN_IDX 7    /* Index of column "file" in the above */
5972342292Scy#define ZIPFILE_BUFFER_SIZE (64*1024)
5973342292Scy
5974342292Scy
5975342292Scy/*
5976342292Scy** Magic numbers used to read and write zip files.
5977342292Scy**
5978342292Scy** ZIPFILE_NEWENTRY_MADEBY:
5979342292Scy**   Use this value for the "version-made-by" field in new zip file
5980342292Scy**   entries. The upper byte indicates "unix", and the lower byte
5981342292Scy**   indicates that the zip file matches pkzip specification 3.0.
5982342292Scy**   This is what info-zip seems to do.
5983342292Scy**
5984342292Scy** ZIPFILE_NEWENTRY_REQUIRED:
5985342292Scy**   Value for "version-required-to-extract" field of new entries.
5986342292Scy**   Version 2.0 is required to support folders and deflate compression.
5987342292Scy**
5988342292Scy** ZIPFILE_NEWENTRY_FLAGS:
5989342292Scy**   Value for "general-purpose-bit-flags" field of new entries. Bit
5990342292Scy**   11 means "utf-8 filename and comment".
5991342292Scy**
5992342292Scy** ZIPFILE_SIGNATURE_CDS:
5993342292Scy**   First 4 bytes of a valid CDS record.
5994342292Scy**
5995342292Scy** ZIPFILE_SIGNATURE_LFH:
5996342292Scy**   First 4 bytes of a valid LFH record.
5997342292Scy**
5998342292Scy** ZIPFILE_SIGNATURE_EOCD
5999342292Scy**   First 4 bytes of a valid EOCD record.
6000342292Scy*/
6001342292Scy#define ZIPFILE_EXTRA_TIMESTAMP   0x5455
6002342292Scy#define ZIPFILE_NEWENTRY_MADEBY   ((3<<8) + 30)
6003342292Scy#define ZIPFILE_NEWENTRY_REQUIRED 20
6004342292Scy#define ZIPFILE_NEWENTRY_FLAGS    0x800
6005342292Scy#define ZIPFILE_SIGNATURE_CDS     0x02014b50
6006342292Scy#define ZIPFILE_SIGNATURE_LFH     0x04034b50
6007342292Scy#define ZIPFILE_SIGNATURE_EOCD    0x06054b50
6008342292Scy
6009342292Scy/*
6010342292Scy** The sizes of the fixed-size part of each of the three main data
6011342292Scy** structures in a zip archive.
6012342292Scy*/
6013342292Scy#define ZIPFILE_LFH_FIXED_SZ      30
6014342292Scy#define ZIPFILE_EOCD_FIXED_SZ     22
6015342292Scy#define ZIPFILE_CDS_FIXED_SZ      46
6016342292Scy
6017342292Scy/*
6018342292Scy*** 4.3.16  End of central directory record:
6019342292Scy***
6020342292Scy***   end of central dir signature    4 bytes  (0x06054b50)
6021342292Scy***   number of this disk             2 bytes
6022342292Scy***   number of the disk with the
6023342292Scy***   start of the central directory  2 bytes
6024342292Scy***   total number of entries in the
6025342292Scy***   central directory on this disk  2 bytes
6026342292Scy***   total number of entries in
6027342292Scy***   the central directory           2 bytes
6028342292Scy***   size of the central directory   4 bytes
6029342292Scy***   offset of start of central
6030342292Scy***   directory with respect to
6031342292Scy***   the starting disk number        4 bytes
6032342292Scy***   .ZIP file comment length        2 bytes
6033342292Scy***   .ZIP file comment       (variable size)
6034342292Scy*/
6035342292Scytypedef struct ZipfileEOCD ZipfileEOCD;
6036342292Scystruct ZipfileEOCD {
6037342292Scy  u16 iDisk;
6038342292Scy  u16 iFirstDisk;
6039342292Scy  u16 nEntry;
6040342292Scy  u16 nEntryTotal;
6041342292Scy  u32 nSize;
6042342292Scy  u32 iOffset;
6043342292Scy};
6044342292Scy
6045342292Scy/*
6046342292Scy*** 4.3.12  Central directory structure:
6047342292Scy***
6048342292Scy*** ...
6049342292Scy***
6050342292Scy***   central file header signature   4 bytes  (0x02014b50)
6051342292Scy***   version made by                 2 bytes
6052342292Scy***   version needed to extract       2 bytes
6053342292Scy***   general purpose bit flag        2 bytes
6054342292Scy***   compression method              2 bytes
6055342292Scy***   last mod file time              2 bytes
6056342292Scy***   last mod file date              2 bytes
6057342292Scy***   crc-32                          4 bytes
6058342292Scy***   compressed size                 4 bytes
6059342292Scy***   uncompressed size               4 bytes
6060342292Scy***   file name length                2 bytes
6061342292Scy***   extra field length              2 bytes
6062342292Scy***   file comment length             2 bytes
6063342292Scy***   disk number start               2 bytes
6064342292Scy***   internal file attributes        2 bytes
6065342292Scy***   external file attributes        4 bytes
6066342292Scy***   relative offset of local header 4 bytes
6067342292Scy*/
6068342292Scytypedef struct ZipfileCDS ZipfileCDS;
6069342292Scystruct ZipfileCDS {
6070342292Scy  u16 iVersionMadeBy;
6071342292Scy  u16 iVersionExtract;
6072342292Scy  u16 flags;
6073342292Scy  u16 iCompression;
6074342292Scy  u16 mTime;
6075342292Scy  u16 mDate;
6076342292Scy  u32 crc32;
6077342292Scy  u32 szCompressed;
6078342292Scy  u32 szUncompressed;
6079342292Scy  u16 nFile;
6080342292Scy  u16 nExtra;
6081342292Scy  u16 nComment;
6082342292Scy  u16 iDiskStart;
6083342292Scy  u16 iInternalAttr;
6084342292Scy  u32 iExternalAttr;
6085342292Scy  u32 iOffset;
6086342292Scy  char *zFile;                    /* Filename (sqlite3_malloc()) */
6087342292Scy};
6088342292Scy
6089342292Scy/*
6090342292Scy*** 4.3.7  Local file header:
6091342292Scy***
6092342292Scy***   local file header signature     4 bytes  (0x04034b50)
6093342292Scy***   version needed to extract       2 bytes
6094342292Scy***   general purpose bit flag        2 bytes
6095342292Scy***   compression method              2 bytes
6096342292Scy***   last mod file time              2 bytes
6097342292Scy***   last mod file date              2 bytes
6098342292Scy***   crc-32                          4 bytes
6099342292Scy***   compressed size                 4 bytes
6100342292Scy***   uncompressed size               4 bytes
6101342292Scy***   file name length                2 bytes
6102342292Scy***   extra field length              2 bytes
6103342292Scy***
6104342292Scy*/
6105342292Scytypedef struct ZipfileLFH ZipfileLFH;
6106342292Scystruct ZipfileLFH {
6107342292Scy  u16 iVersionExtract;
6108342292Scy  u16 flags;
6109342292Scy  u16 iCompression;
6110342292Scy  u16 mTime;
6111342292Scy  u16 mDate;
6112342292Scy  u32 crc32;
6113342292Scy  u32 szCompressed;
6114342292Scy  u32 szUncompressed;
6115342292Scy  u16 nFile;
6116342292Scy  u16 nExtra;
6117342292Scy};
6118342292Scy
6119342292Scytypedef struct ZipfileEntry ZipfileEntry;
6120342292Scystruct ZipfileEntry {
6121342292Scy  ZipfileCDS cds;            /* Parsed CDS record */
6122342292Scy  u32 mUnixTime;             /* Modification time, in UNIX format */
6123342292Scy  u8 *aExtra;                /* cds.nExtra+cds.nComment bytes of extra data */
6124342292Scy  i64 iDataOff;              /* Offset to data in file (if aData==0) */
6125342292Scy  u8 *aData;                 /* cds.szCompressed bytes of compressed data */
6126342292Scy  ZipfileEntry *pNext;       /* Next element in in-memory CDS */
6127342292Scy};
6128342292Scy
6129342292Scy/*
6130342292Scy** Cursor type for zipfile tables.
6131342292Scy*/
6132342292Scytypedef struct ZipfileCsr ZipfileCsr;
6133342292Scystruct ZipfileCsr {
6134342292Scy  sqlite3_vtab_cursor base;  /* Base class - must be first */
6135342292Scy  i64 iId;                   /* Cursor ID */
6136342292Scy  u8 bEof;                   /* True when at EOF */
6137342292Scy  u8 bNoop;                  /* If next xNext() call is no-op */
6138342292Scy
6139342292Scy  /* Used outside of write transactions */
6140342292Scy  FILE *pFile;               /* Zip file */
6141342292Scy  i64 iNextOff;              /* Offset of next record in central directory */
6142342292Scy  ZipfileEOCD eocd;          /* Parse of central directory record */
6143342292Scy
6144342292Scy  ZipfileEntry *pFreeEntry;  /* Free this list when cursor is closed or reset */
6145342292Scy  ZipfileEntry *pCurrent;    /* Current entry */
6146342292Scy  ZipfileCsr *pCsrNext;      /* Next cursor on same virtual table */
6147342292Scy};
6148342292Scy
6149342292Scytypedef struct ZipfileTab ZipfileTab;
6150342292Scystruct ZipfileTab {
6151342292Scy  sqlite3_vtab base;         /* Base class - must be first */
6152342292Scy  char *zFile;               /* Zip file this table accesses (may be NULL) */
6153342292Scy  sqlite3 *db;               /* Host database connection */
6154342292Scy  u8 *aBuffer;               /* Temporary buffer used for various tasks */
6155342292Scy
6156342292Scy  ZipfileCsr *pCsrList;      /* List of cursors */
6157342292Scy  i64 iNextCsrid;
6158342292Scy
6159342292Scy  /* The following are used by write transactions only */
6160342292Scy  ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */
6161342292Scy  ZipfileEntry *pLastEntry;  /* Last element in pFirstEntry list */
6162342292Scy  FILE *pWriteFd;            /* File handle open on zip archive */
6163342292Scy  i64 szCurrent;             /* Current size of zip archive */
6164342292Scy  i64 szOrig;                /* Size of archive at start of transaction */
6165342292Scy};
6166342292Scy
6167342292Scy/*
6168342292Scy** Set the error message contained in context ctx to the results of
6169342292Scy** vprintf(zFmt, ...).
6170342292Scy*/
6171342292Scystatic void zipfileCtxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
6172342292Scy  char *zMsg = 0;
6173342292Scy  va_list ap;
6174342292Scy  va_start(ap, zFmt);
6175342292Scy  zMsg = sqlite3_vmprintf(zFmt, ap);
6176342292Scy  sqlite3_result_error(ctx, zMsg, -1);
6177342292Scy  sqlite3_free(zMsg);
6178342292Scy  va_end(ap);
6179342292Scy}
6180342292Scy
6181342292Scy/*
6182342292Scy** If string zIn is quoted, dequote it in place. Otherwise, if the string
6183342292Scy** is not quoted, do nothing.
6184342292Scy*/
6185342292Scystatic void zipfileDequote(char *zIn){
6186342292Scy  char q = zIn[0];
6187342292Scy  if( q=='"' || q=='\'' || q=='`' || q=='[' ){
6188342292Scy    int iIn = 1;
6189342292Scy    int iOut = 0;
6190342292Scy    if( q=='[' ) q = ']';
6191342292Scy    while( ALWAYS(zIn[iIn]) ){
6192342292Scy      char c = zIn[iIn++];
6193342292Scy      if( c==q && zIn[iIn++]!=q ) break;
6194342292Scy      zIn[iOut++] = c;
6195342292Scy    }
6196342292Scy    zIn[iOut] = '\0';
6197342292Scy  }
6198342292Scy}
6199342292Scy
6200342292Scy/*
6201342292Scy** Construct a new ZipfileTab virtual table object.
6202342292Scy**
6203342292Scy**   argv[0]   -> module name  ("zipfile")
6204342292Scy**   argv[1]   -> database name
6205342292Scy**   argv[2]   -> table name
6206342292Scy**   argv[...] -> "column name" and other module argument fields.
6207342292Scy*/
6208342292Scystatic int zipfileConnect(
6209342292Scy  sqlite3 *db,
6210342292Scy  void *pAux,
6211342292Scy  int argc, const char *const*argv,
6212342292Scy  sqlite3_vtab **ppVtab,
6213342292Scy  char **pzErr
6214342292Scy){
6215342292Scy  int nByte = sizeof(ZipfileTab) + ZIPFILE_BUFFER_SIZE;
6216342292Scy  int nFile = 0;
6217342292Scy  const char *zFile = 0;
6218342292Scy  ZipfileTab *pNew = 0;
6219342292Scy  int rc;
6220342292Scy
6221342292Scy  /* If the table name is not "zipfile", require that the argument be
6222342292Scy  ** specified. This stops zipfile tables from being created as:
6223342292Scy  **
6224342292Scy  **   CREATE VIRTUAL TABLE zzz USING zipfile();
6225342292Scy  **
6226342292Scy  ** It does not prevent:
6227342292Scy  **
6228342292Scy  **   CREATE VIRTUAL TABLE zipfile USING zipfile();
6229342292Scy  */
6230342292Scy  assert( 0==sqlite3_stricmp(argv[0], "zipfile") );
6231342292Scy  if( (0!=sqlite3_stricmp(argv[2], "zipfile") && argc<4) || argc>4 ){
6232342292Scy    *pzErr = sqlite3_mprintf("zipfile constructor requires one argument");
6233342292Scy    return SQLITE_ERROR;
6234342292Scy  }
6235342292Scy
6236342292Scy  if( argc>3 ){
6237342292Scy    zFile = argv[3];
6238342292Scy    nFile = (int)strlen(zFile)+1;
6239342292Scy  }
6240342292Scy
6241342292Scy  rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
6242342292Scy  if( rc==SQLITE_OK ){
6243346442Scy    pNew = (ZipfileTab*)sqlite3_malloc64((sqlite3_int64)nByte+nFile);
6244342292Scy    if( pNew==0 ) return SQLITE_NOMEM;
6245342292Scy    memset(pNew, 0, nByte+nFile);
6246342292Scy    pNew->db = db;
6247342292Scy    pNew->aBuffer = (u8*)&pNew[1];
6248342292Scy    if( zFile ){
6249342292Scy      pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE];
6250342292Scy      memcpy(pNew->zFile, zFile, nFile);
6251342292Scy      zipfileDequote(pNew->zFile);
6252342292Scy    }
6253342292Scy  }
6254361456Scy  sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
6255342292Scy  *ppVtab = (sqlite3_vtab*)pNew;
6256342292Scy  return rc;
6257342292Scy}
6258342292Scy
6259342292Scy/*
6260342292Scy** Free the ZipfileEntry structure indicated by the only argument.
6261342292Scy*/
6262342292Scystatic void zipfileEntryFree(ZipfileEntry *p){
6263342292Scy  if( p ){
6264342292Scy    sqlite3_free(p->cds.zFile);
6265342292Scy    sqlite3_free(p);
6266342292Scy  }
6267342292Scy}
6268342292Scy
6269342292Scy/*
6270342292Scy** Release resources that should be freed at the end of a write
6271342292Scy** transaction.
6272342292Scy*/
6273342292Scystatic void zipfileCleanupTransaction(ZipfileTab *pTab){
6274342292Scy  ZipfileEntry *pEntry;
6275342292Scy  ZipfileEntry *pNext;
6276342292Scy
6277342292Scy  if( pTab->pWriteFd ){
6278342292Scy    fclose(pTab->pWriteFd);
6279342292Scy    pTab->pWriteFd = 0;
6280342292Scy  }
6281342292Scy  for(pEntry=pTab->pFirstEntry; pEntry; pEntry=pNext){
6282342292Scy    pNext = pEntry->pNext;
6283342292Scy    zipfileEntryFree(pEntry);
6284342292Scy  }
6285342292Scy  pTab->pFirstEntry = 0;
6286342292Scy  pTab->pLastEntry = 0;
6287342292Scy  pTab->szCurrent = 0;
6288342292Scy  pTab->szOrig = 0;
6289342292Scy}
6290342292Scy
6291342292Scy/*
6292342292Scy** This method is the destructor for zipfile vtab objects.
6293342292Scy*/
6294342292Scystatic int zipfileDisconnect(sqlite3_vtab *pVtab){
6295342292Scy  zipfileCleanupTransaction((ZipfileTab*)pVtab);
6296342292Scy  sqlite3_free(pVtab);
6297342292Scy  return SQLITE_OK;
6298342292Scy}
6299342292Scy
6300342292Scy/*
6301342292Scy** Constructor for a new ZipfileCsr object.
6302342292Scy*/
6303342292Scystatic int zipfileOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){
6304342292Scy  ZipfileTab *pTab = (ZipfileTab*)p;
6305342292Scy  ZipfileCsr *pCsr;
6306342292Scy  pCsr = sqlite3_malloc(sizeof(*pCsr));
6307342292Scy  *ppCsr = (sqlite3_vtab_cursor*)pCsr;
6308342292Scy  if( pCsr==0 ){
6309342292Scy    return SQLITE_NOMEM;
6310342292Scy  }
6311342292Scy  memset(pCsr, 0, sizeof(*pCsr));
6312342292Scy  pCsr->iId = ++pTab->iNextCsrid;
6313342292Scy  pCsr->pCsrNext = pTab->pCsrList;
6314342292Scy  pTab->pCsrList = pCsr;
6315342292Scy  return SQLITE_OK;
6316342292Scy}
6317342292Scy
6318342292Scy/*
6319342292Scy** Reset a cursor back to the state it was in when first returned
6320342292Scy** by zipfileOpen().
6321342292Scy*/
6322342292Scystatic void zipfileResetCursor(ZipfileCsr *pCsr){
6323342292Scy  ZipfileEntry *p;
6324342292Scy  ZipfileEntry *pNext;
6325342292Scy
6326342292Scy  pCsr->bEof = 0;
6327342292Scy  if( pCsr->pFile ){
6328342292Scy    fclose(pCsr->pFile);
6329342292Scy    pCsr->pFile = 0;
6330342292Scy    zipfileEntryFree(pCsr->pCurrent);
6331342292Scy    pCsr->pCurrent = 0;
6332342292Scy  }
6333342292Scy
6334342292Scy  for(p=pCsr->pFreeEntry; p; p=pNext){
6335342292Scy    pNext = p->pNext;
6336342292Scy    zipfileEntryFree(p);
6337342292Scy  }
6338342292Scy}
6339342292Scy
6340342292Scy/*
6341342292Scy** Destructor for an ZipfileCsr.
6342342292Scy*/
6343342292Scystatic int zipfileClose(sqlite3_vtab_cursor *cur){
6344342292Scy  ZipfileCsr *pCsr = (ZipfileCsr*)cur;
6345342292Scy  ZipfileTab *pTab = (ZipfileTab*)(pCsr->base.pVtab);
6346342292Scy  ZipfileCsr **pp;
6347342292Scy  zipfileResetCursor(pCsr);
6348342292Scy
6349342292Scy  /* Remove this cursor from the ZipfileTab.pCsrList list. */
6350342292Scy  for(pp=&pTab->pCsrList; *pp!=pCsr; pp=&((*pp)->pCsrNext));
6351342292Scy  *pp = pCsr->pCsrNext;
6352342292Scy
6353342292Scy  sqlite3_free(pCsr);
6354342292Scy  return SQLITE_OK;
6355342292Scy}
6356342292Scy
6357342292Scy/*
6358342292Scy** Set the error message for the virtual table associated with cursor
6359342292Scy** pCsr to the results of vprintf(zFmt, ...).
6360342292Scy*/
6361342292Scystatic void zipfileTableErr(ZipfileTab *pTab, const char *zFmt, ...){
6362342292Scy  va_list ap;
6363342292Scy  va_start(ap, zFmt);
6364342292Scy  sqlite3_free(pTab->base.zErrMsg);
6365342292Scy  pTab->base.zErrMsg = sqlite3_vmprintf(zFmt, ap);
6366342292Scy  va_end(ap);
6367342292Scy}
6368342292Scystatic void zipfileCursorErr(ZipfileCsr *pCsr, const char *zFmt, ...){
6369342292Scy  va_list ap;
6370342292Scy  va_start(ap, zFmt);
6371342292Scy  sqlite3_free(pCsr->base.pVtab->zErrMsg);
6372342292Scy  pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
6373342292Scy  va_end(ap);
6374342292Scy}
6375342292Scy
6376342292Scy/*
6377342292Scy** Read nRead bytes of data from offset iOff of file pFile into buffer
6378342292Scy** aRead[]. Return SQLITE_OK if successful, or an SQLite error code
6379342292Scy** otherwise.
6380342292Scy**
6381342292Scy** If an error does occur, output variable (*pzErrmsg) may be set to point
6382342292Scy** to an English language error message. It is the responsibility of the
6383342292Scy** caller to eventually free this buffer using
6384342292Scy** sqlite3_free().
6385342292Scy*/
6386342292Scystatic int zipfileReadData(
6387342292Scy  FILE *pFile,                    /* Read from this file */
6388342292Scy  u8 *aRead,                      /* Read into this buffer */
6389342292Scy  int nRead,                      /* Number of bytes to read */
6390342292Scy  i64 iOff,                       /* Offset to read from */
6391342292Scy  char **pzErrmsg                 /* OUT: Error message (from sqlite3_malloc) */
6392342292Scy){
6393342292Scy  size_t n;
6394342292Scy  fseek(pFile, (long)iOff, SEEK_SET);
6395342292Scy  n = fread(aRead, 1, nRead, pFile);
6396342292Scy  if( (int)n!=nRead ){
6397342292Scy    *pzErrmsg = sqlite3_mprintf("error in fread()");
6398342292Scy    return SQLITE_ERROR;
6399342292Scy  }
6400342292Scy  return SQLITE_OK;
6401342292Scy}
6402342292Scy
6403342292Scystatic int zipfileAppendData(
6404342292Scy  ZipfileTab *pTab,
6405342292Scy  const u8 *aWrite,
6406342292Scy  int nWrite
6407342292Scy){
6408369950Scy  if( nWrite>0 ){
6409369950Scy    size_t n = nWrite;
6410369950Scy    fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
6411369950Scy    n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
6412369950Scy    if( (int)n!=nWrite ){
6413369950Scy      pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
6414369950Scy      return SQLITE_ERROR;
6415369950Scy    }
6416369950Scy    pTab->szCurrent += nWrite;
6417342292Scy  }
6418342292Scy  return SQLITE_OK;
6419342292Scy}
6420342292Scy
6421342292Scy/*
6422342292Scy** Read and return a 16-bit little-endian unsigned integer from buffer aBuf.
6423342292Scy*/
6424342292Scystatic u16 zipfileGetU16(const u8 *aBuf){
6425342292Scy  return (aBuf[1] << 8) + aBuf[0];
6426342292Scy}
6427342292Scy
6428342292Scy/*
6429342292Scy** Read and return a 32-bit little-endian unsigned integer from buffer aBuf.
6430342292Scy*/
6431342292Scystatic u32 zipfileGetU32(const u8 *aBuf){
6432342292Scy  return ((u32)(aBuf[3]) << 24)
6433342292Scy       + ((u32)(aBuf[2]) << 16)
6434342292Scy       + ((u32)(aBuf[1]) <<  8)
6435342292Scy       + ((u32)(aBuf[0]) <<  0);
6436342292Scy}
6437342292Scy
6438342292Scy/*
6439342292Scy** Write a 16-bit little endiate integer into buffer aBuf.
6440342292Scy*/
6441342292Scystatic void zipfilePutU16(u8 *aBuf, u16 val){
6442342292Scy  aBuf[0] = val & 0xFF;
6443342292Scy  aBuf[1] = (val>>8) & 0xFF;
6444342292Scy}
6445342292Scy
6446342292Scy/*
6447342292Scy** Write a 32-bit little endiate integer into buffer aBuf.
6448342292Scy*/
6449342292Scystatic void zipfilePutU32(u8 *aBuf, u32 val){
6450342292Scy  aBuf[0] = val & 0xFF;
6451342292Scy  aBuf[1] = (val>>8) & 0xFF;
6452342292Scy  aBuf[2] = (val>>16) & 0xFF;
6453342292Scy  aBuf[3] = (val>>24) & 0xFF;
6454342292Scy}
6455342292Scy
6456342292Scy#define zipfileRead32(aBuf) ( aBuf+=4, zipfileGetU32(aBuf-4) )
6457342292Scy#define zipfileRead16(aBuf) ( aBuf+=2, zipfileGetU16(aBuf-2) )
6458342292Scy
6459342292Scy#define zipfileWrite32(aBuf,val) { zipfilePutU32(aBuf,val); aBuf+=4; }
6460342292Scy#define zipfileWrite16(aBuf,val) { zipfilePutU16(aBuf,val); aBuf+=2; }
6461342292Scy
6462342292Scy/*
6463342292Scy** Magic numbers used to read CDS records.
6464342292Scy*/
6465342292Scy#define ZIPFILE_CDS_NFILE_OFF        28
6466342292Scy#define ZIPFILE_CDS_SZCOMPRESSED_OFF 20
6467342292Scy
6468342292Scy/*
6469342292Scy** Decode the CDS record in buffer aBuf into (*pCDS). Return SQLITE_ERROR
6470342292Scy** if the record is not well-formed, or SQLITE_OK otherwise.
6471342292Scy*/
6472342292Scystatic int zipfileReadCDS(u8 *aBuf, ZipfileCDS *pCDS){
6473342292Scy  u8 *aRead = aBuf;
6474342292Scy  u32 sig = zipfileRead32(aRead);
6475342292Scy  int rc = SQLITE_OK;
6476342292Scy  if( sig!=ZIPFILE_SIGNATURE_CDS ){
6477342292Scy    rc = SQLITE_ERROR;
6478342292Scy  }else{
6479342292Scy    pCDS->iVersionMadeBy = zipfileRead16(aRead);
6480342292Scy    pCDS->iVersionExtract = zipfileRead16(aRead);
6481342292Scy    pCDS->flags = zipfileRead16(aRead);
6482342292Scy    pCDS->iCompression = zipfileRead16(aRead);
6483342292Scy    pCDS->mTime = zipfileRead16(aRead);
6484342292Scy    pCDS->mDate = zipfileRead16(aRead);
6485342292Scy    pCDS->crc32 = zipfileRead32(aRead);
6486342292Scy    pCDS->szCompressed = zipfileRead32(aRead);
6487342292Scy    pCDS->szUncompressed = zipfileRead32(aRead);
6488342292Scy    assert( aRead==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
6489342292Scy    pCDS->nFile = zipfileRead16(aRead);
6490342292Scy    pCDS->nExtra = zipfileRead16(aRead);
6491342292Scy    pCDS->nComment = zipfileRead16(aRead);
6492342292Scy    pCDS->iDiskStart = zipfileRead16(aRead);
6493342292Scy    pCDS->iInternalAttr = zipfileRead16(aRead);
6494342292Scy    pCDS->iExternalAttr = zipfileRead32(aRead);
6495342292Scy    pCDS->iOffset = zipfileRead32(aRead);
6496342292Scy    assert( aRead==&aBuf[ZIPFILE_CDS_FIXED_SZ] );
6497342292Scy  }
6498342292Scy
6499342292Scy  return rc;
6500342292Scy}
6501342292Scy
6502342292Scy/*
6503342292Scy** Decode the LFH record in buffer aBuf into (*pLFH). Return SQLITE_ERROR
6504342292Scy** if the record is not well-formed, or SQLITE_OK otherwise.
6505342292Scy*/
6506342292Scystatic int zipfileReadLFH(
6507342292Scy  u8 *aBuffer,
6508342292Scy  ZipfileLFH *pLFH
6509342292Scy){
6510342292Scy  u8 *aRead = aBuffer;
6511342292Scy  int rc = SQLITE_OK;
6512342292Scy
6513342292Scy  u32 sig = zipfileRead32(aRead);
6514342292Scy  if( sig!=ZIPFILE_SIGNATURE_LFH ){
6515342292Scy    rc = SQLITE_ERROR;
6516342292Scy  }else{
6517342292Scy    pLFH->iVersionExtract = zipfileRead16(aRead);
6518342292Scy    pLFH->flags = zipfileRead16(aRead);
6519342292Scy    pLFH->iCompression = zipfileRead16(aRead);
6520342292Scy    pLFH->mTime = zipfileRead16(aRead);
6521342292Scy    pLFH->mDate = zipfileRead16(aRead);
6522342292Scy    pLFH->crc32 = zipfileRead32(aRead);
6523342292Scy    pLFH->szCompressed = zipfileRead32(aRead);
6524342292Scy    pLFH->szUncompressed = zipfileRead32(aRead);
6525342292Scy    pLFH->nFile = zipfileRead16(aRead);
6526342292Scy    pLFH->nExtra = zipfileRead16(aRead);
6527342292Scy  }
6528342292Scy  return rc;
6529342292Scy}
6530342292Scy
6531342292Scy
6532342292Scy/*
6533342292Scy** Buffer aExtra (size nExtra bytes) contains zip archive "extra" fields.
6534342292Scy** Scan through this buffer to find an "extra-timestamp" field. If one
6535342292Scy** exists, extract the 32-bit modification-timestamp from it and store
6536342292Scy** the value in output parameter *pmTime.
6537342292Scy**
6538342292Scy** Zero is returned if no extra-timestamp record could be found (and so
6539342292Scy** *pmTime is left unchanged), or non-zero otherwise.
6540342292Scy**
6541342292Scy** The general format of an extra field is:
6542342292Scy**
6543342292Scy**   Header ID    2 bytes
6544342292Scy**   Data Size    2 bytes
6545342292Scy**   Data         N bytes
6546342292Scy*/
6547342292Scystatic int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){
6548342292Scy  int ret = 0;
6549342292Scy  u8 *p = aExtra;
6550342292Scy  u8 *pEnd = &aExtra[nExtra];
6551342292Scy
6552342292Scy  while( p<pEnd ){
6553342292Scy    u16 id = zipfileRead16(p);
6554342292Scy    u16 nByte = zipfileRead16(p);
6555342292Scy
6556342292Scy    switch( id ){
6557342292Scy      case ZIPFILE_EXTRA_TIMESTAMP: {
6558342292Scy        u8 b = p[0];
6559342292Scy        if( b & 0x01 ){     /* 0x01 -> modtime is present */
6560342292Scy          *pmTime = zipfileGetU32(&p[1]);
6561342292Scy          ret = 1;
6562342292Scy        }
6563342292Scy        break;
6564342292Scy      }
6565342292Scy    }
6566342292Scy
6567342292Scy    p += nByte;
6568342292Scy  }
6569342292Scy  return ret;
6570342292Scy}
6571342292Scy
6572342292Scy/*
6573342292Scy** Convert the standard MS-DOS timestamp stored in the mTime and mDate
6574342292Scy** fields of the CDS structure passed as the only argument to a 32-bit
6575342292Scy** UNIX seconds-since-the-epoch timestamp. Return the result.
6576342292Scy**
6577342292Scy** "Standard" MS-DOS time format:
6578342292Scy**
6579342292Scy**   File modification time:
6580342292Scy**     Bits 00-04: seconds divided by 2
6581342292Scy**     Bits 05-10: minute
6582342292Scy**     Bits 11-15: hour
6583342292Scy**   File modification date:
6584342292Scy**     Bits 00-04: day
6585342292Scy**     Bits 05-08: month (1-12)
6586342292Scy**     Bits 09-15: years from 1980
6587342292Scy**
6588342292Scy** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
6589342292Scy*/
6590342292Scystatic u32 zipfileMtime(ZipfileCDS *pCDS){
6591342292Scy  int Y = (1980 + ((pCDS->mDate >> 9) & 0x7F));
6592342292Scy  int M = ((pCDS->mDate >> 5) & 0x0F);
6593342292Scy  int D = (pCDS->mDate & 0x1F);
6594342292Scy  int B = -13;
6595342292Scy
6596342292Scy  int sec = (pCDS->mTime & 0x1F)*2;
6597342292Scy  int min = (pCDS->mTime >> 5) & 0x3F;
6598342292Scy  int hr = (pCDS->mTime >> 11) & 0x1F;
6599342292Scy  i64 JD;
6600342292Scy
6601342292Scy  /* JD = INT(365.25 * (Y+4716)) + INT(30.6001 * (M+1)) + D + B - 1524.5 */
6602342292Scy
6603342292Scy  /* Calculate the JD in seconds for noon on the day in question */
6604342292Scy  if( M<3 ){
6605342292Scy    Y = Y-1;
6606342292Scy    M = M+12;
6607342292Scy  }
6608342292Scy  JD = (i64)(24*60*60) * (
6609342292Scy      (int)(365.25 * (Y + 4716))
6610342292Scy    + (int)(30.6001 * (M + 1))
6611342292Scy    + D + B - 1524
6612342292Scy  );
6613342292Scy
6614342292Scy  /* Correct the JD for the time within the day */
6615342292Scy  JD += (hr-12) * 3600 + min * 60 + sec;
6616342292Scy
6617342292Scy  /* Convert JD to unix timestamp (the JD epoch is 2440587.5) */
6618342292Scy  return (u32)(JD - (i64)(24405875) * 24*60*6);
6619342292Scy}
6620342292Scy
6621342292Scy/*
6622342292Scy** The opposite of zipfileMtime(). This function populates the mTime and
6623342292Scy** mDate fields of the CDS structure passed as the first argument according
6624342292Scy** to the UNIX timestamp value passed as the second.
6625342292Scy*/
6626342292Scystatic void zipfileMtimeToDos(ZipfileCDS *pCds, u32 mUnixTime){
6627342292Scy  /* Convert unix timestamp to JD (2440588 is noon on 1/1/1970) */
6628342292Scy  i64 JD = (i64)2440588 + mUnixTime / (24*60*60);
6629342292Scy
6630342292Scy  int A, B, C, D, E;
6631342292Scy  int yr, mon, day;
6632342292Scy  int hr, min, sec;
6633342292Scy
6634342292Scy  A = (int)((JD - 1867216.25)/36524.25);
6635342292Scy  A = (int)(JD + 1 + A - (A/4));
6636342292Scy  B = A + 1524;
6637342292Scy  C = (int)((B - 122.1)/365.25);
6638342292Scy  D = (36525*(C&32767))/100;
6639342292Scy  E = (int)((B-D)/30.6001);
6640342292Scy
6641342292Scy  day = B - D - (int)(30.6001*E);
6642342292Scy  mon = (E<14 ? E-1 : E-13);
6643342292Scy  yr = mon>2 ? C-4716 : C-4715;
6644342292Scy
6645342292Scy  hr = (mUnixTime % (24*60*60)) / (60*60);
6646342292Scy  min = (mUnixTime % (60*60)) / 60;
6647342292Scy  sec = (mUnixTime % 60);
6648342292Scy
6649342292Scy  if( yr>=1980 ){
6650342292Scy    pCds->mDate = (u16)(day + (mon << 5) + ((yr-1980) << 9));
6651342292Scy    pCds->mTime = (u16)(sec/2 + (min<<5) + (hr<<11));
6652342292Scy  }else{
6653342292Scy    pCds->mDate = pCds->mTime = 0;
6654342292Scy  }
6655342292Scy
6656342292Scy  assert( mUnixTime<315507600
6657342292Scy       || mUnixTime==zipfileMtime(pCds)
6658342292Scy       || ((mUnixTime % 2) && mUnixTime-1==zipfileMtime(pCds))
6659342292Scy       /* || (mUnixTime % 2) */
6660342292Scy  );
6661342292Scy}
6662342292Scy
6663342292Scy/*
6664342292Scy** If aBlob is not NULL, then it is a pointer to a buffer (nBlob bytes in
6665342292Scy** size) containing an entire zip archive image. Or, if aBlob is NULL,
6666342292Scy** then pFile is a file-handle open on a zip file. In either case, this
6667342292Scy** function creates a ZipfileEntry object based on the zip archive entry
6668342292Scy** for which the CDS record is at offset iOff.
6669342292Scy**
6670342292Scy** If successful, SQLITE_OK is returned and (*ppEntry) set to point to
6671342292Scy** the new object. Otherwise, an SQLite error code is returned and the
6672342292Scy** final value of (*ppEntry) undefined.
6673342292Scy*/
6674342292Scystatic int zipfileGetEntry(
6675342292Scy  ZipfileTab *pTab,               /* Store any error message here */
6676342292Scy  const u8 *aBlob,                /* Pointer to in-memory file image */
6677342292Scy  int nBlob,                      /* Size of aBlob[] in bytes */
6678342292Scy  FILE *pFile,                    /* If aBlob==0, read from this file */
6679342292Scy  i64 iOff,                       /* Offset of CDS record */
6680342292Scy  ZipfileEntry **ppEntry          /* OUT: Pointer to new object */
6681342292Scy){
6682342292Scy  u8 *aRead;
6683342292Scy  char **pzErr = &pTab->base.zErrMsg;
6684342292Scy  int rc = SQLITE_OK;
6685342292Scy
6686342292Scy  if( aBlob==0 ){
6687342292Scy    aRead = pTab->aBuffer;
6688342292Scy    rc = zipfileReadData(pFile, aRead, ZIPFILE_CDS_FIXED_SZ, iOff, pzErr);
6689342292Scy  }else{
6690342292Scy    aRead = (u8*)&aBlob[iOff];
6691342292Scy  }
6692342292Scy
6693342292Scy  if( rc==SQLITE_OK ){
6694346442Scy    sqlite3_int64 nAlloc;
6695342292Scy    ZipfileEntry *pNew;
6696342292Scy
6697342292Scy    int nFile = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF]);
6698342292Scy    int nExtra = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+2]);
6699342292Scy    nExtra += zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+4]);
6700342292Scy
6701342292Scy    nAlloc = sizeof(ZipfileEntry) + nExtra;
6702342292Scy    if( aBlob ){
6703342292Scy      nAlloc += zipfileGetU32(&aRead[ZIPFILE_CDS_SZCOMPRESSED_OFF]);
6704342292Scy    }
6705342292Scy
6706346442Scy    pNew = (ZipfileEntry*)sqlite3_malloc64(nAlloc);
6707342292Scy    if( pNew==0 ){
6708342292Scy      rc = SQLITE_NOMEM;
6709342292Scy    }else{
6710342292Scy      memset(pNew, 0, sizeof(ZipfileEntry));
6711342292Scy      rc = zipfileReadCDS(aRead, &pNew->cds);
6712342292Scy      if( rc!=SQLITE_OK ){
6713342292Scy        *pzErr = sqlite3_mprintf("failed to read CDS at offset %lld", iOff);
6714342292Scy      }else if( aBlob==0 ){
6715342292Scy        rc = zipfileReadData(
6716342292Scy            pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr
6717342292Scy        );
6718342292Scy      }else{
6719342292Scy        aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ];
6720342292Scy      }
6721342292Scy    }
6722342292Scy
6723342292Scy    if( rc==SQLITE_OK ){
6724342292Scy      u32 *pt = &pNew->mUnixTime;
6725342292Scy      pNew->cds.zFile = sqlite3_mprintf("%.*s", nFile, aRead);
6726342292Scy      pNew->aExtra = (u8*)&pNew[1];
6727342292Scy      memcpy(pNew->aExtra, &aRead[nFile], nExtra);
6728342292Scy      if( pNew->cds.zFile==0 ){
6729342292Scy        rc = SQLITE_NOMEM;
6730342292Scy      }else if( 0==zipfileScanExtra(&aRead[nFile], pNew->cds.nExtra, pt) ){
6731342292Scy        pNew->mUnixTime = zipfileMtime(&pNew->cds);
6732342292Scy      }
6733342292Scy    }
6734342292Scy
6735342292Scy    if( rc==SQLITE_OK ){
6736342292Scy      static const int szFix = ZIPFILE_LFH_FIXED_SZ;
6737342292Scy      ZipfileLFH lfh;
6738342292Scy      if( pFile ){
6739342292Scy        rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr);
6740342292Scy      }else{
6741342292Scy        aRead = (u8*)&aBlob[pNew->cds.iOffset];
6742342292Scy      }
6743342292Scy
6744342292Scy      rc = zipfileReadLFH(aRead, &lfh);
6745342292Scy      if( rc==SQLITE_OK ){
6746342292Scy        pNew->iDataOff =  pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
6747342292Scy        pNew->iDataOff += lfh.nFile + lfh.nExtra;
6748342292Scy        if( aBlob && pNew->cds.szCompressed ){
6749342292Scy          pNew->aData = &pNew->aExtra[nExtra];
6750342292Scy          memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed);
6751342292Scy        }
6752342292Scy      }else{
6753342292Scy        *pzErr = sqlite3_mprintf("failed to read LFH at offset %d",
6754342292Scy            (int)pNew->cds.iOffset
6755342292Scy        );
6756342292Scy      }
6757342292Scy    }
6758342292Scy
6759342292Scy    if( rc!=SQLITE_OK ){
6760342292Scy      zipfileEntryFree(pNew);
6761342292Scy    }else{
6762342292Scy      *ppEntry = pNew;
6763342292Scy    }
6764342292Scy  }
6765342292Scy
6766342292Scy  return rc;
6767342292Scy}
6768342292Scy
6769342292Scy/*
6770342292Scy** Advance an ZipfileCsr to its next row of output.
6771342292Scy*/
6772342292Scystatic int zipfileNext(sqlite3_vtab_cursor *cur){
6773342292Scy  ZipfileCsr *pCsr = (ZipfileCsr*)cur;
6774342292Scy  int rc = SQLITE_OK;
6775342292Scy
6776342292Scy  if( pCsr->pFile ){
6777342292Scy    i64 iEof = pCsr->eocd.iOffset + pCsr->eocd.nSize;
6778342292Scy    zipfileEntryFree(pCsr->pCurrent);
6779342292Scy    pCsr->pCurrent = 0;
6780342292Scy    if( pCsr->iNextOff>=iEof ){
6781342292Scy      pCsr->bEof = 1;
6782342292Scy    }else{
6783342292Scy      ZipfileEntry *p = 0;
6784342292Scy      ZipfileTab *pTab = (ZipfileTab*)(cur->pVtab);
6785342292Scy      rc = zipfileGetEntry(pTab, 0, 0, pCsr->pFile, pCsr->iNextOff, &p);
6786342292Scy      if( rc==SQLITE_OK ){
6787342292Scy        pCsr->iNextOff += ZIPFILE_CDS_FIXED_SZ;
6788342292Scy        pCsr->iNextOff += (int)p->cds.nExtra + p->cds.nFile + p->cds.nComment;
6789342292Scy      }
6790342292Scy      pCsr->pCurrent = p;
6791342292Scy    }
6792342292Scy  }else{
6793342292Scy    if( !pCsr->bNoop ){
6794342292Scy      pCsr->pCurrent = pCsr->pCurrent->pNext;
6795342292Scy    }
6796342292Scy    if( pCsr->pCurrent==0 ){
6797342292Scy      pCsr->bEof = 1;
6798342292Scy    }
6799342292Scy  }
6800342292Scy
6801342292Scy  pCsr->bNoop = 0;
6802342292Scy  return rc;
6803342292Scy}
6804342292Scy
6805342292Scystatic void zipfileFree(void *p) {
6806342292Scy  sqlite3_free(p);
6807342292Scy}
6808342292Scy
6809342292Scy/*
6810342292Scy** Buffer aIn (size nIn bytes) contains compressed data. Uncompressed, the
6811342292Scy** size is nOut bytes. This function uncompresses the data and sets the
6812342292Scy** return value in context pCtx to the result (a blob).
6813342292Scy**
6814342292Scy** If an error occurs, an error code is left in pCtx instead.
6815342292Scy*/
6816342292Scystatic void zipfileInflate(
6817342292Scy  sqlite3_context *pCtx,          /* Store result here */
6818342292Scy  const u8 *aIn,                  /* Compressed data */
6819342292Scy  int nIn,                        /* Size of buffer aIn[] in bytes */
6820342292Scy  int nOut                        /* Expected output size */
6821342292Scy){
6822342292Scy  u8 *aRes = sqlite3_malloc(nOut);
6823342292Scy  if( aRes==0 ){
6824342292Scy    sqlite3_result_error_nomem(pCtx);
6825342292Scy  }else{
6826342292Scy    int err;
6827342292Scy    z_stream str;
6828342292Scy    memset(&str, 0, sizeof(str));
6829342292Scy
6830342292Scy    str.next_in = (Byte*)aIn;
6831342292Scy    str.avail_in = nIn;
6832342292Scy    str.next_out = (Byte*)aRes;
6833342292Scy    str.avail_out = nOut;
6834342292Scy
6835342292Scy    err = inflateInit2(&str, -15);
6836342292Scy    if( err!=Z_OK ){
6837342292Scy      zipfileCtxErrorMsg(pCtx, "inflateInit2() failed (%d)", err);
6838342292Scy    }else{
6839342292Scy      err = inflate(&str, Z_NO_FLUSH);
6840342292Scy      if( err!=Z_STREAM_END ){
6841342292Scy        zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err);
6842342292Scy      }else{
6843342292Scy        sqlite3_result_blob(pCtx, aRes, nOut, zipfileFree);
6844342292Scy        aRes = 0;
6845342292Scy      }
6846342292Scy    }
6847342292Scy    sqlite3_free(aRes);
6848342292Scy    inflateEnd(&str);
6849342292Scy  }
6850342292Scy}
6851342292Scy
6852342292Scy/*
6853342292Scy** Buffer aIn (size nIn bytes) contains uncompressed data. This function
6854342292Scy** compresses it and sets (*ppOut) to point to a buffer containing the
6855342292Scy** compressed data. The caller is responsible for eventually calling
6856342292Scy** sqlite3_free() to release buffer (*ppOut). Before returning, (*pnOut)
6857342292Scy** is set to the size of buffer (*ppOut) in bytes.
6858342292Scy**
6859342292Scy** If no error occurs, SQLITE_OK is returned. Otherwise, an SQLite error
6860342292Scy** code is returned and an error message left in virtual-table handle
6861342292Scy** pTab. The values of (*ppOut) and (*pnOut) are left unchanged in this
6862342292Scy** case.
6863342292Scy*/
6864342292Scystatic int zipfileDeflate(
6865342292Scy  const u8 *aIn, int nIn,         /* Input */
6866342292Scy  u8 **ppOut, int *pnOut,         /* Output */
6867342292Scy  char **pzErr                    /* OUT: Error message */
6868342292Scy){
6869361456Scy  int rc = SQLITE_OK;
6870361456Scy  sqlite3_int64 nAlloc;
6871361456Scy  z_stream str;
6872342292Scy  u8 *aOut;
6873342292Scy
6874361456Scy  memset(&str, 0, sizeof(str));
6875361456Scy  str.next_in = (Bytef*)aIn;
6876361456Scy  str.avail_in = nIn;
6877361456Scy  deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
6878361456Scy
6879361456Scy  nAlloc = deflateBound(&str, nIn);
6880346442Scy  aOut = (u8*)sqlite3_malloc64(nAlloc);
6881342292Scy  if( aOut==0 ){
6882342292Scy    rc = SQLITE_NOMEM;
6883342292Scy  }else{
6884342292Scy    int res;
6885342292Scy    str.next_out = aOut;
6886342292Scy    str.avail_out = nAlloc;
6887342292Scy    res = deflate(&str, Z_FINISH);
6888342292Scy    if( res==Z_STREAM_END ){
6889342292Scy      *ppOut = aOut;
6890342292Scy      *pnOut = (int)str.total_out;
6891342292Scy    }else{
6892342292Scy      sqlite3_free(aOut);
6893342292Scy      *pzErr = sqlite3_mprintf("zipfile: deflate() error");
6894342292Scy      rc = SQLITE_ERROR;
6895342292Scy    }
6896342292Scy    deflateEnd(&str);
6897342292Scy  }
6898342292Scy
6899342292Scy  return rc;
6900342292Scy}
6901342292Scy
6902342292Scy
6903342292Scy/*
6904342292Scy** Return values of columns for the row at which the series_cursor
6905342292Scy** is currently pointing.
6906342292Scy*/
6907342292Scystatic int zipfileColumn(
6908342292Scy  sqlite3_vtab_cursor *cur,   /* The cursor */
6909342292Scy  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
6910342292Scy  int i                       /* Which column to return */
6911342292Scy){
6912342292Scy  ZipfileCsr *pCsr = (ZipfileCsr*)cur;
6913342292Scy  ZipfileCDS *pCDS = &pCsr->pCurrent->cds;
6914342292Scy  int rc = SQLITE_OK;
6915342292Scy  switch( i ){
6916342292Scy    case 0:   /* name */
6917342292Scy      sqlite3_result_text(ctx, pCDS->zFile, -1, SQLITE_TRANSIENT);
6918342292Scy      break;
6919342292Scy    case 1:   /* mode */
6920342292Scy      /* TODO: Whether or not the following is correct surely depends on
6921342292Scy      ** the platform on which the archive was created.  */
6922342292Scy      sqlite3_result_int(ctx, pCDS->iExternalAttr >> 16);
6923342292Scy      break;
6924342292Scy    case 2: { /* mtime */
6925342292Scy      sqlite3_result_int64(ctx, pCsr->pCurrent->mUnixTime);
6926342292Scy      break;
6927342292Scy    }
6928342292Scy    case 3: { /* sz */
6929342292Scy      if( sqlite3_vtab_nochange(ctx)==0 ){
6930342292Scy        sqlite3_result_int64(ctx, pCDS->szUncompressed);
6931342292Scy      }
6932342292Scy      break;
6933342292Scy    }
6934342292Scy    case 4:   /* rawdata */
6935342292Scy      if( sqlite3_vtab_nochange(ctx) ) break;
6936342292Scy    case 5: { /* data */
6937342292Scy      if( i==4 || pCDS->iCompression==0 || pCDS->iCompression==8 ){
6938342292Scy        int sz = pCDS->szCompressed;
6939342292Scy        int szFinal = pCDS->szUncompressed;
6940342292Scy        if( szFinal>0 ){
6941342292Scy          u8 *aBuf;
6942342292Scy          u8 *aFree = 0;
6943342292Scy          if( pCsr->pCurrent->aData ){
6944342292Scy            aBuf = pCsr->pCurrent->aData;
6945342292Scy          }else{
6946346442Scy            aBuf = aFree = sqlite3_malloc64(sz);
6947342292Scy            if( aBuf==0 ){
6948342292Scy              rc = SQLITE_NOMEM;
6949342292Scy            }else{
6950342292Scy              FILE *pFile = pCsr->pFile;
6951342292Scy              if( pFile==0 ){
6952342292Scy                pFile = ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd;
6953342292Scy              }
6954342292Scy              rc = zipfileReadData(pFile, aBuf, sz, pCsr->pCurrent->iDataOff,
6955342292Scy                  &pCsr->base.pVtab->zErrMsg
6956342292Scy              );
6957342292Scy            }
6958342292Scy          }
6959342292Scy          if( rc==SQLITE_OK ){
6960342292Scy            if( i==5 && pCDS->iCompression ){
6961342292Scy              zipfileInflate(ctx, aBuf, sz, szFinal);
6962342292Scy            }else{
6963342292Scy              sqlite3_result_blob(ctx, aBuf, sz, SQLITE_TRANSIENT);
6964342292Scy            }
6965342292Scy          }
6966342292Scy          sqlite3_free(aFree);
6967342292Scy        }else{
6968342292Scy          /* Figure out if this is a directory or a zero-sized file. Consider
6969342292Scy          ** it to be a directory either if the mode suggests so, or if
6970342292Scy          ** the final character in the name is '/'.  */
6971342292Scy          u32 mode = pCDS->iExternalAttr >> 16;
6972342292Scy          if( !(mode & S_IFDIR) && pCDS->zFile[pCDS->nFile-1]!='/' ){
6973342292Scy            sqlite3_result_blob(ctx, "", 0, SQLITE_STATIC);
6974342292Scy          }
6975342292Scy        }
6976342292Scy      }
6977342292Scy      break;
6978342292Scy    }
6979342292Scy    case 6:   /* method */
6980342292Scy      sqlite3_result_int(ctx, pCDS->iCompression);
6981342292Scy      break;
6982342292Scy    default:  /* z */
6983342292Scy      assert( i==7 );
6984342292Scy      sqlite3_result_int64(ctx, pCsr->iId);
6985342292Scy      break;
6986342292Scy  }
6987342292Scy
6988342292Scy  return rc;
6989342292Scy}
6990342292Scy
6991342292Scy/*
6992342292Scy** Return TRUE if the cursor is at EOF.
6993342292Scy*/
6994342292Scystatic int zipfileEof(sqlite3_vtab_cursor *cur){
6995342292Scy  ZipfileCsr *pCsr = (ZipfileCsr*)cur;
6996342292Scy  return pCsr->bEof;
6997342292Scy}
6998342292Scy
6999342292Scy/*
7000342292Scy** If aBlob is not NULL, then it points to a buffer nBlob bytes in size
7001342292Scy** containing an entire zip archive image. Or, if aBlob is NULL, then pFile
7002342292Scy** is guaranteed to be a file-handle open on a zip file.
7003342292Scy**
7004342292Scy** This function attempts to locate the EOCD record within the zip archive
7005342292Scy** and populate *pEOCD with the results of decoding it. SQLITE_OK is
7006342292Scy** returned if successful. Otherwise, an SQLite error code is returned and
7007342292Scy** an English language error message may be left in virtual-table pTab.
7008342292Scy*/
7009342292Scystatic int zipfileReadEOCD(
7010342292Scy  ZipfileTab *pTab,               /* Return errors here */
7011342292Scy  const u8 *aBlob,                /* Pointer to in-memory file image */
7012342292Scy  int nBlob,                      /* Size of aBlob[] in bytes */
7013342292Scy  FILE *pFile,                    /* Read from this file if aBlob==0 */
7014342292Scy  ZipfileEOCD *pEOCD              /* Object to populate */
7015342292Scy){
7016342292Scy  u8 *aRead = pTab->aBuffer;      /* Temporary buffer */
7017342292Scy  int nRead;                      /* Bytes to read from file */
7018342292Scy  int rc = SQLITE_OK;
7019342292Scy
7020342292Scy  if( aBlob==0 ){
7021342292Scy    i64 iOff;                     /* Offset to read from */
7022342292Scy    i64 szFile;                   /* Total size of file in bytes */
7023342292Scy    fseek(pFile, 0, SEEK_END);
7024342292Scy    szFile = (i64)ftell(pFile);
7025342292Scy    if( szFile==0 ){
7026342292Scy      memset(pEOCD, 0, sizeof(ZipfileEOCD));
7027342292Scy      return SQLITE_OK;
7028342292Scy    }
7029342292Scy    nRead = (int)(MIN(szFile, ZIPFILE_BUFFER_SIZE));
7030342292Scy    iOff = szFile - nRead;
7031342292Scy    rc = zipfileReadData(pFile, aRead, nRead, iOff, &pTab->base.zErrMsg);
7032342292Scy  }else{
7033342292Scy    nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE));
7034342292Scy    aRead = (u8*)&aBlob[nBlob-nRead];
7035342292Scy  }
7036342292Scy
7037342292Scy  if( rc==SQLITE_OK ){
7038342292Scy    int i;
7039342292Scy
7040342292Scy    /* Scan backwards looking for the signature bytes */
7041342292Scy    for(i=nRead-20; i>=0; i--){
7042342292Scy      if( aRead[i]==0x50 && aRead[i+1]==0x4b
7043342292Scy       && aRead[i+2]==0x05 && aRead[i+3]==0x06
7044342292Scy      ){
7045342292Scy        break;
7046342292Scy      }
7047342292Scy    }
7048342292Scy    if( i<0 ){
7049342292Scy      pTab->base.zErrMsg = sqlite3_mprintf(
7050342292Scy          "cannot find end of central directory record"
7051342292Scy      );
7052342292Scy      return SQLITE_ERROR;
7053342292Scy    }
7054342292Scy
7055342292Scy    aRead += i+4;
7056342292Scy    pEOCD->iDisk = zipfileRead16(aRead);
7057342292Scy    pEOCD->iFirstDisk = zipfileRead16(aRead);
7058342292Scy    pEOCD->nEntry = zipfileRead16(aRead);
7059342292Scy    pEOCD->nEntryTotal = zipfileRead16(aRead);
7060342292Scy    pEOCD->nSize = zipfileRead32(aRead);
7061342292Scy    pEOCD->iOffset = zipfileRead32(aRead);
7062342292Scy  }
7063342292Scy
7064342292Scy  return rc;
7065342292Scy}
7066342292Scy
7067342292Scy/*
7068342292Scy** Add object pNew to the linked list that begins at ZipfileTab.pFirstEntry
7069342292Scy** and ends with pLastEntry. If argument pBefore is NULL, then pNew is added
7070342292Scy** to the end of the list. Otherwise, it is added to the list immediately
7071342292Scy** before pBefore (which is guaranteed to be a part of said list).
7072342292Scy*/
7073342292Scystatic void zipfileAddEntry(
7074342292Scy  ZipfileTab *pTab,
7075342292Scy  ZipfileEntry *pBefore,
7076342292Scy  ZipfileEntry *pNew
7077342292Scy){
7078342292Scy  assert( (pTab->pFirstEntry==0)==(pTab->pLastEntry==0) );
7079342292Scy  assert( pNew->pNext==0 );
7080342292Scy  if( pBefore==0 ){
7081342292Scy    if( pTab->pFirstEntry==0 ){
7082342292Scy      pTab->pFirstEntry = pTab->pLastEntry = pNew;
7083342292Scy    }else{
7084342292Scy      assert( pTab->pLastEntry->pNext==0 );
7085342292Scy      pTab->pLastEntry->pNext = pNew;
7086342292Scy      pTab->pLastEntry = pNew;
7087342292Scy    }
7088342292Scy  }else{
7089342292Scy    ZipfileEntry **pp;
7090342292Scy    for(pp=&pTab->pFirstEntry; *pp!=pBefore; pp=&((*pp)->pNext));
7091342292Scy    pNew->pNext = pBefore;
7092342292Scy    *pp = pNew;
7093342292Scy  }
7094342292Scy}
7095342292Scy
7096342292Scystatic int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, int nBlob){
7097342292Scy  ZipfileEOCD eocd;
7098342292Scy  int rc;
7099342292Scy  int i;
7100342292Scy  i64 iOff;
7101342292Scy
7102342292Scy  rc = zipfileReadEOCD(pTab, aBlob, nBlob, pTab->pWriteFd, &eocd);
7103342292Scy  iOff = eocd.iOffset;
7104342292Scy  for(i=0; rc==SQLITE_OK && i<eocd.nEntry; i++){
7105342292Scy    ZipfileEntry *pNew = 0;
7106342292Scy    rc = zipfileGetEntry(pTab, aBlob, nBlob, pTab->pWriteFd, iOff, &pNew);
7107342292Scy
7108342292Scy    if( rc==SQLITE_OK ){
7109342292Scy      zipfileAddEntry(pTab, 0, pNew);
7110342292Scy      iOff += ZIPFILE_CDS_FIXED_SZ;
7111342292Scy      iOff += (int)pNew->cds.nExtra + pNew->cds.nFile + pNew->cds.nComment;
7112342292Scy    }
7113342292Scy  }
7114342292Scy  return rc;
7115342292Scy}
7116342292Scy
7117342292Scy/*
7118342292Scy** xFilter callback.
7119342292Scy*/
7120342292Scystatic int zipfileFilter(
7121342292Scy  sqlite3_vtab_cursor *cur,
7122342292Scy  int idxNum, const char *idxStr,
7123342292Scy  int argc, sqlite3_value **argv
7124342292Scy){
7125342292Scy  ZipfileTab *pTab = (ZipfileTab*)cur->pVtab;
7126342292Scy  ZipfileCsr *pCsr = (ZipfileCsr*)cur;
7127342292Scy  const char *zFile = 0;          /* Zip file to scan */
7128342292Scy  int rc = SQLITE_OK;             /* Return Code */
7129342292Scy  int bInMemory = 0;              /* True for an in-memory zipfile */
7130342292Scy
7131342292Scy  zipfileResetCursor(pCsr);
7132342292Scy
7133342292Scy  if( pTab->zFile ){
7134342292Scy    zFile = pTab->zFile;
7135342292Scy  }else if( idxNum==0 ){
7136342292Scy    zipfileCursorErr(pCsr, "zipfile() function requires an argument");
7137342292Scy    return SQLITE_ERROR;
7138342292Scy  }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
7139342292Scy    const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
7140342292Scy    int nBlob = sqlite3_value_bytes(argv[0]);
7141342292Scy    assert( pTab->pFirstEntry==0 );
7142342292Scy    rc = zipfileLoadDirectory(pTab, aBlob, nBlob);
7143342292Scy    pCsr->pFreeEntry = pTab->pFirstEntry;
7144342292Scy    pTab->pFirstEntry = pTab->pLastEntry = 0;
7145342292Scy    if( rc!=SQLITE_OK ) return rc;
7146342292Scy    bInMemory = 1;
7147342292Scy  }else{
7148342292Scy    zFile = (const char*)sqlite3_value_text(argv[0]);
7149342292Scy  }
7150342292Scy
7151342292Scy  if( 0==pTab->pWriteFd && 0==bInMemory ){
7152342292Scy    pCsr->pFile = fopen(zFile, "rb");
7153342292Scy    if( pCsr->pFile==0 ){
7154342292Scy      zipfileCursorErr(pCsr, "cannot open file: %s", zFile);
7155342292Scy      rc = SQLITE_ERROR;
7156342292Scy    }else{
7157342292Scy      rc = zipfileReadEOCD(pTab, 0, 0, pCsr->pFile, &pCsr->eocd);
7158342292Scy      if( rc==SQLITE_OK ){
7159342292Scy        if( pCsr->eocd.nEntry==0 ){
7160342292Scy          pCsr->bEof = 1;
7161342292Scy        }else{
7162342292Scy          pCsr->iNextOff = pCsr->eocd.iOffset;
7163342292Scy          rc = zipfileNext(cur);
7164342292Scy        }
7165342292Scy      }
7166342292Scy    }
7167342292Scy  }else{
7168342292Scy    pCsr->bNoop = 1;
7169342292Scy    pCsr->pCurrent = pCsr->pFreeEntry ? pCsr->pFreeEntry : pTab->pFirstEntry;
7170342292Scy    rc = zipfileNext(cur);
7171342292Scy  }
7172342292Scy
7173342292Scy  return rc;
7174342292Scy}
7175342292Scy
7176342292Scy/*
7177342292Scy** xBestIndex callback.
7178342292Scy*/
7179342292Scystatic int zipfileBestIndex(
7180342292Scy  sqlite3_vtab *tab,
7181342292Scy  sqlite3_index_info *pIdxInfo
7182342292Scy){
7183342292Scy  int i;
7184342292Scy  int idx = -1;
7185342292Scy  int unusable = 0;
7186342292Scy
7187342292Scy  for(i=0; i<pIdxInfo->nConstraint; i++){
7188342292Scy    const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
7189342292Scy    if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue;
7190342292Scy    if( pCons->usable==0 ){
7191342292Scy      unusable = 1;
7192342292Scy    }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
7193342292Scy      idx = i;
7194342292Scy    }
7195342292Scy  }
7196361456Scy  pIdxInfo->estimatedCost = 1000.0;
7197342292Scy  if( idx>=0 ){
7198342292Scy    pIdxInfo->aConstraintUsage[idx].argvIndex = 1;
7199342292Scy    pIdxInfo->aConstraintUsage[idx].omit = 1;
7200342292Scy    pIdxInfo->idxNum = 1;
7201342292Scy  }else if( unusable ){
7202342292Scy    return SQLITE_CONSTRAINT;
7203342292Scy  }
7204342292Scy  return SQLITE_OK;
7205342292Scy}
7206342292Scy
7207342292Scystatic ZipfileEntry *zipfileNewEntry(const char *zPath){
7208342292Scy  ZipfileEntry *pNew;
7209342292Scy  pNew = sqlite3_malloc(sizeof(ZipfileEntry));
7210342292Scy  if( pNew ){
7211342292Scy    memset(pNew, 0, sizeof(ZipfileEntry));
7212342292Scy    pNew->cds.zFile = sqlite3_mprintf("%s", zPath);
7213342292Scy    if( pNew->cds.zFile==0 ){
7214342292Scy      sqlite3_free(pNew);
7215342292Scy      pNew = 0;
7216342292Scy    }
7217342292Scy  }
7218342292Scy  return pNew;
7219342292Scy}
7220342292Scy
7221342292Scystatic int zipfileSerializeLFH(ZipfileEntry *pEntry, u8 *aBuf){
7222342292Scy  ZipfileCDS *pCds = &pEntry->cds;
7223342292Scy  u8 *a = aBuf;
7224342292Scy
7225342292Scy  pCds->nExtra = 9;
7226342292Scy
7227342292Scy  /* Write the LFH itself */
7228342292Scy  zipfileWrite32(a, ZIPFILE_SIGNATURE_LFH);
7229342292Scy  zipfileWrite16(a, pCds->iVersionExtract);
7230342292Scy  zipfileWrite16(a, pCds->flags);
7231342292Scy  zipfileWrite16(a, pCds->iCompression);
7232342292Scy  zipfileWrite16(a, pCds->mTime);
7233342292Scy  zipfileWrite16(a, pCds->mDate);
7234342292Scy  zipfileWrite32(a, pCds->crc32);
7235342292Scy  zipfileWrite32(a, pCds->szCompressed);
7236342292Scy  zipfileWrite32(a, pCds->szUncompressed);
7237342292Scy  zipfileWrite16(a, (u16)pCds->nFile);
7238342292Scy  zipfileWrite16(a, pCds->nExtra);
7239342292Scy  assert( a==&aBuf[ZIPFILE_LFH_FIXED_SZ] );
7240342292Scy
7241342292Scy  /* Add the file name */
7242342292Scy  memcpy(a, pCds->zFile, (int)pCds->nFile);
7243342292Scy  a += (int)pCds->nFile;
7244342292Scy
7245342292Scy  /* The "extra" data */
7246342292Scy  zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP);
7247342292Scy  zipfileWrite16(a, 5);
7248342292Scy  *a++ = 0x01;
7249342292Scy  zipfileWrite32(a, pEntry->mUnixTime);
7250342292Scy
7251342292Scy  return a-aBuf;
7252342292Scy}
7253342292Scy
7254342292Scystatic int zipfileAppendEntry(
7255342292Scy  ZipfileTab *pTab,
7256342292Scy  ZipfileEntry *pEntry,
7257342292Scy  const u8 *pData,
7258342292Scy  int nData
7259342292Scy){
7260342292Scy  u8 *aBuf = pTab->aBuffer;
7261342292Scy  int nBuf;
7262342292Scy  int rc;
7263342292Scy
7264342292Scy  nBuf = zipfileSerializeLFH(pEntry, aBuf);
7265342292Scy  rc = zipfileAppendData(pTab, aBuf, nBuf);
7266342292Scy  if( rc==SQLITE_OK ){
7267342292Scy    pEntry->iDataOff = pTab->szCurrent;
7268342292Scy    rc = zipfileAppendData(pTab, pData, nData);
7269342292Scy  }
7270342292Scy
7271342292Scy  return rc;
7272342292Scy}
7273342292Scy
7274342292Scystatic int zipfileGetMode(
7275342292Scy  sqlite3_value *pVal,
7276342292Scy  int bIsDir,                     /* If true, default to directory */
7277342292Scy  u32 *pMode,                     /* OUT: Mode value */
7278342292Scy  char **pzErr                    /* OUT: Error message */
7279342292Scy){
7280342292Scy  const char *z = (const char*)sqlite3_value_text(pVal);
7281342292Scy  u32 mode = 0;
7282342292Scy  if( z==0 ){
7283342292Scy    mode = (bIsDir ? (S_IFDIR + 0755) : (S_IFREG + 0644));
7284342292Scy  }else if( z[0]>='0' && z[0]<='9' ){
7285342292Scy    mode = (unsigned int)sqlite3_value_int(pVal);
7286342292Scy  }else{
7287342292Scy    const char zTemplate[11] = "-rwxrwxrwx";
7288342292Scy    int i;
7289342292Scy    if( strlen(z)!=10 ) goto parse_error;
7290342292Scy    switch( z[0] ){
7291342292Scy      case '-': mode |= S_IFREG; break;
7292342292Scy      case 'd': mode |= S_IFDIR; break;
7293342292Scy      case 'l': mode |= S_IFLNK; break;
7294342292Scy      default: goto parse_error;
7295342292Scy    }
7296342292Scy    for(i=1; i<10; i++){
7297342292Scy      if( z[i]==zTemplate[i] ) mode |= 1 << (9-i);
7298342292Scy      else if( z[i]!='-' ) goto parse_error;
7299342292Scy    }
7300342292Scy  }
7301342292Scy  if( ((mode & S_IFDIR)==0)==bIsDir ){
7302342292Scy    /* The "mode" attribute is a directory, but data has been specified.
7303342292Scy    ** Or vice-versa - no data but "mode" is a file or symlink.  */
7304342292Scy    *pzErr = sqlite3_mprintf("zipfile: mode does not match data");
7305342292Scy    return SQLITE_CONSTRAINT;
7306342292Scy  }
7307342292Scy  *pMode = mode;
7308342292Scy  return SQLITE_OK;
7309342292Scy
7310342292Scy parse_error:
7311342292Scy  *pzErr = sqlite3_mprintf("zipfile: parse error in mode: %s", z);
7312342292Scy  return SQLITE_ERROR;
7313342292Scy}
7314342292Scy
7315342292Scy/*
7316342292Scy** Both (const char*) arguments point to nul-terminated strings. Argument
7317342292Scy** nB is the value of strlen(zB). This function returns 0 if the strings are
7318342292Scy** identical, ignoring any trailing '/' character in either path.  */
7319342292Scystatic int zipfileComparePath(const char *zA, const char *zB, int nB){
7320342292Scy  int nA = (int)strlen(zA);
7321361456Scy  if( nA>0 && zA[nA-1]=='/' ) nA--;
7322361456Scy  if( nB>0 && zB[nB-1]=='/' ) nB--;
7323342292Scy  if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
7324342292Scy  return 1;
7325342292Scy}
7326342292Scy
7327342292Scystatic int zipfileBegin(sqlite3_vtab *pVtab){
7328342292Scy  ZipfileTab *pTab = (ZipfileTab*)pVtab;
7329342292Scy  int rc = SQLITE_OK;
7330342292Scy
7331342292Scy  assert( pTab->pWriteFd==0 );
7332361456Scy  if( pTab->zFile==0 || pTab->zFile[0]==0 ){
7333361456Scy    pTab->base.zErrMsg = sqlite3_mprintf("zipfile: missing filename");
7334361456Scy    return SQLITE_ERROR;
7335361456Scy  }
7336342292Scy
7337342292Scy  /* Open a write fd on the file. Also load the entire central directory
7338342292Scy  ** structure into memory. During the transaction any new file data is
7339342292Scy  ** appended to the archive file, but the central directory is accumulated
7340342292Scy  ** in main-memory until the transaction is committed.  */
7341342292Scy  pTab->pWriteFd = fopen(pTab->zFile, "ab+");
7342342292Scy  if( pTab->pWriteFd==0 ){
7343342292Scy    pTab->base.zErrMsg = sqlite3_mprintf(
7344342292Scy        "zipfile: failed to open file %s for writing", pTab->zFile
7345342292Scy        );
7346342292Scy    rc = SQLITE_ERROR;
7347342292Scy  }else{
7348342292Scy    fseek(pTab->pWriteFd, 0, SEEK_END);
7349342292Scy    pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd);
7350342292Scy    rc = zipfileLoadDirectory(pTab, 0, 0);
7351342292Scy  }
7352342292Scy
7353342292Scy  if( rc!=SQLITE_OK ){
7354342292Scy    zipfileCleanupTransaction(pTab);
7355342292Scy  }
7356342292Scy
7357342292Scy  return rc;
7358342292Scy}
7359342292Scy
7360342292Scy/*
7361342292Scy** Return the current time as a 32-bit timestamp in UNIX epoch format (like
7362342292Scy** time(2)).
7363342292Scy*/
7364342292Scystatic u32 zipfileTime(void){
7365342292Scy  sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
7366342292Scy  u32 ret;
7367342292Scy  if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
7368342292Scy    i64 ms;
7369342292Scy    pVfs->xCurrentTimeInt64(pVfs, &ms);
7370342292Scy    ret = (u32)((ms/1000) - ((i64)24405875 * 8640));
7371342292Scy  }else{
7372342292Scy    double day;
7373342292Scy    pVfs->xCurrentTime(pVfs, &day);
7374342292Scy    ret = (u32)((day - 2440587.5) * 86400);
7375342292Scy  }
7376342292Scy  return ret;
7377342292Scy}
7378342292Scy
7379342292Scy/*
7380342292Scy** Return a 32-bit timestamp in UNIX epoch format.
7381342292Scy**
7382342292Scy** If the value passed as the only argument is either NULL or an SQL NULL,
7383342292Scy** return the current time. Otherwise, return the value stored in (*pVal)
7384342292Scy** cast to a 32-bit unsigned integer.
7385342292Scy*/
7386342292Scystatic u32 zipfileGetTime(sqlite3_value *pVal){
7387342292Scy  if( pVal==0 || sqlite3_value_type(pVal)==SQLITE_NULL ){
7388342292Scy    return zipfileTime();
7389342292Scy  }
7390342292Scy  return (u32)sqlite3_value_int64(pVal);
7391342292Scy}
7392342292Scy
7393342292Scy/*
7394342292Scy** Unless it is NULL, entry pOld is currently part of the pTab->pFirstEntry
7395342292Scy** linked list.  Remove it from the list and free the object.
7396342292Scy*/
7397342292Scystatic void zipfileRemoveEntryFromList(ZipfileTab *pTab, ZipfileEntry *pOld){
7398342292Scy  if( pOld ){
7399342292Scy    ZipfileEntry **pp;
7400342292Scy    for(pp=&pTab->pFirstEntry; (*pp)!=pOld; pp=&((*pp)->pNext));
7401342292Scy    *pp = (*pp)->pNext;
7402342292Scy    zipfileEntryFree(pOld);
7403342292Scy  }
7404342292Scy}
7405342292Scy
7406342292Scy/*
7407342292Scy** xUpdate method.
7408342292Scy*/
7409342292Scystatic int zipfileUpdate(
7410342292Scy  sqlite3_vtab *pVtab,
7411342292Scy  int nVal,
7412342292Scy  sqlite3_value **apVal,
7413342292Scy  sqlite_int64 *pRowid
7414342292Scy){
7415342292Scy  ZipfileTab *pTab = (ZipfileTab*)pVtab;
7416342292Scy  int rc = SQLITE_OK;             /* Return Code */
7417342292Scy  ZipfileEntry *pNew = 0;         /* New in-memory CDS entry */
7418342292Scy
7419342292Scy  u32 mode = 0;                   /* Mode for new entry */
7420342292Scy  u32 mTime = 0;                  /* Modification time for new entry */
7421342292Scy  i64 sz = 0;                     /* Uncompressed size */
7422342292Scy  const char *zPath = 0;          /* Path for new entry */
7423342292Scy  int nPath = 0;                  /* strlen(zPath) */
7424342292Scy  const u8 *pData = 0;            /* Pointer to buffer containing content */
7425342292Scy  int nData = 0;                  /* Size of pData buffer in bytes */
7426342292Scy  int iMethod = 0;                /* Compression method for new entry */
7427342292Scy  u8 *pFree = 0;                  /* Free this */
7428342292Scy  char *zFree = 0;                /* Also free this */
7429342292Scy  ZipfileEntry *pOld = 0;
7430342292Scy  ZipfileEntry *pOld2 = 0;
7431342292Scy  int bUpdate = 0;                /* True for an update that modifies "name" */
7432342292Scy  int bIsDir = 0;
7433342292Scy  u32 iCrc32 = 0;
7434342292Scy
7435342292Scy  if( pTab->pWriteFd==0 ){
7436342292Scy    rc = zipfileBegin(pVtab);
7437342292Scy    if( rc!=SQLITE_OK ) return rc;
7438342292Scy  }
7439342292Scy
7440342292Scy  /* If this is a DELETE or UPDATE, find the archive entry to delete. */
7441342292Scy  if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
7442342292Scy    const char *zDelete = (const char*)sqlite3_value_text(apVal[0]);
7443342292Scy    int nDelete = (int)strlen(zDelete);
7444342292Scy    if( nVal>1 ){
7445342292Scy      const char *zUpdate = (const char*)sqlite3_value_text(apVal[1]);
7446342292Scy      if( zUpdate && zipfileComparePath(zUpdate, zDelete, nDelete)!=0 ){
7447342292Scy        bUpdate = 1;
7448342292Scy      }
7449342292Scy    }
7450342292Scy    for(pOld=pTab->pFirstEntry; 1; pOld=pOld->pNext){
7451342292Scy      if( zipfileComparePath(pOld->cds.zFile, zDelete, nDelete)==0 ){
7452342292Scy        break;
7453342292Scy      }
7454342292Scy      assert( pOld->pNext );
7455342292Scy    }
7456342292Scy  }
7457342292Scy
7458342292Scy  if( nVal>1 ){
7459342292Scy    /* Check that "sz" and "rawdata" are both NULL: */
7460342292Scy    if( sqlite3_value_type(apVal[5])!=SQLITE_NULL ){
7461342292Scy      zipfileTableErr(pTab, "sz must be NULL");
7462342292Scy      rc = SQLITE_CONSTRAINT;
7463342292Scy    }
7464342292Scy    if( sqlite3_value_type(apVal[6])!=SQLITE_NULL ){
7465342292Scy      zipfileTableErr(pTab, "rawdata must be NULL");
7466342292Scy      rc = SQLITE_CONSTRAINT;
7467342292Scy    }
7468342292Scy
7469342292Scy    if( rc==SQLITE_OK ){
7470342292Scy      if( sqlite3_value_type(apVal[7])==SQLITE_NULL ){
7471342292Scy        /* data=NULL. A directory */
7472342292Scy        bIsDir = 1;
7473342292Scy      }else{
7474342292Scy        /* Value specified for "data", and possibly "method". This must be
7475342292Scy        ** a regular file or a symlink. */
7476342292Scy        const u8 *aIn = sqlite3_value_blob(apVal[7]);
7477342292Scy        int nIn = sqlite3_value_bytes(apVal[7]);
7478342292Scy        int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL;
7479342292Scy
7480342292Scy        iMethod = sqlite3_value_int(apVal[8]);
7481342292Scy        sz = nIn;
7482342292Scy        pData = aIn;
7483342292Scy        nData = nIn;
7484342292Scy        if( iMethod!=0 && iMethod!=8 ){
7485342292Scy          zipfileTableErr(pTab, "unknown compression method: %d", iMethod);
7486342292Scy          rc = SQLITE_CONSTRAINT;
7487342292Scy        }else{
7488342292Scy          if( bAuto || iMethod ){
7489342292Scy            int nCmp;
7490342292Scy            rc = zipfileDeflate(aIn, nIn, &pFree, &nCmp, &pTab->base.zErrMsg);
7491342292Scy            if( rc==SQLITE_OK ){
7492342292Scy              if( iMethod || nCmp<nIn ){
7493342292Scy                iMethod = 8;
7494342292Scy                pData = pFree;
7495342292Scy                nData = nCmp;
7496342292Scy              }
7497342292Scy            }
7498342292Scy          }
7499342292Scy          iCrc32 = crc32(0, aIn, nIn);
7500342292Scy        }
7501342292Scy      }
7502342292Scy    }
7503342292Scy
7504342292Scy    if( rc==SQLITE_OK ){
7505342292Scy      rc = zipfileGetMode(apVal[3], bIsDir, &mode, &pTab->base.zErrMsg);
7506342292Scy    }
7507342292Scy
7508342292Scy    if( rc==SQLITE_OK ){
7509342292Scy      zPath = (const char*)sqlite3_value_text(apVal[2]);
7510361456Scy      if( zPath==0 ) zPath = "";
7511342292Scy      nPath = (int)strlen(zPath);
7512342292Scy      mTime = zipfileGetTime(apVal[4]);
7513342292Scy    }
7514342292Scy
7515342292Scy    if( rc==SQLITE_OK && bIsDir ){
7516342292Scy      /* For a directory, check that the last character in the path is a
7517342292Scy      ** '/'. This appears to be required for compatibility with info-zip
7518342292Scy      ** (the unzip command on unix). It does not create directories
7519342292Scy      ** otherwise.  */
7520361456Scy      if( nPath<=0 || zPath[nPath-1]!='/' ){
7521342292Scy        zFree = sqlite3_mprintf("%s/", zPath);
7522342292Scy        zPath = (const char*)zFree;
7523361456Scy        if( zFree==0 ){
7524361456Scy          rc = SQLITE_NOMEM;
7525361456Scy          nPath = 0;
7526361456Scy        }else{
7527361456Scy          nPath = (int)strlen(zPath);
7528361456Scy        }
7529342292Scy      }
7530342292Scy    }
7531342292Scy
7532342292Scy    /* Check that we're not inserting a duplicate entry -OR- updating an
7533342292Scy    ** entry with a path, thereby making it into a duplicate. */
7534342292Scy    if( (pOld==0 || bUpdate) && rc==SQLITE_OK ){
7535342292Scy      ZipfileEntry *p;
7536342292Scy      for(p=pTab->pFirstEntry; p; p=p->pNext){
7537342292Scy        if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){
7538342292Scy          switch( sqlite3_vtab_on_conflict(pTab->db) ){
7539342292Scy            case SQLITE_IGNORE: {
7540342292Scy              goto zipfile_update_done;
7541342292Scy            }
7542342292Scy            case SQLITE_REPLACE: {
7543342292Scy              pOld2 = p;
7544342292Scy              break;
7545342292Scy            }
7546342292Scy            default: {
7547342292Scy              zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath);
7548342292Scy              rc = SQLITE_CONSTRAINT;
7549342292Scy              break;
7550342292Scy            }
7551342292Scy          }
7552342292Scy          break;
7553342292Scy        }
7554342292Scy      }
7555342292Scy    }
7556342292Scy
7557342292Scy    if( rc==SQLITE_OK ){
7558342292Scy      /* Create the new CDS record. */
7559342292Scy      pNew = zipfileNewEntry(zPath);
7560342292Scy      if( pNew==0 ){
7561342292Scy        rc = SQLITE_NOMEM;
7562342292Scy      }else{
7563342292Scy        pNew->cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
7564342292Scy        pNew->cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
7565342292Scy        pNew->cds.flags = ZIPFILE_NEWENTRY_FLAGS;
7566342292Scy        pNew->cds.iCompression = (u16)iMethod;
7567342292Scy        zipfileMtimeToDos(&pNew->cds, mTime);
7568342292Scy        pNew->cds.crc32 = iCrc32;
7569342292Scy        pNew->cds.szCompressed = nData;
7570342292Scy        pNew->cds.szUncompressed = (u32)sz;
7571342292Scy        pNew->cds.iExternalAttr = (mode<<16);
7572342292Scy        pNew->cds.iOffset = (u32)pTab->szCurrent;
7573342292Scy        pNew->cds.nFile = (u16)nPath;
7574342292Scy        pNew->mUnixTime = (u32)mTime;
7575342292Scy        rc = zipfileAppendEntry(pTab, pNew, pData, nData);
7576342292Scy        zipfileAddEntry(pTab, pOld, pNew);
7577342292Scy      }
7578342292Scy    }
7579342292Scy  }
7580342292Scy
7581342292Scy  if( rc==SQLITE_OK && (pOld || pOld2) ){
7582342292Scy    ZipfileCsr *pCsr;
7583342292Scy    for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
7584342292Scy      if( pCsr->pCurrent && (pCsr->pCurrent==pOld || pCsr->pCurrent==pOld2) ){
7585342292Scy        pCsr->pCurrent = pCsr->pCurrent->pNext;
7586342292Scy        pCsr->bNoop = 1;
7587342292Scy      }
7588342292Scy    }
7589342292Scy
7590342292Scy    zipfileRemoveEntryFromList(pTab, pOld);
7591342292Scy    zipfileRemoveEntryFromList(pTab, pOld2);
7592342292Scy  }
7593342292Scy
7594342292Scyzipfile_update_done:
7595342292Scy  sqlite3_free(pFree);
7596342292Scy  sqlite3_free(zFree);
7597342292Scy  return rc;
7598342292Scy}
7599342292Scy
7600342292Scystatic int zipfileSerializeEOCD(ZipfileEOCD *p, u8 *aBuf){
7601342292Scy  u8 *a = aBuf;
7602342292Scy  zipfileWrite32(a, ZIPFILE_SIGNATURE_EOCD);
7603342292Scy  zipfileWrite16(a, p->iDisk);
7604342292Scy  zipfileWrite16(a, p->iFirstDisk);
7605342292Scy  zipfileWrite16(a, p->nEntry);
7606342292Scy  zipfileWrite16(a, p->nEntryTotal);
7607342292Scy  zipfileWrite32(a, p->nSize);
7608342292Scy  zipfileWrite32(a, p->iOffset);
7609342292Scy  zipfileWrite16(a, 0);        /* Size of trailing comment in bytes*/
7610342292Scy
7611342292Scy  return a-aBuf;
7612342292Scy}
7613342292Scy
7614342292Scystatic int zipfileAppendEOCD(ZipfileTab *pTab, ZipfileEOCD *p){
7615342292Scy  int nBuf = zipfileSerializeEOCD(p, pTab->aBuffer);
7616342292Scy  assert( nBuf==ZIPFILE_EOCD_FIXED_SZ );
7617342292Scy  return zipfileAppendData(pTab, pTab->aBuffer, nBuf);
7618342292Scy}
7619342292Scy
7620342292Scy/*
7621342292Scy** Serialize the CDS structure into buffer aBuf[]. Return the number
7622342292Scy** of bytes written.
7623342292Scy*/
7624342292Scystatic int zipfileSerializeCDS(ZipfileEntry *pEntry, u8 *aBuf){
7625342292Scy  u8 *a = aBuf;
7626342292Scy  ZipfileCDS *pCDS = &pEntry->cds;
7627342292Scy
7628342292Scy  if( pEntry->aExtra==0 ){
7629342292Scy    pCDS->nExtra = 9;
7630342292Scy  }
7631342292Scy
7632342292Scy  zipfileWrite32(a, ZIPFILE_SIGNATURE_CDS);
7633342292Scy  zipfileWrite16(a, pCDS->iVersionMadeBy);
7634342292Scy  zipfileWrite16(a, pCDS->iVersionExtract);
7635342292Scy  zipfileWrite16(a, pCDS->flags);
7636342292Scy  zipfileWrite16(a, pCDS->iCompression);
7637342292Scy  zipfileWrite16(a, pCDS->mTime);
7638342292Scy  zipfileWrite16(a, pCDS->mDate);
7639342292Scy  zipfileWrite32(a, pCDS->crc32);
7640342292Scy  zipfileWrite32(a, pCDS->szCompressed);
7641342292Scy  zipfileWrite32(a, pCDS->szUncompressed);
7642342292Scy  assert( a==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
7643342292Scy  zipfileWrite16(a, pCDS->nFile);
7644342292Scy  zipfileWrite16(a, pCDS->nExtra);
7645342292Scy  zipfileWrite16(a, pCDS->nComment);
7646342292Scy  zipfileWrite16(a, pCDS->iDiskStart);
7647342292Scy  zipfileWrite16(a, pCDS->iInternalAttr);
7648342292Scy  zipfileWrite32(a, pCDS->iExternalAttr);
7649342292Scy  zipfileWrite32(a, pCDS->iOffset);
7650342292Scy
7651342292Scy  memcpy(a, pCDS->zFile, pCDS->nFile);
7652342292Scy  a += pCDS->nFile;
7653342292Scy
7654342292Scy  if( pEntry->aExtra ){
7655342292Scy    int n = (int)pCDS->nExtra + (int)pCDS->nComment;
7656342292Scy    memcpy(a, pEntry->aExtra, n);
7657342292Scy    a += n;
7658342292Scy  }else{
7659342292Scy    assert( pCDS->nExtra==9 );
7660342292Scy    zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP);
7661342292Scy    zipfileWrite16(a, 5);
7662342292Scy    *a++ = 0x01;
7663342292Scy    zipfileWrite32(a, pEntry->mUnixTime);
7664342292Scy  }
7665342292Scy
7666342292Scy  return a-aBuf;
7667342292Scy}
7668342292Scy
7669342292Scystatic int zipfileCommit(sqlite3_vtab *pVtab){
7670342292Scy  ZipfileTab *pTab = (ZipfileTab*)pVtab;
7671342292Scy  int rc = SQLITE_OK;
7672342292Scy  if( pTab->pWriteFd ){
7673342292Scy    i64 iOffset = pTab->szCurrent;
7674342292Scy    ZipfileEntry *p;
7675342292Scy    ZipfileEOCD eocd;
7676342292Scy    int nEntry = 0;
7677342292Scy
7678342292Scy    /* Write out all entries */
7679342292Scy    for(p=pTab->pFirstEntry; rc==SQLITE_OK && p; p=p->pNext){
7680342292Scy      int n = zipfileSerializeCDS(p, pTab->aBuffer);
7681342292Scy      rc = zipfileAppendData(pTab, pTab->aBuffer, n);
7682342292Scy      nEntry++;
7683342292Scy    }
7684342292Scy
7685342292Scy    /* Write out the EOCD record */
7686342292Scy    eocd.iDisk = 0;
7687342292Scy    eocd.iFirstDisk = 0;
7688342292Scy    eocd.nEntry = (u16)nEntry;
7689342292Scy    eocd.nEntryTotal = (u16)nEntry;
7690342292Scy    eocd.nSize = (u32)(pTab->szCurrent - iOffset);
7691342292Scy    eocd.iOffset = (u32)iOffset;
7692342292Scy    rc = zipfileAppendEOCD(pTab, &eocd);
7693342292Scy
7694342292Scy    zipfileCleanupTransaction(pTab);
7695342292Scy  }
7696342292Scy  return rc;
7697342292Scy}
7698342292Scy
7699342292Scystatic int zipfileRollback(sqlite3_vtab *pVtab){
7700342292Scy  return zipfileCommit(pVtab);
7701342292Scy}
7702342292Scy
7703342292Scystatic ZipfileCsr *zipfileFindCursor(ZipfileTab *pTab, i64 iId){
7704342292Scy  ZipfileCsr *pCsr;
7705342292Scy  for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
7706342292Scy    if( iId==pCsr->iId ) break;
7707342292Scy  }
7708342292Scy  return pCsr;
7709342292Scy}
7710342292Scy
7711342292Scystatic void zipfileFunctionCds(
7712342292Scy  sqlite3_context *context,
7713342292Scy  int argc,
7714342292Scy  sqlite3_value **argv
7715342292Scy){
7716342292Scy  ZipfileCsr *pCsr;
7717342292Scy  ZipfileTab *pTab = (ZipfileTab*)sqlite3_user_data(context);
7718342292Scy  assert( argc>0 );
7719342292Scy
7720342292Scy  pCsr = zipfileFindCursor(pTab, sqlite3_value_int64(argv[0]));
7721342292Scy  if( pCsr ){
7722342292Scy    ZipfileCDS *p = &pCsr->pCurrent->cds;
7723342292Scy    char *zRes = sqlite3_mprintf("{"
7724342292Scy        "\"version-made-by\" : %u, "
7725342292Scy        "\"version-to-extract\" : %u, "
7726342292Scy        "\"flags\" : %u, "
7727342292Scy        "\"compression\" : %u, "
7728342292Scy        "\"time\" : %u, "
7729342292Scy        "\"date\" : %u, "
7730342292Scy        "\"crc32\" : %u, "
7731342292Scy        "\"compressed-size\" : %u, "
7732342292Scy        "\"uncompressed-size\" : %u, "
7733342292Scy        "\"file-name-length\" : %u, "
7734342292Scy        "\"extra-field-length\" : %u, "
7735342292Scy        "\"file-comment-length\" : %u, "
7736342292Scy        "\"disk-number-start\" : %u, "
7737342292Scy        "\"internal-attr\" : %u, "
7738342292Scy        "\"external-attr\" : %u, "
7739342292Scy        "\"offset\" : %u }",
7740342292Scy        (u32)p->iVersionMadeBy, (u32)p->iVersionExtract,
7741342292Scy        (u32)p->flags, (u32)p->iCompression,
7742342292Scy        (u32)p->mTime, (u32)p->mDate,
7743342292Scy        (u32)p->crc32, (u32)p->szCompressed,
7744342292Scy        (u32)p->szUncompressed, (u32)p->nFile,
7745342292Scy        (u32)p->nExtra, (u32)p->nComment,
7746342292Scy        (u32)p->iDiskStart, (u32)p->iInternalAttr,
7747342292Scy        (u32)p->iExternalAttr, (u32)p->iOffset
7748342292Scy    );
7749342292Scy
7750342292Scy    if( zRes==0 ){
7751342292Scy      sqlite3_result_error_nomem(context);
7752342292Scy    }else{
7753342292Scy      sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
7754342292Scy      sqlite3_free(zRes);
7755342292Scy    }
7756342292Scy  }
7757342292Scy}
7758342292Scy
7759342292Scy/*
7760342292Scy** xFindFunction method.
7761342292Scy*/
7762342292Scystatic int zipfileFindFunction(
7763342292Scy  sqlite3_vtab *pVtab,            /* Virtual table handle */
7764342292Scy  int nArg,                       /* Number of SQL function arguments */
7765342292Scy  const char *zName,              /* Name of SQL function */
7766342292Scy  void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
7767342292Scy  void **ppArg                    /* OUT: User data for *pxFunc */
7768342292Scy){
7769342292Scy  if( sqlite3_stricmp("zipfile_cds", zName)==0 ){
7770342292Scy    *pxFunc = zipfileFunctionCds;
7771342292Scy    *ppArg = (void*)pVtab;
7772342292Scy    return 1;
7773342292Scy  }
7774342292Scy  return 0;
7775342292Scy}
7776342292Scy
7777342292Scytypedef struct ZipfileBuffer ZipfileBuffer;
7778342292Scystruct ZipfileBuffer {
7779342292Scy  u8 *a;                          /* Pointer to buffer */
7780342292Scy  int n;                          /* Size of buffer in bytes */
7781342292Scy  int nAlloc;                     /* Byte allocated at a[] */
7782342292Scy};
7783342292Scy
7784342292Scytypedef struct ZipfileCtx ZipfileCtx;
7785342292Scystruct ZipfileCtx {
7786342292Scy  int nEntry;
7787342292Scy  ZipfileBuffer body;
7788342292Scy  ZipfileBuffer cds;
7789342292Scy};
7790342292Scy
7791342292Scystatic int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){
7792342292Scy  if( pBuf->n+nByte>pBuf->nAlloc ){
7793342292Scy    u8 *aNew;
7794346442Scy    sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512;
7795342292Scy    int nReq = pBuf->n + nByte;
7796342292Scy
7797342292Scy    while( nNew<nReq ) nNew = nNew*2;
7798346442Scy    aNew = sqlite3_realloc64(pBuf->a, nNew);
7799342292Scy    if( aNew==0 ) return SQLITE_NOMEM;
7800342292Scy    pBuf->a = aNew;
7801346442Scy    pBuf->nAlloc = (int)nNew;
7802342292Scy  }
7803342292Scy  return SQLITE_OK;
7804342292Scy}
7805342292Scy
7806342292Scy/*
7807342292Scy** xStep() callback for the zipfile() aggregate. This can be called in
7808342292Scy** any of the following ways:
7809342292Scy**
7810342292Scy**   SELECT zipfile(name,data) ...
7811342292Scy**   SELECT zipfile(name,mode,mtime,data) ...
7812342292Scy**   SELECT zipfile(name,mode,mtime,data,method) ...
7813342292Scy*/
7814342292Scyvoid zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
7815342292Scy  ZipfileCtx *p;                  /* Aggregate function context */
7816342292Scy  ZipfileEntry e;                 /* New entry to add to zip archive */
7817342292Scy
7818342292Scy  sqlite3_value *pName = 0;
7819342292Scy  sqlite3_value *pMode = 0;
7820342292Scy  sqlite3_value *pMtime = 0;
7821342292Scy  sqlite3_value *pData = 0;
7822342292Scy  sqlite3_value *pMethod = 0;
7823342292Scy
7824342292Scy  int bIsDir = 0;
7825342292Scy  u32 mode;
7826342292Scy  int rc = SQLITE_OK;
7827342292Scy  char *zErr = 0;
7828342292Scy
7829342292Scy  int iMethod = -1;               /* Compression method to use (0 or 8) */
7830342292Scy
7831342292Scy  const u8 *aData = 0;            /* Possibly compressed data for new entry */
7832342292Scy  int nData = 0;                  /* Size of aData[] in bytes */
7833342292Scy  int szUncompressed = 0;         /* Size of data before compression */
7834342292Scy  u8 *aFree = 0;                  /* Free this before returning */
7835342292Scy  u32 iCrc32 = 0;                 /* crc32 of uncompressed data */
7836342292Scy
7837342292Scy  char *zName = 0;                /* Path (name) of new entry */
7838342292Scy  int nName = 0;                  /* Size of zName in bytes */
7839342292Scy  char *zFree = 0;                /* Free this before returning */
7840342292Scy  int nByte;
7841342292Scy
7842342292Scy  memset(&e, 0, sizeof(e));
7843342292Scy  p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
7844342292Scy  if( p==0 ) return;
7845342292Scy
7846342292Scy  /* Martial the arguments into stack variables */
7847342292Scy  if( nVal!=2 && nVal!=4 && nVal!=5 ){
7848342292Scy    zErr = sqlite3_mprintf("wrong number of arguments to function zipfile()");
7849342292Scy    rc = SQLITE_ERROR;
7850342292Scy    goto zipfile_step_out;
7851342292Scy  }
7852342292Scy  pName = apVal[0];
7853342292Scy  if( nVal==2 ){
7854342292Scy    pData = apVal[1];
7855342292Scy  }else{
7856342292Scy    pMode = apVal[1];
7857342292Scy    pMtime = apVal[2];
7858342292Scy    pData = apVal[3];
7859342292Scy    if( nVal==5 ){
7860342292Scy      pMethod = apVal[4];
7861342292Scy    }
7862342292Scy  }
7863342292Scy
7864342292Scy  /* Check that the 'name' parameter looks ok. */
7865342292Scy  zName = (char*)sqlite3_value_text(pName);
7866342292Scy  nName = sqlite3_value_bytes(pName);
7867342292Scy  if( zName==0 ){
7868342292Scy    zErr = sqlite3_mprintf("first argument to zipfile() must be non-NULL");
7869342292Scy    rc = SQLITE_ERROR;
7870342292Scy    goto zipfile_step_out;
7871342292Scy  }
7872342292Scy
7873342292Scy  /* Inspect the 'method' parameter. This must be either 0 (store), 8 (use
7874342292Scy  ** deflate compression) or NULL (choose automatically).  */
7875342292Scy  if( pMethod && SQLITE_NULL!=sqlite3_value_type(pMethod) ){
7876342292Scy    iMethod = (int)sqlite3_value_int64(pMethod);
7877342292Scy    if( iMethod!=0 && iMethod!=8 ){
7878342292Scy      zErr = sqlite3_mprintf("illegal method value: %d", iMethod);
7879342292Scy      rc = SQLITE_ERROR;
7880342292Scy      goto zipfile_step_out;
7881342292Scy    }
7882342292Scy  }
7883342292Scy
7884342292Scy  /* Now inspect the data. If this is NULL, then the new entry must be a
7885342292Scy  ** directory.  Otherwise, figure out whether or not the data should
7886342292Scy  ** be deflated or simply stored in the zip archive. */
7887342292Scy  if( sqlite3_value_type(pData)==SQLITE_NULL ){
7888342292Scy    bIsDir = 1;
7889342292Scy    iMethod = 0;
7890342292Scy  }else{
7891342292Scy    aData = sqlite3_value_blob(pData);
7892342292Scy    szUncompressed = nData = sqlite3_value_bytes(pData);
7893342292Scy    iCrc32 = crc32(0, aData, nData);
7894342292Scy    if( iMethod<0 || iMethod==8 ){
7895342292Scy      int nOut = 0;
7896342292Scy      rc = zipfileDeflate(aData, nData, &aFree, &nOut, &zErr);
7897342292Scy      if( rc!=SQLITE_OK ){
7898342292Scy        goto zipfile_step_out;
7899342292Scy      }
7900342292Scy      if( iMethod==8 || nOut<nData ){
7901342292Scy        aData = aFree;
7902342292Scy        nData = nOut;
7903342292Scy        iMethod = 8;
7904342292Scy      }else{
7905342292Scy        iMethod = 0;
7906342292Scy      }
7907342292Scy    }
7908342292Scy  }
7909342292Scy
7910342292Scy  /* Decode the "mode" argument. */
7911342292Scy  rc = zipfileGetMode(pMode, bIsDir, &mode, &zErr);
7912342292Scy  if( rc ) goto zipfile_step_out;
7913342292Scy
7914342292Scy  /* Decode the "mtime" argument. */
7915342292Scy  e.mUnixTime = zipfileGetTime(pMtime);
7916342292Scy
7917342292Scy  /* If this is a directory entry, ensure that there is exactly one '/'
7918342292Scy  ** at the end of the path. Or, if this is not a directory and the path
7919342292Scy  ** ends in '/' it is an error. */
7920342292Scy  if( bIsDir==0 ){
7921361456Scy    if( nName>0 && zName[nName-1]=='/' ){
7922342292Scy      zErr = sqlite3_mprintf("non-directory name must not end with /");
7923342292Scy      rc = SQLITE_ERROR;
7924342292Scy      goto zipfile_step_out;
7925342292Scy    }
7926342292Scy  }else{
7927361456Scy    if( nName==0 || zName[nName-1]!='/' ){
7928342292Scy      zName = zFree = sqlite3_mprintf("%s/", zName);
7929342292Scy      if( zName==0 ){
7930342292Scy        rc = SQLITE_NOMEM;
7931342292Scy        goto zipfile_step_out;
7932342292Scy      }
7933361456Scy      nName = (int)strlen(zName);
7934342292Scy    }else{
7935342292Scy      while( nName>1 && zName[nName-2]=='/' ) nName--;
7936342292Scy    }
7937342292Scy  }
7938342292Scy
7939342292Scy  /* Assemble the ZipfileEntry object for the new zip archive entry */
7940342292Scy  e.cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
7941342292Scy  e.cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
7942342292Scy  e.cds.flags = ZIPFILE_NEWENTRY_FLAGS;
7943342292Scy  e.cds.iCompression = (u16)iMethod;
7944342292Scy  zipfileMtimeToDos(&e.cds, (u32)e.mUnixTime);
7945342292Scy  e.cds.crc32 = iCrc32;
7946342292Scy  e.cds.szCompressed = nData;
7947342292Scy  e.cds.szUncompressed = szUncompressed;
7948342292Scy  e.cds.iExternalAttr = (mode<<16);
7949342292Scy  e.cds.iOffset = p->body.n;
7950342292Scy  e.cds.nFile = (u16)nName;
7951342292Scy  e.cds.zFile = zName;
7952342292Scy
7953342292Scy  /* Append the LFH to the body of the new archive */
7954342292Scy  nByte = ZIPFILE_LFH_FIXED_SZ + e.cds.nFile + 9;
7955342292Scy  if( (rc = zipfileBufferGrow(&p->body, nByte)) ) goto zipfile_step_out;
7956342292Scy  p->body.n += zipfileSerializeLFH(&e, &p->body.a[p->body.n]);
7957342292Scy
7958342292Scy  /* Append the data to the body of the new archive */
7959342292Scy  if( nData>0 ){
7960342292Scy    if( (rc = zipfileBufferGrow(&p->body, nData)) ) goto zipfile_step_out;
7961342292Scy    memcpy(&p->body.a[p->body.n], aData, nData);
7962342292Scy    p->body.n += nData;
7963342292Scy  }
7964342292Scy
7965342292Scy  /* Append the CDS record to the directory of the new archive */
7966342292Scy  nByte = ZIPFILE_CDS_FIXED_SZ + e.cds.nFile + 9;
7967342292Scy  if( (rc = zipfileBufferGrow(&p->cds, nByte)) ) goto zipfile_step_out;
7968342292Scy  p->cds.n += zipfileSerializeCDS(&e, &p->cds.a[p->cds.n]);
7969342292Scy
7970342292Scy  /* Increment the count of entries in the archive */
7971342292Scy  p->nEntry++;
7972342292Scy
7973342292Scy zipfile_step_out:
7974342292Scy  sqlite3_free(aFree);
7975342292Scy  sqlite3_free(zFree);
7976342292Scy  if( rc ){
7977342292Scy    if( zErr ){
7978342292Scy      sqlite3_result_error(pCtx, zErr, -1);
7979342292Scy    }else{
7980342292Scy      sqlite3_result_error_code(pCtx, rc);
7981342292Scy    }
7982342292Scy  }
7983342292Scy  sqlite3_free(zErr);
7984342292Scy}
7985342292Scy
7986342292Scy/*
7987342292Scy** xFinalize() callback for zipfile aggregate function.
7988342292Scy*/
7989342292Scyvoid zipfileFinal(sqlite3_context *pCtx){
7990342292Scy  ZipfileCtx *p;
7991342292Scy  ZipfileEOCD eocd;
7992346442Scy  sqlite3_int64 nZip;
7993342292Scy  u8 *aZip;
7994342292Scy
7995342292Scy  p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
7996342292Scy  if( p==0 ) return;
7997342292Scy  if( p->nEntry>0 ){
7998342292Scy    memset(&eocd, 0, sizeof(eocd));
7999342292Scy    eocd.nEntry = (u16)p->nEntry;
8000342292Scy    eocd.nEntryTotal = (u16)p->nEntry;
8001342292Scy    eocd.nSize = p->cds.n;
8002342292Scy    eocd.iOffset = p->body.n;
8003342292Scy
8004342292Scy    nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ;
8005346442Scy    aZip = (u8*)sqlite3_malloc64(nZip);
8006342292Scy    if( aZip==0 ){
8007342292Scy      sqlite3_result_error_nomem(pCtx);
8008342292Scy    }else{
8009342292Scy      memcpy(aZip, p->body.a, p->body.n);
8010342292Scy      memcpy(&aZip[p->body.n], p->cds.a, p->cds.n);
8011342292Scy      zipfileSerializeEOCD(&eocd, &aZip[p->body.n + p->cds.n]);
8012346442Scy      sqlite3_result_blob(pCtx, aZip, (int)nZip, zipfileFree);
8013342292Scy    }
8014342292Scy  }
8015342292Scy
8016342292Scy  sqlite3_free(p->body.a);
8017342292Scy  sqlite3_free(p->cds.a);
8018342292Scy}
8019342292Scy
8020342292Scy
8021342292Scy/*
8022342292Scy** Register the "zipfile" virtual table.
8023342292Scy*/
8024342292Scystatic int zipfileRegister(sqlite3 *db){
8025342292Scy  static sqlite3_module zipfileModule = {
8026342292Scy    1,                         /* iVersion */
8027342292Scy    zipfileConnect,            /* xCreate */
8028342292Scy    zipfileConnect,            /* xConnect */
8029342292Scy    zipfileBestIndex,          /* xBestIndex */
8030342292Scy    zipfileDisconnect,         /* xDisconnect */
8031342292Scy    zipfileDisconnect,         /* xDestroy */
8032342292Scy    zipfileOpen,               /* xOpen - open a cursor */
8033342292Scy    zipfileClose,              /* xClose - close a cursor */
8034342292Scy    zipfileFilter,             /* xFilter - configure scan constraints */
8035342292Scy    zipfileNext,               /* xNext - advance a cursor */
8036342292Scy    zipfileEof,                /* xEof - check for end of scan */
8037342292Scy    zipfileColumn,             /* xColumn - read data */
8038342292Scy    0,                         /* xRowid - read data */
8039342292Scy    zipfileUpdate,             /* xUpdate */
8040342292Scy    zipfileBegin,              /* xBegin */
8041342292Scy    0,                         /* xSync */
8042342292Scy    zipfileCommit,             /* xCommit */
8043342292Scy    zipfileRollback,           /* xRollback */
8044342292Scy    zipfileFindFunction,       /* xFindMethod */
8045342292Scy    0,                         /* xRename */
8046342292Scy  };
8047342292Scy
8048342292Scy  int rc = sqlite3_create_module(db, "zipfile"  , &zipfileModule, 0);
8049342292Scy  if( rc==SQLITE_OK ) rc = sqlite3_overload_function(db, "zipfile_cds", -1);
8050342292Scy  if( rc==SQLITE_OK ){
8051342292Scy    rc = sqlite3_create_function(db, "zipfile", -1, SQLITE_UTF8, 0, 0,
8052342292Scy        zipfileStep, zipfileFinal
8053342292Scy    );
8054342292Scy  }
8055342292Scy  return rc;
8056342292Scy}
8057342292Scy#else         /* SQLITE_OMIT_VIRTUALTABLE */
8058342292Scy# define zipfileRegister(x) SQLITE_OK
8059342292Scy#endif
8060342292Scy
8061342292Scy#ifdef _WIN32
8062342292Scy
8063342292Scy#endif
8064342292Scyint sqlite3_zipfile_init(
8065342292Scy  sqlite3 *db,
8066342292Scy  char **pzErrMsg,
8067342292Scy  const sqlite3_api_routines *pApi
8068342292Scy){
8069342292Scy  SQLITE_EXTENSION_INIT2(pApi);
8070342292Scy  (void)pzErrMsg;  /* Unused parameter */
8071342292Scy  return zipfileRegister(db);
8072342292Scy}
8073342292Scy
8074342292Scy/************************* End ../ext/misc/zipfile.c ********************/
8075342292Scy/************************* Begin ../ext/misc/sqlar.c ******************/
8076342292Scy/*
8077342292Scy** 2017-12-17
8078342292Scy**
8079342292Scy** The author disclaims copyright to this source code.  In place of
8080342292Scy** a legal notice, here is a blessing:
8081342292Scy**
8082342292Scy**    May you do good and not evil.
8083342292Scy**    May you find forgiveness for yourself and forgive others.
8084342292Scy**    May you share freely, never taking more than you give.
8085342292Scy**
8086342292Scy******************************************************************************
8087342292Scy**
8088342292Scy** Utility functions sqlar_compress() and sqlar_uncompress(). Useful
8089342292Scy** for working with sqlar archives and used by the shell tool's built-in
8090342292Scy** sqlar support.
8091342292Scy*/
8092351633Scy/* #include "sqlite3ext.h" */
8093342292ScySQLITE_EXTENSION_INIT1
8094342292Scy#include <zlib.h>
8095362190Scy#include <assert.h>
8096342292Scy
8097342292Scy/*
8098342292Scy** Implementation of the "sqlar_compress(X)" SQL function.
8099342292Scy**
8100342292Scy** If the type of X is SQLITE_BLOB, and compressing that blob using
8101342292Scy** zlib utility function compress() yields a smaller blob, return the
8102342292Scy** compressed blob. Otherwise, return a copy of X.
8103342292Scy**
8104342292Scy** SQLar uses the "zlib format" for compressed content.  The zlib format
8105342292Scy** contains a two-byte identification header and a four-byte checksum at
8106342292Scy** the end.  This is different from ZIP which uses the raw deflate format.
8107342292Scy**
8108342292Scy** Future enhancements to SQLar might add support for new compression formats.
8109342292Scy** If so, those new formats will be identified by alternative headers in the
8110342292Scy** compressed data.
8111342292Scy*/
8112342292Scystatic void sqlarCompressFunc(
8113342292Scy  sqlite3_context *context,
8114342292Scy  int argc,
8115342292Scy  sqlite3_value **argv
8116342292Scy){
8117342292Scy  assert( argc==1 );
8118342292Scy  if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
8119342292Scy    const Bytef *pData = sqlite3_value_blob(argv[0]);
8120342292Scy    uLong nData = sqlite3_value_bytes(argv[0]);
8121342292Scy    uLongf nOut = compressBound(nData);
8122342292Scy    Bytef *pOut;
8123342292Scy
8124342292Scy    pOut = (Bytef*)sqlite3_malloc(nOut);
8125342292Scy    if( pOut==0 ){
8126342292Scy      sqlite3_result_error_nomem(context);
8127342292Scy      return;
8128342292Scy    }else{
8129342292Scy      if( Z_OK!=compress(pOut, &nOut, pData, nData) ){
8130342292Scy        sqlite3_result_error(context, "error in compress()", -1);
8131342292Scy      }else if( nOut<nData ){
8132342292Scy        sqlite3_result_blob(context, pOut, nOut, SQLITE_TRANSIENT);
8133342292Scy      }else{
8134342292Scy        sqlite3_result_value(context, argv[0]);
8135342292Scy      }
8136342292Scy      sqlite3_free(pOut);
8137342292Scy    }
8138342292Scy  }else{
8139342292Scy    sqlite3_result_value(context, argv[0]);
8140342292Scy  }
8141342292Scy}
8142342292Scy
8143342292Scy/*
8144342292Scy** Implementation of the "sqlar_uncompress(X,SZ)" SQL function
8145342292Scy**
8146342292Scy** Parameter SZ is interpreted as an integer. If it is less than or
8147342292Scy** equal to zero, then this function returns a copy of X. Or, if
8148342292Scy** SZ is equal to the size of X when interpreted as a blob, also
8149342292Scy** return a copy of X. Otherwise, decompress blob X using zlib
8150342292Scy** utility function uncompress() and return the results (another
8151342292Scy** blob).
8152342292Scy*/
8153342292Scystatic void sqlarUncompressFunc(
8154342292Scy  sqlite3_context *context,
8155342292Scy  int argc,
8156342292Scy  sqlite3_value **argv
8157342292Scy){
8158342292Scy  uLong nData;
8159342292Scy  uLongf sz;
8160342292Scy
8161342292Scy  assert( argc==2 );
8162342292Scy  sz = sqlite3_value_int(argv[1]);
8163342292Scy
8164342292Scy  if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){
8165342292Scy    sqlite3_result_value(context, argv[0]);
8166342292Scy  }else{
8167342292Scy    const Bytef *pData= sqlite3_value_blob(argv[0]);
8168342292Scy    Bytef *pOut = sqlite3_malloc(sz);
8169342292Scy    if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){
8170342292Scy      sqlite3_result_error(context, "error in uncompress()", -1);
8171342292Scy    }else{
8172342292Scy      sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT);
8173342292Scy    }
8174342292Scy    sqlite3_free(pOut);
8175342292Scy  }
8176342292Scy}
8177342292Scy
8178342292Scy
8179342292Scy#ifdef _WIN32
8180342292Scy
8181342292Scy#endif
8182342292Scyint sqlite3_sqlar_init(
8183342292Scy  sqlite3 *db,
8184342292Scy  char **pzErrMsg,
8185342292Scy  const sqlite3_api_routines *pApi
8186342292Scy){
8187342292Scy  int rc = SQLITE_OK;
8188342292Scy  SQLITE_EXTENSION_INIT2(pApi);
8189342292Scy  (void)pzErrMsg;  /* Unused parameter */
8190361456Scy  rc = sqlite3_create_function(db, "sqlar_compress", 1,
8191361456Scy                               SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
8192342292Scy                               sqlarCompressFunc, 0, 0);
8193342292Scy  if( rc==SQLITE_OK ){
8194361456Scy    rc = sqlite3_create_function(db, "sqlar_uncompress", 2,
8195361456Scy                                 SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
8196342292Scy                                 sqlarUncompressFunc, 0, 0);
8197342292Scy  }
8198342292Scy  return rc;
8199342292Scy}
8200342292Scy
8201342292Scy/************************* End ../ext/misc/sqlar.c ********************/
8202342292Scy#endif
8203342292Scy/************************* Begin ../ext/expert/sqlite3expert.h ******************/
8204342292Scy/*
8205342292Scy** 2017 April 07
8206342292Scy**
8207342292Scy** The author disclaims copyright to this source code.  In place of
8208342292Scy** a legal notice, here is a blessing:
8209342292Scy**
8210342292Scy**    May you do good and not evil.
8211342292Scy**    May you find forgiveness for yourself and forgive others.
8212342292Scy**    May you share freely, never taking more than you give.
8213342292Scy**
8214342292Scy*************************************************************************
8215342292Scy*/
8216361456Scy#if !defined(SQLITEEXPERT_H)
8217361456Scy#define SQLITEEXPERT_H 1
8218351633Scy/* #include "sqlite3.h" */
8219342292Scy
8220342292Scytypedef struct sqlite3expert sqlite3expert;
8221342292Scy
8222342292Scy/*
8223342292Scy** Create a new sqlite3expert object.
8224342292Scy**
8225342292Scy** If successful, a pointer to the new object is returned and (*pzErr) set
8226342292Scy** to NULL. Or, if an error occurs, NULL is returned and (*pzErr) set to
8227342292Scy** an English-language error message. In this case it is the responsibility
8228342292Scy** of the caller to eventually free the error message buffer using
8229342292Scy** sqlite3_free().
8230342292Scy*/
8231342292Scysqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErr);
8232342292Scy
8233342292Scy/*
8234342292Scy** Configure an sqlite3expert object.
8235342292Scy**
8236342292Scy** EXPERT_CONFIG_SAMPLE:
8237342292Scy**   By default, sqlite3_expert_analyze() generates sqlite_stat1 data for
8238342292Scy**   each candidate index. This involves scanning and sorting the entire
8239342292Scy**   contents of each user database table once for each candidate index
8240342292Scy**   associated with the table. For large databases, this can be
8241342292Scy**   prohibitively slow. This option allows the sqlite3expert object to
8242342292Scy**   be configured so that sqlite_stat1 data is instead generated based on a
8243342292Scy**   subset of each table, or so that no sqlite_stat1 data is used at all.
8244342292Scy**
8245342292Scy**   A single integer argument is passed to this option. If the value is less
8246342292Scy**   than or equal to zero, then no sqlite_stat1 data is generated or used by
8247342292Scy**   the analysis - indexes are recommended based on the database schema only.
8248342292Scy**   Or, if the value is 100 or greater, complete sqlite_stat1 data is
8249342292Scy**   generated for each candidate index (this is the default). Finally, if the
8250342292Scy**   value falls between 0 and 100, then it represents the percentage of user
8251342292Scy**   table rows that should be considered when generating sqlite_stat1 data.
8252342292Scy**
8253342292Scy**   Examples:
8254342292Scy**
8255342292Scy**     // Do not generate any sqlite_stat1 data
8256342292Scy**     sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 0);
8257342292Scy**
8258342292Scy**     // Generate sqlite_stat1 data based on 10% of the rows in each table.
8259342292Scy**     sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 10);
8260342292Scy*/
8261342292Scyint sqlite3_expert_config(sqlite3expert *p, int op, ...);
8262342292Scy
8263342292Scy#define EXPERT_CONFIG_SAMPLE 1    /* int */
8264342292Scy
8265342292Scy/*
8266342292Scy** Specify zero or more SQL statements to be included in the analysis.
8267342292Scy**
8268342292Scy** Buffer zSql must contain zero or more complete SQL statements. This
8269342292Scy** function parses all statements contained in the buffer and adds them
8270342292Scy** to the internal list of statements to analyze. If successful, SQLITE_OK
8271342292Scy** is returned and (*pzErr) set to NULL. Or, if an error occurs - for example
8272342292Scy** due to a error in the SQL - an SQLite error code is returned and (*pzErr)
8273342292Scy** may be set to point to an English language error message. In this case
8274342292Scy** the caller is responsible for eventually freeing the error message buffer
8275342292Scy** using sqlite3_free().
8276342292Scy**
8277342292Scy** If an error does occur while processing one of the statements in the
8278342292Scy** buffer passed as the second argument, none of the statements in the
8279342292Scy** buffer are added to the analysis.
8280342292Scy**
8281342292Scy** This function must be called before sqlite3_expert_analyze(). If a call
8282342292Scy** to this function is made on an sqlite3expert object that has already
8283342292Scy** been passed to sqlite3_expert_analyze() SQLITE_MISUSE is returned
8284342292Scy** immediately and no statements are added to the analysis.
8285342292Scy*/
8286342292Scyint sqlite3_expert_sql(
8287342292Scy  sqlite3expert *p,               /* From a successful sqlite3_expert_new() */
8288342292Scy  const char *zSql,               /* SQL statement(s) to add */
8289342292Scy  char **pzErr                    /* OUT: Error message (if any) */
8290342292Scy);
8291342292Scy
8292342292Scy
8293342292Scy/*
8294342292Scy** This function is called after the sqlite3expert object has been configured
8295342292Scy** with all SQL statements using sqlite3_expert_sql() to actually perform
8296342292Scy** the analysis. Once this function has been called, it is not possible to
8297342292Scy** add further SQL statements to the analysis.
8298342292Scy**
8299342292Scy** If successful, SQLITE_OK is returned and (*pzErr) is set to NULL. Or, if
8300342292Scy** an error occurs, an SQLite error code is returned and (*pzErr) set to
8301342292Scy** point to a buffer containing an English language error message. In this
8302342292Scy** case it is the responsibility of the caller to eventually free the buffer
8303342292Scy** using sqlite3_free().
8304342292Scy**
8305342292Scy** If an error does occur within this function, the sqlite3expert object
8306342292Scy** is no longer useful for any purpose. At that point it is no longer
8307342292Scy** possible to add further SQL statements to the object or to re-attempt
8308342292Scy** the analysis. The sqlite3expert object must still be freed using a call
8309342292Scy** sqlite3_expert_destroy().
8310342292Scy*/
8311342292Scyint sqlite3_expert_analyze(sqlite3expert *p, char **pzErr);
8312342292Scy
8313342292Scy/*
8314342292Scy** Return the total number of statements loaded using sqlite3_expert_sql().
8315342292Scy** The total number of SQL statements may be different from the total number
8316342292Scy** to calls to sqlite3_expert_sql().
8317342292Scy*/
8318342292Scyint sqlite3_expert_count(sqlite3expert*);
8319342292Scy
8320342292Scy/*
8321342292Scy** Return a component of the report.
8322342292Scy**
8323342292Scy** This function is called after sqlite3_expert_analyze() to extract the
8324342292Scy** results of the analysis. Each call to this function returns either a
8325342292Scy** NULL pointer or a pointer to a buffer containing a nul-terminated string.
8326342292Scy** The value passed as the third argument must be one of the EXPERT_REPORT_*
8327342292Scy** #define constants defined below.
8328342292Scy**
8329342292Scy** For some EXPERT_REPORT_* parameters, the buffer returned contains
8330342292Scy** information relating to a specific SQL statement. In these cases that
8331342292Scy** SQL statement is identified by the value passed as the second argument.
8332342292Scy** SQL statements are numbered from 0 in the order in which they are parsed.
8333342292Scy** If an out-of-range value (less than zero or equal to or greater than the
8334342292Scy** value returned by sqlite3_expert_count()) is passed as the second argument
8335342292Scy** along with such an EXPERT_REPORT_* parameter, NULL is always returned.
8336342292Scy**
8337342292Scy** EXPERT_REPORT_SQL:
8338342292Scy**   Return the text of SQL statement iStmt.
8339342292Scy**
8340342292Scy** EXPERT_REPORT_INDEXES:
8341342292Scy**   Return a buffer containing the CREATE INDEX statements for all recommended
8342342292Scy**   indexes for statement iStmt. If there are no new recommeded indexes, NULL
8343342292Scy**   is returned.
8344342292Scy**
8345342292Scy** EXPERT_REPORT_PLAN:
8346342292Scy**   Return a buffer containing the EXPLAIN QUERY PLAN output for SQL query
8347342292Scy**   iStmt after the proposed indexes have been added to the database schema.
8348342292Scy**
8349342292Scy** EXPERT_REPORT_CANDIDATES:
8350342292Scy**   Return a pointer to a buffer containing the CREATE INDEX statements
8351342292Scy**   for all indexes that were tested (for all SQL statements). The iStmt
8352342292Scy**   parameter is ignored for EXPERT_REPORT_CANDIDATES calls.
8353342292Scy*/
8354342292Scyconst char *sqlite3_expert_report(sqlite3expert*, int iStmt, int eReport);
8355342292Scy
8356342292Scy/*
8357342292Scy** Values for the third argument passed to sqlite3_expert_report().
8358342292Scy*/
8359342292Scy#define EXPERT_REPORT_SQL        1
8360342292Scy#define EXPERT_REPORT_INDEXES    2
8361342292Scy#define EXPERT_REPORT_PLAN       3
8362342292Scy#define EXPERT_REPORT_CANDIDATES 4
8363342292Scy
8364342292Scy/*
8365342292Scy** Free an (sqlite3expert*) handle and all associated resources. There
8366342292Scy** should be one call to this function for each successful call to
8367342292Scy** sqlite3-expert_new().
8368342292Scy*/
8369342292Scyvoid sqlite3_expert_destroy(sqlite3expert*);
8370342292Scy
8371361456Scy#endif  /* !defined(SQLITEEXPERT_H) */
8372342292Scy
8373342292Scy/************************* End ../ext/expert/sqlite3expert.h ********************/
8374342292Scy/************************* Begin ../ext/expert/sqlite3expert.c ******************/
8375342292Scy/*
8376342292Scy** 2017 April 09
8377342292Scy**
8378342292Scy** The author disclaims copyright to this source code.  In place of
8379342292Scy** a legal notice, here is a blessing:
8380342292Scy**
8381342292Scy**    May you do good and not evil.
8382342292Scy**    May you find forgiveness for yourself and forgive others.
8383342292Scy**    May you share freely, never taking more than you give.
8384342292Scy**
8385342292Scy*************************************************************************
8386342292Scy*/
8387351633Scy/* #include "sqlite3expert.h" */
8388342292Scy#include <assert.h>
8389342292Scy#include <string.h>
8390342292Scy#include <stdio.h>
8391342292Scy
8392342292Scy#ifndef SQLITE_OMIT_VIRTUALTABLE
8393342292Scy
8394342292Scy/* typedef sqlite3_int64 i64; */
8395342292Scy/* typedef sqlite3_uint64 u64; */
8396342292Scy
8397342292Scytypedef struct IdxColumn IdxColumn;
8398342292Scytypedef struct IdxConstraint IdxConstraint;
8399342292Scytypedef struct IdxScan IdxScan;
8400342292Scytypedef struct IdxStatement IdxStatement;
8401342292Scytypedef struct IdxTable IdxTable;
8402342292Scytypedef struct IdxWrite IdxWrite;
8403342292Scy
8404342292Scy#define STRLEN  (int)strlen
8405342292Scy
8406342292Scy/*
8407342292Scy** A temp table name that we assume no user database will actually use.
8408342292Scy** If this assumption proves incorrect triggers on the table with the
8409342292Scy** conflicting name will be ignored.
8410342292Scy*/
8411342292Scy#define UNIQUE_TABLE_NAME "t592690916721053953805701627921227776"
8412342292Scy
8413342292Scy/*
8414342292Scy** A single constraint. Equivalent to either "col = ?" or "col < ?" (or
8415342292Scy** any other type of single-ended range constraint on a column).
8416342292Scy**
8417342292Scy** pLink:
8418342292Scy**   Used to temporarily link IdxConstraint objects into lists while
8419342292Scy**   creating candidate indexes.
8420342292Scy*/
8421342292Scystruct IdxConstraint {
8422342292Scy  char *zColl;                    /* Collation sequence */
8423342292Scy  int bRange;                     /* True for range, false for eq */
8424342292Scy  int iCol;                       /* Constrained table column */
8425342292Scy  int bFlag;                      /* Used by idxFindCompatible() */
8426342292Scy  int bDesc;                      /* True if ORDER BY <expr> DESC */
8427342292Scy  IdxConstraint *pNext;           /* Next constraint in pEq or pRange list */
8428342292Scy  IdxConstraint *pLink;           /* See above */
8429342292Scy};
8430342292Scy
8431342292Scy/*
8432342292Scy** A single scan of a single table.
8433342292Scy*/
8434342292Scystruct IdxScan {
8435342292Scy  IdxTable *pTab;                 /* Associated table object */
8436342292Scy  int iDb;                        /* Database containing table zTable */
8437342292Scy  i64 covering;                   /* Mask of columns required for cov. index */
8438342292Scy  IdxConstraint *pOrder;          /* ORDER BY columns */
8439342292Scy  IdxConstraint *pEq;             /* List of == constraints */
8440342292Scy  IdxConstraint *pRange;          /* List of < constraints */
8441342292Scy  IdxScan *pNextScan;             /* Next IdxScan object for same analysis */
8442342292Scy};
8443342292Scy
8444342292Scy/*
8445342292Scy** Information regarding a single database table. Extracted from
8446342292Scy** "PRAGMA table_info" by function idxGetTableInfo().
8447342292Scy*/
8448342292Scystruct IdxColumn {
8449342292Scy  char *zName;
8450342292Scy  char *zColl;
8451342292Scy  int iPk;
8452342292Scy};
8453342292Scystruct IdxTable {
8454342292Scy  int nCol;
8455342292Scy  char *zName;                    /* Table name */
8456342292Scy  IdxColumn *aCol;
8457342292Scy  IdxTable *pNext;                /* Next table in linked list of all tables */
8458342292Scy};
8459342292Scy
8460342292Scy/*
8461342292Scy** An object of the following type is created for each unique table/write-op
8462342292Scy** seen. The objects are stored in a singly-linked list beginning at
8463342292Scy** sqlite3expert.pWrite.
8464342292Scy*/
8465342292Scystruct IdxWrite {
8466342292Scy  IdxTable *pTab;
8467342292Scy  int eOp;                        /* SQLITE_UPDATE, DELETE or INSERT */
8468342292Scy  IdxWrite *pNext;
8469342292Scy};
8470342292Scy
8471342292Scy/*
8472342292Scy** Each statement being analyzed is represented by an instance of this
8473342292Scy** structure.
8474342292Scy*/
8475342292Scystruct IdxStatement {
8476342292Scy  int iId;                        /* Statement number */
8477342292Scy  char *zSql;                     /* SQL statement */
8478342292Scy  char *zIdx;                     /* Indexes */
8479342292Scy  char *zEQP;                     /* Plan */
8480342292Scy  IdxStatement *pNext;
8481342292Scy};
8482342292Scy
8483342292Scy
8484342292Scy/*
8485342292Scy** A hash table for storing strings. With space for a payload string
8486342292Scy** with each entry. Methods are:
8487342292Scy**
8488342292Scy**   idxHashInit()
8489342292Scy**   idxHashClear()
8490342292Scy**   idxHashAdd()
8491342292Scy**   idxHashSearch()
8492342292Scy*/
8493342292Scy#define IDX_HASH_SIZE 1023
8494342292Scytypedef struct IdxHashEntry IdxHashEntry;
8495342292Scytypedef struct IdxHash IdxHash;
8496342292Scystruct IdxHashEntry {
8497342292Scy  char *zKey;                     /* nul-terminated key */
8498342292Scy  char *zVal;                     /* nul-terminated value string */
8499342292Scy  char *zVal2;                    /* nul-terminated value string 2 */
8500342292Scy  IdxHashEntry *pHashNext;        /* Next entry in same hash bucket */
8501342292Scy  IdxHashEntry *pNext;            /* Next entry in hash */
8502342292Scy};
8503342292Scystruct IdxHash {
8504342292Scy  IdxHashEntry *pFirst;
8505342292Scy  IdxHashEntry *aHash[IDX_HASH_SIZE];
8506342292Scy};
8507342292Scy
8508342292Scy/*
8509342292Scy** sqlite3expert object.
8510342292Scy*/
8511342292Scystruct sqlite3expert {
8512342292Scy  int iSample;                    /* Percentage of tables to sample for stat1 */
8513342292Scy  sqlite3 *db;                    /* User database */
8514342292Scy  sqlite3 *dbm;                   /* In-memory db for this analysis */
8515342292Scy  sqlite3 *dbv;                   /* Vtab schema for this analysis */
8516342292Scy  IdxTable *pTable;               /* List of all IdxTable objects */
8517342292Scy  IdxScan *pScan;                 /* List of scan objects */
8518342292Scy  IdxWrite *pWrite;               /* List of write objects */
8519342292Scy  IdxStatement *pStatement;       /* List of IdxStatement objects */
8520342292Scy  int bRun;                       /* True once analysis has run */
8521342292Scy  char **pzErrmsg;
8522342292Scy  int rc;                         /* Error code from whereinfo hook */
8523342292Scy  IdxHash hIdx;                   /* Hash containing all candidate indexes */
8524342292Scy  char *zCandidates;              /* For EXPERT_REPORT_CANDIDATES */
8525342292Scy};
8526342292Scy
8527342292Scy
8528342292Scy/*
8529342292Scy** Allocate and return nByte bytes of zeroed memory using sqlite3_malloc().
8530342292Scy** If the allocation fails, set *pRc to SQLITE_NOMEM and return NULL.
8531342292Scy*/
8532342292Scystatic void *idxMalloc(int *pRc, int nByte){
8533342292Scy  void *pRet;
8534342292Scy  assert( *pRc==SQLITE_OK );
8535342292Scy  assert( nByte>0 );
8536342292Scy  pRet = sqlite3_malloc(nByte);
8537342292Scy  if( pRet ){
8538342292Scy    memset(pRet, 0, nByte);
8539342292Scy  }else{
8540342292Scy    *pRc = SQLITE_NOMEM;
8541342292Scy  }
8542342292Scy  return pRet;
8543342292Scy}
8544342292Scy
8545342292Scy/*
8546342292Scy** Initialize an IdxHash hash table.
8547342292Scy*/
8548342292Scystatic void idxHashInit(IdxHash *pHash){
8549342292Scy  memset(pHash, 0, sizeof(IdxHash));
8550342292Scy}
8551342292Scy
8552342292Scy/*
8553342292Scy** Reset an IdxHash hash table.
8554342292Scy*/
8555342292Scystatic void idxHashClear(IdxHash *pHash){
8556342292Scy  int i;
8557342292Scy  for(i=0; i<IDX_HASH_SIZE; i++){
8558342292Scy    IdxHashEntry *pEntry;
8559342292Scy    IdxHashEntry *pNext;
8560342292Scy    for(pEntry=pHash->aHash[i]; pEntry; pEntry=pNext){
8561342292Scy      pNext = pEntry->pHashNext;
8562342292Scy      sqlite3_free(pEntry->zVal2);
8563342292Scy      sqlite3_free(pEntry);
8564342292Scy    }
8565342292Scy  }
8566342292Scy  memset(pHash, 0, sizeof(IdxHash));
8567342292Scy}
8568342292Scy
8569342292Scy/*
8570342292Scy** Return the index of the hash bucket that the string specified by the
8571342292Scy** arguments to this function belongs.
8572342292Scy*/
8573342292Scystatic int idxHashString(const char *z, int n){
8574342292Scy  unsigned int ret = 0;
8575342292Scy  int i;
8576342292Scy  for(i=0; i<n; i++){
8577342292Scy    ret += (ret<<3) + (unsigned char)(z[i]);
8578342292Scy  }
8579342292Scy  return (int)(ret % IDX_HASH_SIZE);
8580342292Scy}
8581342292Scy
8582342292Scy/*
8583342292Scy** If zKey is already present in the hash table, return non-zero and do
8584342292Scy** nothing. Otherwise, add an entry with key zKey and payload string zVal to
8585342292Scy** the hash table passed as the second argument.
8586342292Scy*/
8587342292Scystatic int idxHashAdd(
8588342292Scy  int *pRc,
8589342292Scy  IdxHash *pHash,
8590342292Scy  const char *zKey,
8591342292Scy  const char *zVal
8592342292Scy){
8593342292Scy  int nKey = STRLEN(zKey);
8594342292Scy  int iHash = idxHashString(zKey, nKey);
8595342292Scy  int nVal = (zVal ? STRLEN(zVal) : 0);
8596342292Scy  IdxHashEntry *pEntry;
8597342292Scy  assert( iHash>=0 );
8598342292Scy  for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){
8599342292Scy    if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){
8600342292Scy      return 1;
8601342292Scy    }
8602342292Scy  }
8603342292Scy  pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + nKey+1 + nVal+1);
8604342292Scy  if( pEntry ){
8605342292Scy    pEntry->zKey = (char*)&pEntry[1];
8606342292Scy    memcpy(pEntry->zKey, zKey, nKey);
8607342292Scy    if( zVal ){
8608342292Scy      pEntry->zVal = &pEntry->zKey[nKey+1];
8609342292Scy      memcpy(pEntry->zVal, zVal, nVal);
8610342292Scy    }
8611342292Scy    pEntry->pHashNext = pHash->aHash[iHash];
8612342292Scy    pHash->aHash[iHash] = pEntry;
8613342292Scy
8614342292Scy    pEntry->pNext = pHash->pFirst;
8615342292Scy    pHash->pFirst = pEntry;
8616342292Scy  }
8617342292Scy  return 0;
8618342292Scy}
8619342292Scy
8620342292Scy/*
8621342292Scy** If zKey/nKey is present in the hash table, return a pointer to the
8622342292Scy** hash-entry object.
8623342292Scy*/
8624342292Scystatic IdxHashEntry *idxHashFind(IdxHash *pHash, const char *zKey, int nKey){
8625342292Scy  int iHash;
8626342292Scy  IdxHashEntry *pEntry;
8627342292Scy  if( nKey<0 ) nKey = STRLEN(zKey);
8628342292Scy  iHash = idxHashString(zKey, nKey);
8629342292Scy  assert( iHash>=0 );
8630342292Scy  for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){
8631342292Scy    if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){
8632342292Scy      return pEntry;
8633342292Scy    }
8634342292Scy  }
8635342292Scy  return 0;
8636342292Scy}
8637342292Scy
8638342292Scy/*
8639342292Scy** If the hash table contains an entry with a key equal to the string
8640342292Scy** passed as the final two arguments to this function, return a pointer
8641342292Scy** to the payload string. Otherwise, if zKey/nKey is not present in the
8642342292Scy** hash table, return NULL.
8643342292Scy*/
8644342292Scystatic const char *idxHashSearch(IdxHash *pHash, const char *zKey, int nKey){
8645342292Scy  IdxHashEntry *pEntry = idxHashFind(pHash, zKey, nKey);
8646342292Scy  if( pEntry ) return pEntry->zVal;
8647342292Scy  return 0;
8648342292Scy}
8649342292Scy
8650342292Scy/*
8651342292Scy** Allocate and return a new IdxConstraint object. Set the IdxConstraint.zColl
8652342292Scy** variable to point to a copy of nul-terminated string zColl.
8653342292Scy*/
8654342292Scystatic IdxConstraint *idxNewConstraint(int *pRc, const char *zColl){
8655342292Scy  IdxConstraint *pNew;
8656342292Scy  int nColl = STRLEN(zColl);
8657342292Scy
8658342292Scy  assert( *pRc==SQLITE_OK );
8659342292Scy  pNew = (IdxConstraint*)idxMalloc(pRc, sizeof(IdxConstraint) * nColl + 1);
8660342292Scy  if( pNew ){
8661342292Scy    pNew->zColl = (char*)&pNew[1];
8662342292Scy    memcpy(pNew->zColl, zColl, nColl+1);
8663342292Scy  }
8664342292Scy  return pNew;
8665342292Scy}
8666342292Scy
8667342292Scy/*
8668342292Scy** An error associated with database handle db has just occurred. Pass
8669342292Scy** the error message to callback function xOut.
8670342292Scy*/
8671342292Scystatic void idxDatabaseError(
8672342292Scy  sqlite3 *db,                    /* Database handle */
8673342292Scy  char **pzErrmsg                 /* Write error here */
8674342292Scy){
8675342292Scy  *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db));
8676342292Scy}
8677342292Scy
8678342292Scy/*
8679342292Scy** Prepare an SQL statement.
8680342292Scy*/
8681342292Scystatic int idxPrepareStmt(
8682342292Scy  sqlite3 *db,                    /* Database handle to compile against */
8683342292Scy  sqlite3_stmt **ppStmt,          /* OUT: Compiled SQL statement */
8684342292Scy  char **pzErrmsg,                /* OUT: sqlite3_malloc()ed error message */
8685342292Scy  const char *zSql                /* SQL statement to compile */
8686342292Scy){
8687342292Scy  int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
8688342292Scy  if( rc!=SQLITE_OK ){
8689342292Scy    *ppStmt = 0;
8690342292Scy    idxDatabaseError(db, pzErrmsg);
8691342292Scy  }
8692342292Scy  return rc;
8693342292Scy}
8694342292Scy
8695342292Scy/*
8696342292Scy** Prepare an SQL statement using the results of a printf() formatting.
8697342292Scy*/
8698342292Scystatic int idxPrintfPrepareStmt(
8699342292Scy  sqlite3 *db,                    /* Database handle to compile against */
8700342292Scy  sqlite3_stmt **ppStmt,          /* OUT: Compiled SQL statement */
8701342292Scy  char **pzErrmsg,                /* OUT: sqlite3_malloc()ed error message */
8702342292Scy  const char *zFmt,               /* printf() format of SQL statement */
8703342292Scy  ...                             /* Trailing printf() arguments */
8704342292Scy){
8705342292Scy  va_list ap;
8706342292Scy  int rc;
8707342292Scy  char *zSql;
8708342292Scy  va_start(ap, zFmt);
8709342292Scy  zSql = sqlite3_vmprintf(zFmt, ap);
8710342292Scy  if( zSql==0 ){
8711342292Scy    rc = SQLITE_NOMEM;
8712342292Scy  }else{
8713342292Scy    rc = idxPrepareStmt(db, ppStmt, pzErrmsg, zSql);
8714342292Scy    sqlite3_free(zSql);
8715342292Scy  }
8716342292Scy  va_end(ap);
8717342292Scy  return rc;
8718342292Scy}
8719342292Scy
8720342292Scy
8721342292Scy/*************************************************************************
8722342292Scy** Beginning of virtual table implementation.
8723342292Scy*/
8724342292Scytypedef struct ExpertVtab ExpertVtab;
8725342292Scystruct ExpertVtab {
8726342292Scy  sqlite3_vtab base;
8727342292Scy  IdxTable *pTab;
8728342292Scy  sqlite3expert *pExpert;
8729342292Scy};
8730342292Scy
8731342292Scytypedef struct ExpertCsr ExpertCsr;
8732342292Scystruct ExpertCsr {
8733342292Scy  sqlite3_vtab_cursor base;
8734342292Scy  sqlite3_stmt *pData;
8735342292Scy};
8736342292Scy
8737342292Scystatic char *expertDequote(const char *zIn){
8738342292Scy  int n = STRLEN(zIn);
8739342292Scy  char *zRet = sqlite3_malloc(n);
8740342292Scy
8741342292Scy  assert( zIn[0]=='\'' );
8742342292Scy  assert( zIn[n-1]=='\'' );
8743342292Scy
8744342292Scy  if( zRet ){
8745342292Scy    int iOut = 0;
8746342292Scy    int iIn = 0;
8747342292Scy    for(iIn=1; iIn<(n-1); iIn++){
8748342292Scy      if( zIn[iIn]=='\'' ){
8749342292Scy        assert( zIn[iIn+1]=='\'' );
8750342292Scy        iIn++;
8751342292Scy      }
8752342292Scy      zRet[iOut++] = zIn[iIn];
8753342292Scy    }
8754342292Scy    zRet[iOut] = '\0';
8755342292Scy  }
8756342292Scy
8757342292Scy  return zRet;
8758342292Scy}
8759342292Scy
8760342292Scy/*
8761342292Scy** This function is the implementation of both the xConnect and xCreate
8762342292Scy** methods of the r-tree virtual table.
8763342292Scy**
8764342292Scy**   argv[0]   -> module name
8765342292Scy**   argv[1]   -> database name
8766342292Scy**   argv[2]   -> table name
8767342292Scy**   argv[...] -> column names...
8768342292Scy*/
8769342292Scystatic int expertConnect(
8770342292Scy  sqlite3 *db,
8771342292Scy  void *pAux,
8772342292Scy  int argc, const char *const*argv,
8773342292Scy  sqlite3_vtab **ppVtab,
8774342292Scy  char **pzErr
8775342292Scy){
8776342292Scy  sqlite3expert *pExpert = (sqlite3expert*)pAux;
8777342292Scy  ExpertVtab *p = 0;
8778342292Scy  int rc;
8779342292Scy
8780342292Scy  if( argc!=4 ){
8781342292Scy    *pzErr = sqlite3_mprintf("internal error!");
8782342292Scy    rc = SQLITE_ERROR;
8783342292Scy  }else{
8784342292Scy    char *zCreateTable = expertDequote(argv[3]);
8785342292Scy    if( zCreateTable ){
8786342292Scy      rc = sqlite3_declare_vtab(db, zCreateTable);
8787342292Scy      if( rc==SQLITE_OK ){
8788342292Scy        p = idxMalloc(&rc, sizeof(ExpertVtab));
8789342292Scy      }
8790342292Scy      if( rc==SQLITE_OK ){
8791342292Scy        p->pExpert = pExpert;
8792342292Scy        p->pTab = pExpert->pTable;
8793342292Scy        assert( sqlite3_stricmp(p->pTab->zName, argv[2])==0 );
8794342292Scy      }
8795342292Scy      sqlite3_free(zCreateTable);
8796342292Scy    }else{
8797342292Scy      rc = SQLITE_NOMEM;
8798342292Scy    }
8799342292Scy  }
8800342292Scy
8801342292Scy  *ppVtab = (sqlite3_vtab*)p;
8802342292Scy  return rc;
8803342292Scy}
8804342292Scy
8805342292Scystatic int expertDisconnect(sqlite3_vtab *pVtab){
8806342292Scy  ExpertVtab *p = (ExpertVtab*)pVtab;
8807342292Scy  sqlite3_free(p);
8808342292Scy  return SQLITE_OK;
8809342292Scy}
8810342292Scy
8811342292Scystatic int expertBestIndex(sqlite3_vtab *pVtab, sqlite3_index_info *pIdxInfo){
8812342292Scy  ExpertVtab *p = (ExpertVtab*)pVtab;
8813342292Scy  int rc = SQLITE_OK;
8814342292Scy  int n = 0;
8815342292Scy  IdxScan *pScan;
8816342292Scy  const int opmask =
8817342292Scy    SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_GT |
8818342292Scy    SQLITE_INDEX_CONSTRAINT_LT | SQLITE_INDEX_CONSTRAINT_GE |
8819342292Scy    SQLITE_INDEX_CONSTRAINT_LE;
8820342292Scy
8821342292Scy  pScan = idxMalloc(&rc, sizeof(IdxScan));
8822342292Scy  if( pScan ){
8823342292Scy    int i;
8824342292Scy
8825342292Scy    /* Link the new scan object into the list */
8826342292Scy    pScan->pTab = p->pTab;
8827342292Scy    pScan->pNextScan = p->pExpert->pScan;
8828342292Scy    p->pExpert->pScan = pScan;
8829342292Scy
8830342292Scy    /* Add the constraints to the IdxScan object */
8831342292Scy    for(i=0; i<pIdxInfo->nConstraint; i++){
8832342292Scy      struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
8833342292Scy      if( pCons->usable
8834342292Scy       && pCons->iColumn>=0
8835342292Scy       && p->pTab->aCol[pCons->iColumn].iPk==0
8836342292Scy       && (pCons->op & opmask)
8837342292Scy      ){
8838342292Scy        IdxConstraint *pNew;
8839342292Scy        const char *zColl = sqlite3_vtab_collation(pIdxInfo, i);
8840342292Scy        pNew = idxNewConstraint(&rc, zColl);
8841342292Scy        if( pNew ){
8842342292Scy          pNew->iCol = pCons->iColumn;
8843342292Scy          if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
8844342292Scy            pNew->pNext = pScan->pEq;
8845342292Scy            pScan->pEq = pNew;
8846342292Scy          }else{
8847342292Scy            pNew->bRange = 1;
8848342292Scy            pNew->pNext = pScan->pRange;
8849342292Scy            pScan->pRange = pNew;
8850342292Scy          }
8851342292Scy        }
8852342292Scy        n++;
8853342292Scy        pIdxInfo->aConstraintUsage[i].argvIndex = n;
8854342292Scy      }
8855342292Scy    }
8856342292Scy
8857342292Scy    /* Add the ORDER BY to the IdxScan object */
8858342292Scy    for(i=pIdxInfo->nOrderBy-1; i>=0; i--){
8859342292Scy      int iCol = pIdxInfo->aOrderBy[i].iColumn;
8860342292Scy      if( iCol>=0 ){
8861342292Scy        IdxConstraint *pNew = idxNewConstraint(&rc, p->pTab->aCol[iCol].zColl);
8862342292Scy        if( pNew ){
8863342292Scy          pNew->iCol = iCol;
8864342292Scy          pNew->bDesc = pIdxInfo->aOrderBy[i].desc;
8865342292Scy          pNew->pNext = pScan->pOrder;
8866342292Scy          pNew->pLink = pScan->pOrder;
8867342292Scy          pScan->pOrder = pNew;
8868342292Scy          n++;
8869342292Scy        }
8870342292Scy      }
8871342292Scy    }
8872342292Scy  }
8873342292Scy
8874342292Scy  pIdxInfo->estimatedCost = 1000000.0 / (n+1);
8875342292Scy  return rc;
8876342292Scy}
8877342292Scy
8878342292Scystatic int expertUpdate(
8879342292Scy  sqlite3_vtab *pVtab,
8880342292Scy  int nData,
8881342292Scy  sqlite3_value **azData,
8882342292Scy  sqlite_int64 *pRowid
8883342292Scy){
8884342292Scy  (void)pVtab;
8885342292Scy  (void)nData;
8886342292Scy  (void)azData;
8887342292Scy  (void)pRowid;
8888342292Scy  return SQLITE_OK;
8889342292Scy}
8890342292Scy
8891342292Scy/*
8892342292Scy** Virtual table module xOpen method.
8893342292Scy*/
8894342292Scystatic int expertOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
8895342292Scy  int rc = SQLITE_OK;
8896342292Scy  ExpertCsr *pCsr;
8897342292Scy  (void)pVTab;
8898342292Scy  pCsr = idxMalloc(&rc, sizeof(ExpertCsr));
8899342292Scy  *ppCursor = (sqlite3_vtab_cursor*)pCsr;
8900342292Scy  return rc;
8901342292Scy}
8902342292Scy
8903342292Scy/*
8904342292Scy** Virtual table module xClose method.
8905342292Scy*/
8906342292Scystatic int expertClose(sqlite3_vtab_cursor *cur){
8907342292Scy  ExpertCsr *pCsr = (ExpertCsr*)cur;
8908342292Scy  sqlite3_finalize(pCsr->pData);
8909342292Scy  sqlite3_free(pCsr);
8910342292Scy  return SQLITE_OK;
8911342292Scy}
8912342292Scy
8913342292Scy/*
8914342292Scy** Virtual table module xEof method.
8915342292Scy**
8916342292Scy** Return non-zero if the cursor does not currently point to a valid
8917342292Scy** record (i.e if the scan has finished), or zero otherwise.
8918342292Scy*/
8919342292Scystatic int expertEof(sqlite3_vtab_cursor *cur){
8920342292Scy  ExpertCsr *pCsr = (ExpertCsr*)cur;
8921342292Scy  return pCsr->pData==0;
8922342292Scy}
8923342292Scy
8924342292Scy/*
8925342292Scy** Virtual table module xNext method.
8926342292Scy*/
8927342292Scystatic int expertNext(sqlite3_vtab_cursor *cur){
8928342292Scy  ExpertCsr *pCsr = (ExpertCsr*)cur;
8929342292Scy  int rc = SQLITE_OK;
8930342292Scy
8931342292Scy  assert( pCsr->pData );
8932342292Scy  rc = sqlite3_step(pCsr->pData);
8933342292Scy  if( rc!=SQLITE_ROW ){
8934342292Scy    rc = sqlite3_finalize(pCsr->pData);
8935342292Scy    pCsr->pData = 0;
8936342292Scy  }else{
8937342292Scy    rc = SQLITE_OK;
8938342292Scy  }
8939342292Scy
8940342292Scy  return rc;
8941342292Scy}
8942342292Scy
8943342292Scy/*
8944342292Scy** Virtual table module xRowid method.
8945342292Scy*/
8946342292Scystatic int expertRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
8947342292Scy  (void)cur;
8948342292Scy  *pRowid = 0;
8949342292Scy  return SQLITE_OK;
8950342292Scy}
8951342292Scy
8952342292Scy/*
8953342292Scy** Virtual table module xColumn method.
8954342292Scy*/
8955342292Scystatic int expertColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
8956342292Scy  ExpertCsr *pCsr = (ExpertCsr*)cur;
8957342292Scy  sqlite3_value *pVal;
8958342292Scy  pVal = sqlite3_column_value(pCsr->pData, i);
8959342292Scy  if( pVal ){
8960342292Scy    sqlite3_result_value(ctx, pVal);
8961342292Scy  }
8962342292Scy  return SQLITE_OK;
8963342292Scy}
8964342292Scy
8965342292Scy/*
8966342292Scy** Virtual table module xFilter method.
8967342292Scy*/
8968342292Scystatic int expertFilter(
8969342292Scy  sqlite3_vtab_cursor *cur,
8970342292Scy  int idxNum, const char *idxStr,
8971342292Scy  int argc, sqlite3_value **argv
8972342292Scy){
8973342292Scy  ExpertCsr *pCsr = (ExpertCsr*)cur;
8974342292Scy  ExpertVtab *pVtab = (ExpertVtab*)(cur->pVtab);
8975342292Scy  sqlite3expert *pExpert = pVtab->pExpert;
8976342292Scy  int rc;
8977342292Scy
8978342292Scy  (void)idxNum;
8979342292Scy  (void)idxStr;
8980342292Scy  (void)argc;
8981342292Scy  (void)argv;
8982342292Scy  rc = sqlite3_finalize(pCsr->pData);
8983342292Scy  pCsr->pData = 0;
8984342292Scy  if( rc==SQLITE_OK ){
8985342292Scy    rc = idxPrintfPrepareStmt(pExpert->db, &pCsr->pData, &pVtab->base.zErrMsg,
8986342292Scy        "SELECT * FROM main.%Q WHERE sample()", pVtab->pTab->zName
8987342292Scy    );
8988342292Scy  }
8989342292Scy
8990342292Scy  if( rc==SQLITE_OK ){
8991342292Scy    rc = expertNext(cur);
8992342292Scy  }
8993342292Scy  return rc;
8994342292Scy}
8995342292Scy
8996342292Scystatic int idxRegisterVtab(sqlite3expert *p){
8997342292Scy  static sqlite3_module expertModule = {
8998342292Scy    2,                            /* iVersion */
8999342292Scy    expertConnect,                /* xCreate - create a table */
9000342292Scy    expertConnect,                /* xConnect - connect to an existing table */
9001342292Scy    expertBestIndex,              /* xBestIndex - Determine search strategy */
9002342292Scy    expertDisconnect,             /* xDisconnect - Disconnect from a table */
9003342292Scy    expertDisconnect,             /* xDestroy - Drop a table */
9004342292Scy    expertOpen,                   /* xOpen - open a cursor */
9005342292Scy    expertClose,                  /* xClose - close a cursor */
9006342292Scy    expertFilter,                 /* xFilter - configure scan constraints */
9007342292Scy    expertNext,                   /* xNext - advance a cursor */
9008342292Scy    expertEof,                    /* xEof */
9009342292Scy    expertColumn,                 /* xColumn - read data */
9010342292Scy    expertRowid,                  /* xRowid - read data */
9011342292Scy    expertUpdate,                 /* xUpdate - write data */
9012342292Scy    0,                            /* xBegin - begin transaction */
9013342292Scy    0,                            /* xSync - sync transaction */
9014342292Scy    0,                            /* xCommit - commit transaction */
9015342292Scy    0,                            /* xRollback - rollback transaction */
9016342292Scy    0,                            /* xFindFunction - function overloading */
9017342292Scy    0,                            /* xRename - rename the table */
9018342292Scy    0,                            /* xSavepoint */
9019342292Scy    0,                            /* xRelease */
9020342292Scy    0,                            /* xRollbackTo */
9021342292Scy    0,                            /* xShadowName */
9022342292Scy  };
9023342292Scy
9024342292Scy  return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p);
9025342292Scy}
9026342292Scy/*
9027342292Scy** End of virtual table implementation.
9028342292Scy*************************************************************************/
9029342292Scy/*
9030342292Scy** Finalize SQL statement pStmt. If (*pRc) is SQLITE_OK when this function
9031342292Scy** is called, set it to the return value of sqlite3_finalize() before
9032342292Scy** returning. Otherwise, discard the sqlite3_finalize() return value.
9033342292Scy*/
9034342292Scystatic void idxFinalize(int *pRc, sqlite3_stmt *pStmt){
9035342292Scy  int rc = sqlite3_finalize(pStmt);
9036342292Scy  if( *pRc==SQLITE_OK ) *pRc = rc;
9037342292Scy}
9038342292Scy
9039342292Scy/*
9040342292Scy** Attempt to allocate an IdxTable structure corresponding to table zTab
9041342292Scy** in the main database of connection db. If successful, set (*ppOut) to
9042342292Scy** point to the new object and return SQLITE_OK. Otherwise, return an
9043342292Scy** SQLite error code and set (*ppOut) to NULL. In this case *pzErrmsg may be
9044342292Scy** set to point to an error string.
9045342292Scy**
9046342292Scy** It is the responsibility of the caller to eventually free either the
9047342292Scy** IdxTable object or error message using sqlite3_free().
9048342292Scy*/
9049342292Scystatic int idxGetTableInfo(
9050342292Scy  sqlite3 *db,                    /* Database connection to read details from */
9051342292Scy  const char *zTab,               /* Table name */
9052342292Scy  IdxTable **ppOut,               /* OUT: New object (if successful) */
9053342292Scy  char **pzErrmsg                 /* OUT: Error message (if not) */
9054342292Scy){
9055342292Scy  sqlite3_stmt *p1 = 0;
9056342292Scy  int nCol = 0;
9057342292Scy  int nTab = STRLEN(zTab);
9058342292Scy  int nByte = sizeof(IdxTable) + nTab + 1;
9059342292Scy  IdxTable *pNew = 0;
9060342292Scy  int rc, rc2;
9061342292Scy  char *pCsr = 0;
9062369950Scy  int nPk = 0;
9063342292Scy
9064369951Scy  rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_xinfo=%Q", zTab);
9065342292Scy  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
9066342292Scy    const char *zCol = (const char*)sqlite3_column_text(p1, 1);
9067342292Scy    nByte += 1 + STRLEN(zCol);
9068342292Scy    rc = sqlite3_table_column_metadata(
9069342292Scy        db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
9070342292Scy    );
9071342292Scy    nByte += 1 + STRLEN(zCol);
9072342292Scy    nCol++;
9073369950Scy    nPk += (sqlite3_column_int(p1, 5)>0);
9074342292Scy  }
9075342292Scy  rc2 = sqlite3_reset(p1);
9076342292Scy  if( rc==SQLITE_OK ) rc = rc2;
9077342292Scy
9078342292Scy  nByte += sizeof(IdxColumn) * nCol;
9079342292Scy  if( rc==SQLITE_OK ){
9080342292Scy    pNew = idxMalloc(&rc, nByte);
9081342292Scy  }
9082342292Scy  if( rc==SQLITE_OK ){
9083342292Scy    pNew->aCol = (IdxColumn*)&pNew[1];
9084342292Scy    pNew->nCol = nCol;
9085342292Scy    pCsr = (char*)&pNew->aCol[nCol];
9086342292Scy  }
9087342292Scy
9088342292Scy  nCol = 0;
9089342292Scy  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
9090342292Scy    const char *zCol = (const char*)sqlite3_column_text(p1, 1);
9091342292Scy    int nCopy = STRLEN(zCol) + 1;
9092342292Scy    pNew->aCol[nCol].zName = pCsr;
9093369950Scy    pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1);
9094342292Scy    memcpy(pCsr, zCol, nCopy);
9095342292Scy    pCsr += nCopy;
9096342292Scy
9097342292Scy    rc = sqlite3_table_column_metadata(
9098342292Scy        db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
9099342292Scy    );
9100342292Scy    if( rc==SQLITE_OK ){
9101342292Scy      nCopy = STRLEN(zCol) + 1;
9102342292Scy      pNew->aCol[nCol].zColl = pCsr;
9103342292Scy      memcpy(pCsr, zCol, nCopy);
9104342292Scy      pCsr += nCopy;
9105342292Scy    }
9106342292Scy
9107342292Scy    nCol++;
9108342292Scy  }
9109342292Scy  idxFinalize(&rc, p1);
9110342292Scy
9111342292Scy  if( rc!=SQLITE_OK ){
9112342292Scy    sqlite3_free(pNew);
9113342292Scy    pNew = 0;
9114342292Scy  }else{
9115342292Scy    pNew->zName = pCsr;
9116342292Scy    memcpy(pNew->zName, zTab, nTab+1);
9117342292Scy  }
9118342292Scy
9119342292Scy  *ppOut = pNew;
9120342292Scy  return rc;
9121342292Scy}
9122342292Scy
9123342292Scy/*
9124342292Scy** This function is a no-op if *pRc is set to anything other than
9125342292Scy** SQLITE_OK when it is called.
9126342292Scy**
9127342292Scy** If *pRc is initially set to SQLITE_OK, then the text specified by
9128342292Scy** the printf() style arguments is appended to zIn and the result returned
9129342292Scy** in a buffer allocated by sqlite3_malloc(). sqlite3_free() is called on
9130342292Scy** zIn before returning.
9131342292Scy*/
9132342292Scystatic char *idxAppendText(int *pRc, char *zIn, const char *zFmt, ...){
9133342292Scy  va_list ap;
9134342292Scy  char *zAppend = 0;
9135342292Scy  char *zRet = 0;
9136342292Scy  int nIn = zIn ? STRLEN(zIn) : 0;
9137342292Scy  int nAppend = 0;
9138342292Scy  va_start(ap, zFmt);
9139342292Scy  if( *pRc==SQLITE_OK ){
9140342292Scy    zAppend = sqlite3_vmprintf(zFmt, ap);
9141342292Scy    if( zAppend ){
9142342292Scy      nAppend = STRLEN(zAppend);
9143342292Scy      zRet = (char*)sqlite3_malloc(nIn + nAppend + 1);
9144342292Scy    }
9145342292Scy    if( zAppend && zRet ){
9146342292Scy      if( nIn ) memcpy(zRet, zIn, nIn);
9147342292Scy      memcpy(&zRet[nIn], zAppend, nAppend+1);
9148342292Scy    }else{
9149342292Scy      sqlite3_free(zRet);
9150342292Scy      zRet = 0;
9151342292Scy      *pRc = SQLITE_NOMEM;
9152342292Scy    }
9153342292Scy    sqlite3_free(zAppend);
9154342292Scy    sqlite3_free(zIn);
9155342292Scy  }
9156342292Scy  va_end(ap);
9157342292Scy  return zRet;
9158342292Scy}
9159342292Scy
9160342292Scy/*
9161342292Scy** Return true if zId must be quoted in order to use it as an SQL
9162342292Scy** identifier, or false otherwise.
9163342292Scy*/
9164342292Scystatic int idxIdentifierRequiresQuotes(const char *zId){
9165342292Scy  int i;
9166342292Scy  for(i=0; zId[i]; i++){
9167342292Scy    if( !(zId[i]=='_')
9168342292Scy     && !(zId[i]>='0' && zId[i]<='9')
9169342292Scy     && !(zId[i]>='a' && zId[i]<='z')
9170342292Scy     && !(zId[i]>='A' && zId[i]<='Z')
9171342292Scy    ){
9172342292Scy      return 1;
9173342292Scy    }
9174342292Scy  }
9175342292Scy  return 0;
9176342292Scy}
9177342292Scy
9178342292Scy/*
9179342292Scy** This function appends an index column definition suitable for constraint
9180342292Scy** pCons to the string passed as zIn and returns the result.
9181342292Scy*/
9182342292Scystatic char *idxAppendColDefn(
9183342292Scy  int *pRc,                       /* IN/OUT: Error code */
9184342292Scy  char *zIn,                      /* Column defn accumulated so far */
9185342292Scy  IdxTable *pTab,                 /* Table index will be created on */
9186342292Scy  IdxConstraint *pCons
9187342292Scy){
9188342292Scy  char *zRet = zIn;
9189342292Scy  IdxColumn *p = &pTab->aCol[pCons->iCol];
9190342292Scy  if( zRet ) zRet = idxAppendText(pRc, zRet, ", ");
9191342292Scy
9192342292Scy  if( idxIdentifierRequiresQuotes(p->zName) ){
9193342292Scy    zRet = idxAppendText(pRc, zRet, "%Q", p->zName);
9194342292Scy  }else{
9195342292Scy    zRet = idxAppendText(pRc, zRet, "%s", p->zName);
9196342292Scy  }
9197342292Scy
9198342292Scy  if( sqlite3_stricmp(p->zColl, pCons->zColl) ){
9199342292Scy    if( idxIdentifierRequiresQuotes(pCons->zColl) ){
9200342292Scy      zRet = idxAppendText(pRc, zRet, " COLLATE %Q", pCons->zColl);
9201342292Scy    }else{
9202342292Scy      zRet = idxAppendText(pRc, zRet, " COLLATE %s", pCons->zColl);
9203342292Scy    }
9204342292Scy  }
9205342292Scy
9206342292Scy  if( pCons->bDesc ){
9207342292Scy    zRet = idxAppendText(pRc, zRet, " DESC");
9208342292Scy  }
9209342292Scy  return zRet;
9210342292Scy}
9211342292Scy
9212342292Scy/*
9213342292Scy** Search database dbm for an index compatible with the one idxCreateFromCons()
9214342292Scy** would create from arguments pScan, pEq and pTail. If no error occurs and
9215342292Scy** such an index is found, return non-zero. Or, if no such index is found,
9216342292Scy** return zero.
9217342292Scy**
9218342292Scy** If an error occurs, set *pRc to an SQLite error code and return zero.
9219342292Scy*/
9220342292Scystatic int idxFindCompatible(
9221342292Scy  int *pRc,                       /* OUT: Error code */
9222342292Scy  sqlite3* dbm,                   /* Database to search */
9223342292Scy  IdxScan *pScan,                 /* Scan for table to search for index on */
9224342292Scy  IdxConstraint *pEq,             /* List of == constraints */
9225342292Scy  IdxConstraint *pTail            /* List of range constraints */
9226342292Scy){
9227342292Scy  const char *zTbl = pScan->pTab->zName;
9228342292Scy  sqlite3_stmt *pIdxList = 0;
9229342292Scy  IdxConstraint *pIter;
9230342292Scy  int nEq = 0;                    /* Number of elements in pEq */
9231342292Scy  int rc;
9232342292Scy
9233342292Scy  /* Count the elements in list pEq */
9234342292Scy  for(pIter=pEq; pIter; pIter=pIter->pLink) nEq++;
9235342292Scy
9236342292Scy  rc = idxPrintfPrepareStmt(dbm, &pIdxList, 0, "PRAGMA index_list=%Q", zTbl);
9237342292Scy  while( rc==SQLITE_OK && sqlite3_step(pIdxList)==SQLITE_ROW ){
9238342292Scy    int bMatch = 1;
9239342292Scy    IdxConstraint *pT = pTail;
9240342292Scy    sqlite3_stmt *pInfo = 0;
9241342292Scy    const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1);
9242342292Scy
9243342292Scy    /* Zero the IdxConstraint.bFlag values in the pEq list */
9244342292Scy    for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0;
9245342292Scy
9246342292Scy    rc = idxPrintfPrepareStmt(dbm, &pInfo, 0, "PRAGMA index_xInfo=%Q", zIdx);
9247342292Scy    while( rc==SQLITE_OK && sqlite3_step(pInfo)==SQLITE_ROW ){
9248342292Scy      int iIdx = sqlite3_column_int(pInfo, 0);
9249342292Scy      int iCol = sqlite3_column_int(pInfo, 1);
9250342292Scy      const char *zColl = (const char*)sqlite3_column_text(pInfo, 4);
9251342292Scy
9252342292Scy      if( iIdx<nEq ){
9253342292Scy        for(pIter=pEq; pIter; pIter=pIter->pLink){
9254342292Scy          if( pIter->bFlag ) continue;
9255342292Scy          if( pIter->iCol!=iCol ) continue;
9256342292Scy          if( sqlite3_stricmp(pIter->zColl, zColl) ) continue;
9257342292Scy          pIter->bFlag = 1;
9258342292Scy          break;
9259342292Scy        }
9260342292Scy        if( pIter==0 ){
9261342292Scy          bMatch = 0;
9262342292Scy          break;
9263342292Scy        }
9264342292Scy      }else{
9265342292Scy        if( pT ){
9266342292Scy          if( pT->iCol!=iCol || sqlite3_stricmp(pT->zColl, zColl) ){
9267342292Scy            bMatch = 0;
9268342292Scy            break;
9269342292Scy          }
9270342292Scy          pT = pT->pLink;
9271342292Scy        }
9272342292Scy      }
9273342292Scy    }
9274342292Scy    idxFinalize(&rc, pInfo);
9275342292Scy
9276342292Scy    if( rc==SQLITE_OK && bMatch ){
9277342292Scy      sqlite3_finalize(pIdxList);
9278342292Scy      return 1;
9279342292Scy    }
9280342292Scy  }
9281342292Scy  idxFinalize(&rc, pIdxList);
9282342292Scy
9283342292Scy  *pRc = rc;
9284342292Scy  return 0;
9285342292Scy}
9286342292Scy
9287342292Scystatic int idxCreateFromCons(
9288342292Scy  sqlite3expert *p,
9289342292Scy  IdxScan *pScan,
9290342292Scy  IdxConstraint *pEq,
9291342292Scy  IdxConstraint *pTail
9292342292Scy){
9293342292Scy  sqlite3 *dbm = p->dbm;
9294342292Scy  int rc = SQLITE_OK;
9295342292Scy  if( (pEq || pTail) && 0==idxFindCompatible(&rc, dbm, pScan, pEq, pTail) ){
9296342292Scy    IdxTable *pTab = pScan->pTab;
9297342292Scy    char *zCols = 0;
9298342292Scy    char *zIdx = 0;
9299342292Scy    IdxConstraint *pCons;
9300342292Scy    unsigned int h = 0;
9301342292Scy    const char *zFmt;
9302342292Scy
9303342292Scy    for(pCons=pEq; pCons; pCons=pCons->pLink){
9304342292Scy      zCols = idxAppendColDefn(&rc, zCols, pTab, pCons);
9305342292Scy    }
9306342292Scy    for(pCons=pTail; pCons; pCons=pCons->pLink){
9307342292Scy      zCols = idxAppendColDefn(&rc, zCols, pTab, pCons);
9308342292Scy    }
9309342292Scy
9310342292Scy    if( rc==SQLITE_OK ){
9311342292Scy      /* Hash the list of columns to come up with a name for the index */
9312342292Scy      const char *zTable = pScan->pTab->zName;
9313342292Scy      char *zName;                /* Index name */
9314342292Scy      int i;
9315342292Scy      for(i=0; zCols[i]; i++){
9316342292Scy        h += ((h<<3) + zCols[i]);
9317342292Scy      }
9318342292Scy      zName = sqlite3_mprintf("%s_idx_%08x", zTable, h);
9319342292Scy      if( zName==0 ){
9320342292Scy        rc = SQLITE_NOMEM;
9321342292Scy      }else{
9322342292Scy        if( idxIdentifierRequiresQuotes(zTable) ){
9323342292Scy          zFmt = "CREATE INDEX '%q' ON %Q(%s)";
9324342292Scy        }else{
9325342292Scy          zFmt = "CREATE INDEX %s ON %s(%s)";
9326342292Scy        }
9327342292Scy        zIdx = sqlite3_mprintf(zFmt, zName, zTable, zCols);
9328342292Scy        if( !zIdx ){
9329342292Scy          rc = SQLITE_NOMEM;
9330342292Scy        }else{
9331342292Scy          rc = sqlite3_exec(dbm, zIdx, 0, 0, p->pzErrmsg);
9332342292Scy          idxHashAdd(&rc, &p->hIdx, zName, zIdx);
9333342292Scy        }
9334342292Scy        sqlite3_free(zName);
9335342292Scy        sqlite3_free(zIdx);
9336342292Scy      }
9337342292Scy    }
9338342292Scy
9339342292Scy    sqlite3_free(zCols);
9340342292Scy  }
9341342292Scy  return rc;
9342342292Scy}
9343342292Scy
9344342292Scy/*
9345342292Scy** Return true if list pList (linked by IdxConstraint.pLink) contains
9346342292Scy** a constraint compatible with *p. Otherwise return false.
9347342292Scy*/
9348342292Scystatic int idxFindConstraint(IdxConstraint *pList, IdxConstraint *p){
9349342292Scy  IdxConstraint *pCmp;
9350342292Scy  for(pCmp=pList; pCmp; pCmp=pCmp->pLink){
9351342292Scy    if( p->iCol==pCmp->iCol ) return 1;
9352342292Scy  }
9353342292Scy  return 0;
9354342292Scy}
9355342292Scy
9356342292Scystatic int idxCreateFromWhere(
9357342292Scy  sqlite3expert *p,
9358342292Scy  IdxScan *pScan,                 /* Create indexes for this scan */
9359342292Scy  IdxConstraint *pTail            /* range/ORDER BY constraints for inclusion */
9360342292Scy){
9361342292Scy  IdxConstraint *p1 = 0;
9362342292Scy  IdxConstraint *pCon;
9363342292Scy  int rc;
9364342292Scy
9365342292Scy  /* Gather up all the == constraints. */
9366342292Scy  for(pCon=pScan->pEq; pCon; pCon=pCon->pNext){
9367342292Scy    if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
9368342292Scy      pCon->pLink = p1;
9369342292Scy      p1 = pCon;
9370342292Scy    }
9371342292Scy  }
9372342292Scy
9373342292Scy  /* Create an index using the == constraints collected above. And the
9374342292Scy  ** range constraint/ORDER BY terms passed in by the caller, if any. */
9375342292Scy  rc = idxCreateFromCons(p, pScan, p1, pTail);
9376342292Scy
9377342292Scy  /* If no range/ORDER BY passed by the caller, create a version of the
9378342292Scy  ** index for each range constraint.  */
9379342292Scy  if( pTail==0 ){
9380342292Scy    for(pCon=pScan->pRange; rc==SQLITE_OK && pCon; pCon=pCon->pNext){
9381342292Scy      assert( pCon->pLink==0 );
9382342292Scy      if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
9383342292Scy        rc = idxCreateFromCons(p, pScan, p1, pCon);
9384342292Scy      }
9385342292Scy    }
9386342292Scy  }
9387342292Scy
9388342292Scy  return rc;
9389342292Scy}
9390342292Scy
9391342292Scy/*
9392342292Scy** Create candidate indexes in database [dbm] based on the data in
9393342292Scy** linked-list pScan.
9394342292Scy*/
9395342292Scystatic int idxCreateCandidates(sqlite3expert *p){
9396342292Scy  int rc = SQLITE_OK;
9397342292Scy  IdxScan *pIter;
9398342292Scy
9399342292Scy  for(pIter=p->pScan; pIter && rc==SQLITE_OK; pIter=pIter->pNextScan){
9400342292Scy    rc = idxCreateFromWhere(p, pIter, 0);
9401342292Scy    if( rc==SQLITE_OK && pIter->pOrder ){
9402342292Scy      rc = idxCreateFromWhere(p, pIter, pIter->pOrder);
9403342292Scy    }
9404342292Scy  }
9405342292Scy
9406342292Scy  return rc;
9407342292Scy}
9408342292Scy
9409342292Scy/*
9410342292Scy** Free all elements of the linked list starting at pConstraint.
9411342292Scy*/
9412342292Scystatic void idxConstraintFree(IdxConstraint *pConstraint){
9413342292Scy  IdxConstraint *pNext;
9414342292Scy  IdxConstraint *p;
9415342292Scy
9416342292Scy  for(p=pConstraint; p; p=pNext){
9417342292Scy    pNext = p->pNext;
9418342292Scy    sqlite3_free(p);
9419342292Scy  }
9420342292Scy}
9421342292Scy
9422342292Scy/*
9423342292Scy** Free all elements of the linked list starting from pScan up until pLast
9424342292Scy** (pLast is not freed).
9425342292Scy*/
9426342292Scystatic void idxScanFree(IdxScan *pScan, IdxScan *pLast){
9427342292Scy  IdxScan *p;
9428342292Scy  IdxScan *pNext;
9429342292Scy  for(p=pScan; p!=pLast; p=pNext){
9430342292Scy    pNext = p->pNextScan;
9431342292Scy    idxConstraintFree(p->pOrder);
9432342292Scy    idxConstraintFree(p->pEq);
9433342292Scy    idxConstraintFree(p->pRange);
9434342292Scy    sqlite3_free(p);
9435342292Scy  }
9436342292Scy}
9437342292Scy
9438342292Scy/*
9439342292Scy** Free all elements of the linked list starting from pStatement up
9440342292Scy** until pLast (pLast is not freed).
9441342292Scy*/
9442342292Scystatic void idxStatementFree(IdxStatement *pStatement, IdxStatement *pLast){
9443342292Scy  IdxStatement *p;
9444342292Scy  IdxStatement *pNext;
9445342292Scy  for(p=pStatement; p!=pLast; p=pNext){
9446342292Scy    pNext = p->pNext;
9447342292Scy    sqlite3_free(p->zEQP);
9448342292Scy    sqlite3_free(p->zIdx);
9449342292Scy    sqlite3_free(p);
9450342292Scy  }
9451342292Scy}
9452342292Scy
9453342292Scy/*
9454342292Scy** Free the linked list of IdxTable objects starting at pTab.
9455342292Scy*/
9456342292Scystatic void idxTableFree(IdxTable *pTab){
9457342292Scy  IdxTable *pIter;
9458342292Scy  IdxTable *pNext;
9459342292Scy  for(pIter=pTab; pIter; pIter=pNext){
9460342292Scy    pNext = pIter->pNext;
9461342292Scy    sqlite3_free(pIter);
9462342292Scy  }
9463342292Scy}
9464342292Scy
9465342292Scy/*
9466342292Scy** Free the linked list of IdxWrite objects starting at pTab.
9467342292Scy*/
9468342292Scystatic void idxWriteFree(IdxWrite *pTab){
9469342292Scy  IdxWrite *pIter;
9470342292Scy  IdxWrite *pNext;
9471342292Scy  for(pIter=pTab; pIter; pIter=pNext){
9472342292Scy    pNext = pIter->pNext;
9473342292Scy    sqlite3_free(pIter);
9474342292Scy  }
9475342292Scy}
9476342292Scy
9477342292Scy
9478342292Scy
9479342292Scy/*
9480342292Scy** This function is called after candidate indexes have been created. It
9481342292Scy** runs all the queries to see which indexes they prefer, and populates
9482342292Scy** IdxStatement.zIdx and IdxStatement.zEQP with the results.
9483342292Scy*/
9484342292Scyint idxFindIndexes(
9485342292Scy  sqlite3expert *p,
9486342292Scy  char **pzErr                         /* OUT: Error message (sqlite3_malloc) */
9487342292Scy){
9488342292Scy  IdxStatement *pStmt;
9489342292Scy  sqlite3 *dbm = p->dbm;
9490342292Scy  int rc = SQLITE_OK;
9491342292Scy
9492342292Scy  IdxHash hIdx;
9493342292Scy  idxHashInit(&hIdx);
9494342292Scy
9495342292Scy  for(pStmt=p->pStatement; rc==SQLITE_OK && pStmt; pStmt=pStmt->pNext){
9496342292Scy    IdxHashEntry *pEntry;
9497342292Scy    sqlite3_stmt *pExplain = 0;
9498342292Scy    idxHashClear(&hIdx);
9499342292Scy    rc = idxPrintfPrepareStmt(dbm, &pExplain, pzErr,
9500342292Scy        "EXPLAIN QUERY PLAN %s", pStmt->zSql
9501342292Scy    );
9502342292Scy    while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){
9503342292Scy      /* int iId = sqlite3_column_int(pExplain, 0); */
9504342292Scy      /* int iParent = sqlite3_column_int(pExplain, 1); */
9505342292Scy      /* int iNotUsed = sqlite3_column_int(pExplain, 2); */
9506342292Scy      const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
9507362190Scy      int nDetail;
9508342292Scy      int i;
9509342292Scy
9510362190Scy      if( !zDetail ) continue;
9511362190Scy      nDetail = STRLEN(zDetail);
9512362190Scy
9513342292Scy      for(i=0; i<nDetail; i++){
9514342292Scy        const char *zIdx = 0;
9515362190Scy        if( i+13<nDetail && memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
9516342292Scy          zIdx = &zDetail[i+13];
9517362190Scy        }else if( i+22<nDetail
9518362190Scy            && memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0
9519362190Scy        ){
9520342292Scy          zIdx = &zDetail[i+22];
9521342292Scy        }
9522342292Scy        if( zIdx ){
9523342292Scy          const char *zSql;
9524342292Scy          int nIdx = 0;
9525342292Scy          while( zIdx[nIdx]!='\0' && (zIdx[nIdx]!=' ' || zIdx[nIdx+1]!='(') ){
9526342292Scy            nIdx++;
9527342292Scy          }
9528342292Scy          zSql = idxHashSearch(&p->hIdx, zIdx, nIdx);
9529342292Scy          if( zSql ){
9530342292Scy            idxHashAdd(&rc, &hIdx, zSql, 0);
9531342292Scy            if( rc ) goto find_indexes_out;
9532342292Scy          }
9533342292Scy          break;
9534342292Scy        }
9535342292Scy      }
9536342292Scy
9537342292Scy      if( zDetail[0]!='-' ){
9538342292Scy        pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%s\n", zDetail);
9539342292Scy      }
9540342292Scy    }
9541342292Scy
9542342292Scy    for(pEntry=hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
9543342292Scy      pStmt->zIdx = idxAppendText(&rc, pStmt->zIdx, "%s;\n", pEntry->zKey);
9544342292Scy    }
9545342292Scy
9546342292Scy    idxFinalize(&rc, pExplain);
9547342292Scy  }
9548342292Scy
9549342292Scy find_indexes_out:
9550342292Scy  idxHashClear(&hIdx);
9551342292Scy  return rc;
9552342292Scy}
9553342292Scy
9554342292Scystatic int idxAuthCallback(
9555342292Scy  void *pCtx,
9556342292Scy  int eOp,
9557342292Scy  const char *z3,
9558342292Scy  const char *z4,
9559342292Scy  const char *zDb,
9560342292Scy  const char *zTrigger
9561342292Scy){
9562342292Scy  int rc = SQLITE_OK;
9563342292Scy  (void)z4;
9564342292Scy  (void)zTrigger;
9565342292Scy  if( eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE || eOp==SQLITE_DELETE ){
9566342292Scy    if( sqlite3_stricmp(zDb, "main")==0 ){
9567342292Scy      sqlite3expert *p = (sqlite3expert*)pCtx;
9568342292Scy      IdxTable *pTab;
9569342292Scy      for(pTab=p->pTable; pTab; pTab=pTab->pNext){
9570342292Scy        if( 0==sqlite3_stricmp(z3, pTab->zName) ) break;
9571342292Scy      }
9572342292Scy      if( pTab ){
9573342292Scy        IdxWrite *pWrite;
9574342292Scy        for(pWrite=p->pWrite; pWrite; pWrite=pWrite->pNext){
9575342292Scy          if( pWrite->pTab==pTab && pWrite->eOp==eOp ) break;
9576342292Scy        }
9577342292Scy        if( pWrite==0 ){
9578342292Scy          pWrite = idxMalloc(&rc, sizeof(IdxWrite));
9579342292Scy          if( rc==SQLITE_OK ){
9580342292Scy            pWrite->pTab = pTab;
9581342292Scy            pWrite->eOp = eOp;
9582342292Scy            pWrite->pNext = p->pWrite;
9583342292Scy            p->pWrite = pWrite;
9584342292Scy          }
9585342292Scy        }
9586342292Scy      }
9587342292Scy    }
9588342292Scy  }
9589342292Scy  return rc;
9590342292Scy}
9591342292Scy
9592342292Scystatic int idxProcessOneTrigger(
9593342292Scy  sqlite3expert *p,
9594342292Scy  IdxWrite *pWrite,
9595342292Scy  char **pzErr
9596342292Scy){
9597342292Scy  static const char *zInt = UNIQUE_TABLE_NAME;
9598342292Scy  static const char *zDrop = "DROP TABLE " UNIQUE_TABLE_NAME;
9599342292Scy  IdxTable *pTab = pWrite->pTab;
9600342292Scy  const char *zTab = pTab->zName;
9601342292Scy  const char *zSql =
9602366076Scy    "SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_schema "
9603342292Scy    "WHERE tbl_name = %Q AND type IN ('table', 'trigger') "
9604342292Scy    "ORDER BY type;";
9605342292Scy  sqlite3_stmt *pSelect = 0;
9606342292Scy  int rc = SQLITE_OK;
9607342292Scy  char *zWrite = 0;
9608342292Scy
9609342292Scy  /* Create the table and its triggers in the temp schema */
9610342292Scy  rc = idxPrintfPrepareStmt(p->db, &pSelect, pzErr, zSql, zTab, zTab);
9611342292Scy  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSelect) ){
9612342292Scy    const char *zCreate = (const char*)sqlite3_column_text(pSelect, 0);
9613342292Scy    rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr);
9614342292Scy  }
9615342292Scy  idxFinalize(&rc, pSelect);
9616342292Scy
9617342292Scy  /* Rename the table in the temp schema to zInt */
9618342292Scy  if( rc==SQLITE_OK ){
9619342292Scy    char *z = sqlite3_mprintf("ALTER TABLE temp.%Q RENAME TO %Q", zTab, zInt);
9620342292Scy    if( z==0 ){
9621342292Scy      rc = SQLITE_NOMEM;
9622342292Scy    }else{
9623342292Scy      rc = sqlite3_exec(p->dbv, z, 0, 0, pzErr);
9624342292Scy      sqlite3_free(z);
9625342292Scy    }
9626342292Scy  }
9627342292Scy
9628342292Scy  switch( pWrite->eOp ){
9629342292Scy    case SQLITE_INSERT: {
9630342292Scy      int i;
9631342292Scy      zWrite = idxAppendText(&rc, zWrite, "INSERT INTO %Q VALUES(", zInt);
9632342292Scy      for(i=0; i<pTab->nCol; i++){
9633342292Scy        zWrite = idxAppendText(&rc, zWrite, "%s?", i==0 ? "" : ", ");
9634342292Scy      }
9635342292Scy      zWrite = idxAppendText(&rc, zWrite, ")");
9636342292Scy      break;
9637342292Scy    }
9638342292Scy    case SQLITE_UPDATE: {
9639342292Scy      int i;
9640342292Scy      zWrite = idxAppendText(&rc, zWrite, "UPDATE %Q SET ", zInt);
9641342292Scy      for(i=0; i<pTab->nCol; i++){
9642342292Scy        zWrite = idxAppendText(&rc, zWrite, "%s%Q=?", i==0 ? "" : ", ",
9643342292Scy            pTab->aCol[i].zName
9644342292Scy        );
9645342292Scy      }
9646342292Scy      break;
9647342292Scy    }
9648342292Scy    default: {
9649342292Scy      assert( pWrite->eOp==SQLITE_DELETE );
9650342292Scy      if( rc==SQLITE_OK ){
9651342292Scy        zWrite = sqlite3_mprintf("DELETE FROM %Q", zInt);
9652342292Scy        if( zWrite==0 ) rc = SQLITE_NOMEM;
9653342292Scy      }
9654342292Scy    }
9655342292Scy  }
9656342292Scy
9657342292Scy  if( rc==SQLITE_OK ){
9658342292Scy    sqlite3_stmt *pX = 0;
9659342292Scy    rc = sqlite3_prepare_v2(p->dbv, zWrite, -1, &pX, 0);
9660342292Scy    idxFinalize(&rc, pX);
9661342292Scy    if( rc!=SQLITE_OK ){
9662342292Scy      idxDatabaseError(p->dbv, pzErr);
9663342292Scy    }
9664342292Scy  }
9665342292Scy  sqlite3_free(zWrite);
9666342292Scy
9667342292Scy  if( rc==SQLITE_OK ){
9668342292Scy    rc = sqlite3_exec(p->dbv, zDrop, 0, 0, pzErr);
9669342292Scy  }
9670342292Scy
9671342292Scy  return rc;
9672342292Scy}
9673342292Scy
9674342292Scystatic int idxProcessTriggers(sqlite3expert *p, char **pzErr){
9675342292Scy  int rc = SQLITE_OK;
9676342292Scy  IdxWrite *pEnd = 0;
9677342292Scy  IdxWrite *pFirst = p->pWrite;
9678342292Scy
9679342292Scy  while( rc==SQLITE_OK && pFirst!=pEnd ){
9680342292Scy    IdxWrite *pIter;
9681342292Scy    for(pIter=pFirst; rc==SQLITE_OK && pIter!=pEnd; pIter=pIter->pNext){
9682342292Scy      rc = idxProcessOneTrigger(p, pIter, pzErr);
9683342292Scy    }
9684342292Scy    pEnd = pFirst;
9685342292Scy    pFirst = p->pWrite;
9686342292Scy  }
9687342292Scy
9688342292Scy  return rc;
9689342292Scy}
9690342292Scy
9691342292Scy
9692342292Scystatic int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
9693342292Scy  int rc = idxRegisterVtab(p);
9694342292Scy  sqlite3_stmt *pSchema = 0;
9695342292Scy
9696342292Scy  /* For each table in the main db schema:
9697342292Scy  **
9698342292Scy  **   1) Add an entry to the p->pTable list, and
9699342292Scy  **   2) Create the equivalent virtual table in dbv.
9700342292Scy  */
9701342292Scy  rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg,
9702366076Scy      "SELECT type, name, sql, 1 FROM sqlite_schema "
9703342292Scy      "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' "
9704342292Scy      " UNION ALL "
9705366076Scy      "SELECT type, name, sql, 2 FROM sqlite_schema "
9706342292Scy      "WHERE type = 'trigger'"
9707366076Scy      "  AND tbl_name IN(SELECT name FROM sqlite_schema WHERE type = 'view') "
9708342292Scy      "ORDER BY 4, 1"
9709342292Scy  );
9710342292Scy  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){
9711342292Scy    const char *zType = (const char*)sqlite3_column_text(pSchema, 0);
9712342292Scy    const char *zName = (const char*)sqlite3_column_text(pSchema, 1);
9713342292Scy    const char *zSql = (const char*)sqlite3_column_text(pSchema, 2);
9714342292Scy
9715342292Scy    if( zType[0]=='v' || zType[1]=='r' ){
9716342292Scy      rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
9717342292Scy    }else{
9718342292Scy      IdxTable *pTab;
9719342292Scy      rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
9720342292Scy      if( rc==SQLITE_OK ){
9721342292Scy        int i;
9722342292Scy        char *zInner = 0;
9723342292Scy        char *zOuter = 0;
9724342292Scy        pTab->pNext = p->pTable;
9725342292Scy        p->pTable = pTab;
9726342292Scy
9727342292Scy        /* The statement the vtab will pass to sqlite3_declare_vtab() */
9728342292Scy        zInner = idxAppendText(&rc, 0, "CREATE TABLE x(");
9729342292Scy        for(i=0; i<pTab->nCol; i++){
9730342292Scy          zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %s",
9731342292Scy              (i==0 ? "" : ", "), pTab->aCol[i].zName, pTab->aCol[i].zColl
9732342292Scy          );
9733342292Scy        }
9734342292Scy        zInner = idxAppendText(&rc, zInner, ")");
9735342292Scy
9736342292Scy        /* The CVT statement to create the vtab */
9737342292Scy        zOuter = idxAppendText(&rc, 0,
9738342292Scy            "CREATE VIRTUAL TABLE %Q USING expert(%Q)", zName, zInner
9739342292Scy        );
9740342292Scy        if( rc==SQLITE_OK ){
9741342292Scy          rc = sqlite3_exec(p->dbv, zOuter, 0, 0, pzErrmsg);
9742342292Scy        }
9743342292Scy        sqlite3_free(zInner);
9744342292Scy        sqlite3_free(zOuter);
9745342292Scy      }
9746342292Scy    }
9747342292Scy  }
9748342292Scy  idxFinalize(&rc, pSchema);
9749342292Scy  return rc;
9750342292Scy}
9751342292Scy
9752342292Scystruct IdxSampleCtx {
9753342292Scy  int iTarget;
9754342292Scy  double target;                  /* Target nRet/nRow value */
9755342292Scy  double nRow;                    /* Number of rows seen */
9756342292Scy  double nRet;                    /* Number of rows returned */
9757342292Scy};
9758342292Scy
9759342292Scystatic void idxSampleFunc(
9760342292Scy  sqlite3_context *pCtx,
9761342292Scy  int argc,
9762342292Scy  sqlite3_value **argv
9763342292Scy){
9764342292Scy  struct IdxSampleCtx *p = (struct IdxSampleCtx*)sqlite3_user_data(pCtx);
9765342292Scy  int bRet;
9766342292Scy
9767342292Scy  (void)argv;
9768342292Scy  assert( argc==0 );
9769342292Scy  if( p->nRow==0.0 ){
9770342292Scy    bRet = 1;
9771342292Scy  }else{
9772342292Scy    bRet = (p->nRet / p->nRow) <= p->target;
9773342292Scy    if( bRet==0 ){
9774342292Scy      unsigned short rnd;
9775342292Scy      sqlite3_randomness(2, (void*)&rnd);
9776342292Scy      bRet = ((int)rnd % 100) <= p->iTarget;
9777342292Scy    }
9778342292Scy  }
9779342292Scy
9780342292Scy  sqlite3_result_int(pCtx, bRet);
9781342292Scy  p->nRow += 1.0;
9782342292Scy  p->nRet += (double)bRet;
9783342292Scy}
9784342292Scy
9785342292Scystruct IdxRemCtx {
9786342292Scy  int nSlot;
9787342292Scy  struct IdxRemSlot {
9788342292Scy    int eType;                    /* SQLITE_NULL, INTEGER, REAL, TEXT, BLOB */
9789342292Scy    i64 iVal;                     /* SQLITE_INTEGER value */
9790342292Scy    double rVal;                  /* SQLITE_FLOAT value */
9791342292Scy    int nByte;                    /* Bytes of space allocated at z */
9792342292Scy    int n;                        /* Size of buffer z */
9793342292Scy    char *z;                      /* SQLITE_TEXT/BLOB value */
9794342292Scy  } aSlot[1];
9795342292Scy};
9796342292Scy
9797342292Scy/*
9798342292Scy** Implementation of scalar function rem().
9799342292Scy*/
9800342292Scystatic void idxRemFunc(
9801342292Scy  sqlite3_context *pCtx,
9802342292Scy  int argc,
9803342292Scy  sqlite3_value **argv
9804342292Scy){
9805342292Scy  struct IdxRemCtx *p = (struct IdxRemCtx*)sqlite3_user_data(pCtx);
9806342292Scy  struct IdxRemSlot *pSlot;
9807342292Scy  int iSlot;
9808342292Scy  assert( argc==2 );
9809342292Scy
9810342292Scy  iSlot = sqlite3_value_int(argv[0]);
9811342292Scy  assert( iSlot<=p->nSlot );
9812342292Scy  pSlot = &p->aSlot[iSlot];
9813342292Scy
9814342292Scy  switch( pSlot->eType ){
9815342292Scy    case SQLITE_NULL:
9816342292Scy      /* no-op */
9817342292Scy      break;
9818342292Scy
9819342292Scy    case SQLITE_INTEGER:
9820342292Scy      sqlite3_result_int64(pCtx, pSlot->iVal);
9821342292Scy      break;
9822342292Scy
9823342292Scy    case SQLITE_FLOAT:
9824342292Scy      sqlite3_result_double(pCtx, pSlot->rVal);
9825342292Scy      break;
9826342292Scy
9827342292Scy    case SQLITE_BLOB:
9828342292Scy      sqlite3_result_blob(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT);
9829342292Scy      break;
9830342292Scy
9831342292Scy    case SQLITE_TEXT:
9832342292Scy      sqlite3_result_text(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT);
9833342292Scy      break;
9834342292Scy  }
9835342292Scy
9836342292Scy  pSlot->eType = sqlite3_value_type(argv[1]);
9837342292Scy  switch( pSlot->eType ){
9838342292Scy    case SQLITE_NULL:
9839342292Scy      /* no-op */
9840342292Scy      break;
9841342292Scy
9842342292Scy    case SQLITE_INTEGER:
9843342292Scy      pSlot->iVal = sqlite3_value_int64(argv[1]);
9844342292Scy      break;
9845342292Scy
9846342292Scy    case SQLITE_FLOAT:
9847342292Scy      pSlot->rVal = sqlite3_value_double(argv[1]);
9848342292Scy      break;
9849342292Scy
9850342292Scy    case SQLITE_BLOB:
9851342292Scy    case SQLITE_TEXT: {
9852342292Scy      int nByte = sqlite3_value_bytes(argv[1]);
9853342292Scy      if( nByte>pSlot->nByte ){
9854342292Scy        char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2);
9855342292Scy        if( zNew==0 ){
9856342292Scy          sqlite3_result_error_nomem(pCtx);
9857342292Scy          return;
9858342292Scy        }
9859342292Scy        pSlot->nByte = nByte*2;
9860342292Scy        pSlot->z = zNew;
9861342292Scy      }
9862342292Scy      pSlot->n = nByte;
9863342292Scy      if( pSlot->eType==SQLITE_BLOB ){
9864342292Scy        memcpy(pSlot->z, sqlite3_value_blob(argv[1]), nByte);
9865342292Scy      }else{
9866342292Scy        memcpy(pSlot->z, sqlite3_value_text(argv[1]), nByte);
9867342292Scy      }
9868342292Scy      break;
9869342292Scy    }
9870342292Scy  }
9871342292Scy}
9872342292Scy
9873342292Scystatic int idxLargestIndex(sqlite3 *db, int *pnMax, char **pzErr){
9874342292Scy  int rc = SQLITE_OK;
9875342292Scy  const char *zMax =
9876342292Scy    "SELECT max(i.seqno) FROM "
9877366076Scy    "  sqlite_schema AS s, "
9878342292Scy    "  pragma_index_list(s.name) AS l, "
9879342292Scy    "  pragma_index_info(l.name) AS i "
9880342292Scy    "WHERE s.type = 'table'";
9881342292Scy  sqlite3_stmt *pMax = 0;
9882342292Scy
9883342292Scy  *pnMax = 0;
9884342292Scy  rc = idxPrepareStmt(db, &pMax, pzErr, zMax);
9885342292Scy  if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){
9886342292Scy    *pnMax = sqlite3_column_int(pMax, 0) + 1;
9887342292Scy  }
9888342292Scy  idxFinalize(&rc, pMax);
9889342292Scy
9890342292Scy  return rc;
9891342292Scy}
9892342292Scy
9893342292Scystatic int idxPopulateOneStat1(
9894342292Scy  sqlite3expert *p,
9895342292Scy  sqlite3_stmt *pIndexXInfo,
9896342292Scy  sqlite3_stmt *pWriteStat,
9897342292Scy  const char *zTab,
9898342292Scy  const char *zIdx,
9899342292Scy  char **pzErr
9900342292Scy){
9901342292Scy  char *zCols = 0;
9902342292Scy  char *zOrder = 0;
9903342292Scy  char *zQuery = 0;
9904342292Scy  int nCol = 0;
9905342292Scy  int i;
9906342292Scy  sqlite3_stmt *pQuery = 0;
9907342292Scy  int *aStat = 0;
9908342292Scy  int rc = SQLITE_OK;
9909342292Scy
9910342292Scy  assert( p->iSample>0 );
9911342292Scy
9912342292Scy  /* Formulate the query text */
9913342292Scy  sqlite3_bind_text(pIndexXInfo, 1, zIdx, -1, SQLITE_STATIC);
9914342292Scy  while( SQLITE_OK==rc && SQLITE_ROW==sqlite3_step(pIndexXInfo) ){
9915342292Scy    const char *zComma = zCols==0 ? "" : ", ";
9916342292Scy    const char *zName = (const char*)sqlite3_column_text(pIndexXInfo, 0);
9917342292Scy    const char *zColl = (const char*)sqlite3_column_text(pIndexXInfo, 1);
9918342292Scy    zCols = idxAppendText(&rc, zCols,
9919342292Scy        "%sx.%Q IS rem(%d, x.%Q) COLLATE %s", zComma, zName, nCol, zName, zColl
9920342292Scy    );
9921342292Scy    zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol);
9922342292Scy  }
9923342292Scy  sqlite3_reset(pIndexXInfo);
9924342292Scy  if( rc==SQLITE_OK ){
9925342292Scy    if( p->iSample==100 ){
9926342292Scy      zQuery = sqlite3_mprintf(
9927342292Scy          "SELECT %s FROM %Q x ORDER BY %s", zCols, zTab, zOrder
9928342292Scy      );
9929342292Scy    }else{
9930342292Scy      zQuery = sqlite3_mprintf(
9931342292Scy          "SELECT %s FROM temp."UNIQUE_TABLE_NAME" x ORDER BY %s", zCols, zOrder
9932342292Scy      );
9933342292Scy    }
9934342292Scy  }
9935342292Scy  sqlite3_free(zCols);
9936342292Scy  sqlite3_free(zOrder);
9937342292Scy
9938342292Scy  /* Formulate the query text */
9939342292Scy  if( rc==SQLITE_OK ){
9940342292Scy    sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv);
9941342292Scy    rc = idxPrepareStmt(dbrem, &pQuery, pzErr, zQuery);
9942342292Scy  }
9943342292Scy  sqlite3_free(zQuery);
9944342292Scy
9945342292Scy  if( rc==SQLITE_OK ){
9946342292Scy    aStat = (int*)idxMalloc(&rc, sizeof(int)*(nCol+1));
9947342292Scy  }
9948342292Scy  if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){
9949342292Scy    IdxHashEntry *pEntry;
9950342292Scy    char *zStat = 0;
9951342292Scy    for(i=0; i<=nCol; i++) aStat[i] = 1;
9952342292Scy    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){
9953342292Scy      aStat[0]++;
9954342292Scy      for(i=0; i<nCol; i++){
9955342292Scy        if( sqlite3_column_int(pQuery, i)==0 ) break;
9956342292Scy      }
9957342292Scy      for(/*no-op*/; i<nCol; i++){
9958342292Scy        aStat[i+1]++;
9959342292Scy      }
9960342292Scy    }
9961342292Scy
9962342292Scy    if( rc==SQLITE_OK ){
9963342292Scy      int s0 = aStat[0];
9964342292Scy      zStat = sqlite3_mprintf("%d", s0);
9965342292Scy      if( zStat==0 ) rc = SQLITE_NOMEM;
9966342292Scy      for(i=1; rc==SQLITE_OK && i<=nCol; i++){
9967342292Scy        zStat = idxAppendText(&rc, zStat, " %d", (s0+aStat[i]/2) / aStat[i]);
9968342292Scy      }
9969342292Scy    }
9970342292Scy
9971342292Scy    if( rc==SQLITE_OK ){
9972342292Scy      sqlite3_bind_text(pWriteStat, 1, zTab, -1, SQLITE_STATIC);
9973342292Scy      sqlite3_bind_text(pWriteStat, 2, zIdx, -1, SQLITE_STATIC);
9974342292Scy      sqlite3_bind_text(pWriteStat, 3, zStat, -1, SQLITE_STATIC);
9975342292Scy      sqlite3_step(pWriteStat);
9976342292Scy      rc = sqlite3_reset(pWriteStat);
9977342292Scy    }
9978342292Scy
9979342292Scy    pEntry = idxHashFind(&p->hIdx, zIdx, STRLEN(zIdx));
9980342292Scy    if( pEntry ){
9981342292Scy      assert( pEntry->zVal2==0 );
9982342292Scy      pEntry->zVal2 = zStat;
9983342292Scy    }else{
9984342292Scy      sqlite3_free(zStat);
9985342292Scy    }
9986342292Scy  }
9987342292Scy  sqlite3_free(aStat);
9988342292Scy  idxFinalize(&rc, pQuery);
9989342292Scy
9990342292Scy  return rc;
9991342292Scy}
9992342292Scy
9993342292Scystatic int idxBuildSampleTable(sqlite3expert *p, const char *zTab){
9994342292Scy  int rc;
9995342292Scy  char *zSql;
9996342292Scy
9997342292Scy  rc = sqlite3_exec(p->dbv,"DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
9998342292Scy  if( rc!=SQLITE_OK ) return rc;
9999342292Scy
10000342292Scy  zSql = sqlite3_mprintf(
10001342292Scy      "CREATE TABLE temp." UNIQUE_TABLE_NAME " AS SELECT * FROM %Q", zTab
10002342292Scy  );
10003342292Scy  if( zSql==0 ) return SQLITE_NOMEM;
10004342292Scy  rc = sqlite3_exec(p->dbv, zSql, 0, 0, 0);
10005342292Scy  sqlite3_free(zSql);
10006342292Scy
10007342292Scy  return rc;
10008342292Scy}
10009342292Scy
10010342292Scy/*
10011342292Scy** This function is called as part of sqlite3_expert_analyze(). Candidate
10012342292Scy** indexes have already been created in database sqlite3expert.dbm, this
10013342292Scy** function populates sqlite_stat1 table in the same database.
10014342292Scy**
10015342292Scy** The stat1 data is generated by querying the
10016342292Scy*/
10017342292Scystatic int idxPopulateStat1(sqlite3expert *p, char **pzErr){
10018342292Scy  int rc = SQLITE_OK;
10019342292Scy  int nMax =0;
10020342292Scy  struct IdxRemCtx *pCtx = 0;
10021342292Scy  struct IdxSampleCtx samplectx;
10022342292Scy  int i;
10023342292Scy  i64 iPrev = -100000;
10024342292Scy  sqlite3_stmt *pAllIndex = 0;
10025342292Scy  sqlite3_stmt *pIndexXInfo = 0;
10026342292Scy  sqlite3_stmt *pWrite = 0;
10027342292Scy
10028342292Scy  const char *zAllIndex =
10029342292Scy    "SELECT s.rowid, s.name, l.name FROM "
10030366076Scy    "  sqlite_schema AS s, "
10031342292Scy    "  pragma_index_list(s.name) AS l "
10032342292Scy    "WHERE s.type = 'table'";
10033342292Scy  const char *zIndexXInfo =
10034342292Scy    "SELECT name, coll FROM pragma_index_xinfo(?) WHERE key";
10035342292Scy  const char *zWrite = "INSERT INTO sqlite_stat1 VALUES(?, ?, ?)";
10036342292Scy
10037342292Scy  /* If iSample==0, no sqlite_stat1 data is required. */
10038342292Scy  if( p->iSample==0 ) return SQLITE_OK;
10039342292Scy
10040342292Scy  rc = idxLargestIndex(p->dbm, &nMax, pzErr);
10041342292Scy  if( nMax<=0 || rc!=SQLITE_OK ) return rc;
10042342292Scy
10043342292Scy  rc = sqlite3_exec(p->dbm, "ANALYZE; PRAGMA writable_schema=1", 0, 0, 0);
10044342292Scy
10045342292Scy  if( rc==SQLITE_OK ){
10046342292Scy    int nByte = sizeof(struct IdxRemCtx) + (sizeof(struct IdxRemSlot) * nMax);
10047342292Scy    pCtx = (struct IdxRemCtx*)idxMalloc(&rc, nByte);
10048342292Scy  }
10049342292Scy
10050342292Scy  if( rc==SQLITE_OK ){
10051342292Scy    sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv);
10052342292Scy    rc = sqlite3_create_function(
10053342292Scy        dbrem, "rem", 2, SQLITE_UTF8, (void*)pCtx, idxRemFunc, 0, 0
10054342292Scy    );
10055342292Scy  }
10056342292Scy  if( rc==SQLITE_OK ){
10057342292Scy    rc = sqlite3_create_function(
10058342292Scy        p->db, "sample", 0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0
10059342292Scy    );
10060342292Scy  }
10061342292Scy
10062342292Scy  if( rc==SQLITE_OK ){
10063342292Scy    pCtx->nSlot = nMax+1;
10064342292Scy    rc = idxPrepareStmt(p->dbm, &pAllIndex, pzErr, zAllIndex);
10065342292Scy  }
10066342292Scy  if( rc==SQLITE_OK ){
10067342292Scy    rc = idxPrepareStmt(p->dbm, &pIndexXInfo, pzErr, zIndexXInfo);
10068342292Scy  }
10069342292Scy  if( rc==SQLITE_OK ){
10070342292Scy    rc = idxPrepareStmt(p->dbm, &pWrite, pzErr, zWrite);
10071342292Scy  }
10072342292Scy
10073342292Scy  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pAllIndex) ){
10074342292Scy    i64 iRowid = sqlite3_column_int64(pAllIndex, 0);
10075342292Scy    const char *zTab = (const char*)sqlite3_column_text(pAllIndex, 1);
10076342292Scy    const char *zIdx = (const char*)sqlite3_column_text(pAllIndex, 2);
10077342292Scy    if( p->iSample<100 && iPrev!=iRowid ){
10078342292Scy      samplectx.target = (double)p->iSample / 100.0;
10079342292Scy      samplectx.iTarget = p->iSample;
10080342292Scy      samplectx.nRow = 0.0;
10081342292Scy      samplectx.nRet = 0.0;
10082342292Scy      rc = idxBuildSampleTable(p, zTab);
10083342292Scy      if( rc!=SQLITE_OK ) break;
10084342292Scy    }
10085342292Scy    rc = idxPopulateOneStat1(p, pIndexXInfo, pWrite, zTab, zIdx, pzErr);
10086342292Scy    iPrev = iRowid;
10087342292Scy  }
10088342292Scy  if( rc==SQLITE_OK && p->iSample<100 ){
10089342292Scy    rc = sqlite3_exec(p->dbv,
10090342292Scy        "DROP TABLE IF EXISTS temp." UNIQUE_TABLE_NAME, 0,0,0
10091342292Scy    );
10092342292Scy  }
10093342292Scy
10094342292Scy  idxFinalize(&rc, pAllIndex);
10095342292Scy  idxFinalize(&rc, pIndexXInfo);
10096342292Scy  idxFinalize(&rc, pWrite);
10097342292Scy
10098369950Scy  if( pCtx ){
10099369950Scy    for(i=0; i<pCtx->nSlot; i++){
10100369950Scy      sqlite3_free(pCtx->aSlot[i].z);
10101369950Scy    }
10102369950Scy    sqlite3_free(pCtx);
10103342292Scy  }
10104342292Scy
10105342292Scy  if( rc==SQLITE_OK ){
10106366076Scy    rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_schema", 0, 0, 0);
10107342292Scy  }
10108342292Scy
10109342292Scy  sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
10110342292Scy  return rc;
10111342292Scy}
10112342292Scy
10113342292Scy/*
10114342292Scy** Allocate a new sqlite3expert object.
10115342292Scy*/
10116342292Scysqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
10117342292Scy  int rc = SQLITE_OK;
10118342292Scy  sqlite3expert *pNew;
10119342292Scy
10120342292Scy  pNew = (sqlite3expert*)idxMalloc(&rc, sizeof(sqlite3expert));
10121342292Scy
10122342292Scy  /* Open two in-memory databases to work with. The "vtab database" (dbv)
10123342292Scy  ** will contain a virtual table corresponding to each real table in
10124342292Scy  ** the user database schema, and a copy of each view. It is used to
10125342292Scy  ** collect information regarding the WHERE, ORDER BY and other clauses
10126342292Scy  ** of the user's query.
10127342292Scy  */
10128342292Scy  if( rc==SQLITE_OK ){
10129342292Scy    pNew->db = db;
10130342292Scy    pNew->iSample = 100;
10131342292Scy    rc = sqlite3_open(":memory:", &pNew->dbv);
10132342292Scy  }
10133342292Scy  if( rc==SQLITE_OK ){
10134342292Scy    rc = sqlite3_open(":memory:", &pNew->dbm);
10135342292Scy    if( rc==SQLITE_OK ){
10136342292Scy      sqlite3_db_config(pNew->dbm, SQLITE_DBCONFIG_TRIGGER_EQP, 1, (int*)0);
10137342292Scy    }
10138342292Scy  }
10139342292Scy
10140342292Scy
10141342292Scy  /* Copy the entire schema of database [db] into [dbm]. */
10142342292Scy  if( rc==SQLITE_OK ){
10143342292Scy    sqlite3_stmt *pSql;
10144342292Scy    rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg,
10145366076Scy        "SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
10146342292Scy        " AND sql NOT LIKE 'CREATE VIRTUAL %%'"
10147342292Scy    );
10148342292Scy    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
10149342292Scy      const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
10150342292Scy      rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
10151342292Scy    }
10152342292Scy    idxFinalize(&rc, pSql);
10153342292Scy  }
10154342292Scy
10155342292Scy  /* Create the vtab schema */
10156342292Scy  if( rc==SQLITE_OK ){
10157342292Scy    rc = idxCreateVtabSchema(pNew, pzErrmsg);
10158342292Scy  }
10159342292Scy
10160342292Scy  /* Register the auth callback with dbv */
10161342292Scy  if( rc==SQLITE_OK ){
10162342292Scy    sqlite3_set_authorizer(pNew->dbv, idxAuthCallback, (void*)pNew);
10163342292Scy  }
10164342292Scy
10165342292Scy  /* If an error has occurred, free the new object and reutrn NULL. Otherwise,
10166342292Scy  ** return the new sqlite3expert handle.  */
10167342292Scy  if( rc!=SQLITE_OK ){
10168342292Scy    sqlite3_expert_destroy(pNew);
10169342292Scy    pNew = 0;
10170342292Scy  }
10171342292Scy  return pNew;
10172342292Scy}
10173342292Scy
10174342292Scy/*
10175342292Scy** Configure an sqlite3expert object.
10176342292Scy*/
10177342292Scyint sqlite3_expert_config(sqlite3expert *p, int op, ...){
10178342292Scy  int rc = SQLITE_OK;
10179342292Scy  va_list ap;
10180342292Scy  va_start(ap, op);
10181342292Scy  switch( op ){
10182342292Scy    case EXPERT_CONFIG_SAMPLE: {
10183342292Scy      int iVal = va_arg(ap, int);
10184342292Scy      if( iVal<0 ) iVal = 0;
10185342292Scy      if( iVal>100 ) iVal = 100;
10186342292Scy      p->iSample = iVal;
10187342292Scy      break;
10188342292Scy    }
10189342292Scy    default:
10190342292Scy      rc = SQLITE_NOTFOUND;
10191342292Scy      break;
10192342292Scy  }
10193342292Scy
10194342292Scy  va_end(ap);
10195342292Scy  return rc;
10196342292Scy}
10197342292Scy
10198342292Scy/*
10199342292Scy** Add an SQL statement to the analysis.
10200342292Scy*/
10201342292Scyint sqlite3_expert_sql(
10202342292Scy  sqlite3expert *p,               /* From sqlite3_expert_new() */
10203342292Scy  const char *zSql,               /* SQL statement to add */
10204342292Scy  char **pzErr                    /* OUT: Error message (if any) */
10205342292Scy){
10206342292Scy  IdxScan *pScanOrig = p->pScan;
10207342292Scy  IdxStatement *pStmtOrig = p->pStatement;
10208342292Scy  int rc = SQLITE_OK;
10209342292Scy  const char *zStmt = zSql;
10210342292Scy
10211342292Scy  if( p->bRun ) return SQLITE_MISUSE;
10212342292Scy
10213342292Scy  while( rc==SQLITE_OK && zStmt && zStmt[0] ){
10214342292Scy    sqlite3_stmt *pStmt = 0;
10215342292Scy    rc = sqlite3_prepare_v2(p->dbv, zStmt, -1, &pStmt, &zStmt);
10216342292Scy    if( rc==SQLITE_OK ){
10217342292Scy      if( pStmt ){
10218342292Scy        IdxStatement *pNew;
10219342292Scy        const char *z = sqlite3_sql(pStmt);
10220342292Scy        int n = STRLEN(z);
10221342292Scy        pNew = (IdxStatement*)idxMalloc(&rc, sizeof(IdxStatement) + n+1);
10222342292Scy        if( rc==SQLITE_OK ){
10223342292Scy          pNew->zSql = (char*)&pNew[1];
10224342292Scy          memcpy(pNew->zSql, z, n+1);
10225342292Scy          pNew->pNext = p->pStatement;
10226342292Scy          if( p->pStatement ) pNew->iId = p->pStatement->iId+1;
10227342292Scy          p->pStatement = pNew;
10228342292Scy        }
10229342292Scy        sqlite3_finalize(pStmt);
10230342292Scy      }
10231342292Scy    }else{
10232342292Scy      idxDatabaseError(p->dbv, pzErr);
10233342292Scy    }
10234342292Scy  }
10235342292Scy
10236342292Scy  if( rc!=SQLITE_OK ){
10237342292Scy    idxScanFree(p->pScan, pScanOrig);
10238342292Scy    idxStatementFree(p->pStatement, pStmtOrig);
10239342292Scy    p->pScan = pScanOrig;
10240342292Scy    p->pStatement = pStmtOrig;
10241342292Scy  }
10242342292Scy
10243342292Scy  return rc;
10244342292Scy}
10245342292Scy
10246342292Scyint sqlite3_expert_analyze(sqlite3expert *p, char **pzErr){
10247342292Scy  int rc;
10248342292Scy  IdxHashEntry *pEntry;
10249342292Scy
10250342292Scy  /* Do trigger processing to collect any extra IdxScan structures */
10251342292Scy  rc = idxProcessTriggers(p, pzErr);
10252342292Scy
10253342292Scy  /* Create candidate indexes within the in-memory database file */
10254342292Scy  if( rc==SQLITE_OK ){
10255342292Scy    rc = idxCreateCandidates(p);
10256342292Scy  }
10257342292Scy
10258342292Scy  /* Generate the stat1 data */
10259342292Scy  if( rc==SQLITE_OK ){
10260342292Scy    rc = idxPopulateStat1(p, pzErr);
10261342292Scy  }
10262342292Scy
10263342292Scy  /* Formulate the EXPERT_REPORT_CANDIDATES text */
10264342292Scy  for(pEntry=p->hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
10265342292Scy    p->zCandidates = idxAppendText(&rc, p->zCandidates,
10266342292Scy        "%s;%s%s\n", pEntry->zVal,
10267342292Scy        pEntry->zVal2 ? " -- stat1: " : "", pEntry->zVal2
10268342292Scy    );
10269342292Scy  }
10270342292Scy
10271342292Scy  /* Figure out which of the candidate indexes are preferred by the query
10272342292Scy  ** planner and report the results to the user.  */
10273342292Scy  if( rc==SQLITE_OK ){
10274342292Scy    rc = idxFindIndexes(p, pzErr);
10275342292Scy  }
10276342292Scy
10277342292Scy  if( rc==SQLITE_OK ){
10278342292Scy    p->bRun = 1;
10279342292Scy  }
10280342292Scy  return rc;
10281342292Scy}
10282342292Scy
10283342292Scy/*
10284342292Scy** Return the total number of statements that have been added to this
10285342292Scy** sqlite3expert using sqlite3_expert_sql().
10286342292Scy*/
10287342292Scyint sqlite3_expert_count(sqlite3expert *p){
10288342292Scy  int nRet = 0;
10289342292Scy  if( p->pStatement ) nRet = p->pStatement->iId+1;
10290342292Scy  return nRet;
10291342292Scy}
10292342292Scy
10293342292Scy/*
10294342292Scy** Return a component of the report.
10295342292Scy*/
10296342292Scyconst char *sqlite3_expert_report(sqlite3expert *p, int iStmt, int eReport){
10297342292Scy  const char *zRet = 0;
10298342292Scy  IdxStatement *pStmt;
10299342292Scy
10300342292Scy  if( p->bRun==0 ) return 0;
10301342292Scy  for(pStmt=p->pStatement; pStmt && pStmt->iId!=iStmt; pStmt=pStmt->pNext);
10302342292Scy  switch( eReport ){
10303342292Scy    case EXPERT_REPORT_SQL:
10304342292Scy      if( pStmt ) zRet = pStmt->zSql;
10305342292Scy      break;
10306342292Scy    case EXPERT_REPORT_INDEXES:
10307342292Scy      if( pStmt ) zRet = pStmt->zIdx;
10308342292Scy      break;
10309342292Scy    case EXPERT_REPORT_PLAN:
10310342292Scy      if( pStmt ) zRet = pStmt->zEQP;
10311342292Scy      break;
10312342292Scy    case EXPERT_REPORT_CANDIDATES:
10313342292Scy      zRet = p->zCandidates;
10314342292Scy      break;
10315342292Scy  }
10316342292Scy  return zRet;
10317342292Scy}
10318342292Scy
10319342292Scy/*
10320342292Scy** Free an sqlite3expert object.
10321342292Scy*/
10322342292Scyvoid sqlite3_expert_destroy(sqlite3expert *p){
10323342292Scy  if( p ){
10324342292Scy    sqlite3_close(p->dbm);
10325342292Scy    sqlite3_close(p->dbv);
10326342292Scy    idxScanFree(p->pScan, 0);
10327342292Scy    idxStatementFree(p->pStatement, 0);
10328342292Scy    idxTableFree(p->pTable);
10329342292Scy    idxWriteFree(p->pWrite);
10330342292Scy    idxHashClear(&p->hIdx);
10331342292Scy    sqlite3_free(p->zCandidates);
10332342292Scy    sqlite3_free(p);
10333342292Scy  }
10334342292Scy}
10335342292Scy
10336362190Scy#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
10337342292Scy
10338342292Scy/************************* End ../ext/expert/sqlite3expert.c ********************/
10339342292Scy
10340351633Scy#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
10341351633Scy/************************* Begin ../ext/misc/dbdata.c ******************/
10342351633Scy/*
10343351633Scy** 2019-04-17
10344351633Scy**
10345351633Scy** The author disclaims copyright to this source code.  In place of
10346351633Scy** a legal notice, here is a blessing:
10347351633Scy**
10348351633Scy**    May you do good and not evil.
10349351633Scy**    May you find forgiveness for yourself and forgive others.
10350351633Scy**    May you share freely, never taking more than you give.
10351351633Scy**
10352351633Scy******************************************************************************
10353351633Scy**
10354351633Scy** This file contains an implementation of two eponymous virtual tables,
10355351633Scy** "sqlite_dbdata" and "sqlite_dbptr". Both modules require that the
10356351633Scy** "sqlite_dbpage" eponymous virtual table be available.
10357351633Scy**
10358351633Scy** SQLITE_DBDATA:
10359351633Scy**   sqlite_dbdata is used to extract data directly from a database b-tree
10360351633Scy**   page and its associated overflow pages, bypassing the b-tree layer.
10361351633Scy**   The table schema is equivalent to:
10362351633Scy**
10363351633Scy**     CREATE TABLE sqlite_dbdata(
10364351633Scy**       pgno INTEGER,
10365351633Scy**       cell INTEGER,
10366351633Scy**       field INTEGER,
10367351633Scy**       value ANY,
10368351633Scy**       schema TEXT HIDDEN
10369351633Scy**     );
10370351633Scy**
10371351633Scy**   IMPORTANT: THE VIRTUAL TABLE SCHEMA ABOVE IS SUBJECT TO CHANGE. IN THE
10372351633Scy**   FUTURE NEW NON-HIDDEN COLUMNS MAY BE ADDED BETWEEN "value" AND
10373351633Scy**   "schema".
10374351633Scy**
10375351633Scy**   Each page of the database is inspected. If it cannot be interpreted as
10376351633Scy**   a b-tree page, or if it is a b-tree page containing 0 entries, the
10377351633Scy**   sqlite_dbdata table contains no rows for that page.  Otherwise, the
10378351633Scy**   table contains one row for each field in the record associated with
10379351633Scy**   each cell on the page. For intkey b-trees, the key value is stored in
10380351633Scy**   field -1.
10381351633Scy**
10382351633Scy**   For example, for the database:
10383351633Scy**
10384351633Scy**     CREATE TABLE t1(a, b);     -- root page is page 2
10385351633Scy**     INSERT INTO t1(rowid, a, b) VALUES(5, 'v', 'five');
10386351633Scy**     INSERT INTO t1(rowid, a, b) VALUES(10, 'x', 'ten');
10387351633Scy**
10388351633Scy**   the sqlite_dbdata table contains, as well as from entries related to
10389351633Scy**   page 1, content equivalent to:
10390351633Scy**
10391351633Scy**     INSERT INTO sqlite_dbdata(pgno, cell, field, value) VALUES
10392351633Scy**         (2, 0, -1, 5     ),
10393351633Scy**         (2, 0,  0, 'v'   ),
10394351633Scy**         (2, 0,  1, 'five'),
10395351633Scy**         (2, 1, -1, 10    ),
10396351633Scy**         (2, 1,  0, 'x'   ),
10397351633Scy**         (2, 1,  1, 'ten' );
10398351633Scy**
10399351633Scy**   If database corruption is encountered, this module does not report an
10400351633Scy**   error. Instead, it attempts to extract as much data as possible and
10401351633Scy**   ignores the corruption.
10402351633Scy**
10403351633Scy** SQLITE_DBPTR:
10404351633Scy**   The sqlite_dbptr table has the following schema:
10405351633Scy**
10406351633Scy**     CREATE TABLE sqlite_dbptr(
10407351633Scy**       pgno INTEGER,
10408351633Scy**       child INTEGER,
10409351633Scy**       schema TEXT HIDDEN
10410351633Scy**     );
10411351633Scy**
10412351633Scy**   It contains one entry for each b-tree pointer between a parent and
10413351633Scy**   child page in the database.
10414351633Scy*/
10415351633Scy#if !defined(SQLITEINT_H)
10416351633Scy/* #include "sqlite3ext.h" */
10417351633Scy
10418351633Scy/* typedef unsigned char u8; */
10419351633Scy
10420351633Scy#endif
10421351633ScySQLITE_EXTENSION_INIT1
10422351633Scy#include <string.h>
10423351633Scy#include <assert.h>
10424351633Scy
10425351633Scy#define DBDATA_PADDING_BYTES 100
10426351633Scy
10427351633Scytypedef struct DbdataTable DbdataTable;
10428351633Scytypedef struct DbdataCursor DbdataCursor;
10429351633Scy
10430351633Scy/* Cursor object */
10431351633Scystruct DbdataCursor {
10432351633Scy  sqlite3_vtab_cursor base;       /* Base class.  Must be first */
10433351633Scy  sqlite3_stmt *pStmt;            /* For fetching database pages */
10434351633Scy
10435351633Scy  int iPgno;                      /* Current page number */
10436351633Scy  u8 *aPage;                      /* Buffer containing page */
10437351633Scy  int nPage;                      /* Size of aPage[] in bytes */
10438351633Scy  int nCell;                      /* Number of cells on aPage[] */
10439351633Scy  int iCell;                      /* Current cell number */
10440351633Scy  int bOnePage;                   /* True to stop after one page */
10441351633Scy  int szDb;
10442351633Scy  sqlite3_int64 iRowid;
10443351633Scy
10444351633Scy  /* Only for the sqlite_dbdata table */
10445351633Scy  u8 *pRec;                       /* Buffer containing current record */
10446351633Scy  int nRec;                       /* Size of pRec[] in bytes */
10447351633Scy  int nHdr;                       /* Size of header in bytes */
10448351633Scy  int iField;                     /* Current field number */
10449351633Scy  u8 *pHdrPtr;
10450351633Scy  u8 *pPtr;
10451351633Scy
10452351633Scy  sqlite3_int64 iIntkey;          /* Integer key value */
10453351633Scy};
10454351633Scy
10455351633Scy/* Table object */
10456351633Scystruct DbdataTable {
10457351633Scy  sqlite3_vtab base;              /* Base class.  Must be first */
10458351633Scy  sqlite3 *db;                    /* The database connection */
10459351633Scy  sqlite3_stmt *pStmt;            /* For fetching database pages */
10460351633Scy  int bPtr;                       /* True for sqlite3_dbptr table */
10461351633Scy};
10462351633Scy
10463351633Scy/* Column and schema definitions for sqlite_dbdata */
10464351633Scy#define DBDATA_COLUMN_PGNO        0
10465351633Scy#define DBDATA_COLUMN_CELL        1
10466351633Scy#define DBDATA_COLUMN_FIELD       2
10467351633Scy#define DBDATA_COLUMN_VALUE       3
10468351633Scy#define DBDATA_COLUMN_SCHEMA      4
10469351633Scy#define DBDATA_SCHEMA             \
10470351633Scy      "CREATE TABLE x("           \
10471351633Scy      "  pgno INTEGER,"           \
10472351633Scy      "  cell INTEGER,"           \
10473351633Scy      "  field INTEGER,"          \
10474351633Scy      "  value ANY,"              \
10475351633Scy      "  schema TEXT HIDDEN"      \
10476351633Scy      ")"
10477351633Scy
10478351633Scy/* Column and schema definitions for sqlite_dbptr */
10479351633Scy#define DBPTR_COLUMN_PGNO         0
10480351633Scy#define DBPTR_COLUMN_CHILD        1
10481351633Scy#define DBPTR_COLUMN_SCHEMA       2
10482351633Scy#define DBPTR_SCHEMA              \
10483351633Scy      "CREATE TABLE x("           \
10484351633Scy      "  pgno INTEGER,"           \
10485351633Scy      "  child INTEGER,"          \
10486351633Scy      "  schema TEXT HIDDEN"      \
10487351633Scy      ")"
10488351633Scy
10489351633Scy/*
10490351633Scy** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual
10491351633Scy** table.
10492351633Scy*/
10493351633Scystatic int dbdataConnect(
10494351633Scy  sqlite3 *db,
10495351633Scy  void *pAux,
10496351633Scy  int argc, const char *const*argv,
10497351633Scy  sqlite3_vtab **ppVtab,
10498351633Scy  char **pzErr
10499351633Scy){
10500351633Scy  DbdataTable *pTab = 0;
10501351633Scy  int rc = sqlite3_declare_vtab(db, pAux ? DBPTR_SCHEMA : DBDATA_SCHEMA);
10502351633Scy
10503351633Scy  if( rc==SQLITE_OK ){
10504351633Scy    pTab = (DbdataTable*)sqlite3_malloc64(sizeof(DbdataTable));
10505351633Scy    if( pTab==0 ){
10506351633Scy      rc = SQLITE_NOMEM;
10507351633Scy    }else{
10508351633Scy      memset(pTab, 0, sizeof(DbdataTable));
10509351633Scy      pTab->db = db;
10510351633Scy      pTab->bPtr = (pAux!=0);
10511351633Scy    }
10512351633Scy  }
10513351633Scy
10514351633Scy  *ppVtab = (sqlite3_vtab*)pTab;
10515351633Scy  return rc;
10516351633Scy}
10517351633Scy
10518351633Scy/*
10519351633Scy** Disconnect from or destroy a sqlite_dbdata or sqlite_dbptr virtual table.
10520351633Scy*/
10521351633Scystatic int dbdataDisconnect(sqlite3_vtab *pVtab){
10522351633Scy  DbdataTable *pTab = (DbdataTable*)pVtab;
10523351633Scy  if( pTab ){
10524351633Scy    sqlite3_finalize(pTab->pStmt);
10525351633Scy    sqlite3_free(pVtab);
10526351633Scy  }
10527351633Scy  return SQLITE_OK;
10528351633Scy}
10529351633Scy
10530351633Scy/*
10531351633Scy** This function interprets two types of constraints:
10532351633Scy**
10533351633Scy**       schema=?
10534351633Scy**       pgno=?
10535351633Scy**
10536351633Scy** If neither are present, idxNum is set to 0. If schema=? is present,
10537351633Scy** the 0x01 bit in idxNum is set. If pgno=? is present, the 0x02 bit
10538351633Scy** in idxNum is set.
10539351633Scy**
10540351633Scy** If both parameters are present, schema is in position 0 and pgno in
10541351633Scy** position 1.
10542351633Scy*/
10543351633Scystatic int dbdataBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdx){
10544351633Scy  DbdataTable *pTab = (DbdataTable*)tab;
10545351633Scy  int i;
10546351633Scy  int iSchema = -1;
10547351633Scy  int iPgno = -1;
10548351633Scy  int colSchema = (pTab->bPtr ? DBPTR_COLUMN_SCHEMA : DBDATA_COLUMN_SCHEMA);
10549351633Scy
10550351633Scy  for(i=0; i<pIdx->nConstraint; i++){
10551351633Scy    struct sqlite3_index_constraint *p = &pIdx->aConstraint[i];
10552351633Scy    if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
10553351633Scy      if( p->iColumn==colSchema ){
10554351633Scy        if( p->usable==0 ) return SQLITE_CONSTRAINT;
10555351633Scy        iSchema = i;
10556351633Scy      }
10557351633Scy      if( p->iColumn==DBDATA_COLUMN_PGNO && p->usable ){
10558351633Scy        iPgno = i;
10559351633Scy      }
10560351633Scy    }
10561351633Scy  }
10562351633Scy
10563351633Scy  if( iSchema>=0 ){
10564351633Scy    pIdx->aConstraintUsage[iSchema].argvIndex = 1;
10565351633Scy    pIdx->aConstraintUsage[iSchema].omit = 1;
10566351633Scy  }
10567351633Scy  if( iPgno>=0 ){
10568351633Scy    pIdx->aConstraintUsage[iPgno].argvIndex = 1 + (iSchema>=0);
10569351633Scy    pIdx->aConstraintUsage[iPgno].omit = 1;
10570351633Scy    pIdx->estimatedCost = 100;
10571351633Scy    pIdx->estimatedRows =  50;
10572351633Scy
10573351633Scy    if( pTab->bPtr==0 && pIdx->nOrderBy && pIdx->aOrderBy[0].desc==0 ){
10574351633Scy      int iCol = pIdx->aOrderBy[0].iColumn;
10575351633Scy      if( pIdx->nOrderBy==1 ){
10576351633Scy        pIdx->orderByConsumed = (iCol==0 || iCol==1);
10577351633Scy      }else if( pIdx->nOrderBy==2 && pIdx->aOrderBy[1].desc==0 && iCol==0 ){
10578351633Scy        pIdx->orderByConsumed = (pIdx->aOrderBy[1].iColumn==1);
10579351633Scy      }
10580351633Scy    }
10581351633Scy
10582351633Scy  }else{
10583351633Scy    pIdx->estimatedCost = 100000000;
10584351633Scy    pIdx->estimatedRows = 1000000000;
10585351633Scy  }
10586351633Scy  pIdx->idxNum = (iSchema>=0 ? 0x01 : 0x00) | (iPgno>=0 ? 0x02 : 0x00);
10587351633Scy  return SQLITE_OK;
10588351633Scy}
10589351633Scy
10590351633Scy/*
10591351633Scy** Open a new sqlite_dbdata or sqlite_dbptr cursor.
10592351633Scy*/
10593351633Scystatic int dbdataOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
10594351633Scy  DbdataCursor *pCsr;
10595351633Scy
10596351633Scy  pCsr = (DbdataCursor*)sqlite3_malloc64(sizeof(DbdataCursor));
10597351633Scy  if( pCsr==0 ){
10598351633Scy    return SQLITE_NOMEM;
10599351633Scy  }else{
10600351633Scy    memset(pCsr, 0, sizeof(DbdataCursor));
10601351633Scy    pCsr->base.pVtab = pVTab;
10602351633Scy  }
10603351633Scy
10604351633Scy  *ppCursor = (sqlite3_vtab_cursor *)pCsr;
10605351633Scy  return SQLITE_OK;
10606351633Scy}
10607351633Scy
10608351633Scy/*
10609351633Scy** Restore a cursor object to the state it was in when first allocated
10610351633Scy** by dbdataOpen().
10611351633Scy*/
10612351633Scystatic void dbdataResetCursor(DbdataCursor *pCsr){
10613351633Scy  DbdataTable *pTab = (DbdataTable*)(pCsr->base.pVtab);
10614351633Scy  if( pTab->pStmt==0 ){
10615351633Scy    pTab->pStmt = pCsr->pStmt;
10616351633Scy  }else{
10617351633Scy    sqlite3_finalize(pCsr->pStmt);
10618351633Scy  }
10619351633Scy  pCsr->pStmt = 0;
10620351633Scy  pCsr->iPgno = 1;
10621351633Scy  pCsr->iCell = 0;
10622351633Scy  pCsr->iField = 0;
10623351633Scy  pCsr->bOnePage = 0;
10624351633Scy  sqlite3_free(pCsr->aPage);
10625351633Scy  sqlite3_free(pCsr->pRec);
10626351633Scy  pCsr->pRec = 0;
10627351633Scy  pCsr->aPage = 0;
10628351633Scy}
10629351633Scy
10630351633Scy/*
10631351633Scy** Close an sqlite_dbdata or sqlite_dbptr cursor.
10632351633Scy*/
10633351633Scystatic int dbdataClose(sqlite3_vtab_cursor *pCursor){
10634351633Scy  DbdataCursor *pCsr = (DbdataCursor*)pCursor;
10635351633Scy  dbdataResetCursor(pCsr);
10636351633Scy  sqlite3_free(pCsr);
10637351633Scy  return SQLITE_OK;
10638351633Scy}
10639351633Scy
10640351633Scy/*
10641351633Scy** Utility methods to decode 16 and 32-bit big-endian unsigned integers.
10642351633Scy*/
10643351633Scystatic unsigned int get_uint16(unsigned char *a){
10644351633Scy  return (a[0]<<8)|a[1];
10645351633Scy}
10646351633Scystatic unsigned int get_uint32(unsigned char *a){
10647351633Scy  return ((unsigned int)a[0]<<24)
10648351633Scy       | ((unsigned int)a[1]<<16)
10649351633Scy       | ((unsigned int)a[2]<<8)
10650351633Scy       | ((unsigned int)a[3]);
10651351633Scy}
10652351633Scy
10653351633Scy/*
10654351633Scy** Load page pgno from the database via the sqlite_dbpage virtual table.
10655351633Scy** If successful, set (*ppPage) to point to a buffer containing the page
10656351633Scy** data, (*pnPage) to the size of that buffer in bytes and return
10657351633Scy** SQLITE_OK. In this case it is the responsibility of the caller to
10658351633Scy** eventually free the buffer using sqlite3_free().
10659351633Scy**
10660351633Scy** Or, if an error occurs, set both (*ppPage) and (*pnPage) to 0 and
10661351633Scy** return an SQLite error code.
10662351633Scy*/
10663351633Scystatic int dbdataLoadPage(
10664351633Scy  DbdataCursor *pCsr,             /* Cursor object */
10665351633Scy  unsigned int pgno,              /* Page number of page to load */
10666351633Scy  u8 **ppPage,                    /* OUT: pointer to page buffer */
10667351633Scy  int *pnPage                     /* OUT: Size of (*ppPage) in bytes */
10668351633Scy){
10669351633Scy  int rc2;
10670351633Scy  int rc = SQLITE_OK;
10671351633Scy  sqlite3_stmt *pStmt = pCsr->pStmt;
10672351633Scy
10673351633Scy  *ppPage = 0;
10674351633Scy  *pnPage = 0;
10675351633Scy  sqlite3_bind_int64(pStmt, 2, pgno);
10676351633Scy  if( SQLITE_ROW==sqlite3_step(pStmt) ){
10677351633Scy    int nCopy = sqlite3_column_bytes(pStmt, 0);
10678351633Scy    if( nCopy>0 ){
10679351633Scy      u8 *pPage;
10680351633Scy      pPage = (u8*)sqlite3_malloc64(nCopy + DBDATA_PADDING_BYTES);
10681351633Scy      if( pPage==0 ){
10682351633Scy        rc = SQLITE_NOMEM;
10683351633Scy      }else{
10684351633Scy        const u8 *pCopy = sqlite3_column_blob(pStmt, 0);
10685351633Scy        memcpy(pPage, pCopy, nCopy);
10686351633Scy        memset(&pPage[nCopy], 0, DBDATA_PADDING_BYTES);
10687351633Scy      }
10688351633Scy      *ppPage = pPage;
10689351633Scy      *pnPage = nCopy;
10690351633Scy    }
10691351633Scy  }
10692351633Scy  rc2 = sqlite3_reset(pStmt);
10693351633Scy  if( rc==SQLITE_OK ) rc = rc2;
10694351633Scy
10695351633Scy  return rc;
10696351633Scy}
10697351633Scy
10698351633Scy/*
10699351633Scy** Read a varint.  Put the value in *pVal and return the number of bytes.
10700351633Scy*/
10701351633Scystatic int dbdataGetVarint(const u8 *z, sqlite3_int64 *pVal){
10702351633Scy  sqlite3_int64 v = 0;
10703351633Scy  int i;
10704351633Scy  for(i=0; i<8; i++){
10705351633Scy    v = (v<<7) + (z[i]&0x7f);
10706351633Scy    if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
10707351633Scy  }
10708351633Scy  v = (v<<8) + (z[i]&0xff);
10709351633Scy  *pVal = v;
10710351633Scy  return 9;
10711351633Scy}
10712351633Scy
10713351633Scy/*
10714351633Scy** Return the number of bytes of space used by an SQLite value of type
10715351633Scy** eType.
10716351633Scy*/
10717351633Scystatic int dbdataValueBytes(int eType){
10718351633Scy  switch( eType ){
10719351633Scy    case 0: case 8: case 9:
10720351633Scy    case 10: case 11:
10721351633Scy      return 0;
10722351633Scy    case 1:
10723351633Scy      return 1;
10724351633Scy    case 2:
10725351633Scy      return 2;
10726351633Scy    case 3:
10727351633Scy      return 3;
10728351633Scy    case 4:
10729351633Scy      return 4;
10730351633Scy    case 5:
10731351633Scy      return 6;
10732351633Scy    case 6:
10733351633Scy    case 7:
10734351633Scy      return 8;
10735351633Scy    default:
10736351633Scy      if( eType>0 ){
10737351633Scy        return ((eType-12) / 2);
10738351633Scy      }
10739351633Scy      return 0;
10740351633Scy  }
10741351633Scy}
10742351633Scy
10743351633Scy/*
10744351633Scy** Load a value of type eType from buffer pData and use it to set the
10745351633Scy** result of context object pCtx.
10746351633Scy*/
10747351633Scystatic void dbdataValue(
10748351633Scy  sqlite3_context *pCtx,
10749351633Scy  int eType,
10750351633Scy  u8 *pData,
10751351633Scy  int nData
10752351633Scy){
10753351633Scy  if( eType>=0 && dbdataValueBytes(eType)<=nData ){
10754351633Scy    switch( eType ){
10755351633Scy      case 0:
10756351633Scy      case 10:
10757351633Scy      case 11:
10758351633Scy        sqlite3_result_null(pCtx);
10759351633Scy        break;
10760351633Scy
10761351633Scy      case 8:
10762351633Scy        sqlite3_result_int(pCtx, 0);
10763351633Scy        break;
10764351633Scy      case 9:
10765351633Scy        sqlite3_result_int(pCtx, 1);
10766351633Scy        break;
10767351633Scy
10768351633Scy      case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
10769351633Scy        sqlite3_uint64 v = (signed char)pData[0];
10770351633Scy        pData++;
10771351633Scy        switch( eType ){
10772351633Scy          case 7:
10773351633Scy          case 6:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
10774351633Scy          case 5:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
10775351633Scy          case 4:  v = (v<<8) + pData[0];  pData++;
10776351633Scy          case 3:  v = (v<<8) + pData[0];  pData++;
10777351633Scy          case 2:  v = (v<<8) + pData[0];  pData++;
10778351633Scy        }
10779351633Scy
10780351633Scy        if( eType==7 ){
10781351633Scy          double r;
10782351633Scy          memcpy(&r, &v, sizeof(r));
10783351633Scy          sqlite3_result_double(pCtx, r);
10784351633Scy        }else{
10785351633Scy          sqlite3_result_int64(pCtx, (sqlite3_int64)v);
10786351633Scy        }
10787351633Scy        break;
10788351633Scy      }
10789351633Scy
10790351633Scy      default: {
10791351633Scy        int n = ((eType-12) / 2);
10792351633Scy        if( eType % 2 ){
10793351633Scy          sqlite3_result_text(pCtx, (const char*)pData, n, SQLITE_TRANSIENT);
10794351633Scy        }else{
10795351633Scy          sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
10796351633Scy        }
10797351633Scy      }
10798351633Scy    }
10799351633Scy  }
10800351633Scy}
10801351633Scy
10802351633Scy/*
10803351633Scy** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry.
10804351633Scy*/
10805351633Scystatic int dbdataNext(sqlite3_vtab_cursor *pCursor){
10806351633Scy  DbdataCursor *pCsr = (DbdataCursor*)pCursor;
10807351633Scy  DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
10808351633Scy
10809351633Scy  pCsr->iRowid++;
10810351633Scy  while( 1 ){
10811351633Scy    int rc;
10812351633Scy    int iOff = (pCsr->iPgno==1 ? 100 : 0);
10813351633Scy    int bNextPage = 0;
10814351633Scy
10815351633Scy    if( pCsr->aPage==0 ){
10816351633Scy      while( 1 ){
10817351633Scy        if( pCsr->bOnePage==0 && pCsr->iPgno>pCsr->szDb ) return SQLITE_OK;
10818351633Scy        rc = dbdataLoadPage(pCsr, pCsr->iPgno, &pCsr->aPage, &pCsr->nPage);
10819351633Scy        if( rc!=SQLITE_OK ) return rc;
10820351633Scy        if( pCsr->aPage ) break;
10821351633Scy        pCsr->iPgno++;
10822351633Scy      }
10823351633Scy      pCsr->iCell = pTab->bPtr ? -2 : 0;
10824351633Scy      pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]);
10825351633Scy    }
10826351633Scy
10827351633Scy    if( pTab->bPtr ){
10828351633Scy      if( pCsr->aPage[iOff]!=0x02 && pCsr->aPage[iOff]!=0x05 ){
10829351633Scy        pCsr->iCell = pCsr->nCell;
10830351633Scy      }
10831351633Scy      pCsr->iCell++;
10832351633Scy      if( pCsr->iCell>=pCsr->nCell ){
10833351633Scy        sqlite3_free(pCsr->aPage);
10834351633Scy        pCsr->aPage = 0;
10835351633Scy        if( pCsr->bOnePage ) return SQLITE_OK;
10836351633Scy        pCsr->iPgno++;
10837351633Scy      }else{
10838351633Scy        return SQLITE_OK;
10839351633Scy      }
10840351633Scy    }else{
10841351633Scy      /* If there is no record loaded, load it now. */
10842351633Scy      if( pCsr->pRec==0 ){
10843351633Scy        int bHasRowid = 0;
10844351633Scy        int nPointer = 0;
10845351633Scy        sqlite3_int64 nPayload = 0;
10846351633Scy        sqlite3_int64 nHdr = 0;
10847351633Scy        int iHdr;
10848351633Scy        int U, X;
10849351633Scy        int nLocal;
10850351633Scy
10851351633Scy        switch( pCsr->aPage[iOff] ){
10852351633Scy          case 0x02:
10853351633Scy            nPointer = 4;
10854351633Scy            break;
10855351633Scy          case 0x0a:
10856351633Scy            break;
10857351633Scy          case 0x0d:
10858351633Scy            bHasRowid = 1;
10859351633Scy            break;
10860351633Scy          default:
10861351633Scy            /* This is not a b-tree page with records on it. Continue. */
10862351633Scy            pCsr->iCell = pCsr->nCell;
10863351633Scy            break;
10864351633Scy        }
10865351633Scy
10866351633Scy        if( pCsr->iCell>=pCsr->nCell ){
10867351633Scy          bNextPage = 1;
10868351633Scy        }else{
10869351633Scy
10870351633Scy          iOff += 8 + nPointer + pCsr->iCell*2;
10871351633Scy          if( iOff>pCsr->nPage ){
10872351633Scy            bNextPage = 1;
10873351633Scy          }else{
10874351633Scy            iOff = get_uint16(&pCsr->aPage[iOff]);
10875351633Scy          }
10876351633Scy
10877351633Scy          /* For an interior node cell, skip past the child-page number */
10878351633Scy          iOff += nPointer;
10879351633Scy
10880351633Scy          /* Load the "byte of payload including overflow" field */
10881351633Scy          if( bNextPage || iOff>pCsr->nPage ){
10882351633Scy            bNextPage = 1;
10883351633Scy          }else{
10884351633Scy            iOff += dbdataGetVarint(&pCsr->aPage[iOff], &nPayload);
10885351633Scy          }
10886351633Scy
10887351633Scy          /* If this is a leaf intkey cell, load the rowid */
10888351633Scy          if( bHasRowid && !bNextPage && iOff<pCsr->nPage ){
10889351633Scy            iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey);
10890351633Scy          }
10891351633Scy
10892351633Scy          /* Figure out how much data to read from the local page */
10893351633Scy          U = pCsr->nPage;
10894351633Scy          if( bHasRowid ){
10895351633Scy            X = U-35;
10896351633Scy          }else{
10897351633Scy            X = ((U-12)*64/255)-23;
10898351633Scy          }
10899351633Scy          if( nPayload<=X ){
10900351633Scy            nLocal = nPayload;
10901351633Scy          }else{
10902351633Scy            int M, K;
10903351633Scy            M = ((U-12)*32/255)-23;
10904351633Scy            K = M+((nPayload-M)%(U-4));
10905351633Scy            if( K<=X ){
10906351633Scy              nLocal = K;
10907351633Scy            }else{
10908351633Scy              nLocal = M;
10909351633Scy            }
10910351633Scy          }
10911351633Scy
10912351633Scy          if( bNextPage || nLocal+iOff>pCsr->nPage ){
10913351633Scy            bNextPage = 1;
10914351633Scy          }else{
10915351633Scy
10916351633Scy            /* Allocate space for payload. And a bit more to catch small buffer
10917351633Scy            ** overruns caused by attempting to read a varint or similar from
10918351633Scy            ** near the end of a corrupt record.  */
10919351633Scy            pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES);
10920351633Scy            if( pCsr->pRec==0 ) return SQLITE_NOMEM;
10921351633Scy            memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES);
10922351633Scy            pCsr->nRec = nPayload;
10923351633Scy
10924351633Scy            /* Load the nLocal bytes of payload */
10925351633Scy            memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal);
10926351633Scy            iOff += nLocal;
10927351633Scy
10928351633Scy            /* Load content from overflow pages */
10929351633Scy            if( nPayload>nLocal ){
10930351633Scy              sqlite3_int64 nRem = nPayload - nLocal;
10931351633Scy              unsigned int pgnoOvfl = get_uint32(&pCsr->aPage[iOff]);
10932351633Scy              while( nRem>0 ){
10933351633Scy                u8 *aOvfl = 0;
10934351633Scy                int nOvfl = 0;
10935351633Scy                int nCopy;
10936351633Scy                rc = dbdataLoadPage(pCsr, pgnoOvfl, &aOvfl, &nOvfl);
10937351633Scy                assert( rc!=SQLITE_OK || aOvfl==0 || nOvfl==pCsr->nPage );
10938351633Scy                if( rc!=SQLITE_OK ) return rc;
10939351633Scy                if( aOvfl==0 ) break;
10940351633Scy
10941351633Scy                nCopy = U-4;
10942351633Scy                if( nCopy>nRem ) nCopy = nRem;
10943351633Scy                memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy);
10944351633Scy                nRem -= nCopy;
10945351633Scy
10946351633Scy                pgnoOvfl = get_uint32(aOvfl);
10947351633Scy                sqlite3_free(aOvfl);
10948351633Scy              }
10949351633Scy            }
10950351633Scy
10951351633Scy            iHdr = dbdataGetVarint(pCsr->pRec, &nHdr);
10952351633Scy            pCsr->nHdr = nHdr;
10953351633Scy            pCsr->pHdrPtr = &pCsr->pRec[iHdr];
10954351633Scy            pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
10955351633Scy            pCsr->iField = (bHasRowid ? -1 : 0);
10956351633Scy          }
10957351633Scy        }
10958351633Scy      }else{
10959351633Scy        pCsr->iField++;
10960351633Scy        if( pCsr->iField>0 ){
10961351633Scy          sqlite3_int64 iType;
10962351633Scy          if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){
10963351633Scy            bNextPage = 1;
10964351633Scy          }else{
10965351633Scy            pCsr->pHdrPtr += dbdataGetVarint(pCsr->pHdrPtr, &iType);
10966351633Scy            pCsr->pPtr += dbdataValueBytes(iType);
10967351633Scy          }
10968351633Scy        }
10969351633Scy      }
10970351633Scy
10971351633Scy      if( bNextPage ){
10972351633Scy        sqlite3_free(pCsr->aPage);
10973351633Scy        sqlite3_free(pCsr->pRec);
10974351633Scy        pCsr->aPage = 0;
10975351633Scy        pCsr->pRec = 0;
10976351633Scy        if( pCsr->bOnePage ) return SQLITE_OK;
10977351633Scy        pCsr->iPgno++;
10978351633Scy      }else{
10979351633Scy        if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){
10980351633Scy          return SQLITE_OK;
10981351633Scy        }
10982351633Scy
10983351633Scy        /* Advance to the next cell. The next iteration of the loop will load
10984351633Scy        ** the record and so on. */
10985351633Scy        sqlite3_free(pCsr->pRec);
10986351633Scy        pCsr->pRec = 0;
10987351633Scy        pCsr->iCell++;
10988351633Scy      }
10989351633Scy    }
10990351633Scy  }
10991351633Scy
10992351633Scy  assert( !"can't get here" );
10993351633Scy  return SQLITE_OK;
10994351633Scy}
10995351633Scy
10996351633Scy/*
10997351633Scy** Return true if the cursor is at EOF.
10998351633Scy*/
10999351633Scystatic int dbdataEof(sqlite3_vtab_cursor *pCursor){
11000351633Scy  DbdataCursor *pCsr = (DbdataCursor*)pCursor;
11001351633Scy  return pCsr->aPage==0;
11002351633Scy}
11003351633Scy
11004351633Scy/*
11005351633Scy** Determine the size in pages of database zSchema (where zSchema is
11006351633Scy** "main", "temp" or the name of an attached database) and set
11007351633Scy** pCsr->szDb accordingly. If successful, return SQLITE_OK. Otherwise,
11008351633Scy** an SQLite error code.
11009351633Scy*/
11010351633Scystatic int dbdataDbsize(DbdataCursor *pCsr, const char *zSchema){
11011351633Scy  DbdataTable *pTab = (DbdataTable*)pCsr->base.pVtab;
11012351633Scy  char *zSql = 0;
11013351633Scy  int rc, rc2;
11014351633Scy  sqlite3_stmt *pStmt = 0;
11015351633Scy
11016351633Scy  zSql = sqlite3_mprintf("PRAGMA %Q.page_count", zSchema);
11017351633Scy  if( zSql==0 ) return SQLITE_NOMEM;
11018351633Scy  rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pStmt, 0);
11019351633Scy  sqlite3_free(zSql);
11020351633Scy  if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
11021351633Scy    pCsr->szDb = sqlite3_column_int(pStmt, 0);
11022351633Scy  }
11023351633Scy  rc2 = sqlite3_finalize(pStmt);
11024351633Scy  if( rc==SQLITE_OK ) rc = rc2;
11025351633Scy  return rc;
11026351633Scy}
11027351633Scy
11028351633Scy/*
11029351633Scy** xFilter method for sqlite_dbdata and sqlite_dbptr.
11030351633Scy*/
11031351633Scystatic int dbdataFilter(
11032351633Scy  sqlite3_vtab_cursor *pCursor,
11033351633Scy  int idxNum, const char *idxStr,
11034351633Scy  int argc, sqlite3_value **argv
11035351633Scy){
11036351633Scy  DbdataCursor *pCsr = (DbdataCursor*)pCursor;
11037351633Scy  DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
11038351633Scy  int rc = SQLITE_OK;
11039351633Scy  const char *zSchema = "main";
11040351633Scy
11041351633Scy  dbdataResetCursor(pCsr);
11042351633Scy  assert( pCsr->iPgno==1 );
11043351633Scy  if( idxNum & 0x01 ){
11044351633Scy    zSchema = (const char*)sqlite3_value_text(argv[0]);
11045351633Scy  }
11046351633Scy  if( idxNum & 0x02 ){
11047351633Scy    pCsr->iPgno = sqlite3_value_int(argv[(idxNum & 0x01)]);
11048351633Scy    pCsr->bOnePage = 1;
11049351633Scy  }else{
11050351633Scy    pCsr->nPage = dbdataDbsize(pCsr, zSchema);
11051351633Scy    rc = dbdataDbsize(pCsr, zSchema);
11052351633Scy  }
11053351633Scy
11054351633Scy  if( rc==SQLITE_OK ){
11055351633Scy    if( pTab->pStmt ){
11056351633Scy      pCsr->pStmt = pTab->pStmt;
11057351633Scy      pTab->pStmt = 0;
11058351633Scy    }else{
11059351633Scy      rc = sqlite3_prepare_v2(pTab->db,
11060351633Scy          "SELECT data FROM sqlite_dbpage(?) WHERE pgno=?", -1,
11061351633Scy          &pCsr->pStmt, 0
11062351633Scy      );
11063351633Scy    }
11064351633Scy  }
11065351633Scy  if( rc==SQLITE_OK ){
11066351633Scy    rc = sqlite3_bind_text(pCsr->pStmt, 1, zSchema, -1, SQLITE_TRANSIENT);
11067351633Scy  }else{
11068351633Scy    pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
11069351633Scy  }
11070351633Scy  if( rc==SQLITE_OK ){
11071351633Scy    rc = dbdataNext(pCursor);
11072351633Scy  }
11073351633Scy  return rc;
11074351633Scy}
11075351633Scy
11076351633Scy/*
11077351633Scy** Return a column for the sqlite_dbdata or sqlite_dbptr table.
11078351633Scy*/
11079351633Scystatic int dbdataColumn(
11080351633Scy  sqlite3_vtab_cursor *pCursor,
11081351633Scy  sqlite3_context *ctx,
11082351633Scy  int i
11083351633Scy){
11084351633Scy  DbdataCursor *pCsr = (DbdataCursor*)pCursor;
11085351633Scy  DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
11086351633Scy  if( pTab->bPtr ){
11087351633Scy    switch( i ){
11088351633Scy      case DBPTR_COLUMN_PGNO:
11089351633Scy        sqlite3_result_int64(ctx, pCsr->iPgno);
11090351633Scy        break;
11091351633Scy      case DBPTR_COLUMN_CHILD: {
11092351633Scy        int iOff = pCsr->iPgno==1 ? 100 : 0;
11093351633Scy        if( pCsr->iCell<0 ){
11094351633Scy          iOff += 8;
11095351633Scy        }else{
11096351633Scy          iOff += 12 + pCsr->iCell*2;
11097351633Scy          if( iOff>pCsr->nPage ) return SQLITE_OK;
11098351633Scy          iOff = get_uint16(&pCsr->aPage[iOff]);
11099351633Scy        }
11100351633Scy        if( iOff<=pCsr->nPage ){
11101351633Scy          sqlite3_result_int64(ctx, get_uint32(&pCsr->aPage[iOff]));
11102351633Scy        }
11103351633Scy        break;
11104351633Scy      }
11105351633Scy    }
11106351633Scy  }else{
11107351633Scy    switch( i ){
11108351633Scy      case DBDATA_COLUMN_PGNO:
11109351633Scy        sqlite3_result_int64(ctx, pCsr->iPgno);
11110351633Scy        break;
11111351633Scy      case DBDATA_COLUMN_CELL:
11112351633Scy        sqlite3_result_int(ctx, pCsr->iCell);
11113351633Scy        break;
11114351633Scy      case DBDATA_COLUMN_FIELD:
11115351633Scy        sqlite3_result_int(ctx, pCsr->iField);
11116351633Scy        break;
11117351633Scy      case DBDATA_COLUMN_VALUE: {
11118351633Scy        if( pCsr->iField<0 ){
11119351633Scy          sqlite3_result_int64(ctx, pCsr->iIntkey);
11120351633Scy        }else{
11121351633Scy          sqlite3_int64 iType;
11122351633Scy          dbdataGetVarint(pCsr->pHdrPtr, &iType);
11123351633Scy          dbdataValue(
11124351633Scy              ctx, iType, pCsr->pPtr, &pCsr->pRec[pCsr->nRec] - pCsr->pPtr
11125351633Scy          );
11126351633Scy        }
11127351633Scy        break;
11128351633Scy      }
11129351633Scy    }
11130351633Scy  }
11131351633Scy  return SQLITE_OK;
11132351633Scy}
11133351633Scy
11134351633Scy/*
11135351633Scy** Return the rowid for an sqlite_dbdata or sqlite_dptr table.
11136351633Scy*/
11137351633Scystatic int dbdataRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
11138351633Scy  DbdataCursor *pCsr = (DbdataCursor*)pCursor;
11139351633Scy  *pRowid = pCsr->iRowid;
11140351633Scy  return SQLITE_OK;
11141351633Scy}
11142351633Scy
11143351633Scy
11144351633Scy/*
11145351633Scy** Invoke this routine to register the "sqlite_dbdata" virtual table module
11146351633Scy*/
11147351633Scystatic int sqlite3DbdataRegister(sqlite3 *db){
11148351633Scy  static sqlite3_module dbdata_module = {
11149351633Scy    0,                            /* iVersion */
11150351633Scy    0,                            /* xCreate */
11151351633Scy    dbdataConnect,                /* xConnect */
11152351633Scy    dbdataBestIndex,              /* xBestIndex */
11153351633Scy    dbdataDisconnect,             /* xDisconnect */
11154351633Scy    0,                            /* xDestroy */
11155351633Scy    dbdataOpen,                   /* xOpen - open a cursor */
11156351633Scy    dbdataClose,                  /* xClose - close a cursor */
11157351633Scy    dbdataFilter,                 /* xFilter - configure scan constraints */
11158351633Scy    dbdataNext,                   /* xNext - advance a cursor */
11159351633Scy    dbdataEof,                    /* xEof - check for end of scan */
11160351633Scy    dbdataColumn,                 /* xColumn - read data */
11161351633Scy    dbdataRowid,                  /* xRowid - read data */
11162351633Scy    0,                            /* xUpdate */
11163351633Scy    0,                            /* xBegin */
11164351633Scy    0,                            /* xSync */
11165351633Scy    0,                            /* xCommit */
11166351633Scy    0,                            /* xRollback */
11167351633Scy    0,                            /* xFindMethod */
11168351633Scy    0,                            /* xRename */
11169351633Scy    0,                            /* xSavepoint */
11170351633Scy    0,                            /* xRelease */
11171351633Scy    0,                            /* xRollbackTo */
11172351633Scy    0                             /* xShadowName */
11173351633Scy  };
11174351633Scy
11175351633Scy  int rc = sqlite3_create_module(db, "sqlite_dbdata", &dbdata_module, 0);
11176351633Scy  if( rc==SQLITE_OK ){
11177351633Scy    rc = sqlite3_create_module(db, "sqlite_dbptr", &dbdata_module, (void*)1);
11178351633Scy  }
11179351633Scy  return rc;
11180351633Scy}
11181351633Scy
11182351633Scy#ifdef _WIN32
11183351633Scy
11184351633Scy#endif
11185351633Scyint sqlite3_dbdata_init(
11186351633Scy  sqlite3 *db,
11187351633Scy  char **pzErrMsg,
11188351633Scy  const sqlite3_api_routines *pApi
11189351633Scy){
11190351633Scy  SQLITE_EXTENSION_INIT2(pApi);
11191351633Scy  return sqlite3DbdataRegister(db);
11192351633Scy}
11193351633Scy
11194351633Scy/************************* End ../ext/misc/dbdata.c ********************/
11195351633Scy#endif
11196351633Scy
11197305002Scy#if defined(SQLITE_ENABLE_SESSION)
11198274884Sbapt/*
11199305002Scy** State information for a single open session
11200298161Sbapt*/
11201305002Scytypedef struct OpenSession OpenSession;
11202305002Scystruct OpenSession {
11203305002Scy  char *zName;             /* Symbolic name for this session */
11204305002Scy  int nFilter;             /* Number of xFilter rejection GLOB patterns */
11205305002Scy  char **azFilter;         /* Array of xFilter rejection GLOB patterns */
11206305002Scy  sqlite3_session *p;      /* The open session */
11207305002Scy};
11208298161Sbapt#endif
11209298161Sbapt
11210342292Scytypedef struct ExpertInfo ExpertInfo;
11211342292Scystruct ExpertInfo {
11212342292Scy  sqlite3expert *pExpert;
11213342292Scy  int bVerbose;
11214342292Scy};
11215342292Scy
11216342292Scy/* A single line in the EQP output */
11217342292Scytypedef struct EQPGraphRow EQPGraphRow;
11218342292Scystruct EQPGraphRow {
11219342292Scy  int iEqpId;           /* ID for this row */
11220342292Scy  int iParentId;        /* ID of the parent row */
11221342292Scy  EQPGraphRow *pNext;   /* Next row in sequence */
11222342292Scy  char zText[1];        /* Text to display for this row */
11223342292Scy};
11224342292Scy
11225342292Scy/* All EQP output is collected into an instance of the following */
11226342292Scytypedef struct EQPGraph EQPGraph;
11227342292Scystruct EQPGraph {
11228342292Scy  EQPGraphRow *pRow;    /* Linked list of all rows of the EQP output */
11229342292Scy  EQPGraphRow *pLast;   /* Last element of the pRow list */
11230342292Scy  char zPrefix[100];    /* Graph prefix */
11231342292Scy};
11232342292Scy
11233251883Speter/*
11234274884Sbapt** State information about the database connection is contained in an
11235274884Sbapt** instance of the following structure.
11236251883Speter*/
11237274884Sbapttypedef struct ShellState ShellState;
11238274884Sbaptstruct ShellState {
11239251883Speter  sqlite3 *db;           /* The database */
11240342292Scy  u8 autoExplain;        /* Automatically turn on .explain mode */
11241342292Scy  u8 autoEQP;            /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
11242342292Scy  u8 autoEQPtest;        /* autoEQP is in test mode */
11243346442Scy  u8 autoEQPtrace;       /* autoEQP is in trace mode */
11244342292Scy  u8 scanstatsOn;        /* True to display scan stats before each finalize */
11245342292Scy  u8 openMode;           /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
11246342292Scy  u8 doXdgOpen;          /* Invoke start/open/xdg-open in output_reset() */
11247342292Scy  u8 nEqpLevel;          /* Depth of the EQP output graph */
11248346442Scy  u8 eTraceType;         /* SHELL_TRACE_* value for type of trace */
11249369951Scy  unsigned statsOn;      /* True to display memory stats before each finalize */
11250342292Scy  unsigned mEqpLines;    /* Mask of veritical lines in the EQP output graph */
11251269851Speter  int outCount;          /* Revert to stdout when reaching zero */
11252251883Speter  int cnt;               /* Number of records displayed so far */
11253346442Scy  int lineno;            /* Line number of last line read from in */
11254361456Scy  int openFlags;         /* Additional flags to open.  (SQLITE_OPEN_NOFOLLOW) */
11255346442Scy  FILE *in;              /* Read commands from this stream */
11256251883Speter  FILE *out;             /* Write results here */
11257251883Speter  FILE *traceOut;        /* Output for sqlite3_trace() */
11258251883Speter  int nErr;              /* Number of errors seen */
11259251883Speter  int mode;              /* An output mode setting */
11260342292Scy  int modePrior;         /* Saved mode */
11261298161Sbapt  int cMode;             /* temporary output mode for the current query */
11262298161Sbapt  int normalMode;        /* Output mode before ".explain on" */
11263251883Speter  int writableSchema;    /* True if PRAGMA writable_schema=ON */
11264251883Speter  int showHeader;        /* True to show column names in List or Column mode */
11265322444Speter  int nCheck;            /* Number of ".check" commands run */
11266346442Scy  unsigned nProgress;    /* Number of progress callbacks encountered */
11267346442Scy  unsigned mxProgress;   /* Maximum progress callbacks before failing */
11268346442Scy  unsigned flgProgress;  /* Flags for the progress callback */
11269274884Sbapt  unsigned shellFlgs;    /* Various flags */
11270362190Scy  unsigned priorShFlgs;  /* Saved copy of flags */
11271346442Scy  sqlite3_int64 szMax;   /* --maxsize argument to .open */
11272251883Speter  char *zDestTable;      /* Name of destination table when MODE_Insert */
11273342292Scy  char *zTempFile;       /* Temporary file that might need deleting */
11274322444Speter  char zTestcase[30];    /* Name of current test case */
11275282328Sbapt  char colSeparator[20]; /* Column separator character for several modes */
11276282328Sbapt  char rowSeparator[20]; /* Row separator character for MODE_Ascii */
11277342292Scy  char colSepPrior[20];  /* Saved column separator */
11278342292Scy  char rowSepPrior[20];  /* Saved row separator */
11279366076Scy  int *colWidth;         /* Requested width of each column in columnar modes */
11280366076Scy  int *actualWidth;      /* Actual width of each column */
11281366076Scy  int nWidth;            /* Number of slots in colWidth[] and actualWidth[] */
11282282328Sbapt  char nullValue[20];    /* The text to print when a NULL comes back from
11283251883Speter                         ** the database */
11284251883Speter  char outfile[FILENAME_MAX]; /* Filename for *out */
11285251883Speter  const char *zDbFilename;    /* name of the database file */
11286269851Speter  char *zFreeOnClose;         /* Filename to free when closing */
11287251883Speter  const char *zVfs;           /* Name of VFS to use */
11288251883Speter  sqlite3_stmt *pStmt;   /* Current statement if any. */
11289251883Speter  FILE *pLog;            /* Write log output here */
11290269851Speter  int *aiIndent;         /* Array of indents used in MODE_Explain */
11291269851Speter  int nIndent;           /* Size of array aiIndent[] */
11292269851Speter  int iIndent;           /* Index of current op in aiIndent[] */
11293342292Scy  EQPGraph sGraph;       /* Information for the graphical EXPLAIN QUERY PLAN */
11294305002Scy#if defined(SQLITE_ENABLE_SESSION)
11295305002Scy  int nSession;             /* Number of active sessions */
11296305002Scy  OpenSession aSession[4];  /* Array of sessions.  [0] is in focus. */
11297305002Scy#endif
11298342292Scy  ExpertInfo expert;        /* Valid if previous command was ".expert OPT..." */
11299251883Speter};
11300251883Speter
11301342292Scy
11302342292Scy/* Allowed values for ShellState.autoEQP
11303342292Scy*/
11304342292Scy#define AUTOEQP_off      0           /* Automatic EXPLAIN QUERY PLAN is off */
11305342292Scy#define AUTOEQP_on       1           /* Automatic EQP is on */
11306342292Scy#define AUTOEQP_trigger  2           /* On and also show plans for triggers */
11307342292Scy#define AUTOEQP_full     3           /* Show full EXPLAIN */
11308342292Scy
11309342292Scy/* Allowed values for ShellState.openMode
11310342292Scy*/
11311342292Scy#define SHELL_OPEN_UNSPEC      0      /* No open-mode specified */
11312342292Scy#define SHELL_OPEN_NORMAL      1      /* Normal database file */
11313342292Scy#define SHELL_OPEN_APPENDVFS   2      /* Use appendvfs */
11314342292Scy#define SHELL_OPEN_ZIPFILE     3      /* Use the zipfile virtual table */
11315342292Scy#define SHELL_OPEN_READONLY    4      /* Open a normal database read-only */
11316342292Scy#define SHELL_OPEN_DESERIALIZE 5      /* Open using sqlite3_deserialize() */
11317346442Scy#define SHELL_OPEN_HEXDB       6      /* Use "dbtotxt" output as data source */
11318342292Scy
11319346442Scy/* Allowed values for ShellState.eTraceType
11320346442Scy*/
11321346442Scy#define SHELL_TRACE_PLAIN      0      /* Show input SQL text */
11322346442Scy#define SHELL_TRACE_EXPANDED   1      /* Show expanded SQL text */
11323346442Scy#define SHELL_TRACE_NORMALIZED 2      /* Show normalized SQL text */
11324346442Scy
11325346442Scy/* Bits in the ShellState.flgProgress variable */
11326346442Scy#define SHELL_PROGRESS_QUIET 0x01  /* Omit announcing every progress callback */
11327346442Scy#define SHELL_PROGRESS_RESET 0x02  /* Reset the count when the progres
11328346442Scy                                   ** callback limit is reached, and for each
11329346442Scy                                   ** top-level SQL statement */
11330346442Scy#define SHELL_PROGRESS_ONCE  0x04  /* Cancel the --limit after firing once */
11331346442Scy
11332251883Speter/*
11333274884Sbapt** These are the allowed shellFlgs values
11334274884Sbapt*/
11335342292Scy#define SHFLG_Pagecache      0x00000001 /* The --pagecache option is used */
11336342292Scy#define SHFLG_Lookaside      0x00000002 /* Lookaside memory is used */
11337342292Scy#define SHFLG_Backslash      0x00000004 /* The --backslash option is used */
11338342292Scy#define SHFLG_PreserveRowid  0x00000008 /* .dump preserves rowid values */
11339342292Scy#define SHFLG_Newlines       0x00000010 /* .dump --newline flag */
11340342292Scy#define SHFLG_CountChanges   0x00000020 /* .changes setting */
11341342292Scy#define SHFLG_Echo           0x00000040 /* .echo or --echo setting */
11342366076Scy#define SHFLG_HeaderSet      0x00000080 /* .header has been used */
11343369950Scy#define SHFLG_DumpDataOnly   0x00000100 /* .dump show data only */
11344369950Scy#define SHFLG_DumpNoSys      0x00000200 /* .dump omits system tables */
11345274884Sbapt
11346274884Sbapt/*
11347322444Speter** Macros for testing and setting shellFlgs
11348322444Speter*/
11349322444Speter#define ShellHasFlag(P,X)    (((P)->shellFlgs & (X))!=0)
11350322444Speter#define ShellSetFlag(P,X)    ((P)->shellFlgs|=(X))
11351322444Speter#define ShellClearFlag(P,X)  ((P)->shellFlgs&=(~(X)))
11352322444Speter
11353322444Speter/*
11354251883Speter** These are the allowed modes.
11355251883Speter*/
11356251883Speter#define MODE_Line     0  /* One column per line.  Blank line between records */
11357251883Speter#define MODE_Column   1  /* One record per line in neat columns */
11358251883Speter#define MODE_List     2  /* One record per line with a separator */
11359251883Speter#define MODE_Semi     3  /* Same as MODE_List but append ";" to each line */
11360251883Speter#define MODE_Html     4  /* Generate an XHTML table */
11361251883Speter#define MODE_Insert   5  /* Generate SQL "insert" statements */
11362322444Speter#define MODE_Quote    6  /* Quote values as for SQL */
11363322444Speter#define MODE_Tcl      7  /* Generate ANSI-C or TCL quoted elements */
11364322444Speter#define MODE_Csv      8  /* Quote strings, numbers are plain */
11365322444Speter#define MODE_Explain  9  /* Like MODE_Column, but do not truncate data */
11366322444Speter#define MODE_Ascii   10  /* Use ASCII unit and record separators (0x1F/0x1E) */
11367322444Speter#define MODE_Pretty  11  /* Pretty-print schemas */
11368342292Scy#define MODE_EQP     12  /* Converts EXPLAIN QUERY PLAN output into a graph */
11369366076Scy#define MODE_Json    13  /* Output JSON */
11370366076Scy#define MODE_Markdown 14 /* Markdown formatting */
11371366076Scy#define MODE_Table   15  /* MySQL-style table formatting */
11372366076Scy#define MODE_Box     16  /* Unicode box-drawing characters */
11373251883Speter
11374251883Speterstatic const char *modeDescr[] = {
11375251883Speter  "line",
11376251883Speter  "column",
11377251883Speter  "list",
11378251883Speter  "semi",
11379251883Speter  "html",
11380251883Speter  "insert",
11381322444Speter  "quote",
11382251883Speter  "tcl",
11383251883Speter  "csv",
11384251883Speter  "explain",
11385282328Sbapt  "ascii",
11386305002Scy  "prettyprint",
11387366076Scy  "eqp",
11388366076Scy  "json",
11389366076Scy  "markdown",
11390366076Scy  "table",
11391366076Scy  "box"
11392251883Speter};
11393251883Speter
11394251883Speter/*
11395282328Sbapt** These are the column/row/line separators used by the various
11396282328Sbapt** import/export modes.
11397282328Sbapt*/
11398282328Sbapt#define SEP_Column    "|"
11399282328Sbapt#define SEP_Row       "\n"
11400282328Sbapt#define SEP_Tab       "\t"
11401282328Sbapt#define SEP_Space     " "
11402282328Sbapt#define SEP_Comma     ","
11403282328Sbapt#define SEP_CrLf      "\r\n"
11404282328Sbapt#define SEP_Unit      "\x1F"
11405282328Sbapt#define SEP_Record    "\x1E"
11406282328Sbapt
11407282328Sbapt/*
11408251883Speter** A callback for the sqlite3_log() interface.
11409251883Speter*/
11410251883Speterstatic void shellLog(void *pArg, int iErrCode, const char *zMsg){
11411274884Sbapt  ShellState *p = (ShellState*)pArg;
11412251883Speter  if( p->pLog==0 ) return;
11413298161Sbapt  utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
11414251883Speter  fflush(p->pLog);
11415251883Speter}
11416251883Speter
11417251883Speter/*
11418342292Scy** SQL function:  shell_putsnl(X)
11419342292Scy**
11420342292Scy** Write the text X to the screen (or whatever output is being directed)
11421342292Scy** adding a newline at the end, and then return X.
11422342292Scy*/
11423342292Scystatic void shellPutsFunc(
11424342292Scy  sqlite3_context *pCtx,
11425342292Scy  int nVal,
11426342292Scy  sqlite3_value **apVal
11427342292Scy){
11428342292Scy  ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
11429342292Scy  (void)nVal;
11430342292Scy  utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
11431342292Scy  sqlite3_result_value(pCtx, apVal[0]);
11432342292Scy}
11433342292Scy
11434342292Scy/*
11435342292Scy** SQL function:   edit(VALUE)
11436342292Scy**                 edit(VALUE,EDITOR)
11437342292Scy**
11438342292Scy** These steps:
11439342292Scy**
11440342292Scy**     (1) Write VALUE into a temporary file.
11441342292Scy**     (2) Run program EDITOR on that temporary file.
11442342292Scy**     (3) Read the temporary file back and return its content as the result.
11443342292Scy**     (4) Delete the temporary file
11444342292Scy**
11445342292Scy** If the EDITOR argument is omitted, use the value in the VISUAL
11446342292Scy** environment variable.  If still there is no EDITOR, through an error.
11447342292Scy**
11448342292Scy** Also throw an error if the EDITOR program returns a non-zero exit code.
11449342292Scy*/
11450342292Scy#ifndef SQLITE_NOHAVE_SYSTEM
11451342292Scystatic void editFunc(
11452342292Scy  sqlite3_context *context,
11453342292Scy  int argc,
11454342292Scy  sqlite3_value **argv
11455342292Scy){
11456342292Scy  const char *zEditor;
11457342292Scy  char *zTempFile = 0;
11458342292Scy  sqlite3 *db;
11459342292Scy  char *zCmd = 0;
11460342292Scy  int bBin;
11461342292Scy  int rc;
11462342292Scy  int hasCRNL = 0;
11463342292Scy  FILE *f = 0;
11464342292Scy  sqlite3_int64 sz;
11465342292Scy  sqlite3_int64 x;
11466342292Scy  unsigned char *p = 0;
11467342292Scy
11468342292Scy  if( argc==2 ){
11469342292Scy    zEditor = (const char*)sqlite3_value_text(argv[1]);
11470342292Scy  }else{
11471342292Scy    zEditor = getenv("VISUAL");
11472342292Scy  }
11473342292Scy  if( zEditor==0 ){
11474342292Scy    sqlite3_result_error(context, "no editor for edit()", -1);
11475342292Scy    return;
11476342292Scy  }
11477342292Scy  if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
11478342292Scy    sqlite3_result_error(context, "NULL input to edit()", -1);
11479342292Scy    return;
11480342292Scy  }
11481342292Scy  db = sqlite3_context_db_handle(context);
11482342292Scy  zTempFile = 0;
11483342292Scy  sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile);
11484342292Scy  if( zTempFile==0 ){
11485342292Scy    sqlite3_uint64 r = 0;
11486342292Scy    sqlite3_randomness(sizeof(r), &r);
11487342292Scy    zTempFile = sqlite3_mprintf("temp%llx", r);
11488342292Scy    if( zTempFile==0 ){
11489342292Scy      sqlite3_result_error_nomem(context);
11490342292Scy      return;
11491342292Scy    }
11492342292Scy  }
11493342292Scy  bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB;
11494342292Scy  /* When writing the file to be edited, do \n to \r\n conversions on systems
11495342292Scy  ** that want \r\n line endings */
11496342292Scy  f = fopen(zTempFile, bBin ? "wb" : "w");
11497342292Scy  if( f==0 ){
11498342292Scy    sqlite3_result_error(context, "edit() cannot open temp file", -1);
11499342292Scy    goto edit_func_end;
11500342292Scy  }
11501342292Scy  sz = sqlite3_value_bytes(argv[0]);
11502342292Scy  if( bBin ){
11503355326Scy    x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f);
11504342292Scy  }else{
11505342292Scy    const char *z = (const char*)sqlite3_value_text(argv[0]);
11506342292Scy    /* Remember whether or not the value originally contained \r\n */
11507342292Scy    if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
11508355326Scy    x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f);
11509342292Scy  }
11510342292Scy  fclose(f);
11511342292Scy  f = 0;
11512342292Scy  if( x!=sz ){
11513342292Scy    sqlite3_result_error(context, "edit() could not write the whole file", -1);
11514342292Scy    goto edit_func_end;
11515342292Scy  }
11516342292Scy  zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile);
11517342292Scy  if( zCmd==0 ){
11518342292Scy    sqlite3_result_error_nomem(context);
11519342292Scy    goto edit_func_end;
11520342292Scy  }
11521342292Scy  rc = system(zCmd);
11522342292Scy  sqlite3_free(zCmd);
11523342292Scy  if( rc ){
11524342292Scy    sqlite3_result_error(context, "EDITOR returned non-zero", -1);
11525342292Scy    goto edit_func_end;
11526342292Scy  }
11527342292Scy  f = fopen(zTempFile, "rb");
11528342292Scy  if( f==0 ){
11529342292Scy    sqlite3_result_error(context,
11530342292Scy      "edit() cannot reopen temp file after edit", -1);
11531342292Scy    goto edit_func_end;
11532342292Scy  }
11533342292Scy  fseek(f, 0, SEEK_END);
11534342292Scy  sz = ftell(f);
11535342292Scy  rewind(f);
11536355326Scy  p = sqlite3_malloc64( sz+1 );
11537342292Scy  if( p==0 ){
11538342292Scy    sqlite3_result_error_nomem(context);
11539342292Scy    goto edit_func_end;
11540342292Scy  }
11541355326Scy  x = fread(p, 1, (size_t)sz, f);
11542342292Scy  fclose(f);
11543342292Scy  f = 0;
11544342292Scy  if( x!=sz ){
11545342292Scy    sqlite3_result_error(context, "could not read back the whole file", -1);
11546342292Scy    goto edit_func_end;
11547342292Scy  }
11548342292Scy  if( bBin ){
11549342292Scy    sqlite3_result_blob64(context, p, sz, sqlite3_free);
11550342292Scy  }else{
11551342292Scy    sqlite3_int64 i, j;
11552342292Scy    if( hasCRNL ){
11553342292Scy      /* If the original contains \r\n then do no conversions back to \n */
11554342292Scy      j = sz;
11555342292Scy    }else{
11556342292Scy      /* If the file did not originally contain \r\n then convert any new
11557342292Scy      ** \r\n back into \n */
11558342292Scy      for(i=j=0; i<sz; i++){
11559342292Scy        if( p[i]=='\r' && p[i+1]=='\n' ) i++;
11560342292Scy        p[j++] = p[i];
11561342292Scy      }
11562342292Scy      sz = j;
11563342292Scy      p[sz] = 0;
11564342292Scy    }
11565342292Scy    sqlite3_result_text64(context, (const char*)p, sz,
11566342292Scy                          sqlite3_free, SQLITE_UTF8);
11567342292Scy  }
11568342292Scy  p = 0;
11569342292Scy
11570342292Scyedit_func_end:
11571342292Scy  if( f ) fclose(f);
11572342292Scy  unlink(zTempFile);
11573342292Scy  sqlite3_free(zTempFile);
11574342292Scy  sqlite3_free(p);
11575342292Scy}
11576342292Scy#endif /* SQLITE_NOHAVE_SYSTEM */
11577342292Scy
11578342292Scy/*
11579342292Scy** Save or restore the current output mode
11580342292Scy*/
11581342292Scystatic void outputModePush(ShellState *p){
11582342292Scy  p->modePrior = p->mode;
11583362190Scy  p->priorShFlgs = p->shellFlgs;
11584342292Scy  memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));
11585342292Scy  memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));
11586342292Scy}
11587342292Scystatic void outputModePop(ShellState *p){
11588342292Scy  p->mode = p->modePrior;
11589362190Scy  p->shellFlgs = p->priorShFlgs;
11590342292Scy  memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
11591342292Scy  memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
11592342292Scy}
11593342292Scy
11594342292Scy/*
11595251883Speter** Output the given string as a hex-encoded blob (eg. X'1234' )
11596251883Speter*/
11597251883Speterstatic void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
11598251883Speter  int i;
11599251883Speter  char *zBlob = (char *)pBlob;
11600298161Sbapt  raw_printf(out,"X'");
11601298161Sbapt  for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); }
11602298161Sbapt  raw_printf(out,"'");
11603251883Speter}
11604251883Speter
11605251883Speter/*
11606322444Speter** Find a string that is not found anywhere in z[].  Return a pointer
11607322444Speter** to that string.
11608322444Speter**
11609322444Speter** Try to use zA and zB first.  If both of those are already found in z[]
11610322444Speter** then make up some string and store it in the buffer zBuf.
11611322444Speter*/
11612322444Speterstatic const char *unused_string(
11613322444Speter  const char *z,                    /* Result must not appear anywhere in z */
11614322444Speter  const char *zA, const char *zB,   /* Try these first */
11615322444Speter  char *zBuf                        /* Space to store a generated string */
11616322444Speter){
11617322444Speter  unsigned i = 0;
11618322444Speter  if( strstr(z, zA)==0 ) return zA;
11619322444Speter  if( strstr(z, zB)==0 ) return zB;
11620322444Speter  do{
11621322444Speter    sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
11622322444Speter  }while( strstr(z,zBuf)!=0 );
11623322444Speter  return zBuf;
11624322444Speter}
11625322444Speter
11626322444Speter/*
11627251883Speter** Output the given string as a quoted string using SQL quoting conventions.
11628322444Speter**
11629322444Speter** See also: output_quoted_escaped_string()
11630251883Speter*/
11631251883Speterstatic void output_quoted_string(FILE *out, const char *z){
11632251883Speter  int i;
11633322444Speter  char c;
11634305002Scy  setBinaryMode(out, 1);
11635322444Speter  for(i=0; (c = z[i])!=0 && c!='\''; i++){}
11636322444Speter  if( c==0 ){
11637322444Speter    utf8_printf(out,"'%s'",z);
11638322444Speter  }else{
11639322444Speter    raw_printf(out, "'");
11640322444Speter    while( *z ){
11641322444Speter      for(i=0; (c = z[i])!=0 && c!='\''; i++){}
11642322444Speter      if( c=='\'' ) i++;
11643322444Speter      if( i ){
11644322444Speter        utf8_printf(out, "%.*s", i, z);
11645322444Speter        z += i;
11646322444Speter      }
11647322444Speter      if( c=='\'' ){
11648322444Speter        raw_printf(out, "'");
11649322444Speter        continue;
11650322444Speter      }
11651322444Speter      if( c==0 ){
11652322444Speter        break;
11653322444Speter      }
11654322444Speter      z++;
11655322444Speter    }
11656322444Speter    raw_printf(out, "'");
11657251883Speter  }
11658322444Speter  setTextMode(out, 1);
11659322444Speter}
11660322444Speter
11661322444Speter/*
11662322444Speter** Output the given string as a quoted string using SQL quoting conventions.
11663322444Speter** Additionallly , escape the "\n" and "\r" characters so that they do not
11664322444Speter** get corrupted by end-of-line translation facilities in some operating
11665322444Speter** systems.
11666322444Speter**
11667322444Speter** This is like output_quoted_string() but with the addition of the \r\n
11668322444Speter** escape mechanism.
11669322444Speter*/
11670322444Speterstatic void output_quoted_escaped_string(FILE *out, const char *z){
11671322444Speter  int i;
11672322444Speter  char c;
11673322444Speter  setBinaryMode(out, 1);
11674322444Speter  for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
11675322444Speter  if( c==0 ){
11676298161Sbapt    utf8_printf(out,"'%s'",z);
11677251883Speter  }else{
11678322444Speter    const char *zNL = 0;
11679322444Speter    const char *zCR = 0;
11680322444Speter    int nNL = 0;
11681322444Speter    int nCR = 0;
11682322444Speter    char zBuf1[20], zBuf2[20];
11683322444Speter    for(i=0; z[i]; i++){
11684322444Speter      if( z[i]=='\n' ) nNL++;
11685322444Speter      if( z[i]=='\r' ) nCR++;
11686322444Speter    }
11687322444Speter    if( nNL ){
11688322444Speter      raw_printf(out, "replace(");
11689322444Speter      zNL = unused_string(z, "\\n", "\\012", zBuf1);
11690322444Speter    }
11691322444Speter    if( nCR ){
11692322444Speter      raw_printf(out, "replace(");
11693322444Speter      zCR = unused_string(z, "\\r", "\\015", zBuf2);
11694322444Speter    }
11695322444Speter    raw_printf(out, "'");
11696251883Speter    while( *z ){
11697322444Speter      for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
11698322444Speter      if( c=='\'' ) i++;
11699322444Speter      if( i ){
11700322444Speter        utf8_printf(out, "%.*s", i, z);
11701322444Speter        z += i;
11702322444Speter      }
11703322444Speter      if( c=='\'' ){
11704322444Speter        raw_printf(out, "'");
11705322444Speter        continue;
11706322444Speter      }
11707322444Speter      if( c==0 ){
11708251883Speter        break;
11709251883Speter      }
11710322444Speter      z++;
11711322444Speter      if( c=='\n' ){
11712322444Speter        raw_printf(out, "%s", zNL);
11713322444Speter        continue;
11714322444Speter      }
11715322444Speter      raw_printf(out, "%s", zCR);
11716251883Speter    }
11717322444Speter    raw_printf(out, "'");
11718322444Speter    if( nCR ){
11719322444Speter      raw_printf(out, ",'%s',char(13))", zCR);
11720322444Speter    }
11721322444Speter    if( nNL ){
11722322444Speter      raw_printf(out, ",'%s',char(10))", zNL);
11723322444Speter    }
11724251883Speter  }
11725305002Scy  setTextMode(out, 1);
11726251883Speter}
11727251883Speter
11728251883Speter/*
11729251883Speter** Output the given string as a quoted according to C or TCL quoting rules.
11730251883Speter*/
11731251883Speterstatic void output_c_string(FILE *out, const char *z){
11732251883Speter  unsigned int c;
11733251883Speter  fputc('"', out);
11734251883Speter  while( (c = *(z++))!=0 ){
11735251883Speter    if( c=='\\' ){
11736251883Speter      fputc(c, out);
11737251883Speter      fputc(c, out);
11738251883Speter    }else if( c=='"' ){
11739251883Speter      fputc('\\', out);
11740251883Speter      fputc('"', out);
11741251883Speter    }else if( c=='\t' ){
11742251883Speter      fputc('\\', out);
11743251883Speter      fputc('t', out);
11744251883Speter    }else if( c=='\n' ){
11745251883Speter      fputc('\\', out);
11746251883Speter      fputc('n', out);
11747251883Speter    }else if( c=='\r' ){
11748251883Speter      fputc('\\', out);
11749251883Speter      fputc('r', out);
11750269851Speter    }else if( !isprint(c&0xff) ){
11751298161Sbapt      raw_printf(out, "\\%03o", c&0xff);
11752251883Speter    }else{
11753251883Speter      fputc(c, out);
11754251883Speter    }
11755251883Speter  }
11756251883Speter  fputc('"', out);
11757251883Speter}
11758251883Speter
11759251883Speter/*
11760366076Scy** Output the given string as a quoted according to JSON quoting rules.
11761366076Scy*/
11762366076Scystatic void output_json_string(FILE *out, const char *z, int n){
11763366076Scy  unsigned int c;
11764366076Scy  if( n<0 ) n = (int)strlen(z);
11765366076Scy  fputc('"', out);
11766366076Scy  while( n-- ){
11767366076Scy    c = *(z++);
11768366076Scy    if( c=='\\' || c=='"' ){
11769366076Scy      fputc('\\', out);
11770366076Scy      fputc(c, out);
11771366076Scy    }else if( c<=0x1f ){
11772366076Scy      fputc('\\', out);
11773366076Scy      if( c=='\b' ){
11774366076Scy        fputc('b', out);
11775366076Scy      }else if( c=='\f' ){
11776366076Scy        fputc('f', out);
11777366076Scy      }else if( c=='\n' ){
11778366076Scy        fputc('n', out);
11779366076Scy      }else if( c=='\r' ){
11780366076Scy        fputc('r', out);
11781366076Scy      }else if( c=='\t' ){
11782366076Scy        fputc('t', out);
11783366076Scy      }else{
11784366076Scy         raw_printf(out, "u%04x",c);
11785366076Scy      }
11786366076Scy    }else{
11787366076Scy      fputc(c, out);
11788366076Scy    }
11789366076Scy  }
11790366076Scy  fputc('"', out);
11791366076Scy}
11792366076Scy
11793366076Scy/*
11794251883Speter** Output the given string with characters that are special to
11795251883Speter** HTML escaped.
11796251883Speter*/
11797251883Speterstatic void output_html_string(FILE *out, const char *z){
11798251883Speter  int i;
11799269851Speter  if( z==0 ) z = "";
11800251883Speter  while( *z ){
11801305002Scy    for(i=0;   z[i]
11802305002Scy            && z[i]!='<'
11803305002Scy            && z[i]!='&'
11804305002Scy            && z[i]!='>'
11805305002Scy            && z[i]!='\"'
11806251883Speter            && z[i]!='\'';
11807251883Speter        i++){}
11808251883Speter    if( i>0 ){
11809298161Sbapt      utf8_printf(out,"%.*s",i,z);
11810251883Speter    }
11811251883Speter    if( z[i]=='<' ){
11812298161Sbapt      raw_printf(out,"&lt;");
11813251883Speter    }else if( z[i]=='&' ){
11814298161Sbapt      raw_printf(out,"&amp;");
11815251883Speter    }else if( z[i]=='>' ){
11816298161Sbapt      raw_printf(out,"&gt;");
11817251883Speter    }else if( z[i]=='\"' ){
11818298161Sbapt      raw_printf(out,"&quot;");
11819251883Speter    }else if( z[i]=='\'' ){
11820298161Sbapt      raw_printf(out,"&#39;");
11821251883Speter    }else{
11822251883Speter      break;
11823251883Speter    }
11824251883Speter    z += i + 1;
11825251883Speter  }
11826251883Speter}
11827251883Speter
11828251883Speter/*
11829251883Speter** If a field contains any character identified by a 1 in the following
11830251883Speter** array, then the string must be quoted for CSV.
11831251883Speter*/
11832251883Speterstatic const char needCsvQuote[] = {
11833305002Scy  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
11834305002Scy  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
11835305002Scy  1, 0, 1, 0, 0, 0, 0, 1,   0, 0, 0, 0, 0, 0, 0, 0,
11836305002Scy  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
11837305002Scy  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
11838305002Scy  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
11839305002Scy  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
11840305002Scy  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 1,
11841305002Scy  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
11842305002Scy  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
11843305002Scy  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
11844305002Scy  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
11845305002Scy  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
11846305002Scy  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
11847305002Scy  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
11848305002Scy  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
11849251883Speter};
11850251883Speter
11851251883Speter/*
11852282328Sbapt** Output a single term of CSV.  Actually, p->colSeparator is used for
11853282328Sbapt** the separator, which may or may not be a comma.  p->nullValue is
11854274884Sbapt** the null value.  Strings are quoted if necessary.  The separator
11855274884Sbapt** is only issued if bSep is true.
11856251883Speter*/
11857274884Sbaptstatic void output_csv(ShellState *p, const char *z, int bSep){
11858251883Speter  FILE *out = p->out;
11859251883Speter  if( z==0 ){
11860298161Sbapt    utf8_printf(out,"%s",p->nullValue);
11861251883Speter  }else{
11862251883Speter    int i;
11863282328Sbapt    int nSep = strlen30(p->colSeparator);
11864251883Speter    for(i=0; z[i]; i++){
11865305002Scy      if( needCsvQuote[((unsigned char*)z)[i]]
11866305002Scy         || (z[i]==p->colSeparator[0] &&
11867282328Sbapt             (nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){
11868251883Speter        i = 0;
11869251883Speter        break;
11870251883Speter      }
11871251883Speter    }
11872251883Speter    if( i==0 ){
11873342292Scy      char *zQuoted = sqlite3_mprintf("\"%w\"", z);
11874342292Scy      utf8_printf(out, "%s", zQuoted);
11875342292Scy      sqlite3_free(zQuoted);
11876251883Speter    }else{
11877298161Sbapt      utf8_printf(out, "%s", z);
11878251883Speter    }
11879251883Speter  }
11880251883Speter  if( bSep ){
11881298161Sbapt    utf8_printf(p->out, "%s", p->colSeparator);
11882251883Speter  }
11883251883Speter}
11884251883Speter
11885251883Speter/*
11886251883Speter** This routine runs when the user presses Ctrl-C
11887251883Speter*/
11888251883Speterstatic void interrupt_handler(int NotUsed){
11889251883Speter  UNUSED_PARAMETER(NotUsed);
11890269851Speter  seenInterrupt++;
11891269851Speter  if( seenInterrupt>2 ) exit(1);
11892286510Speter  if( globalDb ) sqlite3_interrupt(globalDb);
11893251883Speter}
11894342292Scy
11895342292Scy#if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
11896342292Scy/*
11897342292Scy** This routine runs for console events (e.g. Ctrl-C) on Win32
11898342292Scy*/
11899342292Scystatic BOOL WINAPI ConsoleCtrlHandler(
11900342292Scy  DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */
11901342292Scy){
11902342292Scy  if( dwCtrlType==CTRL_C_EVENT ){
11903342292Scy    interrupt_handler(0);
11904342292Scy    return TRUE;
11905342292Scy  }
11906342292Scy  return FALSE;
11907342292Scy}
11908251883Speter#endif
11909251883Speter
11910322444Speter#ifndef SQLITE_OMIT_AUTHORIZATION
11911251883Speter/*
11912305002Scy** When the ".auth ON" is set, the following authorizer callback is
11913305002Scy** invoked.  It always returns SQLITE_OK.
11914305002Scy*/
11915305002Scystatic int shellAuth(
11916305002Scy  void *pClientData,
11917305002Scy  int op,
11918305002Scy  const char *zA1,
11919305002Scy  const char *zA2,
11920305002Scy  const char *zA3,
11921305002Scy  const char *zA4
11922305002Scy){
11923305002Scy  ShellState *p = (ShellState*)pClientData;
11924305002Scy  static const char *azAction[] = { 0,
11925305002Scy     "CREATE_INDEX",         "CREATE_TABLE",         "CREATE_TEMP_INDEX",
11926305002Scy     "CREATE_TEMP_TABLE",    "CREATE_TEMP_TRIGGER",  "CREATE_TEMP_VIEW",
11927305002Scy     "CREATE_TRIGGER",       "CREATE_VIEW",          "DELETE",
11928305002Scy     "DROP_INDEX",           "DROP_TABLE",           "DROP_TEMP_INDEX",
11929305002Scy     "DROP_TEMP_TABLE",      "DROP_TEMP_TRIGGER",    "DROP_TEMP_VIEW",
11930305002Scy     "DROP_TRIGGER",         "DROP_VIEW",            "INSERT",
11931305002Scy     "PRAGMA",               "READ",                 "SELECT",
11932305002Scy     "TRANSACTION",          "UPDATE",               "ATTACH",
11933305002Scy     "DETACH",               "ALTER_TABLE",          "REINDEX",
11934305002Scy     "ANALYZE",              "CREATE_VTABLE",        "DROP_VTABLE",
11935305002Scy     "FUNCTION",             "SAVEPOINT",            "RECURSIVE"
11936305002Scy  };
11937305002Scy  int i;
11938305002Scy  const char *az[4];
11939305002Scy  az[0] = zA1;
11940305002Scy  az[1] = zA2;
11941305002Scy  az[2] = zA3;
11942305002Scy  az[3] = zA4;
11943322444Speter  utf8_printf(p->out, "authorizer: %s", azAction[op]);
11944305002Scy  for(i=0; i<4; i++){
11945305002Scy    raw_printf(p->out, " ");
11946305002Scy    if( az[i] ){
11947305002Scy      output_c_string(p->out, az[i]);
11948305002Scy    }else{
11949305002Scy      raw_printf(p->out, "NULL");
11950305002Scy    }
11951305002Scy  }
11952305002Scy  raw_printf(p->out, "\n");
11953305002Scy  return SQLITE_OK;
11954305002Scy}
11955322444Speter#endif
11956305002Scy
11957305002Scy/*
11958322444Speter** Print a schema statement.  Part of MODE_Semi and MODE_Pretty output.
11959322444Speter**
11960322444Speter** This routine converts some CREATE TABLE statements for shadow tables
11961322444Speter** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
11962322444Speter*/
11963322444Speterstatic void printSchemaLine(FILE *out, const char *z, const char *zTail){
11964351633Scy  if( z==0 ) return;
11965351633Scy  if( zTail==0 ) return;
11966322444Speter  if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
11967322444Speter    utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
11968322444Speter  }else{
11969322444Speter    utf8_printf(out, "%s%s", z, zTail);
11970322444Speter  }
11971322444Speter}
11972322444Speterstatic void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
11973322444Speter  char c = z[n];
11974322444Speter  z[n] = 0;
11975322444Speter  printSchemaLine(out, z, zTail);
11976322444Speter  z[n] = c;
11977322444Speter}
11978322444Speter
11979322444Speter/*
11980342292Scy** Return true if string z[] has nothing but whitespace and comments to the
11981342292Scy** end of the first line.
11982342292Scy*/
11983342292Scystatic int wsToEol(const char *z){
11984342292Scy  int i;
11985342292Scy  for(i=0; z[i]; i++){
11986342292Scy    if( z[i]=='\n' ) return 1;
11987342292Scy    if( IsSpace(z[i]) ) continue;
11988342292Scy    if( z[i]=='-' && z[i+1]=='-' ) return 1;
11989342292Scy    return 0;
11990342292Scy  }
11991342292Scy  return 1;
11992342292Scy}
11993342292Scy
11994342292Scy/*
11995342292Scy** Add a new entry to the EXPLAIN QUERY PLAN data
11996342292Scy*/
11997342292Scystatic void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
11998342292Scy  EQPGraphRow *pNew;
11999342292Scy  int nText = strlen30(zText);
12000342292Scy  if( p->autoEQPtest ){
12001342292Scy    utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
12002342292Scy  }
12003342292Scy  pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
12004342292Scy  if( pNew==0 ) shell_out_of_memory();
12005342292Scy  pNew->iEqpId = iEqpId;
12006342292Scy  pNew->iParentId = p2;
12007342292Scy  memcpy(pNew->zText, zText, nText+1);
12008342292Scy  pNew->pNext = 0;
12009342292Scy  if( p->sGraph.pLast ){
12010342292Scy    p->sGraph.pLast->pNext = pNew;
12011342292Scy  }else{
12012342292Scy    p->sGraph.pRow = pNew;
12013342292Scy  }
12014342292Scy  p->sGraph.pLast = pNew;
12015342292Scy}
12016342292Scy
12017342292Scy/*
12018342292Scy** Free and reset the EXPLAIN QUERY PLAN data that has been collected
12019342292Scy** in p->sGraph.
12020342292Scy*/
12021342292Scystatic void eqp_reset(ShellState *p){
12022342292Scy  EQPGraphRow *pRow, *pNext;
12023342292Scy  for(pRow = p->sGraph.pRow; pRow; pRow = pNext){
12024342292Scy    pNext = pRow->pNext;
12025342292Scy    sqlite3_free(pRow);
12026342292Scy  }
12027342292Scy  memset(&p->sGraph, 0, sizeof(p->sGraph));
12028342292Scy}
12029342292Scy
12030342292Scy/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after
12031342292Scy** pOld, or return the first such line if pOld is NULL
12032342292Scy*/
12033342292Scystatic EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){
12034342292Scy  EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow;
12035342292Scy  while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext;
12036342292Scy  return pRow;
12037342292Scy}
12038342292Scy
12039342292Scy/* Render a single level of the graph that has iEqpId as its parent.  Called
12040342292Scy** recursively to render sublevels.
12041342292Scy*/
12042342292Scystatic void eqp_render_level(ShellState *p, int iEqpId){
12043342292Scy  EQPGraphRow *pRow, *pNext;
12044342292Scy  int n = strlen30(p->sGraph.zPrefix);
12045342292Scy  char *z;
12046342292Scy  for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
12047342292Scy    pNext = eqp_next_row(p, iEqpId, pRow);
12048342292Scy    z = pRow->zText;
12049355326Scy    utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
12050355326Scy                pNext ? "|--" : "`--", z);
12051342292Scy    if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){
12052342292Scy      memcpy(&p->sGraph.zPrefix[n], pNext ? "|  " : "   ", 4);
12053342292Scy      eqp_render_level(p, pRow->iEqpId);
12054342292Scy      p->sGraph.zPrefix[n] = 0;
12055342292Scy    }
12056342292Scy  }
12057342292Scy}
12058342292Scy
12059342292Scy/*
12060342292Scy** Display and reset the EXPLAIN QUERY PLAN data
12061342292Scy*/
12062342292Scystatic void eqp_render(ShellState *p){
12063342292Scy  EQPGraphRow *pRow = p->sGraph.pRow;
12064342292Scy  if( pRow ){
12065342292Scy    if( pRow->zText[0]=='-' ){
12066342292Scy      if( pRow->pNext==0 ){
12067342292Scy        eqp_reset(p);
12068342292Scy        return;
12069342292Scy      }
12070342292Scy      utf8_printf(p->out, "%s\n", pRow->zText+3);
12071342292Scy      p->sGraph.pRow = pRow->pNext;
12072342292Scy      sqlite3_free(pRow);
12073342292Scy    }else{
12074342292Scy      utf8_printf(p->out, "QUERY PLAN\n");
12075342292Scy    }
12076342292Scy    p->sGraph.zPrefix[0] = 0;
12077342292Scy    eqp_render_level(p, 0);
12078342292Scy    eqp_reset(p);
12079342292Scy  }
12080342292Scy}
12081342292Scy
12082346442Scy#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
12083342292Scy/*
12084346442Scy** Progress handler callback.
12085346442Scy*/
12086346442Scystatic int progress_handler(void *pClientData) {
12087346442Scy  ShellState *p = (ShellState*)pClientData;
12088346442Scy  p->nProgress++;
12089346442Scy  if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
12090346442Scy    raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
12091346442Scy    if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
12092346442Scy    if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
12093346442Scy    return 1;
12094346442Scy  }
12095346442Scy  if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
12096346442Scy    raw_printf(p->out, "Progress %u\n", p->nProgress);
12097346442Scy  }
12098346442Scy  return 0;
12099346442Scy}
12100346442Scy#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
12101346442Scy
12102346442Scy/*
12103366076Scy** Print N dashes
12104366076Scy*/
12105366076Scystatic void print_dashes(FILE *out, int N){
12106366076Scy  const char zDash[] = "--------------------------------------------------";
12107366076Scy  const int nDash = sizeof(zDash) - 1;
12108366076Scy  while( N>nDash ){
12109366076Scy    fputs(zDash, out);
12110366076Scy    N -= nDash;
12111366076Scy  }
12112366076Scy  raw_printf(out, "%.*s", N, zDash);
12113366076Scy}
12114366076Scy
12115366076Scy/*
12116366076Scy** Print a markdown or table-style row separator using ascii-art
12117366076Scy*/
12118366076Scystatic void print_row_separator(
12119366076Scy  ShellState *p,
12120366076Scy  int nArg,
12121366076Scy  const char *zSep
12122366076Scy){
12123366076Scy  int i;
12124366076Scy  if( nArg>0 ){
12125366076Scy    fputs(zSep, p->out);
12126366076Scy    print_dashes(p->out, p->actualWidth[0]+2);
12127366076Scy    for(i=1; i<nArg; i++){
12128366076Scy      fputs(zSep, p->out);
12129366076Scy      print_dashes(p->out, p->actualWidth[i]+2);
12130366076Scy    }
12131366076Scy    fputs(zSep, p->out);
12132366076Scy  }
12133366076Scy  fputs("\n", p->out);
12134366076Scy}
12135366076Scy
12136366076Scy/*
12137251883Speter** This is the callback routine that the shell
12138251883Speter** invokes for each row of a query result.
12139251883Speter*/
12140282328Sbaptstatic int shell_callback(
12141282328Sbapt  void *pArg,
12142282328Sbapt  int nArg,        /* Number of result columns */
12143282328Sbapt  char **azArg,    /* Text of each result column */
12144282328Sbapt  char **azCol,    /* Column names */
12145366076Scy  int *aiType      /* Column types.  Might be NULL */
12146282328Sbapt){
12147251883Speter  int i;
12148274884Sbapt  ShellState *p = (ShellState*)pArg;
12149251883Speter
12150342292Scy  if( azArg==0 ) return 0;
12151298161Sbapt  switch( p->cMode ){
12152251883Speter    case MODE_Line: {
12153251883Speter      int w = 5;
12154251883Speter      if( azArg==0 ) break;
12155251883Speter      for(i=0; i<nArg; i++){
12156251883Speter        int len = strlen30(azCol[i] ? azCol[i] : "");
12157251883Speter        if( len>w ) w = len;
12158251883Speter      }
12159298161Sbapt      if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
12160251883Speter      for(i=0; i<nArg; i++){
12161298161Sbapt        utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
12162282328Sbapt                azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
12163251883Speter      }
12164251883Speter      break;
12165251883Speter    }
12166366076Scy    case MODE_Explain: {
12167366076Scy      static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
12168366076Scy      if( nArg>ArraySize(aExplainWidth) ){
12169366076Scy        nArg = ArraySize(aExplainWidth);
12170298161Sbapt      }
12171251883Speter      if( p->cnt++==0 ){
12172251883Speter        for(i=0; i<nArg; i++){
12173366076Scy          int w = aExplainWidth[i];
12174366076Scy          utf8_width_print(p->out, w, azCol[i]);
12175366076Scy          fputs(i==nArg-1 ? "\n" : "  ", p->out);
12176251883Speter        }
12177366076Scy        for(i=0; i<nArg; i++){
12178366076Scy          int w = aExplainWidth[i];
12179366076Scy          print_dashes(p->out, w);
12180366076Scy          fputs(i==nArg-1 ? "\n" : "  ", p->out);
12181251883Speter        }
12182251883Speter      }
12183251883Speter      if( azArg==0 ) break;
12184251883Speter      for(i=0; i<nArg; i++){
12185366076Scy        int w = aExplainWidth[i];
12186369951Scy        if( i==nArg-1 ) w = 0;
12187366076Scy        if( azArg[i] && strlenChar(azArg[i])>w ){
12188322444Speter          w = strlenChar(azArg[i]);
12189251883Speter        }
12190269851Speter        if( i==1 && p->aiIndent && p->pStmt ){
12191269851Speter          if( p->iIndent<p->nIndent ){
12192298161Sbapt            utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
12193269851Speter          }
12194269851Speter          p->iIndent++;
12195269851Speter        }
12196322444Speter        utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
12197366076Scy        fputs(i==nArg-1 ? "\n" : "  ", p->out);
12198251883Speter      }
12199251883Speter      break;
12200251883Speter    }
12201305002Scy    case MODE_Semi: {   /* .schema and .fullschema output */
12202322444Speter      printSchemaLine(p->out, azArg[0], ";\n");
12203305002Scy      break;
12204305002Scy    }
12205305002Scy    case MODE_Pretty: {  /* .schema and .fullschema with --indent */
12206305002Scy      char *z;
12207305002Scy      int j;
12208305002Scy      int nParen = 0;
12209305002Scy      char cEnd = 0;
12210305002Scy      char c;
12211305002Scy      int nLine = 0;
12212305002Scy      assert( nArg==1 );
12213305002Scy      if( azArg[0]==0 ) break;
12214305002Scy      if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
12215305002Scy       || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
12216305002Scy      ){
12217305002Scy        utf8_printf(p->out, "%s;\n", azArg[0]);
12218305002Scy        break;
12219305002Scy      }
12220305002Scy      z = sqlite3_mprintf("%s", azArg[0]);
12221305002Scy      j = 0;
12222305002Scy      for(i=0; IsSpace(z[i]); i++){}
12223305002Scy      for(; (c = z[i])!=0; i++){
12224305002Scy        if( IsSpace(c) ){
12225342292Scy          if( z[j-1]=='\r' ) z[j-1] = '\n';
12226305002Scy          if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
12227305002Scy        }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
12228305002Scy          j--;
12229305002Scy        }
12230305002Scy        z[j++] = c;
12231305002Scy      }
12232305002Scy      while( j>0 && IsSpace(z[j-1]) ){ j--; }
12233305002Scy      z[j] = 0;
12234305002Scy      if( strlen30(z)>=79 ){
12235355326Scy        for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */
12236305002Scy          if( c==cEnd ){
12237305002Scy            cEnd = 0;
12238305002Scy          }else if( c=='"' || c=='\'' || c=='`' ){
12239305002Scy            cEnd = c;
12240305002Scy          }else if( c=='[' ){
12241305002Scy            cEnd = ']';
12242342292Scy          }else if( c=='-' && z[i+1]=='-' ){
12243342292Scy            cEnd = '\n';
12244305002Scy          }else if( c=='(' ){
12245305002Scy            nParen++;
12246305002Scy          }else if( c==')' ){
12247305002Scy            nParen--;
12248305002Scy            if( nLine>0 && nParen==0 && j>0 ){
12249322444Speter              printSchemaLineN(p->out, z, j, "\n");
12250305002Scy              j = 0;
12251305002Scy            }
12252305002Scy          }
12253305002Scy          z[j++] = c;
12254342292Scy          if( nParen==1 && cEnd==0
12255342292Scy           && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
12256342292Scy          ){
12257305002Scy            if( c=='\n' ) j--;
12258322444Speter            printSchemaLineN(p->out, z, j, "\n  ");
12259305002Scy            j = 0;
12260305002Scy            nLine++;
12261305002Scy            while( IsSpace(z[i+1]) ){ i++; }
12262305002Scy          }
12263305002Scy        }
12264305002Scy        z[j] = 0;
12265305002Scy      }
12266322444Speter      printSchemaLine(p->out, z, ";\n");
12267305002Scy      sqlite3_free(z);
12268305002Scy      break;
12269305002Scy    }
12270251883Speter    case MODE_List: {
12271251883Speter      if( p->cnt++==0 && p->showHeader ){
12272251883Speter        for(i=0; i<nArg; i++){
12273298161Sbapt          utf8_printf(p->out,"%s%s",azCol[i],
12274282328Sbapt                  i==nArg-1 ? p->rowSeparator : p->colSeparator);
12275251883Speter        }
12276251883Speter      }
12277251883Speter      if( azArg==0 ) break;
12278251883Speter      for(i=0; i<nArg; i++){
12279251883Speter        char *z = azArg[i];
12280282328Sbapt        if( z==0 ) z = p->nullValue;
12281298161Sbapt        utf8_printf(p->out, "%s", z);
12282251883Speter        if( i<nArg-1 ){
12283298161Sbapt          utf8_printf(p->out, "%s", p->colSeparator);
12284251883Speter        }else{
12285298161Sbapt          utf8_printf(p->out, "%s", p->rowSeparator);
12286251883Speter        }
12287251883Speter      }
12288251883Speter      break;
12289251883Speter    }
12290251883Speter    case MODE_Html: {
12291251883Speter      if( p->cnt++==0 && p->showHeader ){
12292298161Sbapt        raw_printf(p->out,"<TR>");
12293251883Speter        for(i=0; i<nArg; i++){
12294298161Sbapt          raw_printf(p->out,"<TH>");
12295251883Speter          output_html_string(p->out, azCol[i]);
12296298161Sbapt          raw_printf(p->out,"</TH>\n");
12297251883Speter        }
12298298161Sbapt        raw_printf(p->out,"</TR>\n");
12299251883Speter      }
12300251883Speter      if( azArg==0 ) break;
12301298161Sbapt      raw_printf(p->out,"<TR>");
12302251883Speter      for(i=0; i<nArg; i++){
12303298161Sbapt        raw_printf(p->out,"<TD>");
12304282328Sbapt        output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
12305298161Sbapt        raw_printf(p->out,"</TD>\n");
12306251883Speter      }
12307298161Sbapt      raw_printf(p->out,"</TR>\n");
12308251883Speter      break;
12309251883Speter    }
12310251883Speter    case MODE_Tcl: {
12311251883Speter      if( p->cnt++==0 && p->showHeader ){
12312251883Speter        for(i=0; i<nArg; i++){
12313251883Speter          output_c_string(p->out,azCol[i] ? azCol[i] : "");
12314298161Sbapt          if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
12315251883Speter        }
12316298161Sbapt        utf8_printf(p->out, "%s", p->rowSeparator);
12317251883Speter      }
12318251883Speter      if( azArg==0 ) break;
12319251883Speter      for(i=0; i<nArg; i++){
12320282328Sbapt        output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
12321298161Sbapt        if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
12322251883Speter      }
12323298161Sbapt      utf8_printf(p->out, "%s", p->rowSeparator);
12324251883Speter      break;
12325251883Speter    }
12326251883Speter    case MODE_Csv: {
12327305002Scy      setBinaryMode(p->out, 1);
12328251883Speter      if( p->cnt++==0 && p->showHeader ){
12329251883Speter        for(i=0; i<nArg; i++){
12330251883Speter          output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
12331251883Speter        }
12332298161Sbapt        utf8_printf(p->out, "%s", p->rowSeparator);
12333251883Speter      }
12334282328Sbapt      if( nArg>0 ){
12335274884Sbapt        for(i=0; i<nArg; i++){
12336274884Sbapt          output_csv(p, azArg[i], i<nArg-1);
12337274884Sbapt        }
12338298161Sbapt        utf8_printf(p->out, "%s", p->rowSeparator);
12339251883Speter      }
12340305002Scy      setTextMode(p->out, 1);
12341251883Speter      break;
12342251883Speter    }
12343251883Speter    case MODE_Insert: {
12344251883Speter      if( azArg==0 ) break;
12345298161Sbapt      utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
12346286510Speter      if( p->showHeader ){
12347298161Sbapt        raw_printf(p->out,"(");
12348286510Speter        for(i=0; i<nArg; i++){
12349322444Speter          if( i>0 ) raw_printf(p->out, ",");
12350322444Speter          if( quoteChar(azCol[i]) ){
12351322444Speter            char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
12352322444Speter            utf8_printf(p->out, "%s", z);
12353322444Speter            sqlite3_free(z);
12354322444Speter          }else{
12355322444Speter            raw_printf(p->out, "%s", azCol[i]);
12356322444Speter          }
12357286510Speter        }
12358298161Sbapt        raw_printf(p->out,")");
12359286510Speter      }
12360322444Speter      p->cnt++;
12361251883Speter      for(i=0; i<nArg; i++){
12362322444Speter        raw_printf(p->out, i>0 ? "," : " VALUES(");
12363251883Speter        if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
12364322444Speter          utf8_printf(p->out,"NULL");
12365251883Speter        }else if( aiType && aiType[i]==SQLITE_TEXT ){
12366322444Speter          if( ShellHasFlag(p, SHFLG_Newlines) ){
12367322444Speter            output_quoted_string(p->out, azArg[i]);
12368322444Speter          }else{
12369322444Speter            output_quoted_escaped_string(p->out, azArg[i]);
12370322444Speter          }
12371322444Speter        }else if( aiType && aiType[i]==SQLITE_INTEGER ){
12372322444Speter          utf8_printf(p->out,"%s", azArg[i]);
12373322444Speter        }else if( aiType && aiType[i]==SQLITE_FLOAT ){
12374322444Speter          char z[50];
12375322444Speter          double r = sqlite3_column_double(p->pStmt, i);
12376342292Scy          sqlite3_uint64 ur;
12377342292Scy          memcpy(&ur,&r,sizeof(r));
12378342292Scy          if( ur==0x7ff0000000000000LL ){
12379342292Scy            raw_printf(p->out, "1e999");
12380342292Scy          }else if( ur==0xfff0000000000000LL ){
12381342292Scy            raw_printf(p->out, "-1e999");
12382342292Scy          }else{
12383342292Scy            sqlite3_snprintf(50,z,"%!.20g", r);
12384342292Scy            raw_printf(p->out, "%s", z);
12385342292Scy          }
12386322444Speter        }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
12387322444Speter          const void *pBlob = sqlite3_column_blob(p->pStmt, i);
12388322444Speter          int nBlob = sqlite3_column_bytes(p->pStmt, i);
12389322444Speter          output_hex_blob(p->out, pBlob, nBlob);
12390322444Speter        }else if( isNumber(azArg[i], 0) ){
12391322444Speter          utf8_printf(p->out,"%s", azArg[i]);
12392322444Speter        }else if( ShellHasFlag(p, SHFLG_Newlines) ){
12393251883Speter          output_quoted_string(p->out, azArg[i]);
12394322444Speter        }else{
12395322444Speter          output_quoted_escaped_string(p->out, azArg[i]);
12396322444Speter        }
12397322444Speter      }
12398322444Speter      raw_printf(p->out,");\n");
12399322444Speter      break;
12400322444Speter    }
12401366076Scy    case MODE_Json: {
12402366076Scy      if( azArg==0 ) break;
12403366076Scy      if( p->cnt==0 ){
12404366076Scy        fputs("[{", p->out);
12405366076Scy      }else{
12406366076Scy        fputs(",\n{", p->out);
12407366076Scy      }
12408366076Scy      p->cnt++;
12409366076Scy      for(i=0; i<nArg; i++){
12410366076Scy        output_json_string(p->out, azCol[i], -1);
12411366076Scy        putc(':', p->out);
12412366076Scy        if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
12413366076Scy          fputs("null",p->out);
12414366076Scy        }else if( aiType && aiType[i]==SQLITE_FLOAT ){
12415366076Scy          char z[50];
12416366076Scy          double r = sqlite3_column_double(p->pStmt, i);
12417366076Scy          sqlite3_uint64 ur;
12418366076Scy          memcpy(&ur,&r,sizeof(r));
12419366076Scy          if( ur==0x7ff0000000000000LL ){
12420366076Scy            raw_printf(p->out, "1e999");
12421366076Scy          }else if( ur==0xfff0000000000000LL ){
12422366076Scy            raw_printf(p->out, "-1e999");
12423366076Scy          }else{
12424366076Scy            sqlite3_snprintf(50,z,"%!.20g", r);
12425366076Scy            raw_printf(p->out, "%s", z);
12426366076Scy          }
12427366076Scy        }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
12428366076Scy          const void *pBlob = sqlite3_column_blob(p->pStmt, i);
12429366076Scy          int nBlob = sqlite3_column_bytes(p->pStmt, i);
12430366076Scy          output_json_string(p->out, pBlob, nBlob);
12431366076Scy        }else if( aiType && aiType[i]==SQLITE_TEXT ){
12432366076Scy          output_json_string(p->out, azArg[i], -1);
12433366076Scy        }else{
12434366076Scy          utf8_printf(p->out,"%s", azArg[i]);
12435366076Scy        }
12436366076Scy        if( i<nArg-1 ){
12437366076Scy          putc(',', p->out);
12438366076Scy        }
12439366076Scy      }
12440366076Scy      putc('}', p->out);
12441366076Scy      break;
12442366076Scy    }
12443322444Speter    case MODE_Quote: {
12444322444Speter      if( azArg==0 ) break;
12445322444Speter      if( p->cnt==0 && p->showHeader ){
12446322444Speter        for(i=0; i<nArg; i++){
12447366076Scy          if( i>0 ) fputs(p->colSeparator, p->out);
12448322444Speter          output_quoted_string(p->out, azCol[i]);
12449322444Speter        }
12450366076Scy        fputs(p->rowSeparator, p->out);
12451322444Speter      }
12452322444Speter      p->cnt++;
12453322444Speter      for(i=0; i<nArg; i++){
12454366076Scy        if( i>0 ) fputs(p->colSeparator, p->out);
12455322444Speter        if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
12456322444Speter          utf8_printf(p->out,"NULL");
12457322444Speter        }else if( aiType && aiType[i]==SQLITE_TEXT ){
12458322444Speter          output_quoted_string(p->out, azArg[i]);
12459322444Speter        }else if( aiType && aiType[i]==SQLITE_INTEGER ){
12460322444Speter          utf8_printf(p->out,"%s", azArg[i]);
12461322444Speter        }else if( aiType && aiType[i]==SQLITE_FLOAT ){
12462322444Speter          char z[50];
12463322444Speter          double r = sqlite3_column_double(p->pStmt, i);
12464322444Speter          sqlite3_snprintf(50,z,"%!.20g", r);
12465322444Speter          raw_printf(p->out, "%s", z);
12466251883Speter        }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
12467251883Speter          const void *pBlob = sqlite3_column_blob(p->pStmt, i);
12468251883Speter          int nBlob = sqlite3_column_bytes(p->pStmt, i);
12469251883Speter          output_hex_blob(p->out, pBlob, nBlob);
12470251883Speter        }else if( isNumber(azArg[i], 0) ){
12471322444Speter          utf8_printf(p->out,"%s", azArg[i]);
12472251883Speter        }else{
12473251883Speter          output_quoted_string(p->out, azArg[i]);
12474251883Speter        }
12475251883Speter      }
12476366076Scy      fputs(p->rowSeparator, p->out);
12477251883Speter      break;
12478251883Speter    }
12479282328Sbapt    case MODE_Ascii: {
12480282328Sbapt      if( p->cnt++==0 && p->showHeader ){
12481282328Sbapt        for(i=0; i<nArg; i++){
12482298161Sbapt          if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
12483298161Sbapt          utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
12484282328Sbapt        }
12485298161Sbapt        utf8_printf(p->out, "%s", p->rowSeparator);
12486282328Sbapt      }
12487282328Sbapt      if( azArg==0 ) break;
12488282328Sbapt      for(i=0; i<nArg; i++){
12489298161Sbapt        if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
12490298161Sbapt        utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
12491282328Sbapt      }
12492298161Sbapt      utf8_printf(p->out, "%s", p->rowSeparator);
12493282328Sbapt      break;
12494282328Sbapt    }
12495342292Scy    case MODE_EQP: {
12496342292Scy      eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]);
12497342292Scy      break;
12498342292Scy    }
12499251883Speter  }
12500251883Speter  return 0;
12501251883Speter}
12502251883Speter
12503251883Speter/*
12504251883Speter** This is the callback routine that the SQLite library
12505251883Speter** invokes for each row of a query result.
12506251883Speter*/
12507251883Speterstatic int callback(void *pArg, int nArg, char **azArg, char **azCol){
12508251883Speter  /* since we don't have type info, call the shell_callback with a NULL value */
12509251883Speter  return shell_callback(pArg, nArg, azArg, azCol, NULL);
12510251883Speter}
12511251883Speter
12512251883Speter/*
12513322444Speter** This is the callback routine from sqlite3_exec() that appends all
12514322444Speter** output onto the end of a ShellText object.
12515322444Speter*/
12516322444Speterstatic int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
12517322444Speter  ShellText *p = (ShellText*)pArg;
12518322444Speter  int i;
12519322444Speter  UNUSED_PARAMETER(az);
12520342292Scy  if( azArg==0 ) return 0;
12521322444Speter  if( p->n ) appendText(p, "|", 0);
12522322444Speter  for(i=0; i<nArg; i++){
12523322444Speter    if( i ) appendText(p, ",", 0);
12524322444Speter    if( azArg[i] ) appendText(p, azArg[i], 0);
12525322444Speter  }
12526322444Speter  return 0;
12527322444Speter}
12528322444Speter
12529322444Speter/*
12530322444Speter** Generate an appropriate SELFTEST table in the main database.
12531322444Speter*/
12532322444Speterstatic void createSelftestTable(ShellState *p){
12533322444Speter  char *zErrMsg = 0;
12534322444Speter  sqlite3_exec(p->db,
12535322444Speter    "SAVEPOINT selftest_init;\n"
12536322444Speter    "CREATE TABLE IF NOT EXISTS selftest(\n"
12537322444Speter    "  tno INTEGER PRIMARY KEY,\n"   /* Test number */
12538322444Speter    "  op TEXT,\n"                   /* Operator:  memo run */
12539322444Speter    "  cmd TEXT,\n"                  /* Command text */
12540322444Speter    "  ans TEXT\n"                   /* Desired answer */
12541322444Speter    ");"
12542322444Speter    "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n"
12543322444Speter    "INSERT INTO [_shell$self](rowid,op,cmd)\n"
12544322444Speter    "  VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n"
12545322444Speter    "         'memo','Tests generated by --init');\n"
12546322444Speter    "INSERT INTO [_shell$self]\n"
12547322444Speter    "  SELECT 'run',\n"
12548322444Speter    "    'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql "
12549366076Scy                                 "FROM sqlite_schema ORDER BY 2'',224))',\n"
12550322444Speter    "    hex(sha3_query('SELECT type,name,tbl_name,sql "
12551366076Scy                          "FROM sqlite_schema ORDER BY 2',224));\n"
12552322444Speter    "INSERT INTO [_shell$self]\n"
12553322444Speter    "  SELECT 'run',"
12554322444Speter    "    'SELECT hex(sha3_query(''SELECT * FROM \"' ||"
12555322444Speter    "        printf('%w',name) || '\" NOT INDEXED'',224))',\n"
12556322444Speter    "    hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"
12557322444Speter    "  FROM (\n"
12558366076Scy    "    SELECT name FROM sqlite_schema\n"
12559322444Speter    "     WHERE type='table'\n"
12560322444Speter    "       AND name<>'selftest'\n"
12561322444Speter    "       AND coalesce(rootpage,0)>0\n"
12562322444Speter    "  )\n"
12563322444Speter    " ORDER BY name;\n"
12564322444Speter    "INSERT INTO [_shell$self]\n"
12565322444Speter    "  VALUES('run','PRAGMA integrity_check','ok');\n"
12566322444Speter    "INSERT INTO selftest(tno,op,cmd,ans)"
12567322444Speter    "  SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n"
12568322444Speter    "DROP TABLE [_shell$self];"
12569322444Speter    ,0,0,&zErrMsg);
12570322444Speter  if( zErrMsg ){
12571322444Speter    utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
12572322444Speter    sqlite3_free(zErrMsg);
12573322444Speter  }
12574322444Speter  sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
12575322444Speter}
12576322444Speter
12577322444Speter
12578322444Speter/*
12579274884Sbapt** Set the destination table field of the ShellState structure to
12580251883Speter** the name of the table given.  Escape any quote characters in the
12581251883Speter** table name.
12582251883Speter*/
12583274884Sbaptstatic void set_table_name(ShellState *p, const char *zName){
12584251883Speter  int i, n;
12585342292Scy  char cQuote;
12586251883Speter  char *z;
12587251883Speter
12588251883Speter  if( p->zDestTable ){
12589251883Speter    free(p->zDestTable);
12590251883Speter    p->zDestTable = 0;
12591251883Speter  }
12592251883Speter  if( zName==0 ) return;
12593322444Speter  cQuote = quoteChar(zName);
12594322444Speter  n = strlen30(zName);
12595322444Speter  if( cQuote ) n += n+2;
12596251883Speter  z = p->zDestTable = malloc( n+1 );
12597342292Scy  if( z==0 ) shell_out_of_memory();
12598251883Speter  n = 0;
12599322444Speter  if( cQuote ) z[n++] = cQuote;
12600251883Speter  for(i=0; zName[i]; i++){
12601251883Speter    z[n++] = zName[i];
12602322444Speter    if( zName[i]==cQuote ) z[n++] = cQuote;
12603251883Speter  }
12604322444Speter  if( cQuote ) z[n++] = cQuote;
12605251883Speter  z[n] = 0;
12606251883Speter}
12607251883Speter
12608251883Speter
12609251883Speter/*
12610251883Speter** Execute a query statement that will generate SQL output.  Print
12611251883Speter** the result columns, comma-separated, on a line and then add a
12612251883Speter** semicolon terminator to the end of that line.
12613251883Speter**
12614251883Speter** If the number of columns is 1 and that column contains text "--"
12615305002Scy** then write the semicolon on a separate line.  That way, if a
12616251883Speter** "--" comment occurs at the end of the statement, the comment
12617251883Speter** won't consume the semicolon terminator.
12618251883Speter*/
12619251883Speterstatic int run_table_dump_query(
12620274884Sbapt  ShellState *p,           /* Query context */
12621362190Scy  const char *zSelect      /* SELECT statement to extract content */
12622251883Speter){
12623251883Speter  sqlite3_stmt *pSelect;
12624251883Speter  int rc;
12625251883Speter  int nResult;
12626251883Speter  int i;
12627251883Speter  const char *z;
12628269851Speter  rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
12629251883Speter  if( rc!=SQLITE_OK || !pSelect ){
12630298161Sbapt    utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
12631298161Sbapt                sqlite3_errmsg(p->db));
12632269851Speter    if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
12633251883Speter    return rc;
12634251883Speter  }
12635251883Speter  rc = sqlite3_step(pSelect);
12636251883Speter  nResult = sqlite3_column_count(pSelect);
12637251883Speter  while( rc==SQLITE_ROW ){
12638251883Speter    z = (const char*)sqlite3_column_text(pSelect, 0);
12639298161Sbapt    utf8_printf(p->out, "%s", z);
12640305002Scy    for(i=1; i<nResult; i++){
12641298161Sbapt      utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
12642251883Speter    }
12643251883Speter    if( z==0 ) z = "";
12644251883Speter    while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
12645251883Speter    if( z[0] ){
12646298161Sbapt      raw_printf(p->out, "\n;\n");
12647251883Speter    }else{
12648298161Sbapt      raw_printf(p->out, ";\n");
12649305002Scy    }
12650251883Speter    rc = sqlite3_step(pSelect);
12651251883Speter  }
12652251883Speter  rc = sqlite3_finalize(pSelect);
12653251883Speter  if( rc!=SQLITE_OK ){
12654298161Sbapt    utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
12655298161Sbapt                sqlite3_errmsg(p->db));
12656269851Speter    if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
12657251883Speter  }
12658251883Speter  return rc;
12659251883Speter}
12660251883Speter
12661251883Speter/*
12662251883Speter** Allocate space and save off current error string.
12663251883Speter*/
12664251883Speterstatic char *save_err_msg(
12665251883Speter  sqlite3 *db            /* Database to query */
12666251883Speter){
12667251883Speter  int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
12668286510Speter  char *zErrMsg = sqlite3_malloc64(nErrMsg);
12669251883Speter  if( zErrMsg ){
12670251883Speter    memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
12671251883Speter  }
12672251883Speter  return zErrMsg;
12673251883Speter}
12674251883Speter
12675298161Sbapt#ifdef __linux__
12676251883Speter/*
12677298161Sbapt** Attempt to display I/O stats on Linux using /proc/PID/io
12678298161Sbapt*/
12679298161Sbaptstatic void displayLinuxIoStats(FILE *out){
12680298161Sbapt  FILE *in;
12681298161Sbapt  char z[200];
12682298161Sbapt  sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
12683298161Sbapt  in = fopen(z, "rb");
12684298161Sbapt  if( in==0 ) return;
12685298161Sbapt  while( fgets(z, sizeof(z), in)!=0 ){
12686298161Sbapt    static const struct {
12687298161Sbapt      const char *zPattern;
12688298161Sbapt      const char *zDesc;
12689298161Sbapt    } aTrans[] = {
12690298161Sbapt      { "rchar: ",                  "Bytes received by read():" },
12691298161Sbapt      { "wchar: ",                  "Bytes sent to write():"    },
12692298161Sbapt      { "syscr: ",                  "Read() system calls:"      },
12693298161Sbapt      { "syscw: ",                  "Write() system calls:"     },
12694298161Sbapt      { "read_bytes: ",             "Bytes read from storage:"  },
12695298161Sbapt      { "write_bytes: ",            "Bytes written to storage:" },
12696298161Sbapt      { "cancelled_write_bytes: ",  "Cancelled write bytes:"    },
12697298161Sbapt    };
12698298161Sbapt    int i;
12699298161Sbapt    for(i=0; i<ArraySize(aTrans); i++){
12700342292Scy      int n = strlen30(aTrans[i].zPattern);
12701298161Sbapt      if( strncmp(aTrans[i].zPattern, z, n)==0 ){
12702322444Speter        utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
12703298161Sbapt        break;
12704298161Sbapt      }
12705298161Sbapt    }
12706298161Sbapt  }
12707298161Sbapt  fclose(in);
12708305002Scy}
12709298161Sbapt#endif
12710298161Sbapt
12711322444Speter/*
12712322444Speter** Display a single line of status using 64-bit values.
12713322444Speter*/
12714322444Speterstatic void displayStatLine(
12715322444Speter  ShellState *p,            /* The shell context */
12716322444Speter  char *zLabel,             /* Label for this one line */
12717322444Speter  char *zFormat,            /* Format for the result */
12718322444Speter  int iStatusCtrl,          /* Which status to display */
12719322444Speter  int bReset                /* True to reset the stats */
12720322444Speter){
12721322444Speter  sqlite3_int64 iCur = -1;
12722322444Speter  sqlite3_int64 iHiwtr = -1;
12723322444Speter  int i, nPercent;
12724322444Speter  char zLine[200];
12725322444Speter  sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset);
12726322444Speter  for(i=0, nPercent=0; zFormat[i]; i++){
12727322444Speter    if( zFormat[i]=='%' ) nPercent++;
12728322444Speter  }
12729322444Speter  if( nPercent>1 ){
12730322444Speter    sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr);
12731322444Speter  }else{
12732322444Speter    sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
12733322444Speter  }
12734322444Speter  raw_printf(p->out, "%-36s %s\n", zLabel, zLine);
12735322444Speter}
12736298161Sbapt
12737298161Sbapt/*
12738251883Speter** Display memory stats.
12739251883Speter*/
12740251883Speterstatic int display_stats(
12741251883Speter  sqlite3 *db,                /* Database to query */
12742274884Sbapt  ShellState *pArg,           /* Pointer to ShellState */
12743251883Speter  int bReset                  /* True to reset the stats */
12744251883Speter){
12745251883Speter  int iCur;
12746251883Speter  int iHiwtr;
12747342292Scy  FILE *out;
12748342292Scy  if( pArg==0 || pArg->out==0 ) return 0;
12749342292Scy  out = pArg->out;
12750251883Speter
12751369951Scy  if( pArg->pStmt && pArg->statsOn==2 ){
12752342292Scy    int nCol, i, x;
12753342292Scy    sqlite3_stmt *pStmt = pArg->pStmt;
12754342292Scy    char z[100];
12755342292Scy    nCol = sqlite3_column_count(pStmt);
12756342292Scy    raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
12757342292Scy    for(i=0; i<nCol; i++){
12758342292Scy      sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
12759342292Scy      utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
12760342292Scy#ifndef SQLITE_OMIT_DECLTYPE
12761342292Scy      sqlite3_snprintf(30, z+x, "declared type:");
12762342292Scy      utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
12763342292Scy#endif
12764342292Scy#ifdef SQLITE_ENABLE_COLUMN_METADATA
12765342292Scy      sqlite3_snprintf(30, z+x, "database name:");
12766342292Scy      utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
12767342292Scy      sqlite3_snprintf(30, z+x, "table name:");
12768342292Scy      utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
12769342292Scy      sqlite3_snprintf(30, z+x, "origin name:");
12770342292Scy      utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
12771342292Scy#endif
12772274884Sbapt    }
12773342292Scy  }
12774342292Scy
12775369951Scy  if( pArg->statsOn==3 ){
12776369951Scy    if( pArg->pStmt ){
12777369951Scy      iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
12778369951Scy      raw_printf(pArg->out, "VM-steps: %d\n", iCur);
12779369951Scy    }
12780369951Scy    return 0;
12781369951Scy  }
12782369951Scy
12783342292Scy  displayStatLine(pArg, "Memory Used:",
12784342292Scy     "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
12785342292Scy  displayStatLine(pArg, "Number of Outstanding Allocations:",
12786342292Scy     "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
12787342292Scy  if( pArg->shellFlgs & SHFLG_Pagecache ){
12788342292Scy    displayStatLine(pArg, "Number of Pcache Pages Used:",
12789342292Scy       "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
12790342292Scy  }
12791342292Scy  displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
12792342292Scy     "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
12793342292Scy  displayStatLine(pArg, "Largest Allocation:",
12794342292Scy     "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
12795342292Scy  displayStatLine(pArg, "Largest Pcache Allocation:",
12796342292Scy     "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
12797251883Speter#ifdef YYTRACKMAXSTACKDEPTH
12798342292Scy  displayStatLine(pArg, "Deepest Parser Stack:",
12799342292Scy     "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
12800251883Speter#endif
12801251883Speter
12802342292Scy  if( db ){
12803274884Sbapt    if( pArg->shellFlgs & SHFLG_Lookaside ){
12804274884Sbapt      iHiwtr = iCur = -1;
12805282328Sbapt      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
12806282328Sbapt                        &iCur, &iHiwtr, bReset);
12807298161Sbapt      raw_printf(pArg->out,
12808298161Sbapt              "Lookaside Slots Used:                %d (max %d)\n",
12809282328Sbapt              iCur, iHiwtr);
12810282328Sbapt      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
12811282328Sbapt                        &iCur, &iHiwtr, bReset);
12812298161Sbapt      raw_printf(pArg->out, "Successful lookaside attempts:       %d\n",
12813298161Sbapt              iHiwtr);
12814282328Sbapt      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
12815282328Sbapt                        &iCur, &iHiwtr, bReset);
12816298161Sbapt      raw_printf(pArg->out, "Lookaside failures due to size:      %d\n",
12817298161Sbapt              iHiwtr);
12818282328Sbapt      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
12819282328Sbapt                        &iCur, &iHiwtr, bReset);
12820298161Sbapt      raw_printf(pArg->out, "Lookaside failures due to OOM:       %d\n",
12821298161Sbapt              iHiwtr);
12822274884Sbapt    }
12823251883Speter    iHiwtr = iCur = -1;
12824251883Speter    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
12825298161Sbapt    raw_printf(pArg->out, "Pager Heap Usage:                    %d bytes\n",
12826298161Sbapt            iCur);
12827282328Sbapt    iHiwtr = iCur = -1;
12828251883Speter    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
12829298161Sbapt    raw_printf(pArg->out, "Page cache hits:                     %d\n", iCur);
12830251883Speter    iHiwtr = iCur = -1;
12831251883Speter    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
12832305002Scy    raw_printf(pArg->out, "Page cache misses:                   %d\n", iCur);
12833251883Speter    iHiwtr = iCur = -1;
12834251883Speter    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
12835305002Scy    raw_printf(pArg->out, "Page cache writes:                   %d\n", iCur);
12836251883Speter    iHiwtr = iCur = -1;
12837342292Scy    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
12838342292Scy    raw_printf(pArg->out, "Page cache spills:                   %d\n", iCur);
12839342292Scy    iHiwtr = iCur = -1;
12840251883Speter    sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
12841298161Sbapt    raw_printf(pArg->out, "Schema Heap Usage:                   %d bytes\n",
12842305002Scy            iCur);
12843251883Speter    iHiwtr = iCur = -1;
12844251883Speter    sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
12845298161Sbapt    raw_printf(pArg->out, "Statement Heap/Lookaside Usage:      %d bytes\n",
12846305002Scy            iCur);
12847251883Speter  }
12848251883Speter
12849342292Scy  if( pArg->pStmt ){
12850282328Sbapt    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
12851282328Sbapt                               bReset);
12852298161Sbapt    raw_printf(pArg->out, "Fullscan Steps:                      %d\n", iCur);
12853251883Speter    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
12854298161Sbapt    raw_printf(pArg->out, "Sort Operations:                     %d\n", iCur);
12855282328Sbapt    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
12856298161Sbapt    raw_printf(pArg->out, "Autoindex Inserts:                   %d\n", iCur);
12857269851Speter    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
12858298161Sbapt    raw_printf(pArg->out, "Virtual Machine Steps:               %d\n", iCur);
12859355326Scy    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
12860342292Scy    raw_printf(pArg->out, "Reprepare operations:                %d\n", iCur);
12861342292Scy    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
12862342292Scy    raw_printf(pArg->out, "Number of times run:                 %d\n", iCur);
12863342292Scy    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
12864342292Scy    raw_printf(pArg->out, "Memory used by prepared stmt:        %d\n", iCur);
12865251883Speter  }
12866251883Speter
12867298161Sbapt#ifdef __linux__
12868298161Sbapt  displayLinuxIoStats(pArg->out);
12869298161Sbapt#endif
12870298161Sbapt
12871298161Sbapt  /* Do not remove this machine readable comment: extra-stats-output-here */
12872298161Sbapt
12873251883Speter  return 0;
12874251883Speter}
12875251883Speter
12876251883Speter/*
12877282328Sbapt** Display scan stats.
12878282328Sbapt*/
12879282328Sbaptstatic void display_scanstats(
12880282328Sbapt  sqlite3 *db,                    /* Database to query */
12881282328Sbapt  ShellState *pArg                /* Pointer to ShellState */
12882282328Sbapt){
12883286510Speter#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
12884286510Speter  UNUSED_PARAMETER(db);
12885286510Speter  UNUSED_PARAMETER(pArg);
12886286510Speter#else
12887282328Sbapt  int i, k, n, mx;
12888298161Sbapt  raw_printf(pArg->out, "-------- scanstats --------\n");
12889282328Sbapt  mx = 0;
12890282328Sbapt  for(k=0; k<=mx; k++){
12891282328Sbapt    double rEstLoop = 1.0;
12892282328Sbapt    for(i=n=0; 1; i++){
12893282328Sbapt      sqlite3_stmt *p = pArg->pStmt;
12894282328Sbapt      sqlite3_int64 nLoop, nVisit;
12895282328Sbapt      double rEst;
12896282328Sbapt      int iSid;
12897282328Sbapt      const char *zExplain;
12898282328Sbapt      if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){
12899282328Sbapt        break;
12900282328Sbapt      }
12901282328Sbapt      sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
12902282328Sbapt      if( iSid>mx ) mx = iSid;
12903282328Sbapt      if( iSid!=k ) continue;
12904282328Sbapt      if( n==0 ){
12905282328Sbapt        rEstLoop = (double)nLoop;
12906298161Sbapt        if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k);
12907282328Sbapt      }
12908282328Sbapt      n++;
12909282328Sbapt      sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
12910282328Sbapt      sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
12911282328Sbapt      sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
12912298161Sbapt      utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
12913282328Sbapt      rEstLoop *= rEst;
12914305002Scy      raw_printf(pArg->out,
12915282328Sbapt          "         nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
12916282328Sbapt          nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
12917282328Sbapt      );
12918282328Sbapt    }
12919282328Sbapt  }
12920298161Sbapt  raw_printf(pArg->out, "---------------------------\n");
12921282328Sbapt#endif
12922282328Sbapt}
12923282328Sbapt
12924282328Sbapt/*
12925269851Speter** Parameter azArray points to a zero-terminated array of strings. zStr
12926269851Speter** points to a single nul-terminated string. Return non-zero if zStr
12927269851Speter** is equal, according to strcmp(), to any of the strings in the array.
12928269851Speter** Otherwise, return zero.
12929269851Speter*/
12930269851Speterstatic int str_in_array(const char *zStr, const char **azArray){
12931269851Speter  int i;
12932269851Speter  for(i=0; azArray[i]; i++){
12933269851Speter    if( 0==strcmp(zStr, azArray[i]) ) return 1;
12934269851Speter  }
12935269851Speter  return 0;
12936269851Speter}
12937269851Speter
12938269851Speter/*
12939269851Speter** If compiled statement pSql appears to be an EXPLAIN statement, allocate
12940274884Sbapt** and populate the ShellState.aiIndent[] array with the number of
12941305002Scy** spaces each opcode should be indented before it is output.
12942269851Speter**
12943269851Speter** The indenting rules are:
12944269851Speter**
12945269851Speter**     * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
12946269851Speter**       all opcodes that occur between the p2 jump destination and the opcode
12947269851Speter**       itself by 2 spaces.
12948269851Speter**
12949269851Speter**     * For each "Goto", if the jump destination is earlier in the program
12950269851Speter**       and ends on one of:
12951269851Speter**          Yield  SeekGt  SeekLt  RowSetRead  Rewind
12952269851Speter**       or if the P1 parameter is one instead of zero,
12953269851Speter**       then indent all opcodes between the earlier instruction
12954269851Speter**       and "Goto" by 2 spaces.
12955269851Speter*/
12956274884Sbaptstatic void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
12957269851Speter  const char *zSql;               /* The text of the SQL statement */
12958269851Speter  const char *z;                  /* Used to check if this is an EXPLAIN */
12959269851Speter  int *abYield = 0;               /* True if op is an OP_Yield */
12960269851Speter  int nAlloc = 0;                 /* Allocated size of p->aiIndent[], abYield */
12961269851Speter  int iOp;                        /* Index of operation in p->aiIndent[] */
12962269851Speter
12963342292Scy  const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
12964282328Sbapt  const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
12965282328Sbapt                            "Rewind", 0 };
12966269851Speter  const char *azGoto[] = { "Goto", 0 };
12967269851Speter
12968269851Speter  /* Try to figure out if this is really an EXPLAIN statement. If this
12969269851Speter  ** cannot be verified, return early.  */
12970298161Sbapt  if( sqlite3_column_count(pSql)!=8 ){
12971298161Sbapt    p->cMode = p->mode;
12972298161Sbapt    return;
12973298161Sbapt  }
12974269851Speter  zSql = sqlite3_sql(pSql);
12975269851Speter  if( zSql==0 ) return;
12976269851Speter  for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
12977298161Sbapt  if( sqlite3_strnicmp(z, "explain", 7) ){
12978298161Sbapt    p->cMode = p->mode;
12979298161Sbapt    return;
12980298161Sbapt  }
12981269851Speter
12982269851Speter  for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
12983269851Speter    int i;
12984269851Speter    int iAddr = sqlite3_column_int(pSql, 0);
12985269851Speter    const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
12986269851Speter
12987269851Speter    /* Set p2 to the P2 field of the current opcode. Then, assuming that
12988269851Speter    ** p2 is an instruction address, set variable p2op to the index of that
12989269851Speter    ** instruction in the aiIndent[] array. p2 and p2op may be different if
12990269851Speter    ** the current instruction is part of a sub-program generated by an
12991269851Speter    ** SQL trigger or foreign key.  */
12992269851Speter    int p2 = sqlite3_column_int(pSql, 3);
12993269851Speter    int p2op = (p2 + (iOp-iAddr));
12994269851Speter
12995269851Speter    /* Grow the p->aiIndent array as required */
12996269851Speter    if( iOp>=nAlloc ){
12997298161Sbapt      if( iOp==0 ){
12998298161Sbapt        /* Do further verfication that this is explain output.  Abort if
12999298161Sbapt        ** it is not */
13000298161Sbapt        static const char *explainCols[] = {
13001298161Sbapt           "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" };
13002298161Sbapt        int jj;
13003298161Sbapt        for(jj=0; jj<ArraySize(explainCols); jj++){
13004298161Sbapt          if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
13005298161Sbapt            p->cMode = p->mode;
13006298161Sbapt            sqlite3_reset(pSql);
13007298161Sbapt            return;
13008298161Sbapt          }
13009298161Sbapt        }
13010298161Sbapt      }
13011269851Speter      nAlloc += 100;
13012286510Speter      p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
13013342292Scy      if( p->aiIndent==0 ) shell_out_of_memory();
13014286510Speter      abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
13015342292Scy      if( abYield==0 ) shell_out_of_memory();
13016269851Speter    }
13017269851Speter    abYield[iOp] = str_in_array(zOp, azYield);
13018269851Speter    p->aiIndent[iOp] = 0;
13019269851Speter    p->nIndent = iOp+1;
13020269851Speter
13021269851Speter    if( str_in_array(zOp, azNext) ){
13022269851Speter      for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
13023269851Speter    }
13024269851Speter    if( str_in_array(zOp, azGoto) && p2op<p->nIndent
13025269851Speter     && (abYield[p2op] || sqlite3_column_int(pSql, 2))
13026269851Speter    ){
13027305002Scy      for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
13028269851Speter    }
13029269851Speter  }
13030269851Speter
13031269851Speter  p->iIndent = 0;
13032269851Speter  sqlite3_free(abYield);
13033269851Speter  sqlite3_reset(pSql);
13034269851Speter}
13035269851Speter
13036269851Speter/*
13037269851Speter** Free the array allocated by explain_data_prepare().
13038269851Speter*/
13039274884Sbaptstatic void explain_data_delete(ShellState *p){
13040269851Speter  sqlite3_free(p->aiIndent);
13041269851Speter  p->aiIndent = 0;
13042269851Speter  p->nIndent = 0;
13043269851Speter  p->iIndent = 0;
13044269851Speter}
13045269851Speter
13046269851Speter/*
13047305002Scy** Disable and restore .wheretrace and .selecttrace settings.
13048305002Scy*/
13049369951Scystatic unsigned int savedSelectTrace;
13050369951Scystatic unsigned int savedWhereTrace;
13051305002Scystatic void disable_debug_trace_modes(void){
13052369951Scy  unsigned int zero = 0;
13053369951Scy  sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace);
13054369951Scy  sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero);
13055369951Scy  sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace);
13056369951Scy  sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero);
13057305002Scy}
13058305002Scystatic void restore_debug_trace_modes(void){
13059369951Scy  sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &savedSelectTrace);
13060369951Scy  sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &savedWhereTrace);
13061305002Scy}
13062305002Scy
13063347347Scy/* Create the TEMP table used to store parameter bindings */
13064347347Scystatic void bind_table_init(ShellState *p){
13065347347Scy  int wrSchema = 0;
13066361456Scy  int defensiveMode = 0;
13067361456Scy  sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
13068361456Scy  sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
13069347347Scy  sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
13070347347Scy  sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
13071347347Scy  sqlite3_exec(p->db,
13072347347Scy    "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
13073347347Scy    "  key TEXT PRIMARY KEY,\n"
13074347347Scy    "  value ANY\n"
13075347347Scy    ") WITHOUT ROWID;",
13076347347Scy    0, 0, 0);
13077347347Scy  sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
13078361456Scy  sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0);
13079347347Scy}
13080347347Scy
13081305002Scy/*
13082347347Scy** Bind parameters on a prepared statement.
13083347347Scy**
13084347347Scy** Parameter bindings are taken from a TEMP table of the form:
13085347347Scy**
13086347347Scy**    CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
13087347347Scy**    WITHOUT ROWID;
13088347347Scy**
13089362190Scy** No bindings occur if this table does not exist.  The name of the table
13090362190Scy** begins with "sqlite_" so that it will not collide with ordinary application
13091362190Scy** tables.  The table must be in the TEMP schema.
13092347347Scy*/
13093347347Scystatic void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
13094347347Scy  int nVar;
13095347347Scy  int i;
13096347347Scy  int rc;
13097347347Scy  sqlite3_stmt *pQ = 0;
13098347347Scy
13099347347Scy  nVar = sqlite3_bind_parameter_count(pStmt);
13100347347Scy  if( nVar==0 ) return;  /* Nothing to do */
13101347347Scy  if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters",
13102347347Scy                                    "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
13103347347Scy    return; /* Parameter table does not exist */
13104347347Scy  }
13105347347Scy  rc = sqlite3_prepare_v2(pArg->db,
13106347347Scy          "SELECT value FROM temp.sqlite_parameters"
13107347347Scy          " WHERE key=?1", -1, &pQ, 0);
13108347347Scy  if( rc || pQ==0 ) return;
13109347347Scy  for(i=1; i<=nVar; i++){
13110347347Scy    char zNum[30];
13111347347Scy    const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
13112347347Scy    if( zVar==0 ){
13113347347Scy      sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
13114347347Scy      zVar = zNum;
13115347347Scy    }
13116347347Scy    sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
13117347347Scy    if( sqlite3_step(pQ)==SQLITE_ROW ){
13118347347Scy      sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
13119347347Scy    }else{
13120347347Scy      sqlite3_bind_null(pStmt, i);
13121347347Scy    }
13122347347Scy    sqlite3_reset(pQ);
13123347347Scy  }
13124347347Scy  sqlite3_finalize(pQ);
13125347347Scy}
13126347347Scy
13127347347Scy/*
13128366076Scy** UTF8 box-drawing characters.  Imagine box lines like this:
13129366076Scy**
13130366076Scy**           1
13131366076Scy**           |
13132366076Scy**       4 --+-- 2
13133366076Scy**           |
13134366076Scy**           3
13135366076Scy**
13136366076Scy** Each box characters has between 2 and 4 of the lines leading from
13137366076Scy** the center.  The characters are here identified by the numbers of
13138366076Scy** their corresponding lines.
13139366076Scy*/
13140366076Scy#define BOX_24   "\342\224\200"  /* U+2500 --- */
13141366076Scy#define BOX_13   "\342\224\202"  /* U+2502  |  */
13142366076Scy#define BOX_23   "\342\224\214"  /* U+250c  ,- */
13143366076Scy#define BOX_34   "\342\224\220"  /* U+2510 -,  */
13144366076Scy#define BOX_12   "\342\224\224"  /* U+2514  '- */
13145366076Scy#define BOX_14   "\342\224\230"  /* U+2518 -'  */
13146366076Scy#define BOX_123  "\342\224\234"  /* U+251c  |- */
13147366076Scy#define BOX_134  "\342\224\244"  /* U+2524 -|  */
13148366076Scy#define BOX_234  "\342\224\254"  /* U+252c -,- */
13149366076Scy#define BOX_124  "\342\224\264"  /* U+2534 -'- */
13150366076Scy#define BOX_1234 "\342\224\274"  /* U+253c -|- */
13151366076Scy
13152366076Scy/* Draw horizontal line N characters long using unicode box
13153366076Scy** characters
13154366076Scy*/
13155366076Scystatic void print_box_line(FILE *out, int N){
13156366076Scy  const char zDash[] =
13157366076Scy      BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
13158366076Scy      BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
13159366076Scy  const int nDash = sizeof(zDash) - 1;
13160366076Scy  N *= 3;
13161366076Scy  while( N>nDash ){
13162366076Scy    utf8_printf(out, zDash);
13163366076Scy    N -= nDash;
13164366076Scy  }
13165366076Scy  utf8_printf(out, "%.*s", N, zDash);
13166366076Scy}
13167366076Scy
13168366076Scy/*
13169366076Scy** Draw a horizontal separator for a MODE_Box table.
13170366076Scy*/
13171366076Scystatic void print_box_row_separator(
13172366076Scy  ShellState *p,
13173366076Scy  int nArg,
13174366076Scy  const char *zSep1,
13175366076Scy  const char *zSep2,
13176366076Scy  const char *zSep3
13177366076Scy){
13178366076Scy  int i;
13179366076Scy  if( nArg>0 ){
13180366076Scy    utf8_printf(p->out, "%s", zSep1);
13181366076Scy    print_box_line(p->out, p->actualWidth[0]+2);
13182366076Scy    for(i=1; i<nArg; i++){
13183366076Scy      utf8_printf(p->out, "%s", zSep2);
13184366076Scy      print_box_line(p->out, p->actualWidth[i]+2);
13185366076Scy    }
13186366076Scy    utf8_printf(p->out, "%s", zSep3);
13187366076Scy  }
13188366076Scy  fputs("\n", p->out);
13189366076Scy}
13190366076Scy
13191366076Scy
13192366076Scy
13193366076Scy/*
13194366076Scy** Run a prepared statement and output the result in one of the
13195366076Scy** table-oriented formats: MODE_Column, MODE_Markdown, MODE_Table,
13196366076Scy** or MODE_Box.
13197366076Scy**
13198366076Scy** This is different from ordinary exec_prepared_stmt() in that
13199366076Scy** it has to run the entire query and gather the results into memory
13200366076Scy** first, in order to determine column widths, before providing
13201366076Scy** any output.
13202366076Scy*/
13203366076Scystatic void exec_prepared_stmt_columnar(
13204366076Scy  ShellState *p,                        /* Pointer to ShellState */
13205366076Scy  sqlite3_stmt *pStmt                   /* Statment to run */
13206366076Scy){
13207366076Scy  sqlite3_int64 nRow = 0;
13208366076Scy  int nColumn = 0;
13209366076Scy  char **azData = 0;
13210366076Scy  sqlite3_int64 nAlloc = 0;
13211366076Scy  const char *z;
13212366076Scy  int rc;
13213366076Scy  sqlite3_int64 i, nData;
13214366076Scy  int j, nTotal, w, n;
13215366076Scy  const char *colSep = 0;
13216366076Scy  const char *rowSep = 0;
13217366076Scy
13218366076Scy  rc = sqlite3_step(pStmt);
13219366076Scy  if( rc!=SQLITE_ROW ) return;
13220366076Scy  nColumn = sqlite3_column_count(pStmt);
13221366076Scy  nAlloc = nColumn*4;
13222369951Scy  if( nAlloc<=0 ) nAlloc = 1;
13223366076Scy  azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
13224366076Scy  if( azData==0 ) shell_out_of_memory();
13225366076Scy  for(i=0; i<nColumn; i++){
13226366076Scy    azData[i] = strdup(sqlite3_column_name(pStmt,i));
13227366076Scy  }
13228366076Scy  do{
13229366076Scy    if( (nRow+2)*nColumn >= nAlloc ){
13230366076Scy      nAlloc *= 2;
13231366076Scy      azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*));
13232366076Scy      if( azData==0 ) shell_out_of_memory();
13233366076Scy    }
13234366076Scy    nRow++;
13235366076Scy    for(i=0; i<nColumn; i++){
13236366076Scy      z = (const char*)sqlite3_column_text(pStmt,i);
13237366076Scy      azData[nRow*nColumn + i] = z ? strdup(z) : 0;
13238366076Scy    }
13239366076Scy  }while( (rc = sqlite3_step(pStmt))==SQLITE_ROW );
13240366076Scy  if( nColumn>p->nWidth ){
13241366076Scy    p->colWidth = realloc(p->colWidth, nColumn*2*sizeof(int));
13242366076Scy    if( p->colWidth==0 ) shell_out_of_memory();
13243366076Scy    for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0;
13244366076Scy    p->nWidth = nColumn;
13245366076Scy    p->actualWidth = &p->colWidth[nColumn];
13246366076Scy  }
13247366076Scy  memset(p->actualWidth, 0, nColumn*sizeof(int));
13248366076Scy  for(i=0; i<nColumn; i++){
13249366076Scy    w = p->colWidth[i];
13250366076Scy    if( w<0 ) w = -w;
13251366076Scy    p->actualWidth[i] = w;
13252366076Scy  }
13253366076Scy  nTotal = nColumn*(nRow+1);
13254366076Scy  for(i=0; i<nTotal; i++){
13255366076Scy    z = azData[i];
13256366076Scy    if( z==0 ) z = p->nullValue;
13257366076Scy    n = strlenChar(z);
13258366076Scy    j = i%nColumn;
13259366076Scy    if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
13260366076Scy  }
13261366076Scy  if( seenInterrupt ) goto columnar_end;
13262369951Scy  if( nColumn==0 ) goto columnar_end;
13263366076Scy  switch( p->cMode ){
13264366076Scy    case MODE_Column: {
13265366076Scy      colSep = "  ";
13266366076Scy      rowSep = "\n";
13267366076Scy      if( p->showHeader ){
13268366076Scy        for(i=0; i<nColumn; i++){
13269366076Scy          w = p->actualWidth[i];
13270366076Scy          if( p->colWidth[i]<0 ) w = -w;
13271366076Scy          utf8_width_print(p->out, w, azData[i]);
13272366076Scy          fputs(i==nColumn-1?"\n":"  ", p->out);
13273366076Scy        }
13274366076Scy        for(i=0; i<nColumn; i++){
13275366076Scy          print_dashes(p->out, p->actualWidth[i]);
13276366076Scy          fputs(i==nColumn-1?"\n":"  ", p->out);
13277366076Scy        }
13278366076Scy      }
13279366076Scy      break;
13280366076Scy    }
13281366076Scy    case MODE_Table: {
13282366076Scy      colSep = " | ";
13283366076Scy      rowSep = " |\n";
13284366076Scy      print_row_separator(p, nColumn, "+");
13285366076Scy      fputs("| ", p->out);
13286366076Scy      for(i=0; i<nColumn; i++){
13287366076Scy        w = p->actualWidth[i];
13288366076Scy        n = strlenChar(azData[i]);
13289366076Scy        utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
13290366076Scy        fputs(i==nColumn-1?" |\n":" | ", p->out);
13291366076Scy      }
13292366076Scy      print_row_separator(p, nColumn, "+");
13293366076Scy      break;
13294366076Scy    }
13295366076Scy    case MODE_Markdown: {
13296366076Scy      colSep = " | ";
13297366076Scy      rowSep = " |\n";
13298366076Scy      fputs("| ", p->out);
13299366076Scy      for(i=0; i<nColumn; i++){
13300366076Scy        w = p->actualWidth[i];
13301366076Scy        n = strlenChar(azData[i]);
13302366076Scy        utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
13303366076Scy        fputs(i==nColumn-1?" |\n":" | ", p->out);
13304366076Scy      }
13305366076Scy      print_row_separator(p, nColumn, "|");
13306366076Scy      break;
13307366076Scy    }
13308366076Scy    case MODE_Box: {
13309366076Scy      colSep = " " BOX_13 " ";
13310366076Scy      rowSep = " " BOX_13 "\n";
13311366076Scy      print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34);
13312366076Scy      utf8_printf(p->out, BOX_13 " ");
13313366076Scy      for(i=0; i<nColumn; i++){
13314366076Scy        w = p->actualWidth[i];
13315366076Scy        n = strlenChar(azData[i]);
13316366076Scy        utf8_printf(p->out, "%*s%s%*s%s",
13317366076Scy            (w-n)/2, "", azData[i], (w-n+1)/2, "",
13318366076Scy            i==nColumn-1?" "BOX_13"\n":" "BOX_13" ");
13319366076Scy      }
13320366076Scy      print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
13321366076Scy      break;
13322366076Scy    }
13323366076Scy  }
13324366076Scy  for(i=nColumn, j=0; i<nTotal; i++, j++){
13325366076Scy    if( j==0 && p->cMode!=MODE_Column ){
13326366076Scy      utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| ");
13327366076Scy    }
13328366076Scy    z = azData[i];
13329366076Scy    if( z==0 ) z = p->nullValue;
13330366076Scy    w = p->actualWidth[j];
13331366076Scy    if( p->colWidth[j]<0 ) w = -w;
13332366076Scy    utf8_width_print(p->out, w, z);
13333366076Scy    if( j==nColumn-1 ){
13334366076Scy      utf8_printf(p->out, "%s", rowSep);
13335366076Scy      j = -1;
13336366076Scy      if( seenInterrupt ) goto columnar_end;
13337366076Scy    }else{
13338366076Scy      utf8_printf(p->out, "%s", colSep);
13339366076Scy    }
13340366076Scy  }
13341366076Scy  if( p->cMode==MODE_Table ){
13342366076Scy    print_row_separator(p, nColumn, "+");
13343366076Scy  }else if( p->cMode==MODE_Box ){
13344366076Scy    print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14);
13345366076Scy  }
13346366076Scycolumnar_end:
13347366076Scy  if( seenInterrupt ){
13348366076Scy    utf8_printf(p->out, "Interrupt\n");
13349366076Scy  }
13350366076Scy  nData = (nRow+1)*nColumn;
13351366076Scy  for(i=0; i<nData; i++) free(azData[i]);
13352366076Scy  sqlite3_free(azData);
13353366076Scy}
13354366076Scy
13355366076Scy/*
13356305002Scy** Run a prepared statement
13357305002Scy*/
13358305002Scystatic void exec_prepared_stmt(
13359305002Scy  ShellState *pArg,                                /* Pointer to ShellState */
13360342292Scy  sqlite3_stmt *pStmt                              /* Statment to run */
13361305002Scy){
13362305002Scy  int rc;
13363305002Scy
13364366076Scy  if( pArg->cMode==MODE_Column
13365366076Scy   || pArg->cMode==MODE_Table
13366366076Scy   || pArg->cMode==MODE_Box
13367366076Scy   || pArg->cMode==MODE_Markdown
13368366076Scy  ){
13369366076Scy    exec_prepared_stmt_columnar(pArg, pStmt);
13370366076Scy    return;
13371366076Scy  }
13372366076Scy
13373305002Scy  /* perform the first step.  this will tell us if we
13374305002Scy  ** have a result set or not and how wide it is.
13375305002Scy  */
13376305002Scy  rc = sqlite3_step(pStmt);
13377305002Scy  /* if we have a result set... */
13378305002Scy  if( SQLITE_ROW == rc ){
13379342292Scy    /* allocate space for col name ptr, value ptr, and type */
13380342292Scy    int nCol = sqlite3_column_count(pStmt);
13381342292Scy    void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
13382342292Scy    if( !pData ){
13383342292Scy      rc = SQLITE_NOMEM;
13384342292Scy    }else{
13385342292Scy      char **azCols = (char **)pData;      /* Names of result columns */
13386342292Scy      char **azVals = &azCols[nCol];       /* Results */
13387342292Scy      int *aiTypes = (int *)&azVals[nCol]; /* Result types */
13388342292Scy      int i, x;
13389342292Scy      assert(sizeof(int) <= sizeof(char *));
13390342292Scy      /* save off ptrs to column names */
13391342292Scy      for(i=0; i<nCol; i++){
13392342292Scy        azCols[i] = (char *)sqlite3_column_name(pStmt, i);
13393342292Scy      }
13394342292Scy      do{
13395342292Scy        /* extract the data and data types */
13396305002Scy        for(i=0; i<nCol; i++){
13397342292Scy          aiTypes[i] = x = sqlite3_column_type(pStmt, i);
13398342292Scy          if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
13399342292Scy            azVals[i] = "";
13400342292Scy          }else{
13401342292Scy            azVals[i] = (char*)sqlite3_column_text(pStmt, i);
13402342292Scy          }
13403342292Scy          if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
13404342292Scy            rc = SQLITE_NOMEM;
13405342292Scy            break; /* from for */
13406342292Scy          }
13407342292Scy        } /* end for */
13408342292Scy
13409342292Scy        /* if data and types extracted successfully... */
13410342292Scy        if( SQLITE_ROW == rc ){
13411342292Scy          /* call the supplied callback with the result row data */
13412342292Scy          if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){
13413342292Scy            rc = SQLITE_ABORT;
13414342292Scy          }else{
13415342292Scy            rc = sqlite3_step(pStmt);
13416342292Scy          }
13417305002Scy        }
13418342292Scy      } while( SQLITE_ROW == rc );
13419342292Scy      sqlite3_free(pData);
13420366076Scy      if( pArg->cMode==MODE_Json ){
13421366076Scy        fputs("]\n", pArg->out);
13422366076Scy      }
13423342292Scy    }
13424342292Scy  }
13425342292Scy}
13426305002Scy
13427342292Scy#ifndef SQLITE_OMIT_VIRTUALTABLE
13428342292Scy/*
13429342292Scy** This function is called to process SQL if the previous shell command
13430342292Scy** was ".expert". It passes the SQL in the second argument directly to
13431342292Scy** the sqlite3expert object.
13432342292Scy**
13433342292Scy** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
13434342292Scy** code. In this case, (*pzErr) may be set to point to a buffer containing
13435342292Scy** an English language error message. It is the responsibility of the
13436342292Scy** caller to eventually free this buffer using sqlite3_free().
13437342292Scy*/
13438342292Scystatic int expertHandleSQL(
13439342292Scy  ShellState *pState,
13440342292Scy  const char *zSql,
13441342292Scy  char **pzErr
13442342292Scy){
13443342292Scy  assert( pState->expert.pExpert );
13444342292Scy  assert( pzErr==0 || *pzErr==0 );
13445342292Scy  return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr);
13446342292Scy}
13447342292Scy
13448342292Scy/*
13449342292Scy** This function is called either to silently clean up the object
13450342292Scy** created by the ".expert" command (if bCancel==1), or to generate a
13451342292Scy** report from it and then clean it up (if bCancel==0).
13452342292Scy**
13453342292Scy** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
13454342292Scy** code. In this case, (*pzErr) may be set to point to a buffer containing
13455342292Scy** an English language error message. It is the responsibility of the
13456342292Scy** caller to eventually free this buffer using sqlite3_free().
13457342292Scy*/
13458342292Scystatic int expertFinish(
13459342292Scy  ShellState *pState,
13460342292Scy  int bCancel,
13461342292Scy  char **pzErr
13462342292Scy){
13463342292Scy  int rc = SQLITE_OK;
13464342292Scy  sqlite3expert *p = pState->expert.pExpert;
13465342292Scy  assert( p );
13466342292Scy  assert( bCancel || pzErr==0 || *pzErr==0 );
13467342292Scy  if( bCancel==0 ){
13468342292Scy    FILE *out = pState->out;
13469342292Scy    int bVerbose = pState->expert.bVerbose;
13470342292Scy
13471342292Scy    rc = sqlite3_expert_analyze(p, pzErr);
13472342292Scy    if( rc==SQLITE_OK ){
13473342292Scy      int nQuery = sqlite3_expert_count(p);
13474342292Scy      int i;
13475342292Scy
13476342292Scy      if( bVerbose ){
13477342292Scy        const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
13478342292Scy        raw_printf(out, "-- Candidates -----------------------------\n");
13479342292Scy        raw_printf(out, "%s\n", zCand);
13480305002Scy      }
13481342292Scy      for(i=0; i<nQuery; i++){
13482342292Scy        const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
13483342292Scy        const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
13484342292Scy        const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
13485342292Scy        if( zIdx==0 ) zIdx = "(no new indexes)\n";
13486342292Scy        if( bVerbose ){
13487342292Scy          raw_printf(out, "-- Query %d --------------------------------\n",i+1);
13488342292Scy          raw_printf(out, "%s\n\n", zSql);
13489342292Scy        }
13490342292Scy        raw_printf(out, "%s\n", zIdx);
13491342292Scy        raw_printf(out, "%s\n", zEQP);
13492342292Scy      }
13493342292Scy    }
13494342292Scy  }
13495342292Scy  sqlite3_expert_destroy(p);
13496342292Scy  pState->expert.pExpert = 0;
13497342292Scy  return rc;
13498342292Scy}
13499342292Scy
13500342292Scy/*
13501342292Scy** Implementation of ".expert" dot command.
13502342292Scy*/
13503342292Scystatic int expertDotCommand(
13504342292Scy  ShellState *pState,             /* Current shell tool state */
13505342292Scy  char **azArg,                   /* Array of arguments passed to dot command */
13506342292Scy  int nArg                        /* Number of entries in azArg[] */
13507342292Scy){
13508342292Scy  int rc = SQLITE_OK;
13509342292Scy  char *zErr = 0;
13510342292Scy  int i;
13511342292Scy  int iSample = 0;
13512342292Scy
13513342292Scy  assert( pState->expert.pExpert==0 );
13514342292Scy  memset(&pState->expert, 0, sizeof(ExpertInfo));
13515342292Scy
13516342292Scy  for(i=1; rc==SQLITE_OK && i<nArg; i++){
13517342292Scy    char *z = azArg[i];
13518342292Scy    int n;
13519342292Scy    if( z[0]=='-' && z[1]=='-' ) z++;
13520342292Scy    n = strlen30(z);
13521342292Scy    if( n>=2 && 0==strncmp(z, "-verbose", n) ){
13522342292Scy      pState->expert.bVerbose = 1;
13523342292Scy    }
13524342292Scy    else if( n>=2 && 0==strncmp(z, "-sample", n) ){
13525342292Scy      if( i==(nArg-1) ){
13526342292Scy        raw_printf(stderr, "option requires an argument: %s\n", z);
13527342292Scy        rc = SQLITE_ERROR;
13528342292Scy      }else{
13529342292Scy        iSample = (int)integerValue(azArg[++i]);
13530342292Scy        if( iSample<0 || iSample>100 ){
13531342292Scy          raw_printf(stderr, "value out of range: %s\n", azArg[i]);
13532342292Scy          rc = SQLITE_ERROR;
13533342292Scy        }
13534342292Scy      }
13535342292Scy    }
13536342292Scy    else{
13537342292Scy      raw_printf(stderr, "unknown option: %s\n", z);
13538342292Scy      rc = SQLITE_ERROR;
13539342292Scy    }
13540342292Scy  }
13541342292Scy
13542342292Scy  if( rc==SQLITE_OK ){
13543342292Scy    pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
13544342292Scy    if( pState->expert.pExpert==0 ){
13545342292Scy      raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr);
13546342292Scy      rc = SQLITE_ERROR;
13547305002Scy    }else{
13548342292Scy      sqlite3_expert_config(
13549342292Scy          pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
13550342292Scy      );
13551305002Scy    }
13552305002Scy  }
13553342292Scy
13554342292Scy  return rc;
13555305002Scy}
13556342292Scy#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
13557305002Scy
13558305002Scy/*
13559305002Scy** Execute a statement or set of statements.  Print
13560305002Scy** any result rows/columns depending on the current mode
13561251883Speter** set via the supplied callback.
13562251883Speter**
13563305002Scy** This is very similar to SQLite's built-in sqlite3_exec()
13564305002Scy** function except it takes a slightly different callback
13565251883Speter** and callback data argument.
13566251883Speter*/
13567251883Speterstatic int shell_exec(
13568342292Scy  ShellState *pArg,                         /* Pointer to ShellState */
13569274884Sbapt  const char *zSql,                         /* SQL to be evaluated */
13570274884Sbapt  char **pzErrMsg                           /* Error msg written here */
13571251883Speter){
13572251883Speter  sqlite3_stmt *pStmt = NULL;     /* Statement to execute. */
13573251883Speter  int rc = SQLITE_OK;             /* Return Code */
13574251883Speter  int rc2;
13575251883Speter  const char *zLeftover;          /* Tail of unprocessed SQL */
13576342292Scy  sqlite3 *db = pArg->db;
13577251883Speter
13578251883Speter  if( pzErrMsg ){
13579251883Speter    *pzErrMsg = NULL;
13580251883Speter  }
13581251883Speter
13582342292Scy#ifndef SQLITE_OMIT_VIRTUALTABLE
13583342292Scy  if( pArg->expert.pExpert ){
13584342292Scy    rc = expertHandleSQL(pArg, zSql, pzErrMsg);
13585342292Scy    return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
13586342292Scy  }
13587342292Scy#endif
13588342292Scy
13589251883Speter  while( zSql[0] && (SQLITE_OK == rc) ){
13590305002Scy    static const char *zStmtSql;
13591251883Speter    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
13592251883Speter    if( SQLITE_OK != rc ){
13593251883Speter      if( pzErrMsg ){
13594251883Speter        *pzErrMsg = save_err_msg(db);
13595251883Speter      }
13596251883Speter    }else{
13597251883Speter      if( !pStmt ){
13598251883Speter        /* this happens for a comment or white-space */
13599251883Speter        zSql = zLeftover;
13600251883Speter        while( IsSpace(zSql[0]) ) zSql++;
13601251883Speter        continue;
13602251883Speter      }
13603305002Scy      zStmtSql = sqlite3_sql(pStmt);
13604322444Speter      if( zStmtSql==0 ) zStmtSql = "";
13605305002Scy      while( IsSpace(zStmtSql[0]) ) zStmtSql++;
13606251883Speter
13607251883Speter      /* save off the prepared statment handle and reset row count */
13608251883Speter      if( pArg ){
13609251883Speter        pArg->pStmt = pStmt;
13610251883Speter        pArg->cnt = 0;
13611251883Speter      }
13612251883Speter
13613251883Speter      /* echo the sql statement if echo on */
13614322444Speter      if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
13615298161Sbapt        utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
13616251883Speter      }
13617251883Speter
13618269851Speter      /* Show the EXPLAIN QUERY PLAN if .eqp is on */
13619347347Scy      if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
13620269851Speter        sqlite3_stmt *pExplain;
13621305002Scy        char *zEQP;
13622342292Scy        int triggerEQP = 0;
13623305002Scy        disable_debug_trace_modes();
13624342292Scy        sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
13625342292Scy        if( pArg->autoEQP>=AUTOEQP_trigger ){
13626342292Scy          sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
13627342292Scy        }
13628305002Scy        zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
13629269851Speter        rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
13630269851Speter        if( rc==SQLITE_OK ){
13631269851Speter          while( sqlite3_step(pExplain)==SQLITE_ROW ){
13632342292Scy            const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
13633342292Scy            int iEqpId = sqlite3_column_int(pExplain, 0);
13634342292Scy            int iParentId = sqlite3_column_int(pExplain, 1);
13635362190Scy            if( zEQPLine==0 ) zEQPLine = "";
13636342292Scy            if( zEQPLine[0]=='-' ) eqp_render(pArg);
13637342292Scy            eqp_append(pArg, iEqpId, iParentId, zEQPLine);
13638269851Speter          }
13639342292Scy          eqp_render(pArg);
13640269851Speter        }
13641269851Speter        sqlite3_finalize(pExplain);
13642269851Speter        sqlite3_free(zEQP);
13643342292Scy        if( pArg->autoEQP>=AUTOEQP_full ){
13644305002Scy          /* Also do an EXPLAIN for ".eqp full" mode */
13645305002Scy          zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
13646305002Scy          rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
13647305002Scy          if( rc==SQLITE_OK ){
13648305002Scy            pArg->cMode = MODE_Explain;
13649305002Scy            explain_data_prepare(pArg, pExplain);
13650342292Scy            exec_prepared_stmt(pArg, pExplain);
13651305002Scy            explain_data_delete(pArg);
13652305002Scy          }
13653305002Scy          sqlite3_finalize(pExplain);
13654305002Scy          sqlite3_free(zEQP);
13655305002Scy        }
13656342292Scy        if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
13657342292Scy          sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
13658342292Scy          /* Reprepare pStmt before reactiving trace modes */
13659342292Scy          sqlite3_finalize(pStmt);
13660342292Scy          sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
13661342292Scy          if( pArg ) pArg->pStmt = pStmt;
13662342292Scy        }
13663305002Scy        restore_debug_trace_modes();
13664269851Speter      }
13665269851Speter
13666298161Sbapt      if( pArg ){
13667298161Sbapt        pArg->cMode = pArg->mode;
13668342292Scy        if( pArg->autoExplain ){
13669347347Scy          if( sqlite3_stmt_isexplain(pStmt)==1 ){
13670342292Scy            pArg->cMode = MODE_Explain;
13671342292Scy          }
13672347347Scy          if( sqlite3_stmt_isexplain(pStmt)==2 ){
13673342292Scy            pArg->cMode = MODE_EQP;
13674342292Scy          }
13675298161Sbapt        }
13676305002Scy
13677298161Sbapt        /* If the shell is currently in ".explain" mode, gather the extra
13678298161Sbapt        ** data required to add indents to the output.*/
13679298161Sbapt        if( pArg->cMode==MODE_Explain ){
13680298161Sbapt          explain_data_prepare(pArg, pStmt);
13681298161Sbapt        }
13682269851Speter      }
13683269851Speter
13684347347Scy      bind_prepared_stmt(pArg, pStmt);
13685342292Scy      exec_prepared_stmt(pArg, pStmt);
13686269851Speter      explain_data_delete(pArg);
13687342292Scy      eqp_render(pArg);
13688269851Speter
13689251883Speter      /* print usage stats if stats on */
13690251883Speter      if( pArg && pArg->statsOn ){
13691251883Speter        display_stats(db, pArg, 0);
13692251883Speter      }
13693251883Speter
13694282328Sbapt      /* print loop-counters if required */
13695282328Sbapt      if( pArg && pArg->scanstatsOn ){
13696282328Sbapt        display_scanstats(db, pArg);
13697282328Sbapt      }
13698282328Sbapt
13699305002Scy      /* Finalize the statement just executed. If this fails, save a
13700251883Speter      ** copy of the error message. Otherwise, set zSql to point to the
13701251883Speter      ** next statement to execute. */
13702251883Speter      rc2 = sqlite3_finalize(pStmt);
13703251883Speter      if( rc!=SQLITE_NOMEM ) rc = rc2;
13704251883Speter      if( rc==SQLITE_OK ){
13705251883Speter        zSql = zLeftover;
13706251883Speter        while( IsSpace(zSql[0]) ) zSql++;
13707251883Speter      }else if( pzErrMsg ){
13708251883Speter        *pzErrMsg = save_err_msg(db);
13709251883Speter      }
13710251883Speter
13711251883Speter      /* clear saved stmt handle */
13712251883Speter      if( pArg ){
13713251883Speter        pArg->pStmt = NULL;
13714251883Speter      }
13715251883Speter    }
13716251883Speter  } /* end while */
13717251883Speter
13718251883Speter  return rc;
13719251883Speter}
13720251883Speter
13721322444Speter/*
13722322444Speter** Release memory previously allocated by tableColumnList().
13723322444Speter*/
13724322444Speterstatic void freeColumnList(char **azCol){
13725322444Speter  int i;
13726322444Speter  for(i=1; azCol[i]; i++){
13727322444Speter    sqlite3_free(azCol[i]);
13728322444Speter  }
13729322444Speter  /* azCol[0] is a static string */
13730322444Speter  sqlite3_free(azCol);
13731322444Speter}
13732251883Speter
13733251883Speter/*
13734322444Speter** Return a list of pointers to strings which are the names of all
13735322444Speter** columns in table zTab.   The memory to hold the names is dynamically
13736322444Speter** allocated and must be released by the caller using a subsequent call
13737322444Speter** to freeColumnList().
13738322444Speter**
13739322444Speter** The azCol[0] entry is usually NULL.  However, if zTab contains a rowid
13740322444Speter** value that needs to be preserved, then azCol[0] is filled in with the
13741322444Speter** name of the rowid column.
13742322444Speter**
13743322444Speter** The first regular column in the table is azCol[1].  The list is terminated
13744322444Speter** by an entry with azCol[i]==0.
13745322444Speter*/
13746322444Speterstatic char **tableColumnList(ShellState *p, const char *zTab){
13747322444Speter  char **azCol = 0;
13748322444Speter  sqlite3_stmt *pStmt;
13749322444Speter  char *zSql;
13750322444Speter  int nCol = 0;
13751322444Speter  int nAlloc = 0;
13752322444Speter  int nPK = 0;       /* Number of PRIMARY KEY columns seen */
13753322444Speter  int isIPK = 0;     /* True if one PRIMARY KEY column of type INTEGER */
13754322444Speter  int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
13755322444Speter  int rc;
13756322444Speter
13757322444Speter  zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
13758322444Speter  rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
13759322444Speter  sqlite3_free(zSql);
13760322444Speter  if( rc ) return 0;
13761322444Speter  while( sqlite3_step(pStmt)==SQLITE_ROW ){
13762322444Speter    if( nCol>=nAlloc-2 ){
13763322444Speter      nAlloc = nAlloc*2 + nCol + 10;
13764322444Speter      azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
13765342292Scy      if( azCol==0 ) shell_out_of_memory();
13766322444Speter    }
13767322444Speter    azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
13768322444Speter    if( sqlite3_column_int(pStmt, 5) ){
13769322444Speter      nPK++;
13770322444Speter      if( nPK==1
13771322444Speter       && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
13772322444Speter                          "INTEGER")==0
13773322444Speter      ){
13774322444Speter        isIPK = 1;
13775322444Speter      }else{
13776322444Speter        isIPK = 0;
13777322444Speter      }
13778322444Speter    }
13779322444Speter  }
13780322444Speter  sqlite3_finalize(pStmt);
13781342292Scy  if( azCol==0 ) return 0;
13782322444Speter  azCol[0] = 0;
13783322444Speter  azCol[nCol+1] = 0;
13784322444Speter
13785322444Speter  /* The decision of whether or not a rowid really needs to be preserved
13786322444Speter  ** is tricky.  We never need to preserve a rowid for a WITHOUT ROWID table
13787322444Speter  ** or a table with an INTEGER PRIMARY KEY.  We are unable to preserve
13788322444Speter  ** rowids on tables where the rowid is inaccessible because there are other
13789322444Speter  ** columns in the table named "rowid", "_rowid_", and "oid".
13790322444Speter  */
13791322444Speter  if( preserveRowid && isIPK ){
13792322444Speter    /* If a single PRIMARY KEY column with type INTEGER was seen, then it
13793322444Speter    ** might be an alise for the ROWID.  But it might also be a WITHOUT ROWID
13794322444Speter    ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
13795322444Speter    ** ROWID aliases.  To distinguish these cases, check to see if
13796322444Speter    ** there is a "pk" entry in "PRAGMA index_list".  There will be
13797322444Speter    ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
13798322444Speter    */
13799322444Speter    zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
13800322444Speter                           " WHERE origin='pk'", zTab);
13801322444Speter    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
13802322444Speter    sqlite3_free(zSql);
13803322444Speter    if( rc ){
13804322444Speter      freeColumnList(azCol);
13805322444Speter      return 0;
13806322444Speter    }
13807322444Speter    rc = sqlite3_step(pStmt);
13808322444Speter    sqlite3_finalize(pStmt);
13809322444Speter    preserveRowid = rc==SQLITE_ROW;
13810322444Speter  }
13811322444Speter  if( preserveRowid ){
13812322444Speter    /* Only preserve the rowid if we can find a name to use for the
13813322444Speter    ** rowid */
13814322444Speter    static char *azRowid[] = { "rowid", "_rowid_", "oid" };
13815322444Speter    int i, j;
13816322444Speter    for(j=0; j<3; j++){
13817322444Speter      for(i=1; i<=nCol; i++){
13818322444Speter        if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
13819322444Speter      }
13820322444Speter      if( i>nCol ){
13821322444Speter        /* At this point, we know that azRowid[j] is not the name of any
13822322444Speter        ** ordinary column in the table.  Verify that azRowid[j] is a valid
13823322444Speter        ** name for the rowid before adding it to azCol[0].  WITHOUT ROWID
13824322444Speter        ** tables will fail this last check */
13825322444Speter        rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
13826322444Speter        if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
13827322444Speter        break;
13828322444Speter      }
13829322444Speter    }
13830322444Speter  }
13831322444Speter  return azCol;
13832322444Speter}
13833322444Speter
13834322444Speter/*
13835322444Speter** Toggle the reverse_unordered_selects setting.
13836322444Speter*/
13837322444Speterstatic void toggleSelectOrder(sqlite3 *db){
13838322444Speter  sqlite3_stmt *pStmt = 0;
13839322444Speter  int iSetting = 0;
13840322444Speter  char zStmt[100];
13841322444Speter  sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0);
13842322444Speter  if( sqlite3_step(pStmt)==SQLITE_ROW ){
13843322444Speter    iSetting = sqlite3_column_int(pStmt, 0);
13844322444Speter  }
13845322444Speter  sqlite3_finalize(pStmt);
13846322444Speter  sqlite3_snprintf(sizeof(zStmt), zStmt,
13847322444Speter       "PRAGMA reverse_unordered_selects(%d)", !iSetting);
13848322444Speter  sqlite3_exec(db, zStmt, 0, 0, 0);
13849322444Speter}
13850322444Speter
13851322444Speter/*
13852251883Speter** This is a different callback routine used for dumping the database.
13853251883Speter** Each row received by this callback consists of a table name,
13854251883Speter** the table type ("index" or "table") and SQL to create the table.
13855251883Speter** This routine should print text sufficient to recreate the table.
13856251883Speter*/
13857322444Speterstatic int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
13858251883Speter  int rc;
13859251883Speter  const char *zTable;
13860251883Speter  const char *zType;
13861251883Speter  const char *zSql;
13862274884Sbapt  ShellState *p = (ShellState *)pArg;
13863369950Scy  int dataOnly;
13864369950Scy  int noSys;
13865251883Speter
13866322444Speter  UNUSED_PARAMETER(azNotUsed);
13867342292Scy  if( nArg!=3 || azArg==0 ) return 0;
13868251883Speter  zTable = azArg[0];
13869251883Speter  zType = azArg[1];
13870251883Speter  zSql = azArg[2];
13871369950Scy  dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
13872369950Scy  noSys    = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
13873305002Scy
13874369950Scy  if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
13875369950Scy    if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
13876369950Scy  }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
13877369950Scy    if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
13878251883Speter  }else if( strncmp(zTable, "sqlite_", 7)==0 ){
13879251883Speter    return 0;
13880369950Scy  }else if( dataOnly ){
13881369950Scy    /* no-op */
13882251883Speter  }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
13883251883Speter    char *zIns;
13884251883Speter    if( !p->writableSchema ){
13885298161Sbapt      raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
13886251883Speter      p->writableSchema = 1;
13887251883Speter    }
13888251883Speter    zIns = sqlite3_mprintf(
13889366076Scy       "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
13890251883Speter       "VALUES('table','%q','%q',0,'%q');",
13891251883Speter       zTable, zTable, zSql);
13892298161Sbapt    utf8_printf(p->out, "%s\n", zIns);
13893251883Speter    sqlite3_free(zIns);
13894251883Speter    return 0;
13895251883Speter  }else{
13896322444Speter    printSchemaLine(p->out, zSql, ";\n");
13897251883Speter  }
13898251883Speter
13899251883Speter  if( strcmp(zType, "table")==0 ){
13900322444Speter    ShellText sSelect;
13901322444Speter    ShellText sTable;
13902322444Speter    char **azCol;
13903322444Speter    int i;
13904322444Speter    char *savedDestTable;
13905322444Speter    int savedMode;
13906305002Scy
13907322444Speter    azCol = tableColumnList(p, zTable);
13908322444Speter    if( azCol==0 ){
13909322444Speter      p->nErr++;
13910322444Speter      return 0;
13911251883Speter    }
13912251883Speter
13913251883Speter    /* Always quote the table name, even if it appears to be pure ascii,
13914251883Speter    ** in case it is a keyword. Ex:  INSERT INTO "table" ... */
13915322444Speter    initText(&sTable);
13916322444Speter    appendText(&sTable, zTable, quoteChar(zTable));
13917322444Speter    /* If preserving the rowid, add a column list after the table name.
13918322444Speter    ** In other words:  "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
13919322444Speter    ** instead of the usual "INSERT INTO tab VALUES(...)".
13920322444Speter    */
13921322444Speter    if( azCol[0] ){
13922322444Speter      appendText(&sTable, "(", 0);
13923322444Speter      appendText(&sTable, azCol[0], 0);
13924322444Speter      for(i=1; azCol[i]; i++){
13925322444Speter        appendText(&sTable, ",", 0);
13926322444Speter        appendText(&sTable, azCol[i], quoteChar(azCol[i]));
13927322444Speter      }
13928322444Speter      appendText(&sTable, ")", 0);
13929251883Speter    }
13930322444Speter
13931322444Speter    /* Build an appropriate SELECT statement */
13932322444Speter    initText(&sSelect);
13933322444Speter    appendText(&sSelect, "SELECT ", 0);
13934322444Speter    if( azCol[0] ){
13935322444Speter      appendText(&sSelect, azCol[0], 0);
13936322444Speter      appendText(&sSelect, ",", 0);
13937322444Speter    }
13938322444Speter    for(i=1; azCol[i]; i++){
13939322444Speter      appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
13940322444Speter      if( azCol[i+1] ){
13941322444Speter        appendText(&sSelect, ",", 0);
13942251883Speter      }
13943251883Speter    }
13944322444Speter    freeColumnList(azCol);
13945322444Speter    appendText(&sSelect, " FROM ", 0);
13946322444Speter    appendText(&sSelect, zTable, quoteChar(zTable));
13947251883Speter
13948322444Speter    savedDestTable = p->zDestTable;
13949322444Speter    savedMode = p->mode;
13950322444Speter    p->zDestTable = sTable.z;
13951322444Speter    p->mode = p->cMode = MODE_Insert;
13952342292Scy    rc = shell_exec(p, sSelect.z, 0);
13953322444Speter    if( (rc&0xff)==SQLITE_CORRUPT ){
13954322444Speter      raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
13955322444Speter      toggleSelectOrder(p->db);
13956342292Scy      shell_exec(p, sSelect.z, 0);
13957322444Speter      toggleSelectOrder(p->db);
13958251883Speter    }
13959322444Speter    p->zDestTable = savedDestTable;
13960322444Speter    p->mode = savedMode;
13961322444Speter    freeText(&sTable);
13962322444Speter    freeText(&sSelect);
13963322444Speter    if( rc ) p->nErr++;
13964251883Speter  }
13965251883Speter  return 0;
13966251883Speter}
13967251883Speter
13968251883Speter/*
13969251883Speter** Run zQuery.  Use dump_callback() as the callback routine so that
13970251883Speter** the contents of the query are output as SQL statements.
13971251883Speter**
13972251883Speter** If we get a SQLITE_CORRUPT error, rerun the query after appending
13973251883Speter** "ORDER BY rowid DESC" to the end.
13974251883Speter*/
13975251883Speterstatic int run_schema_dump_query(
13976305002Scy  ShellState *p,
13977251883Speter  const char *zQuery
13978251883Speter){
13979251883Speter  int rc;
13980251883Speter  char *zErr = 0;
13981251883Speter  rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
13982251883Speter  if( rc==SQLITE_CORRUPT ){
13983251883Speter    char *zQ2;
13984251883Speter    int len = strlen30(zQuery);
13985298161Sbapt    raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
13986251883Speter    if( zErr ){
13987298161Sbapt      utf8_printf(p->out, "/****** %s ******/\n", zErr);
13988251883Speter      sqlite3_free(zErr);
13989251883Speter      zErr = 0;
13990251883Speter    }
13991251883Speter    zQ2 = malloc( len+100 );
13992251883Speter    if( zQ2==0 ) return rc;
13993251883Speter    sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
13994251883Speter    rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
13995251883Speter    if( rc ){
13996298161Sbapt      utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
13997251883Speter    }else{
13998251883Speter      rc = SQLITE_CORRUPT;
13999251883Speter    }
14000251883Speter    sqlite3_free(zErr);
14001251883Speter    free(zQ2);
14002251883Speter  }
14003251883Speter  return rc;
14004251883Speter}
14005251883Speter
14006251883Speter/*
14007342292Scy** Text of help messages.
14008342292Scy**
14009342292Scy** The help text for each individual command begins with a line that starts
14010342292Scy** with ".".  Subsequent lines are supplimental information.
14011342292Scy**
14012342292Scy** There must be two or more spaces between the end of the command and the
14013342292Scy** start of the description of what that command does.
14014251883Speter*/
14015342292Scystatic const char *(azHelp[]) = {
14016342292Scy#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
14017342292Scy  ".archive ...             Manage SQL archives",
14018342292Scy  "   Each command must have exactly one of the following options:",
14019342292Scy  "     -c, --create               Create a new archive",
14020355326Scy  "     -u, --update               Add or update files with changed mtime",
14021355326Scy  "     -i, --insert               Like -u but always add even if unchanged",
14022342292Scy  "     -t, --list                 List contents of archive",
14023342292Scy  "     -x, --extract              Extract files from archive",
14024342292Scy  "   Optional arguments:",
14025342292Scy  "     -v, --verbose              Print each filename as it is processed",
14026355326Scy  "     -f FILE, --file FILE       Use archive FILE (default is current db)",
14027355326Scy  "     -a FILE, --append FILE     Open FILE using the apndvfs VFS",
14028355326Scy  "     -C DIR, --directory DIR    Read/extract files from directory DIR",
14029342292Scy  "     -n, --dryrun               Show the SQL that would have occurred",
14030342292Scy  "   Examples:",
14031355326Scy  "     .ar -cf ARCHIVE foo bar  # Create ARCHIVE from files foo and bar",
14032355326Scy  "     .ar -tf ARCHIVE          # List members of ARCHIVE",
14033355326Scy  "     .ar -xvf ARCHIVE         # Verbosely extract files from ARCHIVE",
14034342292Scy  "   See also:",
14035342292Scy  "      http://sqlite.org/cli.html#sqlar_archive_support",
14036342292Scy#endif
14037322444Speter#ifndef SQLITE_OMIT_AUTHORIZATION
14038342292Scy  ".auth ON|OFF             Show authorizer callbacks",
14039322444Speter#endif
14040342292Scy  ".backup ?DB? FILE        Backup DB (default \"main\") to FILE",
14041342292Scy  "       --append            Use the appendvfs",
14042355326Scy  "       --async             Write to FILE without journal and fsync()",
14043342292Scy  ".bail on|off             Stop after hitting an error.  Default OFF",
14044342292Scy  ".binary on|off           Turn binary output on or off.  Default OFF",
14045342292Scy  ".cd DIRECTORY            Change the working directory to DIRECTORY",
14046342292Scy  ".changes on|off          Show number of rows changed by SQL",
14047342292Scy  ".check GLOB              Fail if output since .testcase does not match",
14048342292Scy  ".clone NEWDB             Clone data into NEWDB from the existing database",
14049342292Scy  ".databases               List names and files of attached databases",
14050342292Scy  ".dbconfig ?op? ?val?     List or change sqlite3_db_config() options",
14051342292Scy  ".dbinfo ?DB?             Show status information about the database",
14052369951Scy  ".dump ?OBJECTS?          Render database content as SQL",
14053342292Scy  "   Options:",
14054369950Scy  "     --data-only            Output only INSERT statements",
14055369950Scy  "     --newlines             Allow unescaped newline characters in output",
14056369950Scy  "     --nosys                Omit system tables (ex: \"sqlite_stat1\")",
14057342292Scy  "     --preserve-rowids      Include ROWID values in the output",
14058369951Scy  "   OBJECTS is a LIKE pattern for tables, indexes, triggers or views to dump",
14059362190Scy  "   Additional LIKE patterns can be given in subsequent arguments",
14060342292Scy  ".echo on|off             Turn command echo on or off",
14061346442Scy  ".eqp on|off|full|...     Enable or disable automatic EXPLAIN QUERY PLAN",
14062346442Scy  "   Other Modes:",
14063346442Scy#ifdef SQLITE_DEBUG
14064346442Scy  "      test                  Show raw EXPLAIN QUERY PLAN output",
14065355326Scy  "      trace                 Like \"full\" but enable \"PRAGMA vdbe_trace\"",
14066346442Scy#endif
14067346442Scy  "      trigger               Like \"full\" but also show trigger bytecode",
14068355326Scy  ".excel                   Display the output of next command in spreadsheet",
14069362190Scy  "   --bom                   Put a UTF8 byte-order mark on intermediate file",
14070342292Scy  ".exit ?CODE?             Exit this program with return-code CODE",
14071355326Scy  ".expert                  EXPERIMENTAL. Suggest indexes for queries",
14072361456Scy  ".explain ?on|off|auto?   Change the EXPLAIN formatting mode.  Default: auto",
14073351633Scy  ".filectrl CMD ...        Run various sqlite3_file_control() operations",
14074362190Scy  "   --schema SCHEMA         Use SCHEMA instead of \"main\"",
14075362190Scy  "   --help                  Show CMD details",
14076342292Scy  ".fullschema ?--indent?   Show schema and the content of sqlite_stat tables",
14077342292Scy  ".headers on|off          Turn display of headers on or off",
14078342292Scy  ".help ?-all? ?PATTERN?   Show help text for PATTERN",
14079342292Scy  ".import FILE TABLE       Import data from FILE into TABLE",
14080362190Scy  "   Options:",
14081362190Scy  "     --ascii               Use \\037 and \\036 as column and row separators",
14082362190Scy  "     --csv                 Use , and \\n as column and row separators",
14083362190Scy  "     --skip N              Skip the first N rows of input",
14084362190Scy  "     -v                    \"Verbose\" - increase auxiliary output",
14085362190Scy  "   Notes:",
14086362190Scy  "     *  If TABLE does not exist, it is created.  The first row of input",
14087362190Scy  "        determines the column names.",
14088362190Scy  "     *  If neither --csv or --ascii are used, the input mode is derived",
14089362190Scy  "        from the \".mode\" output mode",
14090362190Scy  "     *  If FILE begins with \"|\" then it is a command that generates the",
14091362190Scy  "        input text.",
14092322444Speter#ifndef SQLITE_OMIT_TEST_CONTROL
14093342292Scy  ".imposter INDEX TABLE    Create imposter table TABLE on index INDEX",
14094322444Speter#endif
14095342292Scy  ".indexes ?TABLE?         Show names of indexes",
14096342292Scy  "                           If TABLE is specified, only show indexes for",
14097342292Scy  "                           tables matching TABLE using the LIKE operator.",
14098251883Speter#ifdef SQLITE_ENABLE_IOTRACE
14099342292Scy  ".iotrace FILE            Enable I/O diagnostic logging to FILE",
14100251883Speter#endif
14101342292Scy  ".limit ?LIMIT? ?VAL?     Display or change the value of an SQLITE_LIMIT",
14102342292Scy  ".lint OPTIONS            Report potential schema issues.",
14103342292Scy  "     Options:",
14104342292Scy  "        fkey-indexes     Find missing foreign key indexes",
14105251883Speter#ifndef SQLITE_OMIT_LOAD_EXTENSION
14106342292Scy  ".load FILE ?ENTRY?       Load an extension library",
14107251883Speter#endif
14108342292Scy  ".log FILE|off            Turn logging on or off.  FILE can be stderr/stdout",
14109342292Scy  ".mode MODE ?TABLE?       Set output mode",
14110342292Scy  "   MODE is one of:",
14111366076Scy  "     ascii     Columns/rows delimited by 0x1F and 0x1E",
14112366076Scy  "     box       Tables using unicode box-drawing characters",
14113366076Scy  "     csv       Comma-separated values",
14114366076Scy  "     column    Output in columns.  (See .width)",
14115366076Scy  "     html      HTML <table> code",
14116366076Scy  "     insert    SQL insert statements for TABLE",
14117366076Scy  "     json      Results in a JSON array",
14118366076Scy  "     line      One value per line",
14119366076Scy  "     list      Values delimited by \"|\"",
14120366076Scy  "     markdown  Markdown table format",
14121366076Scy  "     quote     Escape answers as for SQL",
14122366076Scy  "     table     ASCII-art table",
14123366076Scy  "     tabs      Tab-separated values",
14124366076Scy  "     tcl       TCL list elements",
14125342292Scy  ".nullvalue STRING        Use STRING in place of NULL values",
14126362190Scy  ".once ?OPTIONS? ?FILE?   Output for the next SQL command only to FILE",
14127342292Scy  "     If FILE begins with '|' then open as a pipe",
14128362190Scy  "       --bom  Put a UTF8 byte-order mark at the beginning",
14129362190Scy  "       -e     Send output to the system text editor",
14130362190Scy  "       -x     Send output as CSV to a spreadsheet (same as \".excel\")",
14131362190Scy#ifdef SQLITE_DEBUG
14132366076Scy  ".oom ?--repeat M? ?N?    Simulate an OOM error on the N-th allocation",
14133362190Scy#endif
14134342292Scy  ".open ?OPTIONS? ?FILE?   Close existing database and reopen FILE",
14135342292Scy  "     Options:",
14136342292Scy  "        --append        Use appendvfs to append database to the end of FILE",
14137342292Scy#ifdef SQLITE_ENABLE_DESERIALIZE
14138342292Scy  "        --deserialize   Load into memory useing sqlite3_deserialize()",
14139355326Scy  "        --hexdb         Load the output of \"dbtotxt\" as an in-memory db",
14140346442Scy  "        --maxsize N     Maximum size for --hexdb or --deserialized database",
14141342292Scy#endif
14142342292Scy  "        --new           Initialize FILE to an empty database",
14143361456Scy  "        --nofollow      Do not follow symbolic links",
14144342292Scy  "        --readonly      Open FILE readonly",
14145342292Scy  "        --zip           FILE is a ZIP archive",
14146342292Scy  ".output ?FILE?           Send output to FILE or stdout if FILE is omitted",
14147362190Scy  "   If FILE begins with '|' then open it as a pipe.",
14148362190Scy  "   Options:",
14149362190Scy  "     --bom                 Prefix output with a UTF8 byte-order mark",
14150362190Scy  "     -e                    Send output to the system text editor",
14151362190Scy  "     -x                    Send output as CSV to a spreadsheet",
14152347347Scy  ".parameter CMD ...       Manage SQL parameter bindings",
14153347347Scy  "   clear                   Erase all bindings",
14154347347Scy  "   init                    Initialize the TEMP table that holds bindings",
14155347347Scy  "   list                    List the current parameter bindings",
14156347347Scy  "   set PARAMETER VALUE     Given SQL parameter PARAMETER a value of VALUE",
14157355326Scy  "                           PARAMETER should start with one of: $ : @ ?",
14158347347Scy  "   unset PARAMETER         Remove PARAMETER from the binding table",
14159342292Scy  ".print STRING...         Print literal STRING",
14160346442Scy#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
14161346442Scy  ".progress N              Invoke progress handler after every N opcodes",
14162346442Scy  "   --limit N                 Interrupt after N progress callbacks",
14163346442Scy  "   --once                    Do no more than one progress interrupt",
14164346442Scy  "   --quiet|-q                No output except at interrupts",
14165346442Scy  "   --reset                   Reset the count for each input and interrupt",
14166346442Scy#endif
14167342292Scy  ".prompt MAIN CONTINUE    Replace the standard prompts",
14168342292Scy  ".quit                    Exit this program",
14169342292Scy  ".read FILE               Read input from FILE",
14170351633Scy#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
14171351633Scy  ".recover                 Recover as much data as possible from corrupt db.",
14172355326Scy  "   --freelist-corrupt       Assume the freelist is corrupt",
14173355326Scy  "   --recovery-db NAME       Store recovery metadata in database file NAME",
14174355326Scy  "   --lost-and-found TABLE   Alternative name for the lost-and-found table",
14175355326Scy  "   --no-rowids              Do not attempt to recover rowid values",
14176355326Scy  "                            that are not also INTEGER PRIMARY KEYs",
14177351633Scy#endif
14178342292Scy  ".restore ?DB? FILE       Restore content of DB (default \"main\") from FILE",
14179342292Scy  ".save FILE               Write in-memory database into FILE",
14180342292Scy  ".scanstats on|off        Turn sqlite3_stmt_scanstatus() metrics on or off",
14181342292Scy  ".schema ?PATTERN?        Show the CREATE statements matching PATTERN",
14182369950Scy  "   Options:",
14183369950Scy  "      --indent             Try to pretty-print the schema",
14184369950Scy  "      --nosys              Omit objects whose names start with \"sqlite_\"",
14185342292Scy  ".selftest ?OPTIONS?      Run tests defined in the SELFTEST table",
14186342292Scy  "    Options:",
14187342292Scy  "       --init               Create a new SELFTEST table",
14188342292Scy  "       -v                   Verbose output",
14189342292Scy  ".separator COL ?ROW?     Change the column and row separators",
14190305002Scy#if defined(SQLITE_ENABLE_SESSION)
14191342292Scy  ".session ?NAME? CMD ...  Create or control sessions",
14192342292Scy  "   Subcommands:",
14193342292Scy  "     attach TABLE             Attach TABLE",
14194342292Scy  "     changeset FILE           Write a changeset into FILE",
14195342292Scy  "     close                    Close one session",
14196342292Scy  "     enable ?BOOLEAN?         Set or query the enable bit",
14197342292Scy  "     filter GLOB...           Reject tables matching GLOBs",
14198342292Scy  "     indirect ?BOOLEAN?       Mark or query the indirect status",
14199342292Scy  "     isempty                  Query whether the session is empty",
14200342292Scy  "     list                     List currently open session names",
14201342292Scy  "     open DB NAME             Open a new session on DB",
14202342292Scy  "     patchset FILE            Write a patchset into FILE",
14203342292Scy  "   If ?NAME? is omitted, the first defined session is used.",
14204305002Scy#endif
14205342292Scy  ".sha3sum ...             Compute a SHA3 hash of database content",
14206342292Scy  "    Options:",
14207366076Scy  "      --schema              Also hash the sqlite_schema table",
14208342292Scy  "      --sha3-224            Use the sha3-224 algorithm",
14209355326Scy  "      --sha3-256            Use the sha3-256 algorithm (default)",
14210342292Scy  "      --sha3-384            Use the sha3-384 algorithm",
14211342292Scy  "      --sha3-512            Use the sha3-512 algorithm",
14212342292Scy  "    Any other argument is a LIKE pattern for tables to hash",
14213342292Scy#ifndef SQLITE_NOHAVE_SYSTEM
14214342292Scy  ".shell CMD ARGS...       Run CMD ARGS... in a system shell",
14215342292Scy#endif
14216342292Scy  ".show                    Show the current values for various settings",
14217369951Scy  ".stats ?ARG?             Show stats or turn stats on or off",
14218369951Scy  "   off                      Turn off automatic stat display",
14219369951Scy  "   on                       Turn on automatic stat display",
14220369951Scy  "   stmt                     Show statement stats",
14221369951Scy  "   vmstep                   Show the virtual machine step count only",
14222342292Scy#ifndef SQLITE_NOHAVE_SYSTEM
14223342292Scy  ".system CMD ARGS...      Run CMD ARGS... in a system shell",
14224342292Scy#endif
14225342292Scy  ".tables ?TABLE?          List names of tables matching LIKE pattern TABLE",
14226342292Scy  ".testcase NAME           Begin redirecting output to 'testcase-out.txt'",
14227351633Scy  ".testctrl CMD ...        Run various sqlite3_test_control() operations",
14228351633Scy  "                           Run \".testctrl\" with no arguments for details",
14229342292Scy  ".timeout MS              Try opening locked tables for MS milliseconds",
14230342292Scy  ".timer on|off            Turn SQL timer on or off",
14231346442Scy#ifndef SQLITE_OMIT_TRACE
14232346442Scy  ".trace ?OPTIONS?         Output each SQL statement as it is run",
14233346442Scy  "    FILE                    Send output to FILE",
14234346442Scy  "    stdout                  Send output to stdout",
14235346442Scy  "    stderr                  Send output to stderr",
14236346442Scy  "    off                     Disable tracing",
14237346442Scy  "    --expanded              Expand query parameters",
14238346442Scy#ifdef SQLITE_ENABLE_NORMALIZE
14239346442Scy  "    --normalized            Normal the SQL statements",
14240346442Scy#endif
14241346442Scy  "    --plain                 Show SQL as it is input",
14242346442Scy  "    --stmt                  Trace statement execution (SQLITE_TRACE_STMT)",
14243346442Scy  "    --profile               Profile statements (SQLITE_TRACE_PROFILE)",
14244346442Scy  "    --row                   Trace each row (SQLITE_TRACE_ROW)",
14245346442Scy  "    --close                 Trace connection close (SQLITE_TRACE_CLOSE)",
14246346442Scy#endif /* SQLITE_OMIT_TRACE */
14247355326Scy#ifdef SQLITE_DEBUG
14248355326Scy  ".unmodule NAME ...       Unregister virtual table modules",
14249355326Scy  "    --allexcept             Unregister everything except those named",
14250355326Scy#endif
14251342292Scy  ".vfsinfo ?AUX?           Information about the top-level VFS",
14252342292Scy  ".vfslist                 List all available VFSes",
14253342292Scy  ".vfsname ?AUX?           Print the name of the VFS stack",
14254366076Scy  ".width NUM1 NUM2 ...     Set minimum column widths for columnar output",
14255342292Scy  "     Negative values right-justify",
14256342292Scy};
14257251883Speter
14258305002Scy/*
14259342292Scy** Output help text.
14260342292Scy**
14261342292Scy** zPattern describes the set of commands for which help text is provided.
14262342292Scy** If zPattern is NULL, then show all commands, but only give a one-line
14263342292Scy** description of each.
14264342292Scy**
14265342292Scy** Return the number of matches.
14266305002Scy*/
14267342292Scystatic int showHelp(FILE *out, const char *zPattern){
14268342292Scy  int i = 0;
14269342292Scy  int j = 0;
14270342292Scy  int n = 0;
14271342292Scy  char *zPat;
14272342292Scy  if( zPattern==0
14273342292Scy   || zPattern[0]=='0'
14274342292Scy   || strcmp(zPattern,"-a")==0
14275342292Scy   || strcmp(zPattern,"-all")==0
14276362190Scy   || strcmp(zPattern,"--all")==0
14277342292Scy  ){
14278342292Scy    /* Show all commands, but only one line per command */
14279342292Scy    if( zPattern==0 ) zPattern = "";
14280342292Scy    for(i=0; i<ArraySize(azHelp); i++){
14281342292Scy      if( azHelp[i][0]=='.' || zPattern[0] ){
14282342292Scy        utf8_printf(out, "%s\n", azHelp[i]);
14283342292Scy        n++;
14284342292Scy      }
14285342292Scy    }
14286342292Scy  }else{
14287342292Scy    /* Look for commands that for which zPattern is an exact prefix */
14288342292Scy    zPat = sqlite3_mprintf(".%s*", zPattern);
14289342292Scy    for(i=0; i<ArraySize(azHelp); i++){
14290342292Scy      if( sqlite3_strglob(zPat, azHelp[i])==0 ){
14291342292Scy        utf8_printf(out, "%s\n", azHelp[i]);
14292342292Scy        j = i+1;
14293342292Scy        n++;
14294342292Scy      }
14295342292Scy    }
14296342292Scy    sqlite3_free(zPat);
14297342292Scy    if( n ){
14298342292Scy      if( n==1 ){
14299342292Scy        /* when zPattern is a prefix of exactly one command, then include the
14300342292Scy        ** details of that command, which should begin at offset j */
14301342292Scy        while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){
14302342292Scy          utf8_printf(out, "%s\n", azHelp[j]);
14303342292Scy          j++;
14304342292Scy        }
14305342292Scy      }
14306342292Scy      return n;
14307342292Scy    }
14308342292Scy    /* Look for commands that contain zPattern anywhere.  Show the complete
14309342292Scy    ** text of all commands that match. */
14310342292Scy    zPat = sqlite3_mprintf("%%%s%%", zPattern);
14311342292Scy    for(i=0; i<ArraySize(azHelp); i++){
14312342292Scy      if( azHelp[i][0]=='.' ) j = i;
14313342292Scy      if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
14314342292Scy        utf8_printf(out, "%s\n", azHelp[j]);
14315342292Scy        while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
14316342292Scy          j++;
14317342292Scy          utf8_printf(out, "%s\n", azHelp[j]);
14318342292Scy        }
14319342292Scy        i = j;
14320342292Scy        n++;
14321342292Scy      }
14322342292Scy    }
14323342292Scy    sqlite3_free(zPat);
14324342292Scy  }
14325342292Scy  return n;
14326305002Scy}
14327305002Scy
14328251883Speter/* Forward reference */
14329346442Scystatic int process_input(ShellState *p);
14330322444Speter
14331274884Sbapt/*
14332322444Speter** Read the content of file zName into memory obtained from sqlite3_malloc64()
14333322444Speter** and return a pointer to the buffer. The caller is responsible for freeing
14334322444Speter** the memory.
14335322444Speter**
14336322444Speter** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
14337322444Speter** read.
14338322444Speter**
14339322444Speter** For convenience, a nul-terminator byte is always appended to the data read
14340322444Speter** from the file before the buffer is returned. This byte is not included in
14341322444Speter** the final value of (*pnByte), if applicable.
14342322444Speter**
14343322444Speter** NULL is returned if any error is encountered. The final value of *pnByte
14344322444Speter** is undefined in this case.
14345274884Sbapt*/
14346322444Speterstatic char *readFile(const char *zName, int *pnByte){
14347322444Speter  FILE *in = fopen(zName, "rb");
14348274884Sbapt  long nIn;
14349322444Speter  size_t nRead;
14350322444Speter  char *pBuf;
14351322444Speter  if( in==0 ) return 0;
14352274884Sbapt  fseek(in, 0, SEEK_END);
14353274884Sbapt  nIn = ftell(in);
14354274884Sbapt  rewind(in);
14355322444Speter  pBuf = sqlite3_malloc64( nIn+1 );
14356342292Scy  if( pBuf==0 ){ fclose(in); return 0; }
14357322444Speter  nRead = fread(pBuf, nIn, 1, in);
14358322444Speter  fclose(in);
14359322444Speter  if( nRead!=1 ){
14360274884Sbapt    sqlite3_free(pBuf);
14361322444Speter    return 0;
14362274884Sbapt  }
14363322444Speter  pBuf[nIn] = 0;
14364322444Speter  if( pnByte ) *pnByte = nIn;
14365322444Speter  return pBuf;
14366274884Sbapt}
14367274884Sbapt
14368305002Scy#if defined(SQLITE_ENABLE_SESSION)
14369274884Sbapt/*
14370305002Scy** Close a single OpenSession object and release all of its associated
14371305002Scy** resources.
14372305002Scy*/
14373305002Scystatic void session_close(OpenSession *pSession){
14374305002Scy  int i;
14375305002Scy  sqlite3session_delete(pSession->p);
14376305002Scy  sqlite3_free(pSession->zName);
14377305002Scy  for(i=0; i<pSession->nFilter; i++){
14378305002Scy    sqlite3_free(pSession->azFilter[i]);
14379305002Scy  }
14380305002Scy  sqlite3_free(pSession->azFilter);
14381305002Scy  memset(pSession, 0, sizeof(OpenSession));
14382305002Scy}
14383305002Scy#endif
14384305002Scy
14385305002Scy/*
14386305002Scy** Close all OpenSession objects and release all associated resources.
14387305002Scy*/
14388305002Scy#if defined(SQLITE_ENABLE_SESSION)
14389305002Scystatic void session_close_all(ShellState *p){
14390305002Scy  int i;
14391305002Scy  for(i=0; i<p->nSession; i++){
14392305002Scy    session_close(&p->aSession[i]);
14393305002Scy  }
14394305002Scy  p->nSession = 0;
14395305002Scy}
14396305002Scy#else
14397305002Scy# define session_close_all(X)
14398305002Scy#endif
14399305002Scy
14400305002Scy/*
14401305002Scy** Implementation of the xFilter function for an open session.  Omit
14402305002Scy** any tables named by ".session filter" but let all other table through.
14403305002Scy*/
14404305002Scy#if defined(SQLITE_ENABLE_SESSION)
14405305002Scystatic int session_filter(void *pCtx, const char *zTab){
14406305002Scy  OpenSession *pSession = (OpenSession*)pCtx;
14407305002Scy  int i;
14408305002Scy  for(i=0; i<pSession->nFilter; i++){
14409305002Scy    if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
14410305002Scy  }
14411305002Scy  return 1;
14412305002Scy}
14413305002Scy#endif
14414305002Scy
14415305002Scy/*
14416342292Scy** Try to deduce the type of file for zName based on its content.  Return
14417342292Scy** one of the SHELL_OPEN_* constants.
14418342292Scy**
14419342292Scy** If the file does not exist or is empty but its name looks like a ZIP
14420342292Scy** archive and the dfltZip flag is true, then assume it is a ZIP archive.
14421342292Scy** Otherwise, assume an ordinary database regardless of the filename if
14422342292Scy** the type cannot be determined from content.
14423342292Scy*/
14424342292Scyint deduceDatabaseType(const char *zName, int dfltZip){
14425342292Scy  FILE *f = fopen(zName, "rb");
14426342292Scy  size_t n;
14427342292Scy  int rc = SHELL_OPEN_UNSPEC;
14428342292Scy  char zBuf[100];
14429342292Scy  if( f==0 ){
14430342292Scy    if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
14431342292Scy       return SHELL_OPEN_ZIPFILE;
14432342292Scy    }else{
14433342292Scy       return SHELL_OPEN_NORMAL;
14434342292Scy    }
14435342292Scy  }
14436342292Scy  n = fread(zBuf, 16, 1, f);
14437342292Scy  if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
14438342292Scy    fclose(f);
14439342292Scy    return SHELL_OPEN_NORMAL;
14440342292Scy  }
14441342292Scy  fseek(f, -25, SEEK_END);
14442342292Scy  n = fread(zBuf, 25, 1, f);
14443342292Scy  if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
14444342292Scy    rc = SHELL_OPEN_APPENDVFS;
14445342292Scy  }else{
14446342292Scy    fseek(f, -22, SEEK_END);
14447342292Scy    n = fread(zBuf, 22, 1, f);
14448342292Scy    if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
14449342292Scy       && zBuf[3]==0x06 ){
14450342292Scy      rc = SHELL_OPEN_ZIPFILE;
14451342292Scy    }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
14452342292Scy      rc = SHELL_OPEN_ZIPFILE;
14453342292Scy    }
14454342292Scy  }
14455342292Scy  fclose(f);
14456342292Scy  return rc;
14457342292Scy}
14458342292Scy
14459346442Scy#ifdef SQLITE_ENABLE_DESERIALIZE
14460346442Scy/*
14461346442Scy** Reconstruct an in-memory database using the output from the "dbtotxt"
14462346442Scy** program.  Read content from the file in p->zDbFilename.  If p->zDbFilename
14463346442Scy** is 0, then read from standard input.
14464346442Scy*/
14465346442Scystatic unsigned char *readHexDb(ShellState *p, int *pnData){
14466346442Scy  unsigned char *a = 0;
14467346442Scy  int nLine;
14468346442Scy  int n = 0;
14469346442Scy  int pgsz = 0;
14470346442Scy  int iOffset = 0;
14471346442Scy  int j, k;
14472346442Scy  int rc;
14473346442Scy  FILE *in;
14474351633Scy  unsigned int x[16];
14475346442Scy  char zLine[1000];
14476346442Scy  if( p->zDbFilename ){
14477346442Scy    in = fopen(p->zDbFilename, "r");
14478346442Scy    if( in==0 ){
14479346442Scy      utf8_printf(stderr, "cannot open \"%s\" for reading\n", p->zDbFilename);
14480346442Scy      return 0;
14481346442Scy    }
14482346442Scy    nLine = 0;
14483346442Scy  }else{
14484346442Scy    in = p->in;
14485346442Scy    nLine = p->lineno;
14486351633Scy    if( in==0 ) in = stdin;
14487346442Scy  }
14488346442Scy  *pnData = 0;
14489346442Scy  nLine++;
14490346442Scy  if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
14491346442Scy  rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
14492346442Scy  if( rc!=2 ) goto readHexDb_error;
14493351633Scy  if( n<0 ) goto readHexDb_error;
14494355326Scy  if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
14495355326Scy  n = (n+pgsz-1)&~(pgsz-1);  /* Round n up to the next multiple of pgsz */
14496351633Scy  a = sqlite3_malloc( n ? n : 1 );
14497346442Scy  if( a==0 ){
14498346442Scy    utf8_printf(stderr, "Out of memory!\n");
14499346442Scy    goto readHexDb_error;
14500346442Scy  }
14501346442Scy  memset(a, 0, n);
14502346442Scy  if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
14503346442Scy    utf8_printf(stderr, "invalid pagesize\n");
14504346442Scy    goto readHexDb_error;
14505346442Scy  }
14506346442Scy  for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
14507346442Scy    rc = sscanf(zLine, "| page %d offset %d", &j, &k);
14508346442Scy    if( rc==2 ){
14509346442Scy      iOffset = k;
14510346442Scy      continue;
14511346442Scy    }
14512346442Scy    if( strncmp(zLine, "| end ", 6)==0 ){
14513346442Scy      break;
14514346442Scy    }
14515351633Scy    rc = sscanf(zLine,"| %d: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
14516346442Scy                &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
14517346442Scy                &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
14518346442Scy    if( rc==17 ){
14519346442Scy      k = iOffset+j;
14520346442Scy      if( k+16<=n ){
14521351633Scy        int ii;
14522351633Scy        for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
14523346442Scy      }
14524346442Scy    }
14525346442Scy  }
14526346442Scy  *pnData = n;
14527346442Scy  if( in!=p->in ){
14528346442Scy    fclose(in);
14529346442Scy  }else{
14530346442Scy    p->lineno = nLine;
14531346442Scy  }
14532346442Scy  return a;
14533346442Scy
14534346442ScyreadHexDb_error:
14535351633Scy  if( in!=p->in ){
14536346442Scy    fclose(in);
14537346442Scy  }else{
14538346442Scy    while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
14539346442Scy      nLine++;
14540346442Scy      if(strncmp(zLine, "| end ", 6)==0 ) break;
14541346442Scy    }
14542346442Scy    p->lineno = nLine;
14543346442Scy  }
14544346442Scy  sqlite3_free(a);
14545346442Scy  utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
14546346442Scy  return 0;
14547346442Scy}
14548346442Scy#endif /* SQLITE_ENABLE_DESERIALIZE */
14549346442Scy
14550351633Scy/*
14551351633Scy** Scalar function "shell_int32". The first argument to this function
14552351633Scy** must be a blob. The second a non-negative integer. This function
14553351633Scy** reads and returns a 32-bit big-endian integer from byte
14554351633Scy** offset (4*<arg2>) of the blob.
14555351633Scy*/
14556351633Scystatic void shellInt32(
14557351633Scy  sqlite3_context *context,
14558351633Scy  int argc,
14559351633Scy  sqlite3_value **argv
14560351633Scy){
14561351633Scy  const unsigned char *pBlob;
14562351633Scy  int nBlob;
14563351633Scy  int iInt;
14564351633Scy
14565351633Scy  UNUSED_PARAMETER(argc);
14566351633Scy  nBlob = sqlite3_value_bytes(argv[0]);
14567351633Scy  pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
14568351633Scy  iInt = sqlite3_value_int(argv[1]);
14569351633Scy
14570351633Scy  if( iInt>=0 && (iInt+1)*4<=nBlob ){
14571351633Scy    const unsigned char *a = &pBlob[iInt*4];
14572351633Scy    sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24)
14573351633Scy                       + ((sqlite3_int64)a[1]<<16)
14574351633Scy                       + ((sqlite3_int64)a[2]<< 8)
14575351633Scy                       + ((sqlite3_int64)a[3]<< 0);
14576351633Scy    sqlite3_result_int64(context, iVal);
14577351633Scy  }
14578351633Scy}
14579351633Scy
14580351633Scy/*
14581355326Scy** Scalar function "shell_idquote(X)" returns string X quoted as an identifier,
14582355326Scy** using "..." with internal double-quote characters doubled.
14583355326Scy*/
14584355326Scystatic void shellIdQuote(
14585355326Scy  sqlite3_context *context,
14586355326Scy  int argc,
14587355326Scy  sqlite3_value **argv
14588355326Scy){
14589355326Scy  const char *zName = (const char*)sqlite3_value_text(argv[0]);
14590355326Scy  UNUSED_PARAMETER(argc);
14591355326Scy  if( zName ){
14592355326Scy    char *z = sqlite3_mprintf("\"%w\"", zName);
14593355326Scy    sqlite3_result_text(context, z, -1, sqlite3_free);
14594355326Scy  }
14595355326Scy}
14596355326Scy
14597355326Scy/*
14598369950Scy** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
14599369950Scy*/
14600369950Scystatic void shellUSleepFunc(
14601369950Scy  sqlite3_context *context,
14602369950Scy  int argcUnused,
14603369950Scy  sqlite3_value **argv
14604369950Scy){
14605369950Scy  int sleep = sqlite3_value_int(argv[0]);
14606369950Scy  (void)argcUnused;
14607369950Scy  sqlite3_sleep(sleep/1000);
14608369950Scy  sqlite3_result_int(context, sleep);
14609369950Scy}
14610369950Scy
14611369950Scy/*
14612351633Scy** Scalar function "shell_escape_crnl" used by the .recover command.
14613351633Scy** The argument passed to this function is the output of built-in
14614351633Scy** function quote(). If the first character of the input is "'",
14615351633Scy** indicating that the value passed to quote() was a text value,
14616351633Scy** then this function searches the input for "\n" and "\r" characters
14617351633Scy** and adds a wrapper similar to the following:
14618351633Scy**
14619351633Scy**   replace(replace(<input>, '\n', char(10), '\r', char(13));
14620351633Scy**
14621351633Scy** Or, if the first character of the input is not "'", then a copy
14622351633Scy** of the input is returned.
14623351633Scy*/
14624351633Scystatic void shellEscapeCrnl(
14625351633Scy  sqlite3_context *context,
14626351633Scy  int argc,
14627351633Scy  sqlite3_value **argv
14628351633Scy){
14629351633Scy  const char *zText = (const char*)sqlite3_value_text(argv[0]);
14630351633Scy  UNUSED_PARAMETER(argc);
14631351633Scy  if( zText[0]=='\'' ){
14632351633Scy    int nText = sqlite3_value_bytes(argv[0]);
14633351633Scy    int i;
14634351633Scy    char zBuf1[20];
14635351633Scy    char zBuf2[20];
14636351633Scy    const char *zNL = 0;
14637351633Scy    const char *zCR = 0;
14638351633Scy    int nCR = 0;
14639351633Scy    int nNL = 0;
14640351633Scy
14641351633Scy    for(i=0; zText[i]; i++){
14642351633Scy      if( zNL==0 && zText[i]=='\n' ){
14643351633Scy        zNL = unused_string(zText, "\\n", "\\012", zBuf1);
14644351633Scy        nNL = (int)strlen(zNL);
14645351633Scy      }
14646351633Scy      if( zCR==0 && zText[i]=='\r' ){
14647351633Scy        zCR = unused_string(zText, "\\r", "\\015", zBuf2);
14648351633Scy        nCR = (int)strlen(zCR);
14649351633Scy      }
14650351633Scy    }
14651351633Scy
14652351633Scy    if( zNL || zCR ){
14653351633Scy      int iOut = 0;
14654351633Scy      i64 nMax = (nNL > nCR) ? nNL : nCR;
14655351633Scy      i64 nAlloc = nMax * nText + (nMax+64)*2;
14656351633Scy      char *zOut = (char*)sqlite3_malloc64(nAlloc);
14657351633Scy      if( zOut==0 ){
14658351633Scy        sqlite3_result_error_nomem(context);
14659351633Scy        return;
14660351633Scy      }
14661351633Scy
14662351633Scy      if( zNL && zCR ){
14663351633Scy        memcpy(&zOut[iOut], "replace(replace(", 16);
14664351633Scy        iOut += 16;
14665351633Scy      }else{
14666351633Scy        memcpy(&zOut[iOut], "replace(", 8);
14667351633Scy        iOut += 8;
14668351633Scy      }
14669351633Scy      for(i=0; zText[i]; i++){
14670351633Scy        if( zText[i]=='\n' ){
14671351633Scy          memcpy(&zOut[iOut], zNL, nNL);
14672351633Scy          iOut += nNL;
14673351633Scy        }else if( zText[i]=='\r' ){
14674351633Scy          memcpy(&zOut[iOut], zCR, nCR);
14675351633Scy          iOut += nCR;
14676351633Scy        }else{
14677351633Scy          zOut[iOut] = zText[i];
14678351633Scy          iOut++;
14679351633Scy        }
14680351633Scy      }
14681351633Scy
14682351633Scy      if( zNL ){
14683351633Scy        memcpy(&zOut[iOut], ",'", 2); iOut += 2;
14684351633Scy        memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
14685351633Scy        memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
14686351633Scy      }
14687351633Scy      if( zCR ){
14688351633Scy        memcpy(&zOut[iOut], ",'", 2); iOut += 2;
14689351633Scy        memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
14690351633Scy        memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
14691351633Scy      }
14692351633Scy
14693351633Scy      sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
14694351633Scy      sqlite3_free(zOut);
14695351633Scy      return;
14696351633Scy    }
14697351633Scy  }
14698351633Scy
14699351633Scy  sqlite3_result_value(context, argv[0]);
14700351633Scy}
14701351633Scy
14702342292Scy/* Flags for open_db().
14703342292Scy**
14704342292Scy** The default behavior of open_db() is to exit(1) if the database fails to
14705342292Scy** open.  The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
14706342292Scy** but still returns without calling exit.
14707342292Scy**
14708342292Scy** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a
14709342292Scy** ZIP archive if the file does not exist or is empty and its name matches
14710342292Scy** the *.zip pattern.
14711342292Scy*/
14712342292Scy#define OPEN_DB_KEEPALIVE   0x001   /* Return after error if true */
14713342292Scy#define OPEN_DB_ZIPFILE     0x002   /* Open as ZIP if name matches *.zip */
14714342292Scy
14715342292Scy/*
14716251883Speter** Make sure the database is open.  If it is not, then open it.  If
14717251883Speter** the database fails to open, print an error message and exit.
14718251883Speter*/
14719342292Scystatic void open_db(ShellState *p, int openFlags){
14720251883Speter  if( p->db==0 ){
14721342292Scy    if( p->openMode==SHELL_OPEN_UNSPEC ){
14722342292Scy      if( p->zDbFilename==0 || p->zDbFilename[0]==0 ){
14723342292Scy        p->openMode = SHELL_OPEN_NORMAL;
14724342292Scy      }else{
14725342292Scy        p->openMode = (u8)deduceDatabaseType(p->zDbFilename,
14726342292Scy                             (openFlags & OPEN_DB_ZIPFILE)!=0);
14727342292Scy      }
14728342292Scy    }
14729342292Scy    switch( p->openMode ){
14730342292Scy      case SHELL_OPEN_APPENDVFS: {
14731342292Scy        sqlite3_open_v2(p->zDbFilename, &p->db,
14732361456Scy           SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
14733342292Scy        break;
14734342292Scy      }
14735346442Scy      case SHELL_OPEN_HEXDB:
14736342292Scy      case SHELL_OPEN_DESERIALIZE: {
14737342292Scy        sqlite3_open(0, &p->db);
14738342292Scy        break;
14739342292Scy      }
14740342292Scy      case SHELL_OPEN_ZIPFILE: {
14741342292Scy        sqlite3_open(":memory:", &p->db);
14742342292Scy        break;
14743342292Scy      }
14744342292Scy      case SHELL_OPEN_READONLY: {
14745361456Scy        sqlite3_open_v2(p->zDbFilename, &p->db,
14746361456Scy            SQLITE_OPEN_READONLY|p->openFlags, 0);
14747342292Scy        break;
14748342292Scy      }
14749342292Scy      case SHELL_OPEN_UNSPEC:
14750342292Scy      case SHELL_OPEN_NORMAL: {
14751361456Scy        sqlite3_open_v2(p->zDbFilename, &p->db,
14752361456Scy           SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
14753342292Scy        break;
14754342292Scy      }
14755342292Scy    }
14756286510Speter    globalDb = p->db;
14757286510Speter    if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
14758305002Scy      utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
14759286510Speter          p->zDbFilename, sqlite3_errmsg(p->db));
14760346442Scy      if( openFlags & OPEN_DB_KEEPALIVE ){
14761346442Scy        sqlite3_open(":memory:", &p->db);
14762346442Scy        return;
14763346442Scy      }
14764251883Speter      exit(1);
14765251883Speter    }
14766251883Speter#ifndef SQLITE_OMIT_LOAD_EXTENSION
14767251883Speter    sqlite3_enable_load_extension(p->db, 1);
14768251883Speter#endif
14769322444Speter    sqlite3_fileio_init(p->db, 0, 0);
14770322444Speter    sqlite3_shathree_init(p->db, 0, 0);
14771322444Speter    sqlite3_completion_init(p->db, 0, 0);
14772362190Scy    sqlite3_uint_init(p->db, 0, 0);
14773366076Scy    sqlite3_decimal_init(p->db, 0, 0);
14774366076Scy    sqlite3_ieee_init(p->db, 0, 0);
14775369950Scy    sqlite3_series_init(p->db, 0, 0);
14776351633Scy#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
14777351633Scy    sqlite3_dbdata_init(p->db, 0, 0);
14778351633Scy#endif
14779342292Scy#ifdef SQLITE_HAVE_ZLIB
14780342292Scy    sqlite3_zipfile_init(p->db, 0, 0);
14781342292Scy    sqlite3_sqlar_init(p->db, 0, 0);
14782342292Scy#endif
14783342292Scy    sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
14784322444Speter                            shellAddSchemaName, 0, 0);
14785342292Scy    sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
14786342292Scy                            shellModuleSchema, 0, 0);
14787342292Scy    sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
14788342292Scy                            shellPutsFunc, 0, 0);
14789351633Scy    sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0,
14790351633Scy                            shellEscapeCrnl, 0, 0);
14791351633Scy    sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
14792351633Scy                            shellInt32, 0, 0);
14793355326Scy    sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
14794355326Scy                            shellIdQuote, 0, 0);
14795369950Scy    sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
14796369950Scy                            shellUSleepFunc, 0, 0);
14797342292Scy#ifndef SQLITE_NOHAVE_SYSTEM
14798342292Scy    sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
14799342292Scy                            editFunc, 0, 0);
14800342292Scy    sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
14801342292Scy                            editFunc, 0, 0);
14802342292Scy#endif
14803342292Scy    if( p->openMode==SHELL_OPEN_ZIPFILE ){
14804342292Scy      char *zSql = sqlite3_mprintf(
14805342292Scy         "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename);
14806342292Scy      sqlite3_exec(p->db, zSql, 0, 0, 0);
14807342292Scy      sqlite3_free(zSql);
14808342292Scy    }
14809342292Scy#ifdef SQLITE_ENABLE_DESERIALIZE
14810346442Scy    else
14811346442Scy    if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
14812346442Scy      int rc;
14813342292Scy      int nData = 0;
14814346442Scy      unsigned char *aData;
14815346442Scy      if( p->openMode==SHELL_OPEN_DESERIALIZE ){
14816346442Scy        aData = (unsigned char*)readFile(p->zDbFilename, &nData);
14817346442Scy      }else{
14818346442Scy        aData = readHexDb(p, &nData);
14819346442Scy        if( aData==0 ){
14820346442Scy          return;
14821346442Scy        }
14822346442Scy      }
14823346442Scy      rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
14824342292Scy                   SQLITE_DESERIALIZE_RESIZEABLE |
14825342292Scy                   SQLITE_DESERIALIZE_FREEONCLOSE);
14826342292Scy      if( rc ){
14827342292Scy        utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
14828342292Scy      }
14829346442Scy      if( p->szMax>0 ){
14830346442Scy        sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
14831346442Scy      }
14832342292Scy    }
14833342292Scy#endif
14834251883Speter  }
14835251883Speter}
14836251883Speter
14837342292Scy/*
14838342292Scy** Attempt to close the databaes connection.  Report errors.
14839342292Scy*/
14840342292Scyvoid close_db(sqlite3 *db){
14841342292Scy  int rc = sqlite3_close(db);
14842342292Scy  if( rc ){
14843342292Scy    utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
14844342292Scy        rc, sqlite3_errmsg(db));
14845342292Scy  }
14846342292Scy}
14847342292Scy
14848322444Speter#if HAVE_READLINE || HAVE_EDITLINE
14849251883Speter/*
14850322444Speter** Readline completion callbacks
14851322444Speter*/
14852322444Speterstatic char *readline_completion_generator(const char *text, int state){
14853322444Speter  static sqlite3_stmt *pStmt = 0;
14854322444Speter  char *zRet;
14855322444Speter  if( state==0 ){
14856322444Speter    char *zSql;
14857322444Speter    sqlite3_finalize(pStmt);
14858322444Speter    zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
14859322444Speter                           "  FROM completion(%Q) ORDER BY 1", text);
14860322444Speter    sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
14861322444Speter    sqlite3_free(zSql);
14862322444Speter  }
14863322444Speter  if( sqlite3_step(pStmt)==SQLITE_ROW ){
14864322444Speter    zRet = strdup((const char*)sqlite3_column_text(pStmt, 0));
14865322444Speter  }else{
14866322444Speter    sqlite3_finalize(pStmt);
14867322444Speter    pStmt = 0;
14868322444Speter    zRet = 0;
14869322444Speter  }
14870322444Speter  return zRet;
14871322444Speter}
14872322444Speterstatic char **readline_completion(const char *zText, int iStart, int iEnd){
14873322444Speter  rl_attempted_completion_over = 1;
14874322444Speter  return rl_completion_matches(zText, readline_completion_generator);
14875322444Speter}
14876322444Speter
14877322444Speter#elif HAVE_LINENOISE
14878322444Speter/*
14879322444Speter** Linenoise completion callback
14880322444Speter*/
14881322444Speterstatic void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
14882342292Scy  int nLine = strlen30(zLine);
14883322444Speter  int i, iStart;
14884322444Speter  sqlite3_stmt *pStmt = 0;
14885322444Speter  char *zSql;
14886322444Speter  char zBuf[1000];
14887322444Speter
14888322444Speter  if( nLine>sizeof(zBuf)-30 ) return;
14889342292Scy  if( zLine[0]=='.' || zLine[0]=='#') return;
14890322444Speter  for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
14891322444Speter  if( i==nLine-1 ) return;
14892322444Speter  iStart = i+1;
14893322444Speter  memcpy(zBuf, zLine, iStart);
14894322444Speter  zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
14895322444Speter                         "  FROM completion(%Q,%Q) ORDER BY 1",
14896322444Speter                         &zLine[iStart], zLine);
14897322444Speter  sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
14898322444Speter  sqlite3_free(zSql);
14899322444Speter  sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
14900322444Speter  while( sqlite3_step(pStmt)==SQLITE_ROW ){
14901322444Speter    const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
14902322444Speter    int nCompletion = sqlite3_column_bytes(pStmt, 0);
14903322444Speter    if( iStart+nCompletion < sizeof(zBuf)-1 ){
14904322444Speter      memcpy(zBuf+iStart, zCompletion, nCompletion+1);
14905322444Speter      linenoiseAddCompletion(lc, zBuf);
14906322444Speter    }
14907322444Speter  }
14908322444Speter  sqlite3_finalize(pStmt);
14909322444Speter}
14910322444Speter#endif
14911322444Speter
14912322444Speter/*
14913251883Speter** Do C-language style dequoting.
14914251883Speter**
14915286510Speter**    \a    -> alarm
14916286510Speter**    \b    -> backspace
14917251883Speter**    \t    -> tab
14918251883Speter**    \n    -> newline
14919286510Speter**    \v    -> vertical tab
14920286510Speter**    \f    -> form feed
14921251883Speter**    \r    -> carriage return
14922286510Speter**    \s    -> space
14923269851Speter**    \"    -> "
14924286510Speter**    \'    -> '
14925286510Speter**    \\    -> backslash
14926251883Speter**    \NNN  -> ascii character NNN in octal
14927251883Speter*/
14928251883Speterstatic void resolve_backslashes(char *z){
14929251883Speter  int i, j;
14930251883Speter  char c;
14931269851Speter  while( *z && *z!='\\' ) z++;
14932251883Speter  for(i=j=0; (c = z[i])!=0; i++, j++){
14933286510Speter    if( c=='\\' && z[i+1]!=0 ){
14934251883Speter      c = z[++i];
14935286510Speter      if( c=='a' ){
14936286510Speter        c = '\a';
14937286510Speter      }else if( c=='b' ){
14938286510Speter        c = '\b';
14939251883Speter      }else if( c=='t' ){
14940251883Speter        c = '\t';
14941286510Speter      }else if( c=='n' ){
14942286510Speter        c = '\n';
14943286510Speter      }else if( c=='v' ){
14944286510Speter        c = '\v';
14945286510Speter      }else if( c=='f' ){
14946286510Speter        c = '\f';
14947251883Speter      }else if( c=='r' ){
14948251883Speter        c = '\r';
14949286510Speter      }else if( c=='"' ){
14950286510Speter        c = '"';
14951286510Speter      }else if( c=='\'' ){
14952286510Speter        c = '\'';
14953269851Speter      }else if( c=='\\' ){
14954269851Speter        c = '\\';
14955251883Speter      }else if( c>='0' && c<='7' ){
14956251883Speter        c -= '0';
14957251883Speter        if( z[i+1]>='0' && z[i+1]<='7' ){
14958251883Speter          i++;
14959251883Speter          c = (c<<3) + z[i] - '0';
14960251883Speter          if( z[i+1]>='0' && z[i+1]<='7' ){
14961251883Speter            i++;
14962251883Speter            c = (c<<3) + z[i] - '0';
14963251883Speter          }
14964251883Speter        }
14965251883Speter      }
14966251883Speter    }
14967251883Speter    z[j] = c;
14968251883Speter  }
14969269851Speter  if( j<i ) z[j] = 0;
14970251883Speter}
14971251883Speter
14972251883Speter/*
14973269851Speter** Interpret zArg as either an integer or a boolean value.  Return 1 or 0
14974269851Speter** for TRUE and FALSE.  Return the integer value if appropriate.
14975269851Speter*/
14976322444Speterstatic int booleanValue(const char *zArg){
14977269851Speter  int i;
14978269851Speter  if( zArg[0]=='0' && zArg[1]=='x' ){
14979269851Speter    for(i=2; hexDigitValue(zArg[i])>=0; i++){}
14980269851Speter  }else{
14981269851Speter    for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
14982269851Speter  }
14983269851Speter  if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
14984269851Speter  if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
14985269851Speter    return 1;
14986269851Speter  }
14987269851Speter  if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
14988269851Speter    return 0;
14989269851Speter  }
14990298161Sbapt  utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
14991269851Speter          zArg);
14992269851Speter  return 0;
14993269851Speter}
14994269851Speter
14995269851Speter/*
14996322444Speter** Set or clear a shell flag according to a boolean value.
14997322444Speter*/
14998322444Speterstatic void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){
14999322444Speter  if( booleanValue(zArg) ){
15000322444Speter    ShellSetFlag(p, mFlag);
15001322444Speter  }else{
15002322444Speter    ShellClearFlag(p, mFlag);
15003322444Speter  }
15004322444Speter}
15005322444Speter
15006322444Speter/*
15007251883Speter** Close an output file, assuming it is not stderr or stdout
15008251883Speter*/
15009251883Speterstatic void output_file_close(FILE *f){
15010251883Speter  if( f && f!=stdout && f!=stderr ) fclose(f);
15011251883Speter}
15012251883Speter
15013251883Speter/*
15014251883Speter** Try to open an output file.   The names "stdout" and "stderr" are
15015305002Scy** recognized and do the right thing.  NULL is returned if the output
15016251883Speter** filename is "off".
15017251883Speter*/
15018342292Scystatic FILE *output_file_open(const char *zFile, int bTextMode){
15019251883Speter  FILE *f;
15020251883Speter  if( strcmp(zFile,"stdout")==0 ){
15021251883Speter    f = stdout;
15022251883Speter  }else if( strcmp(zFile, "stderr")==0 ){
15023251883Speter    f = stderr;
15024251883Speter  }else if( strcmp(zFile, "off")==0 ){
15025251883Speter    f = 0;
15026251883Speter  }else{
15027342292Scy    f = fopen(zFile, bTextMode ? "w" : "wb");
15028251883Speter    if( f==0 ){
15029298161Sbapt      utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
15030251883Speter    }
15031251883Speter  }
15032251883Speter  return f;
15033251883Speter}
15034251883Speter
15035346442Scy#ifndef SQLITE_OMIT_TRACE
15036251883Speter/*
15037251883Speter** A routine for handling output from sqlite3_trace().
15038251883Speter*/
15039305002Scystatic int sql_trace_callback(
15040346442Scy  unsigned mType,         /* The trace type */
15041346442Scy  void *pArg,             /* The ShellState pointer */
15042346442Scy  void *pP,               /* Usually a pointer to sqlite_stmt */
15043346442Scy  void *pX                /* Auxiliary output */
15044305002Scy){
15045346442Scy  ShellState *p = (ShellState*)pArg;
15046346442Scy  sqlite3_stmt *pStmt;
15047346442Scy  const char *zSql;
15048346442Scy  int nSql;
15049346442Scy  if( p->traceOut==0 ) return 0;
15050346442Scy  if( mType==SQLITE_TRACE_CLOSE ){
15051346442Scy    utf8_printf(p->traceOut, "-- closing database connection\n");
15052346442Scy    return 0;
15053274884Sbapt  }
15054346442Scy  if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){
15055346442Scy    zSql = (const char*)pX;
15056346442Scy  }else{
15057346442Scy    pStmt = (sqlite3_stmt*)pP;
15058346442Scy    switch( p->eTraceType ){
15059346442Scy      case SHELL_TRACE_EXPANDED: {
15060346442Scy        zSql = sqlite3_expanded_sql(pStmt);
15061346442Scy        break;
15062346442Scy      }
15063346442Scy#ifdef SQLITE_ENABLE_NORMALIZE
15064346442Scy      case SHELL_TRACE_NORMALIZED: {
15065346442Scy        zSql = sqlite3_normalized_sql(pStmt);
15066346442Scy        break;
15067346442Scy      }
15068346442Scy#endif
15069346442Scy      default: {
15070346442Scy        zSql = sqlite3_sql(pStmt);
15071346442Scy        break;
15072346442Scy      }
15073346442Scy    }
15074346442Scy  }
15075346442Scy  if( zSql==0 ) return 0;
15076346442Scy  nSql = strlen30(zSql);
15077346442Scy  while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
15078346442Scy  switch( mType ){
15079346442Scy    case SQLITE_TRACE_ROW:
15080346442Scy    case SQLITE_TRACE_STMT: {
15081346442Scy      utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql);
15082346442Scy      break;
15083346442Scy    }
15084346442Scy    case SQLITE_TRACE_PROFILE: {
15085346442Scy      sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
15086346442Scy      utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec);
15087346442Scy      break;
15088346442Scy    }
15089346442Scy  }
15090305002Scy  return 0;
15091251883Speter}
15092322444Speter#endif
15093251883Speter
15094251883Speter/*
15095251883Speter** A no-op routine that runs with the ".breakpoint" doc-command.  This is
15096251883Speter** a useful spot to set a debugger breakpoint.
15097251883Speter*/
15098251883Speterstatic void test_breakpoint(void){
15099251883Speter  static int nCall = 0;
15100251883Speter  nCall++;
15101251883Speter}
15102251883Speter
15103251883Speter/*
15104282328Sbapt** An object used to read a CSV and other files for import.
15105269851Speter*/
15106282328Sbapttypedef struct ImportCtx ImportCtx;
15107282328Sbaptstruct ImportCtx {
15108269851Speter  const char *zFile;  /* Name of the input file */
15109269851Speter  FILE *in;           /* Read the CSV text from this input stream */
15110366076Scy  int (SQLITE_CDECL *xCloser)(FILE*);      /* Func to close in */
15111269851Speter  char *z;            /* Accumulated text for a field */
15112269851Speter  int n;              /* Number of bytes in z */
15113269851Speter  int nAlloc;         /* Space allocated for z[] */
15114269851Speter  int nLine;          /* Current line number */
15115362190Scy  int nRow;           /* Number of rows imported */
15116362190Scy  int nErr;           /* Number of errors encountered */
15117322444Speter  int bNotFirst;      /* True if one or more bytes already read */
15118269851Speter  int cTerm;          /* Character that terminated the most recent field */
15119282328Sbapt  int cColSep;        /* The column separator character.  (Usually ",") */
15120282328Sbapt  int cRowSep;        /* The row separator character.  (Usually "\n") */
15121269851Speter};
15122269851Speter
15123366076Scy/* Clean up resourced used by an ImportCtx */
15124366076Scystatic void import_cleanup(ImportCtx *p){
15125366076Scy  if( p->in!=0 && p->xCloser!=0 ){
15126366076Scy    p->xCloser(p->in);
15127366076Scy    p->in = 0;
15128366076Scy  }
15129366076Scy  sqlite3_free(p->z);
15130366076Scy  p->z = 0;
15131366076Scy}
15132366076Scy
15133269851Speter/* Append a single byte to z[] */
15134282328Sbaptstatic void import_append_char(ImportCtx *p, int c){
15135269851Speter  if( p->n+1>=p->nAlloc ){
15136269851Speter    p->nAlloc += p->nAlloc + 100;
15137286510Speter    p->z = sqlite3_realloc64(p->z, p->nAlloc);
15138342292Scy    if( p->z==0 ) shell_out_of_memory();
15139269851Speter  }
15140269851Speter  p->z[p->n++] = (char)c;
15141269851Speter}
15142269851Speter
15143269851Speter/* Read a single field of CSV text.  Compatible with rfc4180 and extended
15144269851Speter** with the option of having a separator other than ",".
15145269851Speter**
15146269851Speter**   +  Input comes from p->in.
15147269851Speter**   +  Store results in p->z of length p->n.  Space to hold p->z comes
15148286510Speter**      from sqlite3_malloc64().
15149282328Sbapt**   +  Use p->cSep as the column separator.  The default is ",".
15150282328Sbapt**   +  Use p->rSep as the row separator.  The default is "\n".
15151269851Speter**   +  Keep track of the line number in p->nLine.
15152269851Speter**   +  Store the character that terminates the field in p->cTerm.  Store
15153269851Speter**      EOF on end-of-file.
15154269851Speter**   +  Report syntax errors on stderr
15155269851Speter*/
15156282328Sbaptstatic char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
15157282328Sbapt  int c;
15158282328Sbapt  int cSep = p->cColSep;
15159282328Sbapt  int rSep = p->cRowSep;
15160269851Speter  p->n = 0;
15161269851Speter  c = fgetc(p->in);
15162269851Speter  if( c==EOF || seenInterrupt ){
15163269851Speter    p->cTerm = EOF;
15164269851Speter    return 0;
15165269851Speter  }
15166269851Speter  if( c=='"' ){
15167282328Sbapt    int pc, ppc;
15168269851Speter    int startLine = p->nLine;
15169269851Speter    int cQuote = c;
15170269851Speter    pc = ppc = 0;
15171269851Speter    while( 1 ){
15172269851Speter      c = fgetc(p->in);
15173282328Sbapt      if( c==rSep ) p->nLine++;
15174269851Speter      if( c==cQuote ){
15175269851Speter        if( pc==cQuote ){
15176269851Speter          pc = 0;
15177269851Speter          continue;
15178269851Speter        }
15179269851Speter      }
15180269851Speter      if( (c==cSep && pc==cQuote)
15181282328Sbapt       || (c==rSep && pc==cQuote)
15182282328Sbapt       || (c==rSep && pc=='\r' && ppc==cQuote)
15183269851Speter       || (c==EOF && pc==cQuote)
15184269851Speter      ){
15185269851Speter        do{ p->n--; }while( p->z[p->n]!=cQuote );
15186269851Speter        p->cTerm = c;
15187269851Speter        break;
15188269851Speter      }
15189269851Speter      if( pc==cQuote && c!='\r' ){
15190298161Sbapt        utf8_printf(stderr, "%s:%d: unescaped %c character\n",
15191269851Speter                p->zFile, p->nLine, cQuote);
15192269851Speter      }
15193269851Speter      if( c==EOF ){
15194298161Sbapt        utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
15195269851Speter                p->zFile, startLine, cQuote);
15196282328Sbapt        p->cTerm = c;
15197269851Speter        break;
15198269851Speter      }
15199282328Sbapt      import_append_char(p, c);
15200269851Speter      ppc = pc;
15201269851Speter      pc = c;
15202269851Speter    }
15203269851Speter  }else{
15204322444Speter    /* If this is the first field being parsed and it begins with the
15205322444Speter    ** UTF-8 BOM  (0xEF BB BF) then skip the BOM */
15206322444Speter    if( (c&0xff)==0xef && p->bNotFirst==0 ){
15207322444Speter      import_append_char(p, c);
15208322444Speter      c = fgetc(p->in);
15209322444Speter      if( (c&0xff)==0xbb ){
15210322444Speter        import_append_char(p, c);
15211322444Speter        c = fgetc(p->in);
15212322444Speter        if( (c&0xff)==0xbf ){
15213322444Speter          p->bNotFirst = 1;
15214322444Speter          p->n = 0;
15215322444Speter          return csv_read_one_field(p);
15216322444Speter        }
15217322444Speter      }
15218322444Speter    }
15219282328Sbapt    while( c!=EOF && c!=cSep && c!=rSep ){
15220282328Sbapt      import_append_char(p, c);
15221269851Speter      c = fgetc(p->in);
15222269851Speter    }
15223282328Sbapt    if( c==rSep ){
15224269851Speter      p->nLine++;
15225269851Speter      if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
15226269851Speter    }
15227269851Speter    p->cTerm = c;
15228269851Speter  }
15229269851Speter  if( p->z ) p->z[p->n] = 0;
15230322444Speter  p->bNotFirst = 1;
15231269851Speter  return p->z;
15232269851Speter}
15233269851Speter
15234282328Sbapt/* Read a single field of ASCII delimited text.
15235282328Sbapt**
15236282328Sbapt**   +  Input comes from p->in.
15237282328Sbapt**   +  Store results in p->z of length p->n.  Space to hold p->z comes
15238286510Speter**      from sqlite3_malloc64().
15239282328Sbapt**   +  Use p->cSep as the column separator.  The default is "\x1F".
15240282328Sbapt**   +  Use p->rSep as the row separator.  The default is "\x1E".
15241282328Sbapt**   +  Keep track of the row number in p->nLine.
15242282328Sbapt**   +  Store the character that terminates the field in p->cTerm.  Store
15243282328Sbapt**      EOF on end-of-file.
15244282328Sbapt**   +  Report syntax errors on stderr
15245282328Sbapt*/
15246282328Sbaptstatic char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
15247282328Sbapt  int c;
15248282328Sbapt  int cSep = p->cColSep;
15249282328Sbapt  int rSep = p->cRowSep;
15250282328Sbapt  p->n = 0;
15251282328Sbapt  c = fgetc(p->in);
15252282328Sbapt  if( c==EOF || seenInterrupt ){
15253282328Sbapt    p->cTerm = EOF;
15254282328Sbapt    return 0;
15255282328Sbapt  }
15256282328Sbapt  while( c!=EOF && c!=cSep && c!=rSep ){
15257282328Sbapt    import_append_char(p, c);
15258282328Sbapt    c = fgetc(p->in);
15259282328Sbapt  }
15260282328Sbapt  if( c==rSep ){
15261282328Sbapt    p->nLine++;
15262282328Sbapt  }
15263282328Sbapt  p->cTerm = c;
15264282328Sbapt  if( p->z ) p->z[p->n] = 0;
15265282328Sbapt  return p->z;
15266282328Sbapt}
15267282328Sbapt
15268269851Speter/*
15269269851Speter** Try to transfer data for table zTable.  If an error is seen while
15270269851Speter** moving forward, try to go backwards.  The backwards movement won't
15271269851Speter** work for WITHOUT ROWID tables.
15272269851Speter*/
15273269851Speterstatic void tryToCloneData(
15274274884Sbapt  ShellState *p,
15275269851Speter  sqlite3 *newDb,
15276269851Speter  const char *zTable
15277269851Speter){
15278305002Scy  sqlite3_stmt *pQuery = 0;
15279269851Speter  sqlite3_stmt *pInsert = 0;
15280269851Speter  char *zQuery = 0;
15281269851Speter  char *zInsert = 0;
15282269851Speter  int rc;
15283269851Speter  int i, j, n;
15284342292Scy  int nTable = strlen30(zTable);
15285269851Speter  int k = 0;
15286269851Speter  int cnt = 0;
15287269851Speter  const int spinRate = 10000;
15288269851Speter
15289269851Speter  zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
15290269851Speter  rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
15291269851Speter  if( rc ){
15292298161Sbapt    utf8_printf(stderr, "Error %d: %s on [%s]\n",
15293269851Speter            sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
15294269851Speter            zQuery);
15295269851Speter    goto end_data_xfer;
15296269851Speter  }
15297269851Speter  n = sqlite3_column_count(pQuery);
15298286510Speter  zInsert = sqlite3_malloc64(200 + nTable + n*3);
15299342292Scy  if( zInsert==0 ) shell_out_of_memory();
15300269851Speter  sqlite3_snprintf(200+nTable,zInsert,
15301269851Speter                   "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
15302342292Scy  i = strlen30(zInsert);
15303269851Speter  for(j=1; j<n; j++){
15304269851Speter    memcpy(zInsert+i, ",?", 2);
15305269851Speter    i += 2;
15306269851Speter  }
15307269851Speter  memcpy(zInsert+i, ");", 3);
15308269851Speter  rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
15309269851Speter  if( rc ){
15310298161Sbapt    utf8_printf(stderr, "Error %d: %s on [%s]\n",
15311269851Speter            sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
15312269851Speter            zQuery);
15313269851Speter    goto end_data_xfer;
15314269851Speter  }
15315269851Speter  for(k=0; k<2; k++){
15316269851Speter    while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
15317269851Speter      for(i=0; i<n; i++){
15318269851Speter        switch( sqlite3_column_type(pQuery, i) ){
15319269851Speter          case SQLITE_NULL: {
15320269851Speter            sqlite3_bind_null(pInsert, i+1);
15321269851Speter            break;
15322269851Speter          }
15323269851Speter          case SQLITE_INTEGER: {
15324269851Speter            sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
15325269851Speter            break;
15326269851Speter          }
15327269851Speter          case SQLITE_FLOAT: {
15328269851Speter            sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
15329269851Speter            break;
15330269851Speter          }
15331269851Speter          case SQLITE_TEXT: {
15332269851Speter            sqlite3_bind_text(pInsert, i+1,
15333269851Speter                             (const char*)sqlite3_column_text(pQuery,i),
15334269851Speter                             -1, SQLITE_STATIC);
15335269851Speter            break;
15336269851Speter          }
15337269851Speter          case SQLITE_BLOB: {
15338269851Speter            sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
15339269851Speter                                            sqlite3_column_bytes(pQuery,i),
15340269851Speter                                            SQLITE_STATIC);
15341269851Speter            break;
15342269851Speter          }
15343269851Speter        }
15344269851Speter      } /* End for */
15345269851Speter      rc = sqlite3_step(pInsert);
15346269851Speter      if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
15347298161Sbapt        utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
15348269851Speter                        sqlite3_errmsg(newDb));
15349269851Speter      }
15350269851Speter      sqlite3_reset(pInsert);
15351269851Speter      cnt++;
15352269851Speter      if( (cnt%spinRate)==0 ){
15353269851Speter        printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
15354269851Speter        fflush(stdout);
15355269851Speter      }
15356269851Speter    } /* End while */
15357269851Speter    if( rc==SQLITE_DONE ) break;
15358269851Speter    sqlite3_finalize(pQuery);
15359269851Speter    sqlite3_free(zQuery);
15360269851Speter    zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
15361269851Speter                             zTable);
15362269851Speter    rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
15363269851Speter    if( rc ){
15364298161Sbapt      utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
15365269851Speter      break;
15366269851Speter    }
15367269851Speter  } /* End for(k=0...) */
15368269851Speter
15369269851Speterend_data_xfer:
15370269851Speter  sqlite3_finalize(pQuery);
15371269851Speter  sqlite3_finalize(pInsert);
15372269851Speter  sqlite3_free(zQuery);
15373269851Speter  sqlite3_free(zInsert);
15374269851Speter}
15375269851Speter
15376269851Speter
15377269851Speter/*
15378269851Speter** Try to transfer all rows of the schema that match zWhere.  For
15379269851Speter** each row, invoke xForEach() on the object defined by that row.
15380269851Speter** If an error is encountered while moving forward through the
15381366076Scy** sqlite_schema table, try again moving backwards.
15382269851Speter*/
15383269851Speterstatic void tryToCloneSchema(
15384274884Sbapt  ShellState *p,
15385269851Speter  sqlite3 *newDb,
15386269851Speter  const char *zWhere,
15387274884Sbapt  void (*xForEach)(ShellState*,sqlite3*,const char*)
15388269851Speter){
15389269851Speter  sqlite3_stmt *pQuery = 0;
15390269851Speter  char *zQuery = 0;
15391269851Speter  int rc;
15392269851Speter  const unsigned char *zName;
15393269851Speter  const unsigned char *zSql;
15394269851Speter  char *zErrMsg = 0;
15395269851Speter
15396366076Scy  zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
15397269851Speter                           " WHERE %s", zWhere);
15398269851Speter  rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
15399269851Speter  if( rc ){
15400298161Sbapt    utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
15401269851Speter                    sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
15402269851Speter                    zQuery);
15403269851Speter    goto end_schema_xfer;
15404269851Speter  }
15405269851Speter  while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
15406269851Speter    zName = sqlite3_column_text(pQuery, 0);
15407269851Speter    zSql = sqlite3_column_text(pQuery, 1);
15408269851Speter    printf("%s... ", zName); fflush(stdout);
15409269851Speter    sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
15410269851Speter    if( zErrMsg ){
15411298161Sbapt      utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
15412269851Speter      sqlite3_free(zErrMsg);
15413269851Speter      zErrMsg = 0;
15414269851Speter    }
15415269851Speter    if( xForEach ){
15416269851Speter      xForEach(p, newDb, (const char*)zName);
15417269851Speter    }
15418269851Speter    printf("done\n");
15419269851Speter  }
15420269851Speter  if( rc!=SQLITE_DONE ){
15421269851Speter    sqlite3_finalize(pQuery);
15422269851Speter    sqlite3_free(zQuery);
15423366076Scy    zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
15424269851Speter                             " WHERE %s ORDER BY rowid DESC", zWhere);
15425269851Speter    rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
15426269851Speter    if( rc ){
15427298161Sbapt      utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
15428269851Speter                      sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
15429269851Speter                      zQuery);
15430269851Speter      goto end_schema_xfer;
15431269851Speter    }
15432269851Speter    while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
15433269851Speter      zName = sqlite3_column_text(pQuery, 0);
15434269851Speter      zSql = sqlite3_column_text(pQuery, 1);
15435269851Speter      printf("%s... ", zName); fflush(stdout);
15436269851Speter      sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
15437269851Speter      if( zErrMsg ){
15438298161Sbapt        utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
15439269851Speter        sqlite3_free(zErrMsg);
15440269851Speter        zErrMsg = 0;
15441269851Speter      }
15442269851Speter      if( xForEach ){
15443269851Speter        xForEach(p, newDb, (const char*)zName);
15444269851Speter      }
15445269851Speter      printf("done\n");
15446269851Speter    }
15447269851Speter  }
15448269851Speterend_schema_xfer:
15449269851Speter  sqlite3_finalize(pQuery);
15450269851Speter  sqlite3_free(zQuery);
15451269851Speter}
15452269851Speter
15453269851Speter/*
15454269851Speter** Open a new database file named "zNewDb".  Try to recover as much information
15455269851Speter** as possible out of the main database (which might be corrupt) and write it
15456269851Speter** into zNewDb.
15457269851Speter*/
15458274884Sbaptstatic void tryToClone(ShellState *p, const char *zNewDb){
15459269851Speter  int rc;
15460269851Speter  sqlite3 *newDb = 0;
15461269851Speter  if( access(zNewDb,0)==0 ){
15462298161Sbapt    utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
15463269851Speter    return;
15464269851Speter  }
15465269851Speter  rc = sqlite3_open(zNewDb, &newDb);
15466269851Speter  if( rc ){
15467298161Sbapt    utf8_printf(stderr, "Cannot create output database: %s\n",
15468269851Speter            sqlite3_errmsg(newDb));
15469269851Speter  }else{
15470269851Speter    sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
15471269851Speter    sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
15472269851Speter    tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
15473269851Speter    tryToCloneSchema(p, newDb, "type!='table'", 0);
15474269851Speter    sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
15475269851Speter    sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
15476269851Speter  }
15477342292Scy  close_db(newDb);
15478269851Speter}
15479269851Speter
15480269851Speter/*
15481342292Scy** Change the output file back to stdout.
15482342292Scy**
15483342292Scy** If the p->doXdgOpen flag is set, that means the output was being
15484342292Scy** redirected to a temporary file named by p->zTempFile.  In that case,
15485342292Scy** launch start/open/xdg-open on that temporary file.
15486269851Speter*/
15487274884Sbaptstatic void output_reset(ShellState *p){
15488269851Speter  if( p->outfile[0]=='|' ){
15489282328Sbapt#ifndef SQLITE_OMIT_POPEN
15490269851Speter    pclose(p->out);
15491282328Sbapt#endif
15492269851Speter  }else{
15493269851Speter    output_file_close(p->out);
15494342292Scy#ifndef SQLITE_NOHAVE_SYSTEM
15495342292Scy    if( p->doXdgOpen ){
15496342292Scy      const char *zXdgOpenCmd =
15497342292Scy#if defined(_WIN32)
15498342292Scy      "start";
15499342292Scy#elif defined(__APPLE__)
15500342292Scy      "open";
15501342292Scy#else
15502342292Scy      "xdg-open";
15503342292Scy#endif
15504342292Scy      char *zCmd;
15505342292Scy      zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
15506342292Scy      if( system(zCmd) ){
15507342292Scy        utf8_printf(stderr, "Failed: [%s]\n", zCmd);
15508362190Scy      }else{
15509362190Scy        /* Give the start/open/xdg-open command some time to get
15510362190Scy        ** going before we continue, and potential delete the
15511362190Scy        ** p->zTempFile data file out from under it */
15512362190Scy        sqlite3_sleep(2000);
15513342292Scy      }
15514342292Scy      sqlite3_free(zCmd);
15515342292Scy      outputModePop(p);
15516342292Scy      p->doXdgOpen = 0;
15517342292Scy    }
15518342292Scy#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
15519269851Speter  }
15520269851Speter  p->outfile[0] = 0;
15521269851Speter  p->out = stdout;
15522269851Speter}
15523269851Speter
15524269851Speter/*
15525282328Sbapt** Run an SQL command and return the single integer result.
15526282328Sbapt*/
15527282328Sbaptstatic int db_int(ShellState *p, const char *zSql){
15528282328Sbapt  sqlite3_stmt *pStmt;
15529282328Sbapt  int res = 0;
15530282328Sbapt  sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
15531282328Sbapt  if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
15532282328Sbapt    res = sqlite3_column_int(pStmt,0);
15533282328Sbapt  }
15534282328Sbapt  sqlite3_finalize(pStmt);
15535282328Sbapt  return res;
15536282328Sbapt}
15537282328Sbapt
15538282328Sbapt/*
15539282328Sbapt** Convert a 2-byte or 4-byte big-endian integer into a native integer
15540282328Sbapt*/
15541305002Scystatic unsigned int get2byteInt(unsigned char *a){
15542282328Sbapt  return (a[0]<<8) + a[1];
15543282328Sbapt}
15544305002Scystatic unsigned int get4byteInt(unsigned char *a){
15545282328Sbapt  return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
15546282328Sbapt}
15547282328Sbapt
15548282328Sbapt/*
15549361456Scy** Implementation of the ".dbinfo" command.
15550282328Sbapt**
15551282328Sbapt** Return 1 on error, 2 to exit, and 0 otherwise.
15552282328Sbapt*/
15553282328Sbaptstatic int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
15554282328Sbapt  static const struct { const char *zName; int ofst; } aField[] = {
15555282328Sbapt     { "file change counter:",  24  },
15556282328Sbapt     { "database page count:",  28  },
15557282328Sbapt     { "freelist page count:",  36  },
15558282328Sbapt     { "schema cookie:",        40  },
15559282328Sbapt     { "schema format:",        44  },
15560282328Sbapt     { "default cache size:",   48  },
15561282328Sbapt     { "autovacuum top root:",  52  },
15562282328Sbapt     { "incremental vacuum:",   64  },
15563282328Sbapt     { "text encoding:",        56  },
15564282328Sbapt     { "user version:",         60  },
15565282328Sbapt     { "application id:",       68  },
15566282328Sbapt     { "software version:",     96  },
15567282328Sbapt  };
15568282328Sbapt  static const struct { const char *zName; const char *zSql; } aQuery[] = {
15569282328Sbapt     { "number of tables:",
15570282328Sbapt       "SELECT count(*) FROM %s WHERE type='table'" },
15571282328Sbapt     { "number of indexes:",
15572282328Sbapt       "SELECT count(*) FROM %s WHERE type='index'" },
15573282328Sbapt     { "number of triggers:",
15574282328Sbapt       "SELECT count(*) FROM %s WHERE type='trigger'" },
15575282328Sbapt     { "number of views:",
15576282328Sbapt       "SELECT count(*) FROM %s WHERE type='view'" },
15577282328Sbapt     { "schema size:",
15578282328Sbapt       "SELECT total(length(sql)) FROM %s" },
15579282328Sbapt  };
15580347347Scy  int i, rc;
15581342292Scy  unsigned iDataVersion;
15582282328Sbapt  char *zSchemaTab;
15583282328Sbapt  char *zDb = nArg>=2 ? azArg[1] : "main";
15584342292Scy  sqlite3_stmt *pStmt = 0;
15585282328Sbapt  unsigned char aHdr[100];
15586282328Sbapt  open_db(p, 0);
15587282328Sbapt  if( p->db==0 ) return 1;
15588347347Scy  rc = sqlite3_prepare_v2(p->db,
15589347347Scy             "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
15590347347Scy             -1, &pStmt, 0);
15591347347Scy  if( rc ){
15592362190Scy    utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
15593347347Scy    sqlite3_finalize(pStmt);
15594347347Scy    return 1;
15595347347Scy  }
15596342292Scy  sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
15597342292Scy  if( sqlite3_step(pStmt)==SQLITE_ROW
15598342292Scy   && sqlite3_column_bytes(pStmt,0)>100
15599342292Scy  ){
15600342292Scy    memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
15601342292Scy    sqlite3_finalize(pStmt);
15602342292Scy  }else{
15603298161Sbapt    raw_printf(stderr, "unable to read database header\n");
15604342292Scy    sqlite3_finalize(pStmt);
15605282328Sbapt    return 1;
15606282328Sbapt  }
15607282328Sbapt  i = get2byteInt(aHdr+16);
15608282328Sbapt  if( i==1 ) i = 65536;
15609298161Sbapt  utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
15610298161Sbapt  utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
15611298161Sbapt  utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
15612298161Sbapt  utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
15613286510Speter  for(i=0; i<ArraySize(aField); i++){
15614282328Sbapt    int ofst = aField[i].ofst;
15615282328Sbapt    unsigned int val = get4byteInt(aHdr + ofst);
15616298161Sbapt    utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
15617282328Sbapt    switch( ofst ){
15618282328Sbapt      case 56: {
15619305002Scy        if( val==1 ) raw_printf(p->out, " (utf8)");
15620305002Scy        if( val==2 ) raw_printf(p->out, " (utf16le)");
15621305002Scy        if( val==3 ) raw_printf(p->out, " (utf16be)");
15622282328Sbapt      }
15623282328Sbapt    }
15624298161Sbapt    raw_printf(p->out, "\n");
15625282328Sbapt  }
15626282328Sbapt  if( zDb==0 ){
15627366076Scy    zSchemaTab = sqlite3_mprintf("main.sqlite_schema");
15628282328Sbapt  }else if( strcmp(zDb,"temp")==0 ){
15629366076Scy    zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
15630282328Sbapt  }else{
15631366076Scy    zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
15632282328Sbapt  }
15633286510Speter  for(i=0; i<ArraySize(aQuery); i++){
15634282328Sbapt    char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
15635282328Sbapt    int val = db_int(p, zSql);
15636282328Sbapt    sqlite3_free(zSql);
15637298161Sbapt    utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
15638282328Sbapt  }
15639282328Sbapt  sqlite3_free(zSchemaTab);
15640342292Scy  sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
15641342292Scy  utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
15642282328Sbapt  return 0;
15643282328Sbapt}
15644282328Sbapt
15645298161Sbapt/*
15646298161Sbapt** Print the current sqlite3_errmsg() value to stderr and return 1.
15647298161Sbapt*/
15648298161Sbaptstatic int shellDatabaseError(sqlite3 *db){
15649298161Sbapt  const char *zErr = sqlite3_errmsg(db);
15650298161Sbapt  utf8_printf(stderr, "Error: %s\n", zErr);
15651298161Sbapt  return 1;
15652298161Sbapt}
15653282328Sbapt
15654282328Sbapt/*
15655322444Speter** Compare the pattern in zGlob[] against the text in z[].  Return TRUE
15656322444Speter** if they match and FALSE (0) if they do not match.
15657322444Speter**
15658322444Speter** Globbing rules:
15659322444Speter**
15660322444Speter**      '*'       Matches any sequence of zero or more characters.
15661322444Speter**
15662322444Speter**      '?'       Matches exactly one character.
15663322444Speter**
15664322444Speter**     [...]      Matches one character from the enclosed list of
15665322444Speter**                characters.
15666322444Speter**
15667322444Speter**     [^...]     Matches one character not in the enclosed list.
15668322444Speter**
15669322444Speter**      '#'       Matches any sequence of one or more digits with an
15670322444Speter**                optional + or - sign in front
15671322444Speter**
15672322444Speter**      ' '       Any span of whitespace matches any other span of
15673322444Speter**                whitespace.
15674322444Speter**
15675322444Speter** Extra whitespace at the end of z[] is ignored.
15676322444Speter*/
15677322444Speterstatic int testcase_glob(const char *zGlob, const char *z){
15678322444Speter  int c, c2;
15679322444Speter  int invert;
15680322444Speter  int seen;
15681322444Speter
15682322444Speter  while( (c = (*(zGlob++)))!=0 ){
15683322444Speter    if( IsSpace(c) ){
15684322444Speter      if( !IsSpace(*z) ) return 0;
15685322444Speter      while( IsSpace(*zGlob) ) zGlob++;
15686322444Speter      while( IsSpace(*z) ) z++;
15687322444Speter    }else if( c=='*' ){
15688322444Speter      while( (c=(*(zGlob++))) == '*' || c=='?' ){
15689322444Speter        if( c=='?' && (*(z++))==0 ) return 0;
15690322444Speter      }
15691322444Speter      if( c==0 ){
15692322444Speter        return 1;
15693322444Speter      }else if( c=='[' ){
15694322444Speter        while( *z && testcase_glob(zGlob-1,z)==0 ){
15695322444Speter          z++;
15696322444Speter        }
15697322444Speter        return (*z)!=0;
15698322444Speter      }
15699322444Speter      while( (c2 = (*(z++)))!=0 ){
15700322444Speter        while( c2!=c ){
15701322444Speter          c2 = *(z++);
15702322444Speter          if( c2==0 ) return 0;
15703322444Speter        }
15704322444Speter        if( testcase_glob(zGlob,z) ) return 1;
15705322444Speter      }
15706322444Speter      return 0;
15707322444Speter    }else if( c=='?' ){
15708322444Speter      if( (*(z++))==0 ) return 0;
15709322444Speter    }else if( c=='[' ){
15710322444Speter      int prior_c = 0;
15711322444Speter      seen = 0;
15712322444Speter      invert = 0;
15713322444Speter      c = *(z++);
15714322444Speter      if( c==0 ) return 0;
15715322444Speter      c2 = *(zGlob++);
15716322444Speter      if( c2=='^' ){
15717322444Speter        invert = 1;
15718322444Speter        c2 = *(zGlob++);
15719322444Speter      }
15720322444Speter      if( c2==']' ){
15721322444Speter        if( c==']' ) seen = 1;
15722322444Speter        c2 = *(zGlob++);
15723322444Speter      }
15724322444Speter      while( c2 && c2!=']' ){
15725322444Speter        if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
15726322444Speter          c2 = *(zGlob++);
15727322444Speter          if( c>=prior_c && c<=c2 ) seen = 1;
15728322444Speter          prior_c = 0;
15729322444Speter        }else{
15730322444Speter          if( c==c2 ){
15731322444Speter            seen = 1;
15732322444Speter          }
15733322444Speter          prior_c = c2;
15734322444Speter        }
15735322444Speter        c2 = *(zGlob++);
15736322444Speter      }
15737322444Speter      if( c2==0 || (seen ^ invert)==0 ) return 0;
15738322444Speter    }else if( c=='#' ){
15739322444Speter      if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++;
15740322444Speter      if( !IsDigit(z[0]) ) return 0;
15741322444Speter      z++;
15742322444Speter      while( IsDigit(z[0]) ){ z++; }
15743322444Speter    }else{
15744322444Speter      if( c!=(*(z++)) ) return 0;
15745322444Speter    }
15746322444Speter  }
15747322444Speter  while( IsSpace(*z) ){ z++; }
15748322444Speter  return *z==0;
15749322444Speter}
15750322444Speter
15751322444Speter
15752322444Speter/*
15753305002Scy** Compare the string as a command-line option with either one or two
15754305002Scy** initial "-" characters.
15755305002Scy*/
15756305002Scystatic int optionMatch(const char *zStr, const char *zOpt){
15757305002Scy  if( zStr[0]!='-' ) return 0;
15758305002Scy  zStr++;
15759305002Scy  if( zStr[0]=='-' ) zStr++;
15760305002Scy  return strcmp(zStr, zOpt)==0;
15761305002Scy}
15762305002Scy
15763305002Scy/*
15764322444Speter** Delete a file.
15765322444Speter*/
15766322444Speterint shellDeleteFile(const char *zFilename){
15767322444Speter  int rc;
15768322444Speter#ifdef _WIN32
15769322444Speter  wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
15770322444Speter  rc = _wunlink(z);
15771322444Speter  sqlite3_free(z);
15772322444Speter#else
15773322444Speter  rc = unlink(zFilename);
15774322444Speter#endif
15775322444Speter  return rc;
15776322444Speter}
15777322444Speter
15778342292Scy/*
15779342292Scy** Try to delete the temporary file (if there is one) and free the
15780342292Scy** memory used to hold the name of the temp file.
15781342292Scy*/
15782342292Scystatic void clearTempFile(ShellState *p){
15783342292Scy  if( p->zTempFile==0 ) return;
15784342292Scy  if( p->doXdgOpen ) return;
15785342292Scy  if( shellDeleteFile(p->zTempFile) ) return;
15786342292Scy  sqlite3_free(p->zTempFile);
15787342292Scy  p->zTempFile = 0;
15788342292Scy}
15789322444Speter
15790322444Speter/*
15791342292Scy** Create a new temp file name with the given suffix.
15792342292Scy*/
15793342292Scystatic void newTempFile(ShellState *p, const char *zSuffix){
15794342292Scy  clearTempFile(p);
15795342292Scy  sqlite3_free(p->zTempFile);
15796342292Scy  p->zTempFile = 0;
15797342292Scy  if( p->db ){
15798342292Scy    sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
15799342292Scy  }
15800342292Scy  if( p->zTempFile==0 ){
15801362190Scy    /* If p->db is an in-memory database then the TEMPFILENAME file-control
15802362190Scy    ** will not work and we will need to fallback to guessing */
15803362190Scy    char *zTemp;
15804342292Scy    sqlite3_uint64 r;
15805342292Scy    sqlite3_randomness(sizeof(r), &r);
15806362190Scy    zTemp = getenv("TEMP");
15807362190Scy    if( zTemp==0 ) zTemp = getenv("TMP");
15808362190Scy    if( zTemp==0 ){
15809362190Scy#ifdef _WIN32
15810362190Scy      zTemp = "\\tmp";
15811362190Scy#else
15812362190Scy      zTemp = "/tmp";
15813362190Scy#endif
15814362190Scy    }
15815362190Scy    p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix);
15816342292Scy  }else{
15817342292Scy    p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
15818342292Scy  }
15819342292Scy  if( p->zTempFile==0 ){
15820342292Scy    raw_printf(stderr, "out of memory\n");
15821342292Scy    exit(1);
15822342292Scy  }
15823342292Scy}
15824342292Scy
15825342292Scy
15826342292Scy/*
15827322444Speter** The implementation of SQL scalar function fkey_collate_clause(), used
15828322444Speter** by the ".lint fkey-indexes" command. This scalar function is always
15829322444Speter** called with four arguments - the parent table name, the parent column name,
15830322444Speter** the child table name and the child column name.
15831322444Speter**
15832322444Speter**   fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
15833322444Speter**
15834322444Speter** If either of the named tables or columns do not exist, this function
15835322444Speter** returns an empty string. An empty string is also returned if both tables
15836322444Speter** and columns exist but have the same default collation sequence. Or,
15837322444Speter** if both exist but the default collation sequences are different, this
15838322444Speter** function returns the string " COLLATE <parent-collation>", where
15839322444Speter** <parent-collation> is the default collation sequence of the parent column.
15840322444Speter*/
15841322444Speterstatic void shellFkeyCollateClause(
15842322444Speter  sqlite3_context *pCtx,
15843322444Speter  int nVal,
15844322444Speter  sqlite3_value **apVal
15845322444Speter){
15846322444Speter  sqlite3 *db = sqlite3_context_db_handle(pCtx);
15847322444Speter  const char *zParent;
15848322444Speter  const char *zParentCol;
15849322444Speter  const char *zParentSeq;
15850322444Speter  const char *zChild;
15851322444Speter  const char *zChildCol;
15852322444Speter  const char *zChildSeq = 0;  /* Initialize to avoid false-positive warning */
15853322444Speter  int rc;
15854322444Speter
15855322444Speter  assert( nVal==4 );
15856322444Speter  zParent = (const char*)sqlite3_value_text(apVal[0]);
15857322444Speter  zParentCol = (const char*)sqlite3_value_text(apVal[1]);
15858322444Speter  zChild = (const char*)sqlite3_value_text(apVal[2]);
15859322444Speter  zChildCol = (const char*)sqlite3_value_text(apVal[3]);
15860322444Speter
15861322444Speter  sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
15862322444Speter  rc = sqlite3_table_column_metadata(
15863322444Speter      db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0
15864322444Speter  );
15865322444Speter  if( rc==SQLITE_OK ){
15866322444Speter    rc = sqlite3_table_column_metadata(
15867322444Speter        db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0
15868322444Speter    );
15869322444Speter  }
15870322444Speter
15871322444Speter  if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){
15872322444Speter    char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq);
15873322444Speter    sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
15874322444Speter    sqlite3_free(z);
15875322444Speter  }
15876322444Speter}
15877322444Speter
15878322444Speter
15879322444Speter/*
15880322444Speter** The implementation of dot-command ".lint fkey-indexes".
15881322444Speter*/
15882322444Speterstatic int lintFkeyIndexes(
15883322444Speter  ShellState *pState,             /* Current shell tool state */
15884322444Speter  char **azArg,                   /* Array of arguments passed to dot command */
15885322444Speter  int nArg                        /* Number of entries in azArg[] */
15886322444Speter){
15887322444Speter  sqlite3 *db = pState->db;       /* Database handle to query "main" db of */
15888322444Speter  FILE *out = pState->out;        /* Stream to write non-error output to */
15889322444Speter  int bVerbose = 0;               /* If -verbose is present */
15890322444Speter  int bGroupByParent = 0;         /* If -groupbyparent is present */
15891322444Speter  int i;                          /* To iterate through azArg[] */
15892322444Speter  const char *zIndent = "";       /* How much to indent CREATE INDEX by */
15893322444Speter  int rc;                         /* Return code */
15894322444Speter  sqlite3_stmt *pSql = 0;         /* Compiled version of SQL statement below */
15895322444Speter
15896322444Speter  /*
15897322444Speter  ** This SELECT statement returns one row for each foreign key constraint
15898322444Speter  ** in the schema of the main database. The column values are:
15899322444Speter  **
15900322444Speter  ** 0. The text of an SQL statement similar to:
15901322444Speter  **
15902342292Scy  **      "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?"
15903322444Speter  **
15904342292Scy  **    This SELECT is similar to the one that the foreign keys implementation
15905342292Scy  **    needs to run internally on child tables. If there is an index that can
15906322444Speter  **    be used to optimize this query, then it can also be used by the FK
15907322444Speter  **    implementation to optimize DELETE or UPDATE statements on the parent
15908322444Speter  **    table.
15909322444Speter  **
15910322444Speter  ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by
15911322444Speter  **    the EXPLAIN QUERY PLAN command matches this pattern, then the schema
15912322444Speter  **    contains an index that can be used to optimize the query.
15913322444Speter  **
15914322444Speter  ** 2. Human readable text that describes the child table and columns. e.g.
15915322444Speter  **
15916322444Speter  **       "child_table(child_key1, child_key2)"
15917322444Speter  **
15918322444Speter  ** 3. Human readable text that describes the parent table and columns. e.g.
15919322444Speter  **
15920322444Speter  **       "parent_table(parent_key1, parent_key2)"
15921322444Speter  **
15922322444Speter  ** 4. A full CREATE INDEX statement for an index that could be used to
15923322444Speter  **    optimize DELETE or UPDATE statements on the parent table. e.g.
15924322444Speter  **
15925322444Speter  **       "CREATE INDEX child_table_child_key ON child_table(child_key)"
15926322444Speter  **
15927322444Speter  ** 5. The name of the parent table.
15928322444Speter  **
15929322444Speter  ** These six values are used by the C logic below to generate the report.
15930322444Speter  */
15931322444Speter  const char *zSql =
15932322444Speter  "SELECT "
15933342292Scy    "     'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
15934322444Speter    "  || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
15935322444Speter    "  || fkey_collate_clause("
15936322444Speter    "       f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
15937322444Speter    ", "
15938322444Speter    "     'SEARCH TABLE ' || s.name || ' USING COVERING INDEX*('"
15939322444Speter    "  || group_concat('*=?', ' AND ') || ')'"
15940322444Speter    ", "
15941322444Speter    "     s.name  || '(' || group_concat(f.[from],  ', ') || ')'"
15942322444Speter    ", "
15943322444Speter    "     f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
15944322444Speter    ", "
15945322444Speter    "     'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
15946322444Speter    "  || ' ON ' || quote(s.name) || '('"
15947322444Speter    "  || group_concat(quote(f.[from]) ||"
15948322444Speter    "        fkey_collate_clause("
15949322444Speter    "          f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
15950322444Speter    "  || ');'"
15951322444Speter    ", "
15952322444Speter    "     f.[table] "
15953366076Scy    "FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f "
15954322444Speter    "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
15955322444Speter    "GROUP BY s.name, f.id "
15956322444Speter    "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
15957322444Speter  ;
15958322444Speter  const char *zGlobIPK = "SEARCH TABLE * USING INTEGER PRIMARY KEY (rowid=?)";
15959322444Speter
15960322444Speter  for(i=2; i<nArg; i++){
15961342292Scy    int n = strlen30(azArg[i]);
15962322444Speter    if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
15963322444Speter      bVerbose = 1;
15964322444Speter    }
15965322444Speter    else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
15966322444Speter      bGroupByParent = 1;
15967322444Speter      zIndent = "    ";
15968322444Speter    }
15969322444Speter    else{
15970322444Speter      raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
15971322444Speter          azArg[0], azArg[1]
15972322444Speter      );
15973322444Speter      return SQLITE_ERROR;
15974322444Speter    }
15975322444Speter  }
15976322444Speter
15977322444Speter  /* Register the fkey_collate_clause() SQL function */
15978322444Speter  rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
15979322444Speter      0, shellFkeyCollateClause, 0, 0
15980322444Speter  );
15981322444Speter
15982322444Speter
15983322444Speter  if( rc==SQLITE_OK ){
15984322444Speter    rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
15985322444Speter  }
15986322444Speter  if( rc==SQLITE_OK ){
15987322444Speter    sqlite3_bind_int(pSql, 1, bGroupByParent);
15988322444Speter  }
15989322444Speter
15990322444Speter  if( rc==SQLITE_OK ){
15991322444Speter    int rc2;
15992322444Speter    char *zPrev = 0;
15993322444Speter    while( SQLITE_ROW==sqlite3_step(pSql) ){
15994322444Speter      int res = -1;
15995322444Speter      sqlite3_stmt *pExplain = 0;
15996322444Speter      const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
15997322444Speter      const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
15998322444Speter      const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
15999322444Speter      const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
16000322444Speter      const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
16001322444Speter      const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
16002322444Speter
16003322444Speter      rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
16004322444Speter      if( rc!=SQLITE_OK ) break;
16005322444Speter      if( SQLITE_ROW==sqlite3_step(pExplain) ){
16006322444Speter        const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
16007322444Speter        res = (
16008322444Speter              0==sqlite3_strglob(zGlob, zPlan)
16009322444Speter           || 0==sqlite3_strglob(zGlobIPK, zPlan)
16010322444Speter        );
16011322444Speter      }
16012322444Speter      rc = sqlite3_finalize(pExplain);
16013322444Speter      if( rc!=SQLITE_OK ) break;
16014322444Speter
16015322444Speter      if( res<0 ){
16016322444Speter        raw_printf(stderr, "Error: internal error");
16017322444Speter        break;
16018322444Speter      }else{
16019322444Speter        if( bGroupByParent
16020322444Speter        && (bVerbose || res==0)
16021322444Speter        && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
16022322444Speter        ){
16023322444Speter          raw_printf(out, "-- Parent table %s\n", zParent);
16024322444Speter          sqlite3_free(zPrev);
16025322444Speter          zPrev = sqlite3_mprintf("%s", zParent);
16026322444Speter        }
16027322444Speter
16028322444Speter        if( res==0 ){
16029322444Speter          raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
16030322444Speter        }else if( bVerbose ){
16031322444Speter          raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
16032322444Speter              zIndent, zFrom, zTarget
16033322444Speter          );
16034322444Speter        }
16035322444Speter      }
16036322444Speter    }
16037322444Speter    sqlite3_free(zPrev);
16038322444Speter
16039322444Speter    if( rc!=SQLITE_OK ){
16040322444Speter      raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
16041322444Speter    }
16042322444Speter
16043322444Speter    rc2 = sqlite3_finalize(pSql);
16044322444Speter    if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
16045322444Speter      rc = rc2;
16046322444Speter      raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
16047322444Speter    }
16048322444Speter  }else{
16049322444Speter    raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
16050322444Speter  }
16051322444Speter
16052322444Speter  return rc;
16053322444Speter}
16054322444Speter
16055322444Speter/*
16056322444Speter** Implementation of ".lint" dot command.
16057322444Speter*/
16058322444Speterstatic int lintDotCommand(
16059322444Speter  ShellState *pState,             /* Current shell tool state */
16060322444Speter  char **azArg,                   /* Array of arguments passed to dot command */
16061322444Speter  int nArg                        /* Number of entries in azArg[] */
16062322444Speter){
16063322444Speter  int n;
16064342292Scy  n = (nArg>=2 ? strlen30(azArg[1]) : 0);
16065322444Speter  if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
16066322444Speter  return lintFkeyIndexes(pState, azArg, nArg);
16067322444Speter
16068322444Speter usage:
16069322444Speter  raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
16070322444Speter  raw_printf(stderr, "Where sub-commands are:\n");
16071322444Speter  raw_printf(stderr, "    fkey-indexes\n");
16072322444Speter  return SQLITE_ERROR;
16073322444Speter}
16074322444Speter
16075351633Scy#if !defined SQLITE_OMIT_VIRTUALTABLE
16076342292Scystatic void shellPrepare(
16077342292Scy  sqlite3 *db,
16078342292Scy  int *pRc,
16079342292Scy  const char *zSql,
16080342292Scy  sqlite3_stmt **ppStmt
16081342292Scy){
16082342292Scy  *ppStmt = 0;
16083342292Scy  if( *pRc==SQLITE_OK ){
16084342292Scy    int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
16085342292Scy    if( rc!=SQLITE_OK ){
16086342292Scy      raw_printf(stderr, "sql error: %s (%d)\n",
16087342292Scy          sqlite3_errmsg(db), sqlite3_errcode(db)
16088342292Scy      );
16089342292Scy      *pRc = rc;
16090342292Scy    }
16091342292Scy  }
16092342292Scy}
16093322444Speter
16094351633Scy/*
16095351633Scy** Create a prepared statement using printf-style arguments for the SQL.
16096351633Scy**
16097351633Scy** This routine is could be marked "static".  But it is not always used,
16098351633Scy** depending on compile-time options.  By omitting the "static", we avoid
16099351633Scy** nuisance compiler warnings about "defined but not used".
16100351633Scy*/
16101351633Scyvoid shellPreparePrintf(
16102342292Scy  sqlite3 *db,
16103342292Scy  int *pRc,
16104342292Scy  sqlite3_stmt **ppStmt,
16105342292Scy  const char *zFmt,
16106342292Scy  ...
16107342292Scy){
16108342292Scy  *ppStmt = 0;
16109342292Scy  if( *pRc==SQLITE_OK ){
16110342292Scy    va_list ap;
16111342292Scy    char *z;
16112342292Scy    va_start(ap, zFmt);
16113342292Scy    z = sqlite3_vmprintf(zFmt, ap);
16114342292Scy    va_end(ap);
16115342292Scy    if( z==0 ){
16116342292Scy      *pRc = SQLITE_NOMEM;
16117342292Scy    }else{
16118342292Scy      shellPrepare(db, pRc, z, ppStmt);
16119342292Scy      sqlite3_free(z);
16120342292Scy    }
16121342292Scy  }
16122342292Scy}
16123342292Scy
16124351633Scy/* Finalize the prepared statement created using shellPreparePrintf().
16125351633Scy**
16126351633Scy** This routine is could be marked "static".  But it is not always used,
16127351633Scy** depending on compile-time options.  By omitting the "static", we avoid
16128351633Scy** nuisance compiler warnings about "defined but not used".
16129351633Scy*/
16130351633Scyvoid shellFinalize(
16131342292Scy  int *pRc,
16132342292Scy  sqlite3_stmt *pStmt
16133342292Scy){
16134342292Scy  if( pStmt ){
16135342292Scy    sqlite3 *db = sqlite3_db_handle(pStmt);
16136342292Scy    int rc = sqlite3_finalize(pStmt);
16137342292Scy    if( *pRc==SQLITE_OK ){
16138342292Scy      if( rc!=SQLITE_OK ){
16139342292Scy        raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
16140342292Scy      }
16141342292Scy      *pRc = rc;
16142342292Scy    }
16143342292Scy  }
16144342292Scy}
16145342292Scy
16146351633Scy/* Reset the prepared statement created using shellPreparePrintf().
16147351633Scy**
16148351633Scy** This routine is could be marked "static".  But it is not always used,
16149351633Scy** depending on compile-time options.  By omitting the "static", we avoid
16150351633Scy** nuisance compiler warnings about "defined but not used".
16151351633Scy*/
16152351633Scyvoid shellReset(
16153342292Scy  int *pRc,
16154342292Scy  sqlite3_stmt *pStmt
16155342292Scy){
16156342292Scy  int rc = sqlite3_reset(pStmt);
16157342292Scy  if( *pRc==SQLITE_OK ){
16158342292Scy    if( rc!=SQLITE_OK ){
16159342292Scy      sqlite3 *db = sqlite3_db_handle(pStmt);
16160342292Scy      raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
16161342292Scy    }
16162342292Scy    *pRc = rc;
16163342292Scy  }
16164342292Scy}
16165351633Scy#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
16166351633Scy
16167351633Scy#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
16168355326Scy/******************************************************************************
16169351633Scy** The ".archive" or ".ar" command.
16170351633Scy*/
16171322444Speter/*
16172342292Scy** Structure representing a single ".ar" command.
16173342292Scy*/
16174342292Scytypedef struct ArCommand ArCommand;
16175342292Scystruct ArCommand {
16176342292Scy  u8 eCmd;                        /* An AR_CMD_* value */
16177342292Scy  u8 bVerbose;                    /* True if --verbose */
16178342292Scy  u8 bZip;                        /* True if the archive is a ZIP */
16179342292Scy  u8 bDryRun;                     /* True if --dry-run */
16180342292Scy  u8 bAppend;                     /* True if --append */
16181342292Scy  u8 fromCmdLine;                 /* Run from -A instead of .archive */
16182342292Scy  int nArg;                       /* Number of command arguments */
16183342292Scy  char *zSrcTable;                /* "sqlar", "zipfile($file)" or "zip" */
16184342292Scy  const char *zFile;              /* --file argument, or NULL */
16185342292Scy  const char *zDir;               /* --directory argument, or NULL */
16186342292Scy  char **azArg;                   /* Array of command arguments */
16187342292Scy  ShellState *p;                  /* Shell state */
16188342292Scy  sqlite3 *db;                    /* Database containing the archive */
16189342292Scy};
16190342292Scy
16191342292Scy/*
16192342292Scy** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
16193342292Scy*/
16194342292Scystatic int arUsage(FILE *f){
16195342292Scy  showHelp(f,"archive");
16196342292Scy  return SQLITE_ERROR;
16197342292Scy}
16198342292Scy
16199342292Scy/*
16200342292Scy** Print an error message for the .ar command to stderr and return
16201342292Scy** SQLITE_ERROR.
16202342292Scy*/
16203342292Scystatic int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
16204342292Scy  va_list ap;
16205342292Scy  char *z;
16206342292Scy  va_start(ap, zFmt);
16207342292Scy  z = sqlite3_vmprintf(zFmt, ap);
16208342292Scy  va_end(ap);
16209342292Scy  utf8_printf(stderr, "Error: %s\n", z);
16210342292Scy  if( pAr->fromCmdLine ){
16211342292Scy    utf8_printf(stderr, "Use \"-A\" for more help\n");
16212342292Scy  }else{
16213342292Scy    utf8_printf(stderr, "Use \".archive --help\" for more help\n");
16214342292Scy  }
16215342292Scy  sqlite3_free(z);
16216342292Scy  return SQLITE_ERROR;
16217342292Scy}
16218342292Scy
16219342292Scy/*
16220342292Scy** Values for ArCommand.eCmd.
16221342292Scy*/
16222342292Scy#define AR_CMD_CREATE       1
16223347347Scy#define AR_CMD_UPDATE       2
16224347347Scy#define AR_CMD_INSERT       3
16225347347Scy#define AR_CMD_EXTRACT      4
16226347347Scy#define AR_CMD_LIST         5
16227347347Scy#define AR_CMD_HELP         6
16228342292Scy
16229342292Scy/*
16230342292Scy** Other (non-command) switches.
16231342292Scy*/
16232347347Scy#define AR_SWITCH_VERBOSE     7
16233347347Scy#define AR_SWITCH_FILE        8
16234347347Scy#define AR_SWITCH_DIRECTORY   9
16235347347Scy#define AR_SWITCH_APPEND     10
16236347347Scy#define AR_SWITCH_DRYRUN     11
16237342292Scy
16238342292Scystatic int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
16239342292Scy  switch( eSwitch ){
16240342292Scy    case AR_CMD_CREATE:
16241342292Scy    case AR_CMD_EXTRACT:
16242342292Scy    case AR_CMD_LIST:
16243342292Scy    case AR_CMD_UPDATE:
16244347347Scy    case AR_CMD_INSERT:
16245342292Scy    case AR_CMD_HELP:
16246342292Scy      if( pAr->eCmd ){
16247342292Scy        return arErrorMsg(pAr, "multiple command options");
16248342292Scy      }
16249342292Scy      pAr->eCmd = eSwitch;
16250342292Scy      break;
16251342292Scy
16252342292Scy    case AR_SWITCH_DRYRUN:
16253342292Scy      pAr->bDryRun = 1;
16254342292Scy      break;
16255342292Scy    case AR_SWITCH_VERBOSE:
16256342292Scy      pAr->bVerbose = 1;
16257342292Scy      break;
16258342292Scy    case AR_SWITCH_APPEND:
16259342292Scy      pAr->bAppend = 1;
16260342292Scy      /* Fall thru into --file */
16261342292Scy    case AR_SWITCH_FILE:
16262342292Scy      pAr->zFile = zArg;
16263342292Scy      break;
16264342292Scy    case AR_SWITCH_DIRECTORY:
16265342292Scy      pAr->zDir = zArg;
16266342292Scy      break;
16267342292Scy  }
16268342292Scy
16269342292Scy  return SQLITE_OK;
16270342292Scy}
16271342292Scy
16272342292Scy/*
16273342292Scy** Parse the command line for an ".ar" command. The results are written into
16274342292Scy** structure (*pAr). SQLITE_OK is returned if the command line is parsed
16275342292Scy** successfully, otherwise an error message is written to stderr and
16276342292Scy** SQLITE_ERROR returned.
16277342292Scy*/
16278342292Scystatic int arParseCommand(
16279342292Scy  char **azArg,                   /* Array of arguments passed to dot command */
16280342292Scy  int nArg,                       /* Number of entries in azArg[] */
16281342292Scy  ArCommand *pAr                  /* Populate this object */
16282342292Scy){
16283342292Scy  struct ArSwitch {
16284342292Scy    const char *zLong;
16285342292Scy    char cShort;
16286342292Scy    u8 eSwitch;
16287342292Scy    u8 bArg;
16288342292Scy  } aSwitch[] = {
16289342292Scy    { "create",    'c', AR_CMD_CREATE,       0 },
16290342292Scy    { "extract",   'x', AR_CMD_EXTRACT,      0 },
16291347347Scy    { "insert",    'i', AR_CMD_INSERT,       0 },
16292342292Scy    { "list",      't', AR_CMD_LIST,         0 },
16293342292Scy    { "update",    'u', AR_CMD_UPDATE,       0 },
16294342292Scy    { "help",      'h', AR_CMD_HELP,         0 },
16295342292Scy    { "verbose",   'v', AR_SWITCH_VERBOSE,   0 },
16296342292Scy    { "file",      'f', AR_SWITCH_FILE,      1 },
16297342292Scy    { "append",    'a', AR_SWITCH_APPEND,    1 },
16298342292Scy    { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
16299342292Scy    { "dryrun",    'n', AR_SWITCH_DRYRUN,    0 },
16300342292Scy  };
16301342292Scy  int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
16302342292Scy  struct ArSwitch *pEnd = &aSwitch[nSwitch];
16303342292Scy
16304342292Scy  if( nArg<=1 ){
16305342292Scy    utf8_printf(stderr, "Wrong number of arguments.  Usage:\n");
16306342292Scy    return arUsage(stderr);
16307342292Scy  }else{
16308342292Scy    char *z = azArg[1];
16309342292Scy    if( z[0]!='-' ){
16310342292Scy      /* Traditional style [tar] invocation */
16311342292Scy      int i;
16312342292Scy      int iArg = 2;
16313342292Scy      for(i=0; z[i]; i++){
16314342292Scy        const char *zArg = 0;
16315342292Scy        struct ArSwitch *pOpt;
16316342292Scy        for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
16317342292Scy          if( z[i]==pOpt->cShort ) break;
16318342292Scy        }
16319342292Scy        if( pOpt==pEnd ){
16320342292Scy          return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
16321342292Scy        }
16322342292Scy        if( pOpt->bArg ){
16323342292Scy          if( iArg>=nArg ){
16324342292Scy            return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
16325342292Scy          }
16326342292Scy          zArg = azArg[iArg++];
16327342292Scy        }
16328342292Scy        if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
16329342292Scy      }
16330342292Scy      pAr->nArg = nArg-iArg;
16331342292Scy      if( pAr->nArg>0 ){
16332342292Scy        pAr->azArg = &azArg[iArg];
16333342292Scy      }
16334342292Scy    }else{
16335342292Scy      /* Non-traditional invocation */
16336342292Scy      int iArg;
16337342292Scy      for(iArg=1; iArg<nArg; iArg++){
16338342292Scy        int n;
16339342292Scy        z = azArg[iArg];
16340342292Scy        if( z[0]!='-' ){
16341342292Scy          /* All remaining command line words are command arguments. */
16342342292Scy          pAr->azArg = &azArg[iArg];
16343342292Scy          pAr->nArg = nArg-iArg;
16344342292Scy          break;
16345342292Scy        }
16346342292Scy        n = strlen30(z);
16347342292Scy
16348342292Scy        if( z[1]!='-' ){
16349342292Scy          int i;
16350342292Scy          /* One or more short options */
16351342292Scy          for(i=1; i<n; i++){
16352342292Scy            const char *zArg = 0;
16353342292Scy            struct ArSwitch *pOpt;
16354342292Scy            for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
16355342292Scy              if( z[i]==pOpt->cShort ) break;
16356342292Scy            }
16357342292Scy            if( pOpt==pEnd ){
16358342292Scy              return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
16359342292Scy            }
16360342292Scy            if( pOpt->bArg ){
16361342292Scy              if( i<(n-1) ){
16362342292Scy                zArg = &z[i+1];
16363342292Scy                i = n;
16364342292Scy              }else{
16365342292Scy                if( iArg>=(nArg-1) ){
16366355326Scy                  return arErrorMsg(pAr, "option requires an argument: %c",
16367355326Scy                                    z[i]);
16368342292Scy                }
16369342292Scy                zArg = azArg[++iArg];
16370342292Scy              }
16371342292Scy            }
16372342292Scy            if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
16373342292Scy          }
16374342292Scy        }else if( z[2]=='\0' ){
16375342292Scy          /* A -- option, indicating that all remaining command line words
16376342292Scy          ** are command arguments.  */
16377342292Scy          pAr->azArg = &azArg[iArg+1];
16378342292Scy          pAr->nArg = nArg-iArg-1;
16379342292Scy          break;
16380342292Scy        }else{
16381342292Scy          /* A long option */
16382342292Scy          const char *zArg = 0;             /* Argument for option, if any */
16383342292Scy          struct ArSwitch *pMatch = 0;      /* Matching option */
16384342292Scy          struct ArSwitch *pOpt;            /* Iterator */
16385342292Scy          for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
16386342292Scy            const char *zLong = pOpt->zLong;
16387342292Scy            if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
16388342292Scy              if( pMatch ){
16389342292Scy                return arErrorMsg(pAr, "ambiguous option: %s",z);
16390342292Scy              }else{
16391342292Scy                pMatch = pOpt;
16392342292Scy              }
16393342292Scy            }
16394342292Scy          }
16395342292Scy
16396342292Scy          if( pMatch==0 ){
16397342292Scy            return arErrorMsg(pAr, "unrecognized option: %s", z);
16398342292Scy          }
16399342292Scy          if( pMatch->bArg ){
16400342292Scy            if( iArg>=(nArg-1) ){
16401342292Scy              return arErrorMsg(pAr, "option requires an argument: %s", z);
16402342292Scy            }
16403342292Scy            zArg = azArg[++iArg];
16404342292Scy          }
16405342292Scy          if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
16406342292Scy        }
16407342292Scy      }
16408342292Scy    }
16409342292Scy  }
16410342292Scy
16411342292Scy  return SQLITE_OK;
16412342292Scy}
16413342292Scy
16414342292Scy/*
16415342292Scy** This function assumes that all arguments within the ArCommand.azArg[]
16416342292Scy** array refer to archive members, as for the --extract or --list commands.
16417342292Scy** It checks that each of them are present. If any specified file is not
16418342292Scy** present in the archive, an error is printed to stderr and an error
16419342292Scy** code returned. Otherwise, if all specified arguments are present in
16420342292Scy** the archive, SQLITE_OK is returned.
16421342292Scy**
16422342292Scy** This function strips any trailing '/' characters from each argument.
16423342292Scy** This is consistent with the way the [tar] command seems to work on
16424342292Scy** Linux.
16425342292Scy*/
16426342292Scystatic int arCheckEntries(ArCommand *pAr){
16427342292Scy  int rc = SQLITE_OK;
16428342292Scy  if( pAr->nArg ){
16429342292Scy    int i, j;
16430342292Scy    sqlite3_stmt *pTest = 0;
16431342292Scy
16432342292Scy    shellPreparePrintf(pAr->db, &rc, &pTest,
16433342292Scy        "SELECT name FROM %s WHERE name=$name",
16434342292Scy        pAr->zSrcTable
16435342292Scy    );
16436342292Scy    j = sqlite3_bind_parameter_index(pTest, "$name");
16437342292Scy    for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
16438342292Scy      char *z = pAr->azArg[i];
16439342292Scy      int n = strlen30(z);
16440342292Scy      int bOk = 0;
16441342292Scy      while( n>0 && z[n-1]=='/' ) n--;
16442342292Scy      z[n] = '\0';
16443342292Scy      sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
16444342292Scy      if( SQLITE_ROW==sqlite3_step(pTest) ){
16445342292Scy        bOk = 1;
16446342292Scy      }
16447342292Scy      shellReset(&rc, pTest);
16448342292Scy      if( rc==SQLITE_OK && bOk==0 ){
16449342292Scy        utf8_printf(stderr, "not found in archive: %s\n", z);
16450342292Scy        rc = SQLITE_ERROR;
16451342292Scy      }
16452342292Scy    }
16453342292Scy    shellFinalize(&rc, pTest);
16454342292Scy  }
16455342292Scy  return rc;
16456342292Scy}
16457342292Scy
16458342292Scy/*
16459342292Scy** Format a WHERE clause that can be used against the "sqlar" table to
16460342292Scy** identify all archive members that match the command arguments held
16461342292Scy** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
16462342292Scy** The caller is responsible for eventually calling sqlite3_free() on
16463342292Scy** any non-NULL (*pzWhere) value.
16464342292Scy*/
16465342292Scystatic void arWhereClause(
16466342292Scy  int *pRc,
16467342292Scy  ArCommand *pAr,
16468342292Scy  char **pzWhere                  /* OUT: New WHERE clause */
16469342292Scy){
16470342292Scy  char *zWhere = 0;
16471342292Scy  if( *pRc==SQLITE_OK ){
16472342292Scy    if( pAr->nArg==0 ){
16473342292Scy      zWhere = sqlite3_mprintf("1");
16474342292Scy    }else{
16475342292Scy      int i;
16476342292Scy      const char *zSep = "";
16477342292Scy      for(i=0; i<pAr->nArg; i++){
16478342292Scy        const char *z = pAr->azArg[i];
16479342292Scy        zWhere = sqlite3_mprintf(
16480342292Scy          "%z%s name = '%q' OR substr(name,1,%d) = '%q/'",
16481342292Scy          zWhere, zSep, z, strlen30(z)+1, z
16482342292Scy        );
16483342292Scy        if( zWhere==0 ){
16484342292Scy          *pRc = SQLITE_NOMEM;
16485342292Scy          break;
16486342292Scy        }
16487342292Scy        zSep = " OR ";
16488342292Scy      }
16489342292Scy    }
16490342292Scy  }
16491342292Scy  *pzWhere = zWhere;
16492342292Scy}
16493342292Scy
16494342292Scy/*
16495342292Scy** Implementation of .ar "lisT" command.
16496342292Scy*/
16497342292Scystatic int arListCommand(ArCommand *pAr){
16498342292Scy  const char *zSql = "SELECT %s FROM %s WHERE %s";
16499342292Scy  const char *azCols[] = {
16500342292Scy    "name",
16501342292Scy    "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
16502342292Scy  };
16503342292Scy
16504342292Scy  char *zWhere = 0;
16505342292Scy  sqlite3_stmt *pSql = 0;
16506342292Scy  int rc;
16507342292Scy
16508342292Scy  rc = arCheckEntries(pAr);
16509342292Scy  arWhereClause(&rc, pAr, &zWhere);
16510342292Scy
16511342292Scy  shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
16512342292Scy                     pAr->zSrcTable, zWhere);
16513342292Scy  if( pAr->bDryRun ){
16514342292Scy    utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
16515342292Scy  }else{
16516342292Scy    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
16517342292Scy      if( pAr->bVerbose ){
16518342292Scy        utf8_printf(pAr->p->out, "%s % 10d  %s  %s\n",
16519342292Scy            sqlite3_column_text(pSql, 0),
16520342292Scy            sqlite3_column_int(pSql, 1),
16521342292Scy            sqlite3_column_text(pSql, 2),
16522342292Scy            sqlite3_column_text(pSql, 3)
16523342292Scy        );
16524342292Scy      }else{
16525342292Scy        utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
16526342292Scy      }
16527342292Scy    }
16528342292Scy  }
16529342292Scy  shellFinalize(&rc, pSql);
16530342292Scy  sqlite3_free(zWhere);
16531342292Scy  return rc;
16532342292Scy}
16533342292Scy
16534342292Scy
16535342292Scy/*
16536342292Scy** Implementation of .ar "eXtract" command.
16537342292Scy*/
16538342292Scystatic int arExtractCommand(ArCommand *pAr){
16539342292Scy  const char *zSql1 =
16540342292Scy    "SELECT "
16541342292Scy    " ($dir || name),"
16542342292Scy    " writefile(($dir || name), %s, mode, mtime) "
16543342292Scy    "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
16544342292Scy    " AND name NOT GLOB '*..[/\\]*'";
16545342292Scy
16546342292Scy  const char *azExtraArg[] = {
16547342292Scy    "sqlar_uncompress(data, sz)",
16548342292Scy    "data"
16549342292Scy  };
16550342292Scy
16551342292Scy  sqlite3_stmt *pSql = 0;
16552342292Scy  int rc = SQLITE_OK;
16553342292Scy  char *zDir = 0;
16554342292Scy  char *zWhere = 0;
16555342292Scy  int i, j;
16556342292Scy
16557342292Scy  /* If arguments are specified, check that they actually exist within
16558342292Scy  ** the archive before proceeding. And formulate a WHERE clause to
16559342292Scy  ** match them.  */
16560342292Scy  rc = arCheckEntries(pAr);
16561342292Scy  arWhereClause(&rc, pAr, &zWhere);
16562342292Scy
16563342292Scy  if( rc==SQLITE_OK ){
16564342292Scy    if( pAr->zDir ){
16565342292Scy      zDir = sqlite3_mprintf("%s/", pAr->zDir);
16566342292Scy    }else{
16567342292Scy      zDir = sqlite3_mprintf("");
16568342292Scy    }
16569342292Scy    if( zDir==0 ) rc = SQLITE_NOMEM;
16570342292Scy  }
16571342292Scy
16572342292Scy  shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
16573342292Scy      azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
16574342292Scy  );
16575342292Scy
16576342292Scy  if( rc==SQLITE_OK ){
16577342292Scy    j = sqlite3_bind_parameter_index(pSql, "$dir");
16578342292Scy    sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
16579342292Scy
16580342292Scy    /* Run the SELECT statement twice. The first time, writefile() is called
16581342292Scy    ** for all archive members that should be extracted. The second time,
16582342292Scy    ** only for the directories. This is because the timestamps for
16583342292Scy    ** extracted directories must be reset after they are populated (as
16584342292Scy    ** populating them changes the timestamp).  */
16585342292Scy    for(i=0; i<2; i++){
16586342292Scy      j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
16587342292Scy      sqlite3_bind_int(pSql, j, i);
16588342292Scy      if( pAr->bDryRun ){
16589342292Scy        utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
16590342292Scy      }else{
16591342292Scy        while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
16592342292Scy          if( i==0 && pAr->bVerbose ){
16593342292Scy            utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
16594342292Scy          }
16595342292Scy        }
16596342292Scy      }
16597342292Scy      shellReset(&rc, pSql);
16598342292Scy    }
16599342292Scy    shellFinalize(&rc, pSql);
16600342292Scy  }
16601342292Scy
16602342292Scy  sqlite3_free(zDir);
16603342292Scy  sqlite3_free(zWhere);
16604342292Scy  return rc;
16605342292Scy}
16606342292Scy
16607342292Scy/*
16608342292Scy** Run the SQL statement in zSql.  Or if doing a --dryrun, merely print it out.
16609342292Scy*/
16610342292Scystatic int arExecSql(ArCommand *pAr, const char *zSql){
16611342292Scy  int rc;
16612342292Scy  if( pAr->bDryRun ){
16613342292Scy    utf8_printf(pAr->p->out, "%s\n", zSql);
16614342292Scy    rc = SQLITE_OK;
16615342292Scy  }else{
16616342292Scy    char *zErr = 0;
16617342292Scy    rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
16618342292Scy    if( zErr ){
16619342292Scy      utf8_printf(stdout, "ERROR: %s\n", zErr);
16620342292Scy      sqlite3_free(zErr);
16621342292Scy    }
16622342292Scy  }
16623342292Scy  return rc;
16624342292Scy}
16625342292Scy
16626342292Scy
16627342292Scy/*
16628347347Scy** Implementation of .ar "create", "insert", and "update" commands.
16629342292Scy**
16630347347Scy**     create    ->     Create a new SQL archive
16631347347Scy**     insert    ->     Insert or reinsert all files listed
16632347347Scy**     update    ->     Insert files that have changed or that were not
16633347347Scy**                      previously in the archive
16634347347Scy**
16635342292Scy** Create the "sqlar" table in the database if it does not already exist.
16636342292Scy** Then add each file in the azFile[] array to the archive. Directories
16637342292Scy** are added recursively. If argument bVerbose is non-zero, a message is
16638342292Scy** printed on stdout for each file archived.
16639342292Scy**
16640342292Scy** The create command is the same as update, except that it drops
16641347347Scy** any existing "sqlar" table before beginning.  The "insert" command
16642347347Scy** always overwrites every file named on the command-line, where as
16643347347Scy** "update" only overwrites if the size or mtime or mode has changed.
16644342292Scy*/
16645342292Scystatic int arCreateOrUpdateCommand(
16646342292Scy  ArCommand *pAr,                 /* Command arguments and options */
16647347347Scy  int bUpdate,                    /* true for a --create. */
16648347347Scy  int bOnlyIfChanged              /* Only update if file has changed */
16649342292Scy){
16650342292Scy  const char *zCreate =
16651342292Scy      "CREATE TABLE IF NOT EXISTS sqlar(\n"
16652342292Scy      "  name TEXT PRIMARY KEY,  -- name of the file\n"
16653342292Scy      "  mode INT,               -- access permissions\n"
16654342292Scy      "  mtime INT,              -- last modification time\n"
16655342292Scy      "  sz INT,                 -- original file size\n"
16656342292Scy      "  data BLOB               -- compressed content\n"
16657342292Scy      ")";
16658342292Scy  const char *zDrop = "DROP TABLE IF EXISTS sqlar";
16659342292Scy  const char *zInsertFmt[2] = {
16660342292Scy     "REPLACE INTO %s(name,mode,mtime,sz,data)\n"
16661342292Scy     "  SELECT\n"
16662342292Scy     "    %s,\n"
16663342292Scy     "    mode,\n"
16664342292Scy     "    mtime,\n"
16665342292Scy     "    CASE substr(lsmode(mode),1,1)\n"
16666342292Scy     "      WHEN '-' THEN length(data)\n"
16667342292Scy     "      WHEN 'd' THEN 0\n"
16668342292Scy     "      ELSE -1 END,\n"
16669342292Scy     "    sqlar_compress(data)\n"
16670347347Scy     "  FROM fsdir(%Q,%Q) AS disk\n"
16671347347Scy     "  WHERE lsmode(mode) NOT LIKE '?%%'%s;"
16672347347Scy     ,
16673342292Scy     "REPLACE INTO %s(name,mode,mtime,data)\n"
16674342292Scy     "  SELECT\n"
16675342292Scy     "    %s,\n"
16676342292Scy     "    mode,\n"
16677342292Scy     "    mtime,\n"
16678342292Scy     "    data\n"
16679347347Scy     "  FROM fsdir(%Q,%Q) AS disk\n"
16680347347Scy     "  WHERE lsmode(mode) NOT LIKE '?%%'%s;"
16681342292Scy  };
16682342292Scy  int i;                          /* For iterating through azFile[] */
16683342292Scy  int rc;                         /* Return code */
16684342292Scy  const char *zTab = 0;           /* SQL table into which to insert */
16685342292Scy  char *zSql;
16686342292Scy  char zTemp[50];
16687347347Scy  char *zExists = 0;
16688342292Scy
16689342292Scy  arExecSql(pAr, "PRAGMA page_size=512");
16690342292Scy  rc = arExecSql(pAr, "SAVEPOINT ar;");
16691342292Scy  if( rc!=SQLITE_OK ) return rc;
16692342292Scy  zTemp[0] = 0;
16693342292Scy  if( pAr->bZip ){
16694342292Scy    /* Initialize the zipfile virtual table, if necessary */
16695342292Scy    if( pAr->zFile ){
16696342292Scy      sqlite3_uint64 r;
16697342292Scy      sqlite3_randomness(sizeof(r),&r);
16698342292Scy      sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
16699342292Scy      zTab = zTemp;
16700342292Scy      zSql = sqlite3_mprintf(
16701342292Scy         "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)",
16702342292Scy         zTab, pAr->zFile
16703342292Scy      );
16704342292Scy      rc = arExecSql(pAr, zSql);
16705342292Scy      sqlite3_free(zSql);
16706342292Scy    }else{
16707342292Scy      zTab = "zip";
16708342292Scy    }
16709342292Scy  }else{
16710342292Scy    /* Initialize the table for an SQLAR */
16711342292Scy    zTab = "sqlar";
16712342292Scy    if( bUpdate==0 ){
16713342292Scy      rc = arExecSql(pAr, zDrop);
16714342292Scy      if( rc!=SQLITE_OK ) goto end_ar_transaction;
16715342292Scy    }
16716342292Scy    rc = arExecSql(pAr, zCreate);
16717342292Scy  }
16718347347Scy  if( bOnlyIfChanged ){
16719347347Scy    zExists = sqlite3_mprintf(
16720347347Scy      " AND NOT EXISTS("
16721347347Scy          "SELECT 1 FROM %s AS mem"
16722347347Scy          " WHERE mem.name=disk.name"
16723347347Scy          " AND mem.mtime=disk.mtime"
16724347347Scy          " AND mem.mode=disk.mode)", zTab);
16725347347Scy  }else{
16726347347Scy    zExists = sqlite3_mprintf("");
16727347347Scy  }
16728347347Scy  if( zExists==0 ) rc = SQLITE_NOMEM;
16729342292Scy  for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
16730342292Scy    char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
16731342292Scy        pAr->bVerbose ? "shell_putsnl(name)" : "name",
16732347347Scy        pAr->azArg[i], pAr->zDir, zExists);
16733342292Scy    rc = arExecSql(pAr, zSql2);
16734342292Scy    sqlite3_free(zSql2);
16735342292Scy  }
16736342292Scyend_ar_transaction:
16737342292Scy  if( rc!=SQLITE_OK ){
16738346442Scy    sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
16739342292Scy  }else{
16740342292Scy    rc = arExecSql(pAr, "RELEASE ar;");
16741342292Scy    if( pAr->bZip && pAr->zFile ){
16742342292Scy      zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
16743342292Scy      arExecSql(pAr, zSql);
16744342292Scy      sqlite3_free(zSql);
16745342292Scy    }
16746342292Scy  }
16747347347Scy  sqlite3_free(zExists);
16748342292Scy  return rc;
16749342292Scy}
16750342292Scy
16751342292Scy/*
16752342292Scy** Implementation of ".ar" dot command.
16753342292Scy*/
16754342292Scystatic int arDotCommand(
16755355326Scy  ShellState *pState,          /* Current shell tool state */
16756355326Scy  int fromCmdLine,             /* True if -A command-line option, not .ar cmd */
16757355326Scy  char **azArg,                /* Array of arguments passed to dot command */
16758355326Scy  int nArg                     /* Number of entries in azArg[] */
16759342292Scy){
16760342292Scy  ArCommand cmd;
16761342292Scy  int rc;
16762342292Scy  memset(&cmd, 0, sizeof(cmd));
16763342292Scy  cmd.fromCmdLine = fromCmdLine;
16764342292Scy  rc = arParseCommand(azArg, nArg, &cmd);
16765342292Scy  if( rc==SQLITE_OK ){
16766342292Scy    int eDbType = SHELL_OPEN_UNSPEC;
16767342292Scy    cmd.p = pState;
16768342292Scy    cmd.db = pState->db;
16769342292Scy    if( cmd.zFile ){
16770342292Scy      eDbType = deduceDatabaseType(cmd.zFile, 1);
16771342292Scy    }else{
16772342292Scy      eDbType = pState->openMode;
16773342292Scy    }
16774342292Scy    if( eDbType==SHELL_OPEN_ZIPFILE ){
16775342292Scy      if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){
16776342292Scy        if( cmd.zFile==0 ){
16777342292Scy          cmd.zSrcTable = sqlite3_mprintf("zip");
16778342292Scy        }else{
16779342292Scy          cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
16780342292Scy        }
16781342292Scy      }
16782342292Scy      cmd.bZip = 1;
16783342292Scy    }else if( cmd.zFile ){
16784342292Scy      int flags;
16785342292Scy      if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
16786347347Scy      if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
16787347347Scy           || cmd.eCmd==AR_CMD_UPDATE ){
16788342292Scy        flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
16789342292Scy      }else{
16790342292Scy        flags = SQLITE_OPEN_READONLY;
16791342292Scy      }
16792342292Scy      cmd.db = 0;
16793342292Scy      if( cmd.bDryRun ){
16794342292Scy        utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
16795342292Scy             eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
16796342292Scy      }
16797342292Scy      rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
16798342292Scy             eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
16799342292Scy      if( rc!=SQLITE_OK ){
16800342292Scy        utf8_printf(stderr, "cannot open file: %s (%s)\n",
16801342292Scy            cmd.zFile, sqlite3_errmsg(cmd.db)
16802342292Scy        );
16803342292Scy        goto end_ar_command;
16804342292Scy      }
16805342292Scy      sqlite3_fileio_init(cmd.db, 0, 0);
16806342292Scy      sqlite3_sqlar_init(cmd.db, 0, 0);
16807342292Scy      sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
16808342292Scy                              shellPutsFunc, 0, 0);
16809342292Scy
16810342292Scy    }
16811342292Scy    if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
16812342292Scy      if( cmd.eCmd!=AR_CMD_CREATE
16813342292Scy       && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
16814342292Scy      ){
16815342292Scy        utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
16816342292Scy        rc = SQLITE_ERROR;
16817342292Scy        goto end_ar_command;
16818342292Scy      }
16819342292Scy      cmd.zSrcTable = sqlite3_mprintf("sqlar");
16820342292Scy    }
16821342292Scy
16822342292Scy    switch( cmd.eCmd ){
16823342292Scy      case AR_CMD_CREATE:
16824347347Scy        rc = arCreateOrUpdateCommand(&cmd, 0, 0);
16825342292Scy        break;
16826342292Scy
16827342292Scy      case AR_CMD_EXTRACT:
16828342292Scy        rc = arExtractCommand(&cmd);
16829342292Scy        break;
16830342292Scy
16831342292Scy      case AR_CMD_LIST:
16832342292Scy        rc = arListCommand(&cmd);
16833342292Scy        break;
16834342292Scy
16835342292Scy      case AR_CMD_HELP:
16836342292Scy        arUsage(pState->out);
16837342292Scy        break;
16838342292Scy
16839347347Scy      case AR_CMD_INSERT:
16840347347Scy        rc = arCreateOrUpdateCommand(&cmd, 1, 0);
16841347347Scy        break;
16842347347Scy
16843342292Scy      default:
16844342292Scy        assert( cmd.eCmd==AR_CMD_UPDATE );
16845347347Scy        rc = arCreateOrUpdateCommand(&cmd, 1, 1);
16846342292Scy        break;
16847342292Scy    }
16848342292Scy  }
16849342292Scyend_ar_command:
16850342292Scy  if( cmd.db!=pState->db ){
16851342292Scy    close_db(cmd.db);
16852342292Scy  }
16853342292Scy  sqlite3_free(cmd.zSrcTable);
16854342292Scy
16855342292Scy  return rc;
16856342292Scy}
16857342292Scy/* End of the ".archive" or ".ar" command logic
16858355326Scy*******************************************************************************/
16859342292Scy#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
16860342292Scy
16861351633Scy#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
16862351633Scy/*
16863351633Scy** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
16864351633Scy** Otherwise, the SQL statement or statements in zSql are executed using
16865351633Scy** database connection db and the error code written to *pRc before
16866351633Scy** this function returns.
16867351633Scy*/
16868351633Scystatic void shellExec(sqlite3 *db, int *pRc, const char *zSql){
16869351633Scy  int rc = *pRc;
16870351633Scy  if( rc==SQLITE_OK ){
16871351633Scy    char *zErr = 0;
16872351633Scy    rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
16873351633Scy    if( rc!=SQLITE_OK ){
16874351633Scy      raw_printf(stderr, "SQL error: %s\n", zErr);
16875351633Scy    }
16876351633Scy    *pRc = rc;
16877351633Scy  }
16878351633Scy}
16879342292Scy
16880342292Scy/*
16881351633Scy** Like shellExec(), except that zFmt is a printf() style format string.
16882351633Scy*/
16883351633Scystatic void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){
16884351633Scy  char *z = 0;
16885351633Scy  if( *pRc==SQLITE_OK ){
16886351633Scy    va_list ap;
16887351633Scy    va_start(ap, zFmt);
16888351633Scy    z = sqlite3_vmprintf(zFmt, ap);
16889351633Scy    va_end(ap);
16890351633Scy    if( z==0 ){
16891351633Scy      *pRc = SQLITE_NOMEM;
16892351633Scy    }else{
16893351633Scy      shellExec(db, pRc, z);
16894351633Scy    }
16895351633Scy    sqlite3_free(z);
16896351633Scy  }
16897351633Scy}
16898351633Scy
16899351633Scy/*
16900351633Scy** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
16901351633Scy** Otherwise, an attempt is made to allocate, zero and return a pointer
16902351633Scy** to a buffer nByte bytes in size. If an OOM error occurs, *pRc is set
16903351633Scy** to SQLITE_NOMEM and NULL returned.
16904351633Scy*/
16905351633Scystatic void *shellMalloc(int *pRc, sqlite3_int64 nByte){
16906351633Scy  void *pRet = 0;
16907351633Scy  if( *pRc==SQLITE_OK ){
16908351633Scy    pRet = sqlite3_malloc64(nByte);
16909351633Scy    if( pRet==0 ){
16910351633Scy      *pRc = SQLITE_NOMEM;
16911351633Scy    }else{
16912351633Scy      memset(pRet, 0, nByte);
16913351633Scy    }
16914351633Scy  }
16915351633Scy  return pRet;
16916351633Scy}
16917351633Scy
16918351633Scy/*
16919351633Scy** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
16920351633Scy** Otherwise, zFmt is treated as a printf() style string. The result of
16921351633Scy** formatting it along with any trailing arguments is written into a
16922351633Scy** buffer obtained from sqlite3_malloc(), and pointer to which is returned.
16923351633Scy** It is the responsibility of the caller to eventually free this buffer
16924351633Scy** using a call to sqlite3_free().
16925351633Scy**
16926351633Scy** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL
16927351633Scy** pointer returned.
16928351633Scy*/
16929351633Scystatic char *shellMPrintf(int *pRc, const char *zFmt, ...){
16930351633Scy  char *z = 0;
16931351633Scy  if( *pRc==SQLITE_OK ){
16932351633Scy    va_list ap;
16933351633Scy    va_start(ap, zFmt);
16934351633Scy    z = sqlite3_vmprintf(zFmt, ap);
16935351633Scy    va_end(ap);
16936351633Scy    if( z==0 ){
16937351633Scy      *pRc = SQLITE_NOMEM;
16938351633Scy    }
16939351633Scy  }
16940351633Scy  return z;
16941351633Scy}
16942351633Scy
16943351633Scy/*
16944351633Scy** When running the ".recover" command, each output table, and the special
16945351633Scy** orphaned row table if it is required, is represented by an instance
16946351633Scy** of the following struct.
16947351633Scy*/
16948351633Scytypedef struct RecoverTable RecoverTable;
16949351633Scystruct RecoverTable {
16950351633Scy  char *zQuoted;                  /* Quoted version of table name */
16951351633Scy  int nCol;                       /* Number of columns in table */
16952351633Scy  char **azlCol;                  /* Array of column lists */
16953351633Scy  int iPk;                        /* Index of IPK column */
16954351633Scy};
16955351633Scy
16956351633Scy/*
16957351633Scy** Free a RecoverTable object allocated by recoverFindTable() or
16958351633Scy** recoverOrphanTable().
16959351633Scy*/
16960351633Scystatic void recoverFreeTable(RecoverTable *pTab){
16961351633Scy  if( pTab ){
16962351633Scy    sqlite3_free(pTab->zQuoted);
16963351633Scy    if( pTab->azlCol ){
16964351633Scy      int i;
16965351633Scy      for(i=0; i<=pTab->nCol; i++){
16966351633Scy        sqlite3_free(pTab->azlCol[i]);
16967351633Scy      }
16968351633Scy      sqlite3_free(pTab->azlCol);
16969351633Scy    }
16970351633Scy    sqlite3_free(pTab);
16971351633Scy  }
16972351633Scy}
16973351633Scy
16974351633Scy/*
16975351633Scy** This function is a no-op if (*pRc) is not SQLITE_OK when it is called.
16976351633Scy** Otherwise, it allocates and returns a RecoverTable object based on the
16977351633Scy** final four arguments passed to this function. It is the responsibility
16978351633Scy** of the caller to eventually free the returned object using
16979351633Scy** recoverFreeTable().
16980351633Scy*/
16981351633Scystatic RecoverTable *recoverNewTable(
16982351633Scy  int *pRc,                       /* IN/OUT: Error code */
16983351633Scy  const char *zName,              /* Name of table */
16984351633Scy  const char *zSql,               /* CREATE TABLE statement */
16985351633Scy  int bIntkey,
16986351633Scy  int nCol
16987351633Scy){
16988351633Scy  sqlite3 *dbtmp = 0;             /* sqlite3 handle for testing CREATE TABLE */
16989351633Scy  int rc = *pRc;
16990351633Scy  RecoverTable *pTab = 0;
16991351633Scy
16992351633Scy  pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable));
16993351633Scy  if( rc==SQLITE_OK ){
16994351633Scy    int nSqlCol = 0;
16995351633Scy    int bSqlIntkey = 0;
16996351633Scy    sqlite3_stmt *pStmt = 0;
16997351633Scy
16998351633Scy    rc = sqlite3_open("", &dbtmp);
16999351633Scy    if( rc==SQLITE_OK ){
17000355326Scy      sqlite3_create_function(dbtmp, "shell_idquote", 1, SQLITE_UTF8, 0,
17001355326Scy                              shellIdQuote, 0, 0);
17002355326Scy    }
17003355326Scy    if( rc==SQLITE_OK ){
17004351633Scy      rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
17005351633Scy    }
17006351633Scy    if( rc==SQLITE_OK ){
17007351633Scy      rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0);
17008351633Scy      if( rc==SQLITE_ERROR ){
17009351633Scy        rc = SQLITE_OK;
17010351633Scy        goto finished;
17011351633Scy      }
17012351633Scy    }
17013351633Scy    shellPreparePrintf(dbtmp, &rc, &pStmt,
17014351633Scy        "SELECT count(*) FROM pragma_table_info(%Q)", zName
17015351633Scy    );
17016351633Scy    if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
17017351633Scy      nSqlCol = sqlite3_column_int(pStmt, 0);
17018351633Scy    }
17019351633Scy    shellFinalize(&rc, pStmt);
17020351633Scy
17021351633Scy    if( rc!=SQLITE_OK || nSqlCol<nCol ){
17022351633Scy      goto finished;
17023351633Scy    }
17024351633Scy
17025351633Scy    shellPreparePrintf(dbtmp, &rc, &pStmt,
17026351633Scy      "SELECT ("
17027351633Scy      "  SELECT substr(data,1,1)==X'0D' FROM sqlite_dbpage WHERE pgno=rootpage"
17028366076Scy      ") FROM sqlite_schema WHERE name = %Q", zName
17029351633Scy    );
17030351633Scy    if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
17031351633Scy      bSqlIntkey = sqlite3_column_int(pStmt, 0);
17032351633Scy    }
17033351633Scy    shellFinalize(&rc, pStmt);
17034351633Scy
17035351633Scy    if( bIntkey==bSqlIntkey ){
17036351633Scy      int i;
17037351633Scy      const char *zPk = "_rowid_";
17038351633Scy      sqlite3_stmt *pPkFinder = 0;
17039351633Scy
17040351633Scy      /* If this is an intkey table and there is an INTEGER PRIMARY KEY,
17041351633Scy      ** set zPk to the name of the PK column, and pTab->iPk to the index
17042351633Scy      ** of the column, where columns are 0-numbered from left to right.
17043351633Scy      ** Or, if this is a WITHOUT ROWID table or if there is no IPK column,
17044351633Scy      ** leave zPk as "_rowid_" and pTab->iPk at -2.  */
17045351633Scy      pTab->iPk = -2;
17046351633Scy      if( bIntkey ){
17047351633Scy        shellPreparePrintf(dbtmp, &rc, &pPkFinder,
17048351633Scy          "SELECT cid, name FROM pragma_table_info(%Q) "
17049351633Scy          "  WHERE pk=1 AND type='integer' COLLATE nocase"
17050351633Scy          "  AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
17051351633Scy          , zName, zName
17052351633Scy        );
17053351633Scy        if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){
17054351633Scy          pTab->iPk = sqlite3_column_int(pPkFinder, 0);
17055351633Scy          zPk = (const char*)sqlite3_column_text(pPkFinder, 1);
17056351633Scy        }
17057351633Scy      }
17058351633Scy
17059355326Scy      pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName);
17060351633Scy      pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
17061351633Scy      pTab->nCol = nSqlCol;
17062351633Scy
17063351633Scy      if( bIntkey ){
17064355326Scy        pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk);
17065351633Scy      }else{
17066351633Scy        pTab->azlCol[0] = shellMPrintf(&rc, "");
17067351633Scy      }
17068351633Scy      i = 1;
17069351633Scy      shellPreparePrintf(dbtmp, &rc, &pStmt,
17070355326Scy          "SELECT %Q || group_concat(shell_idquote(name), ', ') "
17071351633Scy          "  FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
17072351633Scy          "FROM pragma_table_info(%Q)",
17073351633Scy          bIntkey ? ", " : "", pTab->iPk,
17074351633Scy          bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ",
17075351633Scy          zName
17076351633Scy      );
17077351633Scy      while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
17078351633Scy        const char *zText = (const char*)sqlite3_column_text(pStmt, 0);
17079351633Scy        pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText);
17080351633Scy        i++;
17081351633Scy      }
17082351633Scy      shellFinalize(&rc, pStmt);
17083351633Scy
17084351633Scy      shellFinalize(&rc, pPkFinder);
17085351633Scy    }
17086351633Scy  }
17087351633Scy
17088351633Scy finished:
17089351633Scy  sqlite3_close(dbtmp);
17090351633Scy  *pRc = rc;
17091351633Scy  if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){
17092351633Scy    recoverFreeTable(pTab);
17093351633Scy    pTab = 0;
17094351633Scy  }
17095351633Scy  return pTab;
17096351633Scy}
17097351633Scy
17098351633Scy/*
17099351633Scy** This function is called to search the schema recovered from the
17100366076Scy** sqlite_schema table of the (possibly) corrupt database as part
17101351633Scy** of a ".recover" command. Specifically, for a table with root page
17102351633Scy** iRoot and at least nCol columns. Additionally, if bIntkey is 0, the
17103351633Scy** table must be a WITHOUT ROWID table, or if non-zero, not one of
17104351633Scy** those.
17105351633Scy**
17106351633Scy** If a table is found, a (RecoverTable*) object is returned. Or, if
17107351633Scy** no such table is found, but bIntkey is false and iRoot is the
17108351633Scy** root page of an index in the recovered schema, then (*pbNoop) is
17109351633Scy** set to true and NULL returned. Or, if there is no such table or
17110351633Scy** index, NULL is returned and (*pbNoop) set to 0, indicating that
17111351633Scy** the caller should write data to the orphans table.
17112351633Scy*/
17113351633Scystatic RecoverTable *recoverFindTable(
17114351633Scy  ShellState *pState,             /* Shell state object */
17115351633Scy  int *pRc,                       /* IN/OUT: Error code */
17116351633Scy  int iRoot,                      /* Root page of table */
17117351633Scy  int bIntkey,                    /* True for an intkey table */
17118351633Scy  int nCol,                       /* Number of columns in table */
17119351633Scy  int *pbNoop                     /* OUT: True if iRoot is root of index */
17120351633Scy){
17121351633Scy  sqlite3_stmt *pStmt = 0;
17122351633Scy  RecoverTable *pRet = 0;
17123351633Scy  int bNoop = 0;
17124351633Scy  const char *zSql = 0;
17125351633Scy  const char *zName = 0;
17126351633Scy
17127351633Scy  /* Search the recovered schema for an object with root page iRoot. */
17128351633Scy  shellPreparePrintf(pState->db, pRc, &pStmt,
17129351633Scy      "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot
17130351633Scy  );
17131351633Scy  while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
17132351633Scy    const char *zType = (const char*)sqlite3_column_text(pStmt, 0);
17133351633Scy    if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){
17134351633Scy      bNoop = 1;
17135351633Scy      break;
17136351633Scy    }
17137351633Scy    if( sqlite3_stricmp(zType, "table")==0 ){
17138351633Scy      zName = (const char*)sqlite3_column_text(pStmt, 1);
17139351633Scy      zSql = (const char*)sqlite3_column_text(pStmt, 2);
17140351633Scy      pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol);
17141351633Scy      break;
17142351633Scy    }
17143351633Scy  }
17144351633Scy
17145351633Scy  shellFinalize(pRc, pStmt);
17146351633Scy  *pbNoop = bNoop;
17147351633Scy  return pRet;
17148351633Scy}
17149351633Scy
17150351633Scy/*
17151351633Scy** Return a RecoverTable object representing the orphans table.
17152351633Scy*/
17153351633Scystatic RecoverTable *recoverOrphanTable(
17154351633Scy  ShellState *pState,             /* Shell state object */
17155351633Scy  int *pRc,                       /* IN/OUT: Error code */
17156351633Scy  const char *zLostAndFound,      /* Base name for orphans table */
17157351633Scy  int nCol                        /* Number of user data columns */
17158351633Scy){
17159351633Scy  RecoverTable *pTab = 0;
17160351633Scy  if( nCol>=0 && *pRc==SQLITE_OK ){
17161351633Scy    int i;
17162351633Scy
17163351633Scy    /* This block determines the name of the orphan table. The prefered
17164351633Scy    ** name is zLostAndFound. But if that clashes with another name
17165351633Scy    ** in the recovered schema, try zLostAndFound_0, zLostAndFound_1
17166351633Scy    ** and so on until a non-clashing name is found.  */
17167351633Scy    int iTab = 0;
17168351633Scy    char *zTab = shellMPrintf(pRc, "%s", zLostAndFound);
17169351633Scy    sqlite3_stmt *pTest = 0;
17170351633Scy    shellPrepare(pState->db, pRc,
17171351633Scy        "SELECT 1 FROM recovery.schema WHERE name=?", &pTest
17172351633Scy    );
17173351633Scy    if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
17174351633Scy    while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){
17175351633Scy      shellReset(pRc, pTest);
17176351633Scy      sqlite3_free(zTab);
17177351633Scy      zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++);
17178351633Scy      sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
17179351633Scy    }
17180351633Scy    shellFinalize(pRc, pTest);
17181351633Scy
17182351633Scy    pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
17183351633Scy    if( pTab ){
17184355326Scy      pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab);
17185351633Scy      pTab->nCol = nCol;
17186351633Scy      pTab->iPk = -2;
17187351633Scy      if( nCol>0 ){
17188351633Scy        pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1));
17189351633Scy        if( pTab->azlCol ){
17190351633Scy          pTab->azlCol[nCol] = shellMPrintf(pRc, "");
17191351633Scy          for(i=nCol-1; i>=0; i--){
17192351633Scy            pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]);
17193351633Scy          }
17194351633Scy        }
17195351633Scy      }
17196351633Scy
17197351633Scy      if( *pRc!=SQLITE_OK ){
17198351633Scy        recoverFreeTable(pTab);
17199351633Scy        pTab = 0;
17200351633Scy      }else{
17201351633Scy        raw_printf(pState->out,
17202351633Scy            "CREATE TABLE %s(rootpgno INTEGER, "
17203351633Scy            "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted
17204351633Scy        );
17205351633Scy        for(i=0; i<nCol; i++){
17206351633Scy          raw_printf(pState->out, ", c%d", i);
17207351633Scy        }
17208351633Scy        raw_printf(pState->out, ");\n");
17209351633Scy      }
17210351633Scy    }
17211351633Scy    sqlite3_free(zTab);
17212351633Scy  }
17213351633Scy  return pTab;
17214351633Scy}
17215351633Scy
17216351633Scy/*
17217351633Scy** This function is called to recover data from the database. A script
17218351633Scy** to construct a new database containing all recovered data is output
17219351633Scy** on stream pState->out.
17220351633Scy*/
17221351633Scystatic int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
17222351633Scy  int rc = SQLITE_OK;
17223351633Scy  sqlite3_stmt *pLoop = 0;        /* Loop through all root pages */
17224351633Scy  sqlite3_stmt *pPages = 0;       /* Loop through all pages in a group */
17225351633Scy  sqlite3_stmt *pCells = 0;       /* Loop through all cells in a page */
17226351633Scy  const char *zRecoveryDb = "";   /* Name of "recovery" database */
17227351633Scy  const char *zLostAndFound = "lost_and_found";
17228351633Scy  int i;
17229351633Scy  int nOrphan = -1;
17230351633Scy  RecoverTable *pOrphan = 0;
17231351633Scy
17232351633Scy  int bFreelist = 1;              /* 0 if --freelist-corrupt is specified */
17233355326Scy  int bRowids = 1;                /* 0 if --no-rowids */
17234351633Scy  for(i=1; i<nArg; i++){
17235351633Scy    char *z = azArg[i];
17236351633Scy    int n;
17237351633Scy    if( z[0]=='-' && z[1]=='-' ) z++;
17238351633Scy    n = strlen30(z);
17239351633Scy    if( n<=17 && memcmp("-freelist-corrupt", z, n)==0 ){
17240351633Scy      bFreelist = 0;
17241351633Scy    }else
17242351633Scy    if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
17243351633Scy      i++;
17244351633Scy      zRecoveryDb = azArg[i];
17245351633Scy    }else
17246351633Scy    if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
17247351633Scy      i++;
17248351633Scy      zLostAndFound = azArg[i];
17249355326Scy    }else
17250355326Scy    if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
17251355326Scy      bRowids = 0;
17252351633Scy    }
17253351633Scy    else{
17254355326Scy      utf8_printf(stderr, "unexpected option: %s\n", azArg[i]);
17255355326Scy      showHelp(pState->out, azArg[0]);
17256351633Scy      return 1;
17257351633Scy    }
17258351633Scy  }
17259351633Scy
17260351633Scy  shellExecPrintf(pState->db, &rc,
17261351633Scy    /* Attach an in-memory database named 'recovery'. Create an indexed
17262351633Scy    ** cache of the sqlite_dbptr virtual table. */
17263355326Scy    "PRAGMA writable_schema = on;"
17264351633Scy    "ATTACH %Q AS recovery;"
17265351633Scy    "DROP TABLE IF EXISTS recovery.dbptr;"
17266351633Scy    "DROP TABLE IF EXISTS recovery.freelist;"
17267351633Scy    "DROP TABLE IF EXISTS recovery.map;"
17268351633Scy    "DROP TABLE IF EXISTS recovery.schema;"
17269351633Scy    "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb
17270351633Scy  );
17271351633Scy
17272351633Scy  if( bFreelist ){
17273351633Scy    shellExec(pState->db, &rc,
17274351633Scy      "WITH trunk(pgno) AS ("
17275351633Scy      "  SELECT shell_int32("
17276351633Scy      "      (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x "
17277351633Scy      "      WHERE x>0"
17278351633Scy      "    UNION"
17279351633Scy      "  SELECT shell_int32("
17280351633Scy      "      (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x "
17281351633Scy      "      FROM trunk WHERE x>0"
17282351633Scy      "),"
17283351633Scy      "freelist(data, n, freepgno) AS ("
17284351633Scy      "  SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno "
17285351633Scy      "      FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno"
17286351633Scy      "    UNION ALL"
17287351633Scy      "  SELECT data, n-1, shell_int32(data, 2+n) "
17288351633Scy      "      FROM freelist WHERE n>=0"
17289351633Scy      ")"
17290351633Scy      "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;"
17291351633Scy    );
17292351633Scy  }
17293351633Scy
17294355326Scy  /* If this is an auto-vacuum database, add all pointer-map pages to
17295355326Scy  ** the freelist table. Do this regardless of whether or not
17296355326Scy  ** --freelist-corrupt was specified.  */
17297351633Scy  shellExec(pState->db, &rc,
17298355326Scy    "WITH ptrmap(pgno) AS ("
17299355326Scy    "  SELECT 2 WHERE shell_int32("
17300355326Scy    "    (SELECT data FROM sqlite_dbpage WHERE pgno=1), 13"
17301355326Scy    "  )"
17302355326Scy    "    UNION ALL "
17303355326Scy    "  SELECT pgno+1+(SELECT page_size FROM pragma_page_size)/5 AS pp "
17304355326Scy    "  FROM ptrmap WHERE pp<=(SELECT page_count FROM pragma_page_count)"
17305355326Scy    ")"
17306355326Scy    "REPLACE INTO recovery.freelist SELECT pgno FROM ptrmap"
17307355326Scy  );
17308355326Scy
17309355326Scy  shellExec(pState->db, &rc,
17310351633Scy    "CREATE TABLE recovery.dbptr("
17311351633Scy    "      pgno, child, PRIMARY KEY(child, pgno)"
17312351633Scy    ") WITHOUT ROWID;"
17313351633Scy    "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) "
17314351633Scy    "    SELECT * FROM sqlite_dbptr"
17315351633Scy    "      WHERE pgno NOT IN freelist AND child NOT IN freelist;"
17316351633Scy
17317351633Scy    /* Delete any pointer to page 1. This ensures that page 1 is considered
17318351633Scy    ** a root page, regardless of how corrupt the db is. */
17319351633Scy    "DELETE FROM recovery.dbptr WHERE child = 1;"
17320351633Scy
17321351633Scy    /* Delete all pointers to any pages that have more than one pointer
17322351633Scy    ** to them. Such pages will be treated as root pages when recovering
17323351633Scy    ** data.  */
17324351633Scy    "DELETE FROM recovery.dbptr WHERE child IN ("
17325351633Scy    "  SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1"
17326351633Scy    ");"
17327351633Scy
17328351633Scy    /* Create the "map" table that will (eventually) contain instructions
17329351633Scy    ** for dealing with each page in the db that contains one or more
17330351633Scy    ** records. */
17331351633Scy    "CREATE TABLE recovery.map("
17332351633Scy      "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT"
17333351633Scy    ");"
17334351633Scy
17335351633Scy    /* Populate table [map]. If there are circular loops of pages in the
17336351633Scy    ** database, the following adds all pages in such a loop to the map
17337351633Scy    ** as individual root pages. This could be handled better.  */
17338351633Scy    "WITH pages(i, maxlen) AS ("
17339351633Scy    "  SELECT page_count, ("
17340351633Scy    "    SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count"
17341351633Scy    "  ) FROM pragma_page_count WHERE page_count>0"
17342351633Scy    "    UNION ALL"
17343351633Scy    "  SELECT i-1, ("
17344351633Scy    "    SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1"
17345351633Scy    "  ) FROM pages WHERE i>=2"
17346351633Scy    ")"
17347351633Scy    "INSERT INTO recovery.map(pgno, maxlen, intkey, root) "
17348351633Scy    "  SELECT i, maxlen, NULL, ("
17349351633Scy    "    WITH p(orig, pgno, parent) AS ("
17350351633Scy    "      SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)"
17351351633Scy    "        UNION "
17352351633Scy    "      SELECT i, p.parent, "
17353351633Scy    "        (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p"
17354351633Scy    "    )"
17355351633Scy    "    SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
17356351633Scy    ") "
17357355326Scy    "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;"
17358351633Scy    "UPDATE recovery.map AS o SET intkey = ("
17359351633Scy    "  SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
17360351633Scy    ");"
17361351633Scy
17362351633Scy    /* Extract data from page 1 and any linked pages into table
17363366076Scy    ** recovery.schema. With the same schema as an sqlite_schema table.  */
17364351633Scy    "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
17365351633Scy    "INSERT INTO recovery.schema SELECT "
17366351633Scy    "  max(CASE WHEN field=0 THEN value ELSE NULL END),"
17367351633Scy    "  max(CASE WHEN field=1 THEN value ELSE NULL END),"
17368351633Scy    "  max(CASE WHEN field=2 THEN value ELSE NULL END),"
17369351633Scy    "  max(CASE WHEN field=3 THEN value ELSE NULL END),"
17370351633Scy    "  max(CASE WHEN field=4 THEN value ELSE NULL END)"
17371351633Scy    "FROM sqlite_dbdata WHERE pgno IN ("
17372351633Scy    "  SELECT pgno FROM recovery.map WHERE root=1"
17373351633Scy    ")"
17374351633Scy    "GROUP BY pgno, cell;"
17375351633Scy    "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);"
17376351633Scy  );
17377351633Scy
17378351633Scy  /* Open a transaction, then print out all non-virtual, non-"sqlite_%"
17379351633Scy  ** CREATE TABLE statements that extracted from the existing schema.  */
17380351633Scy  if( rc==SQLITE_OK ){
17381351633Scy    sqlite3_stmt *pStmt = 0;
17382355326Scy    /* ".recover" might output content in an order which causes immediate
17383355326Scy    ** foreign key constraints to be violated. So disable foreign-key
17384355326Scy    ** constraint enforcement to prevent problems when running the output
17385355326Scy    ** script. */
17386355326Scy    raw_printf(pState->out, "PRAGMA foreign_keys=OFF;\n");
17387351633Scy    raw_printf(pState->out, "BEGIN;\n");
17388351633Scy    raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
17389351633Scy    shellPrepare(pState->db, &rc,
17390351633Scy        "SELECT sql FROM recovery.schema "
17391351633Scy        "WHERE type='table' AND sql LIKE 'create table%'", &pStmt
17392351633Scy    );
17393351633Scy    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
17394351633Scy      const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0);
17395351633Scy      raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n",
17396351633Scy          &zCreateTable[12]
17397351633Scy      );
17398351633Scy    }
17399351633Scy    shellFinalize(&rc, pStmt);
17400351633Scy  }
17401351633Scy
17402351633Scy  /* Figure out if an orphan table will be required. And if so, how many
17403351633Scy  ** user columns it should contain */
17404351633Scy  shellPrepare(pState->db, &rc,
17405351633Scy      "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1"
17406351633Scy      , &pLoop
17407351633Scy  );
17408351633Scy  if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
17409351633Scy    nOrphan = sqlite3_column_int(pLoop, 0);
17410351633Scy  }
17411351633Scy  shellFinalize(&rc, pLoop);
17412351633Scy  pLoop = 0;
17413351633Scy
17414351633Scy  shellPrepare(pState->db, &rc,
17415351633Scy      "SELECT pgno FROM recovery.map WHERE root=?", &pPages
17416351633Scy  );
17417355326Scy
17418351633Scy  shellPrepare(pState->db, &rc,
17419355326Scy      "SELECT max(field), group_concat(shell_escape_crnl(quote"
17420355326Scy      "(case when (? AND field<0) then NULL else value end)"
17421355326Scy      "), ', ')"
17422355326Scy      ", min(field) "
17423351633Scy      "FROM sqlite_dbdata WHERE pgno = ? AND field != ?"
17424351633Scy      "GROUP BY cell", &pCells
17425351633Scy  );
17426351633Scy
17427351633Scy  /* Loop through each root page. */
17428351633Scy  shellPrepare(pState->db, &rc,
17429351633Scy      "SELECT root, intkey, max(maxlen) FROM recovery.map"
17430351633Scy      " WHERE root>1 GROUP BY root, intkey ORDER BY root=("
17431351633Scy      "  SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'"
17432351633Scy      ")", &pLoop
17433351633Scy  );
17434351633Scy  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
17435351633Scy    int iRoot = sqlite3_column_int(pLoop, 0);
17436351633Scy    int bIntkey = sqlite3_column_int(pLoop, 1);
17437351633Scy    int nCol = sqlite3_column_int(pLoop, 2);
17438351633Scy    int bNoop = 0;
17439351633Scy    RecoverTable *pTab;
17440351633Scy
17441355326Scy    assert( bIntkey==0 || bIntkey==1 );
17442351633Scy    pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);
17443351633Scy    if( bNoop || rc ) continue;
17444351633Scy    if( pTab==0 ){
17445351633Scy      if( pOrphan==0 ){
17446351633Scy        pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
17447351633Scy      }
17448351633Scy      pTab = pOrphan;
17449351633Scy      if( pTab==0 ) break;
17450351633Scy    }
17451351633Scy
17452355326Scy    if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){
17453351633Scy      raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
17454351633Scy    }
17455351633Scy    sqlite3_bind_int(pPages, 1, iRoot);
17456355326Scy    if( bRowids==0 && pTab->iPk<0 ){
17457355326Scy      sqlite3_bind_int(pCells, 1, 1);
17458355326Scy    }else{
17459355326Scy      sqlite3_bind_int(pCells, 1, 0);
17460355326Scy    }
17461355326Scy    sqlite3_bind_int(pCells, 3, pTab->iPk);
17462351633Scy
17463351633Scy    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){
17464351633Scy      int iPgno = sqlite3_column_int(pPages, 0);
17465355326Scy      sqlite3_bind_int(pCells, 2, iPgno);
17466351633Scy      while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){
17467351633Scy        int nField = sqlite3_column_int(pCells, 0);
17468355326Scy        int iMin = sqlite3_column_int(pCells, 2);
17469351633Scy        const char *zVal = (const char*)sqlite3_column_text(pCells, 1);
17470351633Scy
17471355326Scy        RecoverTable *pTab2 = pTab;
17472355326Scy        if( pTab!=pOrphan && (iMin<0)!=bIntkey ){
17473355326Scy          if( pOrphan==0 ){
17474355326Scy            pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
17475355326Scy          }
17476355326Scy          pTab2 = pOrphan;
17477355326Scy          if( pTab2==0 ) break;
17478355326Scy        }
17479355326Scy
17480351633Scy        nField = nField+1;
17481355326Scy        if( pTab2==pOrphan ){
17482351633Scy          raw_printf(pState->out,
17483351633Scy              "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",
17484355326Scy              pTab2->zQuoted, iRoot, iPgno, nField,
17485355326Scy              iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField]
17486351633Scy          );
17487351633Scy        }else{
17488351633Scy          raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n",
17489355326Scy              pTab2->zQuoted, pTab2->azlCol[nField], zVal
17490351633Scy          );
17491351633Scy        }
17492351633Scy      }
17493351633Scy      shellReset(&rc, pCells);
17494351633Scy    }
17495351633Scy    shellReset(&rc, pPages);
17496351633Scy    if( pTab!=pOrphan ) recoverFreeTable(pTab);
17497351633Scy  }
17498351633Scy  shellFinalize(&rc, pLoop);
17499351633Scy  shellFinalize(&rc, pPages);
17500351633Scy  shellFinalize(&rc, pCells);
17501351633Scy  recoverFreeTable(pOrphan);
17502351633Scy
17503351633Scy  /* The rest of the schema */
17504351633Scy  if( rc==SQLITE_OK ){
17505351633Scy    sqlite3_stmt *pStmt = 0;
17506351633Scy    shellPrepare(pState->db, &rc,
17507351633Scy        "SELECT sql, name FROM recovery.schema "
17508351633Scy        "WHERE sql NOT LIKE 'create table%'", &pStmt
17509351633Scy    );
17510351633Scy    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
17511351633Scy      const char *zSql = (const char*)sqlite3_column_text(pStmt, 0);
17512351633Scy      if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){
17513351633Scy        const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
17514351633Scy        char *zPrint = shellMPrintf(&rc,
17515366076Scy          "INSERT INTO sqlite_schema VALUES('table', %Q, %Q, 0, %Q)",
17516351633Scy          zName, zName, zSql
17517351633Scy        );
17518351633Scy        raw_printf(pState->out, "%s;\n", zPrint);
17519351633Scy        sqlite3_free(zPrint);
17520351633Scy      }else{
17521351633Scy        raw_printf(pState->out, "%s;\n", zSql);
17522351633Scy      }
17523351633Scy    }
17524351633Scy    shellFinalize(&rc, pStmt);
17525351633Scy  }
17526351633Scy
17527351633Scy  if( rc==SQLITE_OK ){
17528351633Scy    raw_printf(pState->out, "PRAGMA writable_schema = off;\n");
17529351633Scy    raw_printf(pState->out, "COMMIT;\n");
17530351633Scy  }
17531351633Scy  sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
17532351633Scy  return rc;
17533351633Scy}
17534351633Scy#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
17535351633Scy
17536351633Scy
17537351633Scy/*
17538251883Speter** If an input line begins with "." then invoke this routine to
17539251883Speter** process that line.
17540251883Speter**
17541251883Speter** Return 1 on error, 2 to exit, and 0 otherwise.
17542251883Speter*/
17543274884Sbaptstatic int do_meta_command(char *zLine, ShellState *p){
17544286510Speter  int h = 1;
17545251883Speter  int nArg = 0;
17546251883Speter  int n, c;
17547251883Speter  int rc = 0;
17548355326Scy  char *azArg[52];
17549251883Speter
17550342292Scy#ifndef SQLITE_OMIT_VIRTUALTABLE
17551342292Scy  if( p->expert.pExpert ){
17552342292Scy    expertFinish(p, 1, 0);
17553342292Scy  }
17554342292Scy#endif
17555342292Scy
17556251883Speter  /* Parse the input line into tokens.
17557251883Speter  */
17558355326Scy  while( zLine[h] && nArg<ArraySize(azArg)-1 ){
17559286510Speter    while( IsSpace(zLine[h]) ){ h++; }
17560286510Speter    if( zLine[h]==0 ) break;
17561286510Speter    if( zLine[h]=='\'' || zLine[h]=='"' ){
17562286510Speter      int delim = zLine[h++];
17563286510Speter      azArg[nArg++] = &zLine[h];
17564305002Scy      while( zLine[h] && zLine[h]!=delim ){
17565286510Speter        if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
17566305002Scy        h++;
17567269851Speter      }
17568286510Speter      if( zLine[h]==delim ){
17569286510Speter        zLine[h++] = 0;
17570251883Speter      }
17571251883Speter      if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
17572251883Speter    }else{
17573286510Speter      azArg[nArg++] = &zLine[h];
17574286510Speter      while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
17575286510Speter      if( zLine[h] ) zLine[h++] = 0;
17576251883Speter      resolve_backslashes(azArg[nArg-1]);
17577251883Speter    }
17578251883Speter  }
17579355326Scy  azArg[nArg] = 0;
17580251883Speter
17581251883Speter  /* Process the input line.
17582251883Speter  */
17583251883Speter  if( nArg==0 ) return 0; /* no tokens, no error */
17584251883Speter  n = strlen30(azArg[0]);
17585251883Speter  c = azArg[0][0];
17586342292Scy  clearTempFile(p);
17587305002Scy
17588322444Speter#ifndef SQLITE_OMIT_AUTHORIZATION
17589305002Scy  if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
17590305002Scy    if( nArg!=2 ){
17591305002Scy      raw_printf(stderr, "Usage: .auth ON|OFF\n");
17592305002Scy      rc = 1;
17593305002Scy      goto meta_command_exit;
17594305002Scy    }
17595305002Scy    open_db(p, 0);
17596305002Scy    if( booleanValue(azArg[1]) ){
17597305002Scy      sqlite3_set_authorizer(p->db, shellAuth, p);
17598305002Scy    }else{
17599305002Scy      sqlite3_set_authorizer(p->db, 0, 0);
17600305002Scy    }
17601305002Scy  }else
17602322444Speter#endif
17603305002Scy
17604342292Scy#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
17605342292Scy  if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
17606342292Scy    open_db(p, 0);
17607342292Scy    rc = arDotCommand(p, 0, azArg, nArg);
17608342292Scy  }else
17609342292Scy#endif
17610342292Scy
17611269851Speter  if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
17612269851Speter   || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
17613269851Speter  ){
17614251883Speter    const char *zDestFile = 0;
17615251883Speter    const char *zDb = 0;
17616251883Speter    sqlite3 *pDest;
17617251883Speter    sqlite3_backup *pBackup;
17618251883Speter    int j;
17619346442Scy    int bAsync = 0;
17620342292Scy    const char *zVfs = 0;
17621251883Speter    for(j=1; j<nArg; j++){
17622251883Speter      const char *z = azArg[j];
17623251883Speter      if( z[0]=='-' ){
17624342292Scy        if( z[1]=='-' ) z++;
17625342292Scy        if( strcmp(z, "-append")==0 ){
17626342292Scy          zVfs = "apndvfs";
17627342292Scy        }else
17628346442Scy        if( strcmp(z, "-async")==0 ){
17629346442Scy          bAsync = 1;
17630346442Scy        }else
17631251883Speter        {
17632298161Sbapt          utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
17633251883Speter          return 1;
17634251883Speter        }
17635251883Speter      }else if( zDestFile==0 ){
17636251883Speter        zDestFile = azArg[j];
17637251883Speter      }else if( zDb==0 ){
17638251883Speter        zDb = zDestFile;
17639251883Speter        zDestFile = azArg[j];
17640251883Speter      }else{
17641346442Scy        raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
17642251883Speter        return 1;
17643251883Speter      }
17644251883Speter    }
17645251883Speter    if( zDestFile==0 ){
17646298161Sbapt      raw_printf(stderr, "missing FILENAME argument on .backup\n");
17647251883Speter      return 1;
17648251883Speter    }
17649251883Speter    if( zDb==0 ) zDb = "main";
17650342292Scy    rc = sqlite3_open_v2(zDestFile, &pDest,
17651342292Scy                  SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
17652251883Speter    if( rc!=SQLITE_OK ){
17653298161Sbapt      utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
17654342292Scy      close_db(pDest);
17655251883Speter      return 1;
17656251883Speter    }
17657346442Scy    if( bAsync ){
17658346442Scy      sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
17659346442Scy                   0, 0, 0);
17660346442Scy    }
17661269851Speter    open_db(p, 0);
17662251883Speter    pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
17663251883Speter    if( pBackup==0 ){
17664298161Sbapt      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
17665342292Scy      close_db(pDest);
17666251883Speter      return 1;
17667251883Speter    }
17668251883Speter    while(  (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
17669251883Speter    sqlite3_backup_finish(pBackup);
17670251883Speter    if( rc==SQLITE_DONE ){
17671251883Speter      rc = 0;
17672251883Speter    }else{
17673298161Sbapt      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
17674251883Speter      rc = 1;
17675251883Speter    }
17676342292Scy    close_db(pDest);
17677251883Speter  }else
17678251883Speter
17679269851Speter  if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
17680269851Speter    if( nArg==2 ){
17681269851Speter      bail_on_error = booleanValue(azArg[1]);
17682269851Speter    }else{
17683298161Sbapt      raw_printf(stderr, "Usage: .bail on|off\n");
17684269851Speter      rc = 1;
17685269851Speter    }
17686251883Speter  }else
17687251883Speter
17688286510Speter  if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
17689286510Speter    if( nArg==2 ){
17690286510Speter      if( booleanValue(azArg[1]) ){
17691305002Scy        setBinaryMode(p->out, 1);
17692286510Speter      }else{
17693305002Scy        setTextMode(p->out, 1);
17694286510Speter      }
17695286510Speter    }else{
17696298161Sbapt      raw_printf(stderr, "Usage: .binary on|off\n");
17697286510Speter      rc = 1;
17698286510Speter    }
17699286510Speter  }else
17700286510Speter
17701322444Speter  if( c=='c' && strcmp(azArg[0],"cd")==0 ){
17702322444Speter    if( nArg==2 ){
17703322444Speter#if defined(_WIN32) || defined(WIN32)
17704322444Speter      wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
17705322444Speter      rc = !SetCurrentDirectoryW(z);
17706322444Speter      sqlite3_free(z);
17707322444Speter#else
17708322444Speter      rc = chdir(azArg[1]);
17709322444Speter#endif
17710322444Speter      if( rc ){
17711322444Speter        utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
17712322444Speter        rc = 1;
17713322444Speter      }
17714322444Speter    }else{
17715322444Speter      raw_printf(stderr, "Usage: .cd DIRECTORY\n");
17716322444Speter      rc = 1;
17717322444Speter    }
17718322444Speter  }else
17719322444Speter
17720251883Speter  /* The undocumented ".breakpoint" command causes a call to the no-op
17721251883Speter  ** routine named test_breakpoint().
17722251883Speter  */
17723251883Speter  if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
17724251883Speter    test_breakpoint();
17725251883Speter  }else
17726251883Speter
17727298161Sbapt  if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
17728298161Sbapt    if( nArg==2 ){
17729322444Speter      setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
17730298161Sbapt    }else{
17731298161Sbapt      raw_printf(stderr, "Usage: .changes on|off\n");
17732298161Sbapt      rc = 1;
17733298161Sbapt    }
17734298161Sbapt  }else
17735298161Sbapt
17736322444Speter  /* Cancel output redirection, if it is currently set (by .testcase)
17737322444Speter  ** Then read the content of the testcase-out.txt file and compare against
17738322444Speter  ** azArg[1].  If there are differences, report an error and exit.
17739322444Speter  */
17740322444Speter  if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
17741322444Speter    char *zRes = 0;
17742322444Speter    output_reset(p);
17743322444Speter    if( nArg!=2 ){
17744322444Speter      raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
17745322444Speter      rc = 2;
17746322444Speter    }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
17747322444Speter      raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
17748322444Speter      rc = 2;
17749322444Speter    }else if( testcase_glob(azArg[1],zRes)==0 ){
17750322444Speter      utf8_printf(stderr,
17751322444Speter                 "testcase-%s FAILED\n Expected: [%s]\n      Got: [%s]\n",
17752322444Speter                 p->zTestcase, azArg[1], zRes);
17753342292Scy      rc = 1;
17754322444Speter    }else{
17755322444Speter      utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
17756322444Speter      p->nCheck++;
17757322444Speter    }
17758322444Speter    sqlite3_free(zRes);
17759322444Speter  }else
17760322444Speter
17761269851Speter  if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
17762269851Speter    if( nArg==2 ){
17763269851Speter      tryToClone(p, azArg[1]);
17764269851Speter    }else{
17765298161Sbapt      raw_printf(stderr, "Usage: .clone FILENAME\n");
17766269851Speter      rc = 1;
17767269851Speter    }
17768269851Speter  }else
17769269851Speter
17770269851Speter  if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
17771369950Scy    char **azName = 0;
17772369950Scy    int nName = 0;
17773369950Scy    sqlite3_stmt *pStmt;
17774369950Scy    int i;
17775269851Speter    open_db(p, 0);
17776369950Scy    rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
17777369950Scy    if( rc ){
17778369950Scy      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
17779251883Speter      rc = 1;
17780369950Scy    }else{
17781369950Scy      while( sqlite3_step(pStmt)==SQLITE_ROW ){
17782369950Scy        const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
17783369950Scy        const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
17784369950Scy        azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
17785369950Scy        if( azName==0 ){ shell_out_of_memory();  /* Does not return */ }
17786369950Scy        azName[nName*2] = strdup(zSchema);
17787369950Scy        azName[nName*2+1] = strdup(zFile);
17788369950Scy        nName++;
17789369950Scy      }
17790251883Speter    }
17791369950Scy    sqlite3_finalize(pStmt);
17792369950Scy    for(i=0; i<nName; i++){
17793369950Scy      int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
17794369950Scy      int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
17795369950Scy      const char *z = azName[i*2+1];
17796369950Scy      utf8_printf(p->out, "%s: %s %s%s\n",
17797369950Scy         azName[i*2],
17798369950Scy         z && z[0] ? z : "\"\"",
17799369950Scy         bRdonly ? "r/o" : "r/w",
17800369950Scy         eTxn==SQLITE_TXN_NONE ? "" :
17801369950Scy            eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
17802369950Scy      free(azName[i*2]);
17803369950Scy      free(azName[i*2+1]);
17804369950Scy    }
17805369950Scy    sqlite3_free(azName);
17806251883Speter  }else
17807251883Speter
17808342292Scy  if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
17809342292Scy    static const struct DbConfigChoices {
17810342292Scy      const char *zName;
17811342292Scy      int op;
17812342292Scy    } aDbConfig[] = {
17813361456Scy        { "defensive",          SQLITE_DBCONFIG_DEFENSIVE             },
17814361456Scy        { "dqs_ddl",            SQLITE_DBCONFIG_DQS_DDL               },
17815361456Scy        { "dqs_dml",            SQLITE_DBCONFIG_DQS_DML               },
17816351633Scy        { "enable_fkey",        SQLITE_DBCONFIG_ENABLE_FKEY           },
17817361456Scy        { "enable_qpsg",        SQLITE_DBCONFIG_ENABLE_QPSG           },
17818351633Scy        { "enable_trigger",     SQLITE_DBCONFIG_ENABLE_TRIGGER        },
17819355326Scy        { "enable_view",        SQLITE_DBCONFIG_ENABLE_VIEW           },
17820351633Scy        { "fts3_tokenizer",     SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
17821361456Scy        { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE    },
17822361456Scy        { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT    },
17823351633Scy        { "load_extension",     SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
17824351633Scy        { "no_ckpt_on_close",   SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE      },
17825361456Scy        { "reset_database",     SQLITE_DBCONFIG_RESET_DATABASE        },
17826351633Scy        { "trigger_eqp",        SQLITE_DBCONFIG_TRIGGER_EQP           },
17827361456Scy        { "trusted_schema",     SQLITE_DBCONFIG_TRUSTED_SCHEMA        },
17828351633Scy        { "writable_schema",    SQLITE_DBCONFIG_WRITABLE_SCHEMA       },
17829342292Scy    };
17830342292Scy    int ii, v;
17831342292Scy    open_db(p, 0);
17832342292Scy    for(ii=0; ii<ArraySize(aDbConfig); ii++){
17833342292Scy      if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
17834342292Scy      if( nArg>=3 ){
17835342292Scy        sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
17836342292Scy      }
17837342292Scy      sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
17838361456Scy      utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
17839342292Scy      if( nArg>1 ) break;
17840342292Scy    }
17841342292Scy    if( nArg>1 && ii==ArraySize(aDbConfig) ){
17842342292Scy      utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
17843342292Scy      utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
17844342292Scy    }
17845342292Scy  }else
17846342292Scy
17847342292Scy  if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
17848282328Sbapt    rc = shell_dbinfo_command(p, nArg, azArg);
17849282328Sbapt  }else
17850282328Sbapt
17851351633Scy#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
17852351633Scy  if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){
17853351633Scy    open_db(p, 0);
17854351633Scy    rc = recoverDatabaseCmd(p, nArg, azArg);
17855351633Scy  }else
17856351633Scy#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
17857351633Scy
17858269851Speter  if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
17859362190Scy    char *zLike = 0;
17860362190Scy    char *zSql;
17861322444Speter    int i;
17862322444Speter    int savedShowHeader = p->showHeader;
17863342292Scy    int savedShellFlags = p->shellFlgs;
17864369950Scy    ShellClearFlag(p,
17865369950Scy       SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
17866369950Scy       |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
17867322444Speter    for(i=1; i<nArg; i++){
17868322444Speter      if( azArg[i][0]=='-' ){
17869322444Speter        const char *z = azArg[i]+1;
17870322444Speter        if( z[0]=='-' ) z++;
17871322444Speter        if( strcmp(z,"preserve-rowids")==0 ){
17872322444Speter#ifdef SQLITE_OMIT_VIRTUALTABLE
17873322444Speter          raw_printf(stderr, "The --preserve-rowids option is not compatible"
17874322444Speter                             " with SQLITE_OMIT_VIRTUALTABLE\n");
17875322444Speter          rc = 1;
17876366076Scy          sqlite3_free(zLike);
17877322444Speter          goto meta_command_exit;
17878322444Speter#else
17879322444Speter          ShellSetFlag(p, SHFLG_PreserveRowid);
17880322444Speter#endif
17881322444Speter        }else
17882322444Speter        if( strcmp(z,"newlines")==0 ){
17883322444Speter          ShellSetFlag(p, SHFLG_Newlines);
17884322444Speter        }else
17885369950Scy        if( strcmp(z,"data-only")==0 ){
17886369950Scy          ShellSetFlag(p, SHFLG_DumpDataOnly);
17887369950Scy        }else
17888369950Scy        if( strcmp(z,"nosys")==0 ){
17889369950Scy          ShellSetFlag(p, SHFLG_DumpNoSys);
17890369950Scy        }else
17891322444Speter        {
17892322444Speter          raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
17893322444Speter          rc = 1;
17894366076Scy          sqlite3_free(zLike);
17895322444Speter          goto meta_command_exit;
17896322444Speter        }
17897322444Speter      }else if( zLike ){
17898362190Scy        zLike = sqlite3_mprintf("%z OR name LIKE %Q ESCAPE '\\'",
17899362190Scy                zLike, azArg[i]);
17900322444Speter      }else{
17901362190Scy        zLike = sqlite3_mprintf("name LIKE %Q ESCAPE '\\'", azArg[i]);
17902322444Speter      }
17903322444Speter    }
17904351633Scy
17905269851Speter    open_db(p, 0);
17906351633Scy
17907369950Scy    if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
17908369950Scy      /* When playing back a "dump", the content might appear in an order
17909369950Scy      ** which causes immediate foreign key constraints to be violated.
17910369950Scy      ** So disable foreign-key constraint enforcement to prevent problems. */
17911369950Scy      raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
17912369950Scy      raw_printf(p->out, "BEGIN TRANSACTION;\n");
17913369950Scy    }
17914251883Speter    p->writableSchema = 0;
17915322444Speter    p->showHeader = 0;
17916322444Speter    /* Set writable_schema=ON since doing so forces SQLite to initialize
17917366076Scy    ** as much of the schema as it can even if the sqlite_schema table is
17918322444Speter    ** corrupt. */
17919251883Speter    sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
17920251883Speter    p->nErr = 0;
17921362190Scy    if( zLike==0 ) zLike = sqlite3_mprintf("true");
17922362190Scy    zSql = sqlite3_mprintf(
17923366076Scy      "SELECT name, type, sql FROM sqlite_schema "
17924362190Scy      "WHERE (%s) AND type=='table'"
17925362190Scy      "  AND sql NOT NULL"
17926362190Scy      " ORDER BY tbl_name='sqlite_sequence', rowid",
17927362190Scy      zLike
17928362190Scy    );
17929362190Scy    run_schema_dump_query(p,zSql);
17930362190Scy    sqlite3_free(zSql);
17931369950Scy    if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
17932369950Scy      zSql = sqlite3_mprintf(
17933369950Scy        "SELECT sql FROM sqlite_schema "
17934369950Scy        "WHERE (%s) AND sql NOT NULL"
17935369950Scy        "  AND type IN ('index','trigger','view')",
17936369950Scy        zLike
17937369950Scy      );
17938369950Scy      run_table_dump_query(p, zSql);
17939369950Scy      sqlite3_free(zSql);
17940369950Scy    }
17941362190Scy    sqlite3_free(zLike);
17942251883Speter    if( p->writableSchema ){
17943298161Sbapt      raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
17944251883Speter      p->writableSchema = 0;
17945251883Speter    }
17946251883Speter    sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
17947251883Speter    sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
17948369950Scy    if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
17949369950Scy      raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
17950369950Scy    }
17951322444Speter    p->showHeader = savedShowHeader;
17952342292Scy    p->shellFlgs = savedShellFlags;
17953251883Speter  }else
17954251883Speter
17955269851Speter  if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
17956269851Speter    if( nArg==2 ){
17957322444Speter      setOrClearFlag(p, SHFLG_Echo, azArg[1]);
17958269851Speter    }else{
17959298161Sbapt      raw_printf(stderr, "Usage: .echo on|off\n");
17960269851Speter      rc = 1;
17961269851Speter    }
17962251883Speter  }else
17963251883Speter
17964269851Speter  if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
17965269851Speter    if( nArg==2 ){
17966342292Scy      p->autoEQPtest = 0;
17967346442Scy      if( p->autoEQPtrace ){
17968346442Scy        if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
17969346442Scy        p->autoEQPtrace = 0;
17970346442Scy      }
17971305002Scy      if( strcmp(azArg[1],"full")==0 ){
17972342292Scy        p->autoEQP = AUTOEQP_full;
17973342292Scy      }else if( strcmp(azArg[1],"trigger")==0 ){
17974342292Scy        p->autoEQP = AUTOEQP_trigger;
17975346442Scy#ifdef SQLITE_DEBUG
17976342292Scy      }else if( strcmp(azArg[1],"test")==0 ){
17977342292Scy        p->autoEQP = AUTOEQP_on;
17978342292Scy        p->autoEQPtest = 1;
17979346442Scy      }else if( strcmp(azArg[1],"trace")==0 ){
17980346442Scy        p->autoEQP = AUTOEQP_full;
17981346442Scy        p->autoEQPtrace = 1;
17982346442Scy        open_db(p, 0);
17983366076Scy        sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0);
17984346442Scy        sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
17985346442Scy#endif
17986305002Scy      }else{
17987342292Scy        p->autoEQP = (u8)booleanValue(azArg[1]);
17988305002Scy      }
17989269851Speter    }else{
17990346442Scy      raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
17991269851Speter      rc = 1;
17992305002Scy    }
17993269851Speter  }else
17994269851Speter
17995251883Speter  if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
17996269851Speter    if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
17997251883Speter    rc = 2;
17998251883Speter  }else
17999251883Speter
18000322444Speter  /* The ".explain" command is automatic now.  It is largely pointless.  It
18001322444Speter  ** retained purely for backwards compatibility */
18002269851Speter  if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
18003298161Sbapt    int val = 1;
18004298161Sbapt    if( nArg>=2 ){
18005298161Sbapt      if( strcmp(azArg[1],"auto")==0 ){
18006298161Sbapt        val = 99;
18007298161Sbapt      }else{
18008298161Sbapt        val =  booleanValue(azArg[1]);
18009251883Speter      }
18010298161Sbapt    }
18011298161Sbapt    if( val==1 && p->mode!=MODE_Explain ){
18012298161Sbapt      p->normalMode = p->mode;
18013251883Speter      p->mode = MODE_Explain;
18014298161Sbapt      p->autoExplain = 0;
18015298161Sbapt    }else if( val==0 ){
18016298161Sbapt      if( p->mode==MODE_Explain ) p->mode = p->normalMode;
18017298161Sbapt      p->autoExplain = 0;
18018298161Sbapt    }else if( val==99 ){
18019298161Sbapt      if( p->mode==MODE_Explain ) p->mode = p->normalMode;
18020298161Sbapt      p->autoExplain = 1;
18021251883Speter    }
18022251883Speter  }else
18023251883Speter
18024342292Scy#ifndef SQLITE_OMIT_VIRTUALTABLE
18025342292Scy  if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
18026342292Scy    open_db(p, 0);
18027342292Scy    expertDotCommand(p, azArg, nArg);
18028342292Scy  }else
18029342292Scy#endif
18030342292Scy
18031351633Scy  if( c=='f' && strncmp(azArg[0], "filectrl", n)==0 ){
18032351633Scy    static const struct {
18033351633Scy       const char *zCtrlName;   /* Name of a test-control option */
18034351633Scy       int ctrlCode;            /* Integer code for that option */
18035351633Scy       const char *zUsage;      /* Usage notes */
18036351633Scy    } aCtrl[] = {
18037351633Scy      { "chunk_size",     SQLITE_FCNTL_CHUNK_SIZE,      "SIZE"           },
18038369951Scy      { "data_version",   SQLITE_FCNTL_DATA_VERSION,    ""               },
18039369951Scy      { "has_moved",      SQLITE_FCNTL_HAS_MOVED,       ""               },
18040369951Scy      { "lock_timeout",   SQLITE_FCNTL_LOCK_TIMEOUT,    "MILLISEC"       },
18041351633Scy      { "persist_wal",    SQLITE_FCNTL_PERSIST_WAL,     "[BOOLEAN]"      },
18042369951Scy   /* { "pragma",         SQLITE_FCNTL_PRAGMA,          "NAME ARG"       },*/
18043351633Scy      { "psow",       SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]"      },
18044369951Scy      { "reserve_bytes",  SQLITE_FCNTL_RESERVE_BYTES,   "[N]"            },
18045369951Scy      { "size_limit",     SQLITE_FCNTL_SIZE_LIMIT,      "[LIMIT]"        },
18046351633Scy      { "tempfilename",   SQLITE_FCNTL_TEMPFILENAME,    ""               },
18047369951Scy   /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY,  "COUNT DELAY"    },*/
18048351633Scy    };
18049351633Scy    int filectrl = -1;
18050351633Scy    int iCtrl = -1;
18051351633Scy    sqlite3_int64 iRes = 0;  /* Integer result to display if rc2==1 */
18052351633Scy    int isOk = 0;            /* 0: usage  1: %lld  2: no-result */
18053351633Scy    int n2, i;
18054351633Scy    const char *zCmd = 0;
18055362190Scy    const char *zSchema = 0;
18056351633Scy
18057351633Scy    open_db(p, 0);
18058351633Scy    zCmd = nArg>=2 ? azArg[1] : "help";
18059351633Scy
18060362190Scy    if( zCmd[0]=='-'
18061362190Scy     && (strcmp(zCmd,"--schema")==0 || strcmp(zCmd,"-schema")==0)
18062362190Scy     && nArg>=4
18063362190Scy    ){
18064362190Scy      zSchema = azArg[2];
18065362190Scy      for(i=3; i<nArg; i++) azArg[i-2] = azArg[i];
18066362190Scy      nArg -= 2;
18067362190Scy      zCmd = azArg[1];
18068362190Scy    }
18069362190Scy
18070351633Scy    /* The argument can optionally begin with "-" or "--" */
18071351633Scy    if( zCmd[0]=='-' && zCmd[1] ){
18072351633Scy      zCmd++;
18073351633Scy      if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
18074351633Scy    }
18075351633Scy
18076351633Scy    /* --help lists all file-controls */
18077351633Scy    if( strcmp(zCmd,"help")==0 ){
18078351633Scy      utf8_printf(p->out, "Available file-controls:\n");
18079351633Scy      for(i=0; i<ArraySize(aCtrl); i++){
18080351633Scy        utf8_printf(p->out, "  .filectrl %s %s\n",
18081351633Scy                    aCtrl[i].zCtrlName, aCtrl[i].zUsage);
18082351633Scy      }
18083351633Scy      rc = 1;
18084351633Scy      goto meta_command_exit;
18085351633Scy    }
18086351633Scy
18087351633Scy    /* convert filectrl text option to value. allow any unique prefix
18088351633Scy    ** of the option name, or a numerical value. */
18089351633Scy    n2 = strlen30(zCmd);
18090351633Scy    for(i=0; i<ArraySize(aCtrl); i++){
18091351633Scy      if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
18092351633Scy        if( filectrl<0 ){
18093351633Scy          filectrl = aCtrl[i].ctrlCode;
18094351633Scy          iCtrl = i;
18095351633Scy        }else{
18096351633Scy          utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n"
18097351633Scy                              "Use \".filectrl --help\" for help\n", zCmd);
18098351633Scy          rc = 1;
18099351633Scy          goto meta_command_exit;
18100351633Scy        }
18101351633Scy      }
18102351633Scy    }
18103351633Scy    if( filectrl<0 ){
18104351633Scy      utf8_printf(stderr,"Error: unknown file-control: %s\n"
18105351633Scy                         "Use \".filectrl --help\" for help\n", zCmd);
18106351633Scy    }else{
18107351633Scy      switch(filectrl){
18108351633Scy        case SQLITE_FCNTL_SIZE_LIMIT: {
18109351633Scy          if( nArg!=2 && nArg!=3 ) break;
18110351633Scy          iRes = nArg==3 ? integerValue(azArg[2]) : -1;
18111362190Scy          sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
18112351633Scy          isOk = 1;
18113351633Scy          break;
18114351633Scy        }
18115351633Scy        case SQLITE_FCNTL_LOCK_TIMEOUT:
18116351633Scy        case SQLITE_FCNTL_CHUNK_SIZE: {
18117351633Scy          int x;
18118351633Scy          if( nArg!=3 ) break;
18119351633Scy          x = (int)integerValue(azArg[2]);
18120362190Scy          sqlite3_file_control(p->db, zSchema, filectrl, &x);
18121351633Scy          isOk = 2;
18122351633Scy          break;
18123351633Scy        }
18124351633Scy        case SQLITE_FCNTL_PERSIST_WAL:
18125351633Scy        case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
18126351633Scy          int x;
18127351633Scy          if( nArg!=2 && nArg!=3 ) break;
18128351633Scy          x = nArg==3 ? booleanValue(azArg[2]) : -1;
18129362190Scy          sqlite3_file_control(p->db, zSchema, filectrl, &x);
18130351633Scy          iRes = x;
18131351633Scy          isOk = 1;
18132351633Scy          break;
18133351633Scy        }
18134369951Scy        case SQLITE_FCNTL_DATA_VERSION:
18135351633Scy        case SQLITE_FCNTL_HAS_MOVED: {
18136351633Scy          int x;
18137351633Scy          if( nArg!=2 ) break;
18138362190Scy          sqlite3_file_control(p->db, zSchema, filectrl, &x);
18139351633Scy          iRes = x;
18140351633Scy          isOk = 1;
18141351633Scy          break;
18142351633Scy        }
18143351633Scy        case SQLITE_FCNTL_TEMPFILENAME: {
18144351633Scy          char *z = 0;
18145351633Scy          if( nArg!=2 ) break;
18146362190Scy          sqlite3_file_control(p->db, zSchema, filectrl, &z);
18147351633Scy          if( z ){
18148351633Scy            utf8_printf(p->out, "%s\n", z);
18149351633Scy            sqlite3_free(z);
18150351633Scy          }
18151351633Scy          isOk = 2;
18152351633Scy          break;
18153351633Scy        }
18154362190Scy        case SQLITE_FCNTL_RESERVE_BYTES: {
18155362190Scy          int x;
18156362190Scy          if( nArg>=3 ){
18157362190Scy            x = atoi(azArg[2]);
18158362190Scy            sqlite3_file_control(p->db, zSchema, filectrl, &x);
18159362190Scy          }
18160362190Scy          x = -1;
18161362190Scy          sqlite3_file_control(p->db, zSchema, filectrl, &x);
18162362190Scy          utf8_printf(p->out,"%d\n", x);
18163362190Scy          isOk = 2;
18164362190Scy          break;
18165362190Scy        }
18166351633Scy      }
18167351633Scy    }
18168351633Scy    if( isOk==0 && iCtrl>=0 ){
18169351633Scy      utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
18170351633Scy      rc = 1;
18171351633Scy    }else if( isOk==1 ){
18172351633Scy      char zBuf[100];
18173351633Scy      sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
18174351633Scy      raw_printf(p->out, "%s\n", zBuf);
18175351633Scy    }
18176351633Scy  }else
18177351633Scy
18178274884Sbapt  if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
18179274884Sbapt    ShellState data;
18180274884Sbapt    char *zErrMsg = 0;
18181274884Sbapt    int doStats = 0;
18182305002Scy    memcpy(&data, p, sizeof(data));
18183305002Scy    data.showHeader = 0;
18184305002Scy    data.cMode = data.mode = MODE_Semi;
18185305002Scy    if( nArg==2 && optionMatch(azArg[1], "indent") ){
18186305002Scy      data.cMode = data.mode = MODE_Pretty;
18187305002Scy      nArg = 1;
18188305002Scy    }
18189274884Sbapt    if( nArg!=1 ){
18190305002Scy      raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
18191274884Sbapt      rc = 1;
18192274884Sbapt      goto meta_command_exit;
18193274884Sbapt    }
18194274884Sbapt    open_db(p, 0);
18195274884Sbapt    rc = sqlite3_exec(p->db,
18196274884Sbapt       "SELECT sql FROM"
18197274884Sbapt       "  (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
18198366076Scy       "     FROM sqlite_schema UNION ALL"
18199366076Scy       "   SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
18200274884Sbapt       "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
18201274884Sbapt       "ORDER BY rowid",
18202274884Sbapt       callback, &data, &zErrMsg
18203274884Sbapt    );
18204274884Sbapt    if( rc==SQLITE_OK ){
18205274884Sbapt      sqlite3_stmt *pStmt;
18206274884Sbapt      rc = sqlite3_prepare_v2(p->db,
18207366076Scy               "SELECT rowid FROM sqlite_schema"
18208274884Sbapt               " WHERE name GLOB 'sqlite_stat[134]'",
18209274884Sbapt               -1, &pStmt, 0);
18210274884Sbapt      doStats = sqlite3_step(pStmt)==SQLITE_ROW;
18211274884Sbapt      sqlite3_finalize(pStmt);
18212274884Sbapt    }
18213274884Sbapt    if( doStats==0 ){
18214298161Sbapt      raw_printf(p->out, "/* No STAT tables available */\n");
18215274884Sbapt    }else{
18216366076Scy      raw_printf(p->out, "ANALYZE sqlite_schema;\n");
18217366076Scy      sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_schema'",
18218274884Sbapt                   callback, &data, &zErrMsg);
18219298161Sbapt      data.cMode = data.mode = MODE_Insert;
18220274884Sbapt      data.zDestTable = "sqlite_stat1";
18221342292Scy      shell_exec(&data, "SELECT * FROM sqlite_stat1", &zErrMsg);
18222274884Sbapt      data.zDestTable = "sqlite_stat4";
18223342292Scy      shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg);
18224366076Scy      raw_printf(p->out, "ANALYZE sqlite_schema;\n");
18225274884Sbapt    }
18226274884Sbapt  }else
18227274884Sbapt
18228269851Speter  if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
18229269851Speter    if( nArg==2 ){
18230269851Speter      p->showHeader = booleanValue(azArg[1]);
18231366076Scy      p->shellFlgs |= SHFLG_HeaderSet;
18232269851Speter    }else{
18233298161Sbapt      raw_printf(stderr, "Usage: .headers on|off\n");
18234269851Speter      rc = 1;
18235269851Speter    }
18236251883Speter  }else
18237251883Speter
18238251883Speter  if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
18239342292Scy    if( nArg>=2 ){
18240342292Scy      n = showHelp(p->out, azArg[1]);
18241342292Scy      if( n==0 ){
18242342292Scy        utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
18243342292Scy      }
18244342292Scy    }else{
18245342292Scy      showHelp(p->out, 0);
18246342292Scy    }
18247251883Speter  }else
18248251883Speter
18249269851Speter  if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
18250362190Scy    char *zTable = 0;           /* Insert data into this table */
18251362190Scy    char *zFile = 0;            /* Name of file to extra content from */
18252251883Speter    sqlite3_stmt *pStmt = NULL; /* A statement */
18253251883Speter    int nCol;                   /* Number of columns in the table */
18254251883Speter    int nByte;                  /* Number of bytes in an SQL string */
18255251883Speter    int i, j;                   /* Loop counters */
18256269851Speter    int needCommit;             /* True to COMMIT or ROLLBACK at end */
18257282328Sbapt    int nSep;                   /* Number of bytes in p->colSeparator[] */
18258251883Speter    char *zSql;                 /* An SQL statement */
18259282328Sbapt    ImportCtx sCtx;             /* Reader context */
18260282328Sbapt    char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
18261362190Scy    int eVerbose = 0;           /* Larger for more console output */
18262362190Scy    int nSkip = 0;              /* Initial lines to skip */
18263362190Scy    int useOutputMode = 1;      /* Use output mode to determine separators */
18264251883Speter
18265362190Scy    memset(&sCtx, 0, sizeof(sCtx));
18266362190Scy    if( p->mode==MODE_Ascii ){
18267362190Scy      xRead = ascii_read_one_field;
18268362190Scy    }else{
18269362190Scy      xRead = csv_read_one_field;
18270362190Scy    }
18271362190Scy    for(i=1; i<nArg; i++){
18272362190Scy      char *z = azArg[i];
18273362190Scy      if( z[0]=='-' && z[1]=='-' ) z++;
18274362190Scy      if( z[0]!='-' ){
18275362190Scy        if( zFile==0 ){
18276362190Scy          zFile = z;
18277362190Scy        }else if( zTable==0 ){
18278362190Scy          zTable = z;
18279362190Scy        }else{
18280362190Scy          utf8_printf(p->out, "ERROR: extra argument: \"%s\".  Usage:\n", z);
18281362190Scy          showHelp(p->out, "import");
18282362190Scy          rc = 1;
18283362190Scy          goto meta_command_exit;
18284362190Scy        }
18285362190Scy      }else if( strcmp(z,"-v")==0 ){
18286362190Scy        eVerbose++;
18287362190Scy      }else if( strcmp(z,"-skip")==0 && i<nArg-1 ){
18288362190Scy        nSkip = integerValue(azArg[++i]);
18289362190Scy      }else if( strcmp(z,"-ascii")==0 ){
18290362190Scy        sCtx.cColSep = SEP_Unit[0];
18291362190Scy        sCtx.cRowSep = SEP_Record[0];
18292362190Scy        xRead = ascii_read_one_field;
18293362190Scy        useOutputMode = 0;
18294362190Scy      }else if( strcmp(z,"-csv")==0 ){
18295362190Scy        sCtx.cColSep = ',';
18296362190Scy        sCtx.cRowSep = '\n';
18297362190Scy        xRead = csv_read_one_field;
18298362190Scy        useOutputMode = 0;
18299362190Scy      }else{
18300362190Scy        utf8_printf(p->out, "ERROR: unknown option: \"%s\".  Usage:\n", z);
18301362190Scy        showHelp(p->out, "import");
18302362190Scy        rc = 1;
18303362190Scy        goto meta_command_exit;
18304362190Scy      }
18305362190Scy    }
18306362190Scy    if( zTable==0 ){
18307362190Scy      utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
18308362190Scy                  zFile==0 ? "FILE" : "TABLE");
18309362190Scy      showHelp(p->out, "import");
18310362190Scy      rc = 1;
18311269851Speter      goto meta_command_exit;
18312269851Speter    }
18313269851Speter    seenInterrupt = 0;
18314269851Speter    open_db(p, 0);
18315362190Scy    if( useOutputMode ){
18316362190Scy      /* If neither the --csv or --ascii options are specified, then set
18317362190Scy      ** the column and row separator characters from the output mode. */
18318362190Scy      nSep = strlen30(p->colSeparator);
18319362190Scy      if( nSep==0 ){
18320362190Scy        raw_printf(stderr,
18321362190Scy                   "Error: non-null column separator required for import\n");
18322362190Scy        rc = 1;
18323362190Scy        goto meta_command_exit;
18324362190Scy      }
18325362190Scy      if( nSep>1 ){
18326362190Scy        raw_printf(stderr,
18327362190Scy              "Error: multi-character column separators not allowed"
18328362190Scy              " for import\n");
18329362190Scy        rc = 1;
18330362190Scy        goto meta_command_exit;
18331362190Scy      }
18332282328Sbapt      nSep = strlen30(p->rowSeparator);
18333362190Scy      if( nSep==0 ){
18334362190Scy        raw_printf(stderr,
18335362190Scy            "Error: non-null row separator required for import\n");
18336362190Scy        rc = 1;
18337362190Scy        goto meta_command_exit;
18338362190Scy      }
18339362190Scy      if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator,SEP_CrLf)==0 ){
18340362190Scy        /* When importing CSV (only), if the row separator is set to the
18341362190Scy        ** default output row separator, change it to the default input
18342362190Scy        ** row separator.  This avoids having to maintain different input
18343362190Scy        ** and output row separators. */
18344362190Scy        sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
18345362190Scy        nSep = strlen30(p->rowSeparator);
18346362190Scy      }
18347362190Scy      if( nSep>1 ){
18348362190Scy        raw_printf(stderr, "Error: multi-character row separators not allowed"
18349362190Scy                           " for import\n");
18350362190Scy        rc = 1;
18351362190Scy        goto meta_command_exit;
18352362190Scy      }
18353362190Scy      sCtx.cColSep = p->colSeparator[0];
18354362190Scy      sCtx.cRowSep = p->rowSeparator[0];
18355282328Sbapt    }
18356282328Sbapt    sCtx.zFile = zFile;
18357282328Sbapt    sCtx.nLine = 1;
18358282328Sbapt    if( sCtx.zFile[0]=='|' ){
18359282328Sbapt#ifdef SQLITE_OMIT_POPEN
18360298161Sbapt      raw_printf(stderr, "Error: pipes are not supported in this OS\n");
18361362190Scy      rc = 1;
18362362190Scy      goto meta_command_exit;
18363282328Sbapt#else
18364282328Sbapt      sCtx.in = popen(sCtx.zFile+1, "r");
18365282328Sbapt      sCtx.zFile = "<pipe>";
18366366076Scy      sCtx.xCloser = pclose;
18367282328Sbapt#endif
18368269851Speter    }else{
18369282328Sbapt      sCtx.in = fopen(sCtx.zFile, "rb");
18370366076Scy      sCtx.xCloser = fclose;
18371269851Speter    }
18372282328Sbapt    if( sCtx.in==0 ){
18373298161Sbapt      utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
18374362190Scy      rc = 1;
18375362190Scy      goto meta_command_exit;
18376269851Speter    }
18377362190Scy    if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
18378362190Scy      char zSep[2];
18379362190Scy      zSep[1] = 0;
18380362190Scy      zSep[0] = sCtx.cColSep;
18381362190Scy      utf8_printf(p->out, "Column separator ");
18382362190Scy      output_c_string(p->out, zSep);
18383362190Scy      utf8_printf(p->out, ", row separator ");
18384362190Scy      zSep[0] = sCtx.cRowSep;
18385362190Scy      output_c_string(p->out, zSep);
18386362190Scy      utf8_printf(p->out, "\n");
18387362190Scy    }
18388362190Scy    while( (nSkip--)>0 ){
18389362190Scy      while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
18390362190Scy    }
18391369950Scy    zSql = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
18392251883Speter    if( zSql==0 ){
18393366076Scy      import_cleanup(&sCtx);
18394342292Scy      shell_out_of_memory();
18395251883Speter    }
18396251883Speter    nByte = strlen30(zSql);
18397269851Speter    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
18398282328Sbapt    import_append_char(&sCtx, 0);    /* To ensure sCtx.z is allocated */
18399286510Speter    if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
18400369950Scy      char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"", zTable);
18401269851Speter      char cSep = '(';
18402282328Sbapt      while( xRead(&sCtx) ){
18403298161Sbapt        zCreate = sqlite3_mprintf("%z%c\n  \"%w\" TEXT", zCreate, cSep, sCtx.z);
18404269851Speter        cSep = ',';
18405282328Sbapt        if( sCtx.cTerm!=sCtx.cColSep ) break;
18406269851Speter      }
18407269851Speter      if( cSep=='(' ){
18408269851Speter        sqlite3_free(zCreate);
18409366076Scy        import_cleanup(&sCtx);
18410298161Sbapt        utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
18411362190Scy        rc = 1;
18412362190Scy        goto meta_command_exit;
18413269851Speter      }
18414269851Speter      zCreate = sqlite3_mprintf("%z\n)", zCreate);
18415362190Scy      if( eVerbose>=1 ){
18416362190Scy        utf8_printf(p->out, "%s\n", zCreate);
18417362190Scy      }
18418269851Speter      rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
18419269851Speter      sqlite3_free(zCreate);
18420269851Speter      if( rc ){
18421369950Scy        utf8_printf(stderr, "CREATE TABLE \"%s\"(...) failed: %s\n", zTable,
18422286510Speter                sqlite3_errmsg(p->db));
18423366076Scy        import_cleanup(&sCtx);
18424362190Scy        rc = 1;
18425362190Scy        goto meta_command_exit;
18426269851Speter      }
18427269851Speter      rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
18428269851Speter    }
18429251883Speter    sqlite3_free(zSql);
18430251883Speter    if( rc ){
18431251883Speter      if (pStmt) sqlite3_finalize(pStmt);
18432298161Sbapt      utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
18433366076Scy      import_cleanup(&sCtx);
18434362190Scy      rc = 1;
18435362190Scy      goto meta_command_exit;
18436251883Speter    }
18437251883Speter    nCol = sqlite3_column_count(pStmt);
18438251883Speter    sqlite3_finalize(pStmt);
18439251883Speter    pStmt = 0;
18440251883Speter    if( nCol==0 ) return 0; /* no columns, no error */
18441286510Speter    zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
18442251883Speter    if( zSql==0 ){
18443366076Scy      import_cleanup(&sCtx);
18444342292Scy      shell_out_of_memory();
18445251883Speter    }
18446269851Speter    sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
18447251883Speter    j = strlen30(zSql);
18448251883Speter    for(i=1; i<nCol; i++){
18449251883Speter      zSql[j++] = ',';
18450251883Speter      zSql[j++] = '?';
18451251883Speter    }
18452251883Speter    zSql[j++] = ')';
18453251883Speter    zSql[j] = 0;
18454362190Scy    if( eVerbose>=2 ){
18455362190Scy      utf8_printf(p->out, "Insert using: %s\n", zSql);
18456362190Scy    }
18457269851Speter    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
18458269851Speter    sqlite3_free(zSql);
18459251883Speter    if( rc ){
18460298161Sbapt      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
18461251883Speter      if (pStmt) sqlite3_finalize(pStmt);
18462366076Scy      import_cleanup(&sCtx);
18463362190Scy      rc = 1;
18464362190Scy      goto meta_command_exit;
18465251883Speter    }
18466286510Speter    needCommit = sqlite3_get_autocommit(p->db);
18467286510Speter    if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
18468269851Speter    do{
18469282328Sbapt      int startLine = sCtx.nLine;
18470269851Speter      for(i=0; i<nCol; i++){
18471282328Sbapt        char *z = xRead(&sCtx);
18472282328Sbapt        /*
18473282328Sbapt        ** Did we reach end-of-file before finding any columns?
18474282328Sbapt        ** If so, stop instead of NULL filling the remaining columns.
18475282328Sbapt        */
18476269851Speter        if( z==0 && i==0 ) break;
18477282328Sbapt        /*
18478282328Sbapt        ** Did we reach end-of-file OR end-of-line before finding any
18479282328Sbapt        ** columns in ASCII mode?  If so, stop instead of NULL filling
18480282328Sbapt        ** the remaining columns.
18481282328Sbapt        */
18482282328Sbapt        if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
18483269851Speter        sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
18484282328Sbapt        if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
18485298161Sbapt          utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
18486269851Speter                          "filling the rest with NULL\n",
18487282328Sbapt                          sCtx.zFile, startLine, nCol, i+1);
18488282328Sbapt          i += 2;
18489274884Sbapt          while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
18490251883Speter        }
18491251883Speter      }
18492282328Sbapt      if( sCtx.cTerm==sCtx.cColSep ){
18493269851Speter        do{
18494282328Sbapt          xRead(&sCtx);
18495269851Speter          i++;
18496282328Sbapt        }while( sCtx.cTerm==sCtx.cColSep );
18497298161Sbapt        utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
18498269851Speter                        "extras ignored\n",
18499282328Sbapt                        sCtx.zFile, startLine, nCol, i);
18500269851Speter      }
18501269851Speter      if( i>=nCol ){
18502269851Speter        sqlite3_step(pStmt);
18503269851Speter        rc = sqlite3_reset(pStmt);
18504269851Speter        if( rc!=SQLITE_OK ){
18505298161Sbapt          utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
18506298161Sbapt                      startLine, sqlite3_errmsg(p->db));
18507362190Scy          sCtx.nErr++;
18508362190Scy        }else{
18509362190Scy          sCtx.nRow++;
18510251883Speter        }
18511251883Speter      }
18512282328Sbapt    }while( sCtx.cTerm!=EOF );
18513269851Speter
18514366076Scy    import_cleanup(&sCtx);
18515251883Speter    sqlite3_finalize(pStmt);
18516286510Speter    if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
18517362190Scy    if( eVerbose>0 ){
18518362190Scy      utf8_printf(p->out,
18519362190Scy          "Added %d rows with %d errors using %d lines of input\n",
18520362190Scy          sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
18521362190Scy    }
18522251883Speter  }else
18523251883Speter
18524322444Speter#ifndef SQLITE_UNTESTABLE
18525322444Speter  if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
18526322444Speter    char *zSql;
18527322444Speter    char *zCollist = 0;
18528322444Speter    sqlite3_stmt *pStmt;
18529322444Speter    int tnum = 0;
18530361456Scy    int isWO = 0;  /* True if making an imposter of a WITHOUT ROWID table */
18531361456Scy    int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
18532322444Speter    int i;
18533342292Scy    if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
18534342292Scy      utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
18535342292Scy                          "       .imposter off\n");
18536361456Scy      /* Also allowed, but not documented:
18537361456Scy      **
18538361456Scy      **    .imposter TABLE IMPOSTER
18539361456Scy      **
18540361456Scy      ** where TABLE is a WITHOUT ROWID table.  In that case, the
18541361456Scy      ** imposter is another WITHOUT ROWID table with the columns in
18542361456Scy      ** storage order. */
18543322444Speter      rc = 1;
18544322444Speter      goto meta_command_exit;
18545322444Speter    }
18546269851Speter    open_db(p, 0);
18547342292Scy    if( nArg==2 ){
18548342292Scy      sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
18549342292Scy      goto meta_command_exit;
18550342292Scy    }
18551361456Scy    zSql = sqlite3_mprintf(
18552366076Scy      "SELECT rootpage, 0 FROM sqlite_schema"
18553361456Scy      " WHERE name='%q' AND type='index'"
18554361456Scy      "UNION ALL "
18555366076Scy      "SELECT rootpage, 1 FROM sqlite_schema"
18556361456Scy      " WHERE name='%q' AND type='table'"
18557361456Scy      "   AND sql LIKE '%%without%%rowid%%'",
18558361456Scy      azArg[1], azArg[1]
18559361456Scy    );
18560322444Speter    sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
18561322444Speter    sqlite3_free(zSql);
18562322444Speter    if( sqlite3_step(pStmt)==SQLITE_ROW ){
18563322444Speter      tnum = sqlite3_column_int(pStmt, 0);
18564361456Scy      isWO = sqlite3_column_int(pStmt, 1);
18565322444Speter    }
18566322444Speter    sqlite3_finalize(pStmt);
18567322444Speter    zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
18568322444Speter    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
18569322444Speter    sqlite3_free(zSql);
18570322444Speter    i = 0;
18571322444Speter    while( sqlite3_step(pStmt)==SQLITE_ROW ){
18572322444Speter      char zLabel[20];
18573322444Speter      const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
18574322444Speter      i++;
18575322444Speter      if( zCol==0 ){
18576322444Speter        if( sqlite3_column_int(pStmt,1)==-1 ){
18577322444Speter          zCol = "_ROWID_";
18578322444Speter        }else{
18579322444Speter          sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
18580322444Speter          zCol = zLabel;
18581322444Speter        }
18582322444Speter      }
18583361456Scy      if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){
18584361456Scy        lenPK = (int)strlen(zCollist);
18585361456Scy      }
18586322444Speter      if( zCollist==0 ){
18587322444Speter        zCollist = sqlite3_mprintf("\"%w\"", zCol);
18588322444Speter      }else{
18589322444Speter        zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
18590322444Speter      }
18591322444Speter    }
18592322444Speter    sqlite3_finalize(pStmt);
18593361456Scy    if( i==0 || tnum==0 ){
18594361456Scy      utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
18595361456Scy      rc = 1;
18596361456Scy      sqlite3_free(zCollist);
18597361456Scy      goto meta_command_exit;
18598361456Scy    }
18599361456Scy    if( lenPK==0 ) lenPK = 100000;
18600322444Speter    zSql = sqlite3_mprintf(
18601361456Scy          "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
18602361456Scy          azArg[2], zCollist, lenPK, zCollist);
18603322444Speter    sqlite3_free(zCollist);
18604322444Speter    rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
18605322444Speter    if( rc==SQLITE_OK ){
18606322444Speter      rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
18607322444Speter      sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
18608322444Speter      if( rc ){
18609322444Speter        utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
18610322444Speter      }else{
18611322444Speter        utf8_printf(stdout, "%s;\n", zSql);
18612322444Speter        raw_printf(stdout,
18613361456Scy          "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
18614361456Scy          azArg[1], isWO ? "table" : "index"
18615322444Speter        );
18616322444Speter      }
18617322444Speter    }else{
18618322444Speter      raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
18619251883Speter      rc = 1;
18620251883Speter    }
18621322444Speter    sqlite3_free(zSql);
18622251883Speter  }else
18623322444Speter#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
18624251883Speter
18625251883Speter#ifdef SQLITE_ENABLE_IOTRACE
18626251883Speter  if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
18627282328Sbapt    SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
18628251883Speter    if( iotrace && iotrace!=stdout ) fclose(iotrace);
18629251883Speter    iotrace = 0;
18630251883Speter    if( nArg<2 ){
18631251883Speter      sqlite3IoTrace = 0;
18632251883Speter    }else if( strcmp(azArg[1], "-")==0 ){
18633251883Speter      sqlite3IoTrace = iotracePrintf;
18634251883Speter      iotrace = stdout;
18635251883Speter    }else{
18636251883Speter      iotrace = fopen(azArg[1], "w");
18637251883Speter      if( iotrace==0 ){
18638298161Sbapt        utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
18639251883Speter        sqlite3IoTrace = 0;
18640251883Speter        rc = 1;
18641251883Speter      }else{
18642251883Speter        sqlite3IoTrace = iotracePrintf;
18643251883Speter      }
18644251883Speter    }
18645251883Speter  }else
18646251883Speter#endif
18647322444Speter
18648286510Speter  if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
18649286510Speter    static const struct {
18650286510Speter       const char *zLimitName;   /* Name of a limit */
18651286510Speter       int limitCode;            /* Integer code for that limit */
18652286510Speter    } aLimit[] = {
18653286510Speter      { "length",                SQLITE_LIMIT_LENGTH                    },
18654286510Speter      { "sql_length",            SQLITE_LIMIT_SQL_LENGTH                },
18655286510Speter      { "column",                SQLITE_LIMIT_COLUMN                    },
18656286510Speter      { "expr_depth",            SQLITE_LIMIT_EXPR_DEPTH                },
18657286510Speter      { "compound_select",       SQLITE_LIMIT_COMPOUND_SELECT           },
18658286510Speter      { "vdbe_op",               SQLITE_LIMIT_VDBE_OP                   },
18659286510Speter      { "function_arg",          SQLITE_LIMIT_FUNCTION_ARG              },
18660286510Speter      { "attached",              SQLITE_LIMIT_ATTACHED                  },
18661286510Speter      { "like_pattern_length",   SQLITE_LIMIT_LIKE_PATTERN_LENGTH       },
18662286510Speter      { "variable_number",       SQLITE_LIMIT_VARIABLE_NUMBER           },
18663286510Speter      { "trigger_depth",         SQLITE_LIMIT_TRIGGER_DEPTH             },
18664286510Speter      { "worker_threads",        SQLITE_LIMIT_WORKER_THREADS            },
18665286510Speter    };
18666286510Speter    int i, n2;
18667286510Speter    open_db(p, 0);
18668286510Speter    if( nArg==1 ){
18669286510Speter      for(i=0; i<ArraySize(aLimit); i++){
18670305002Scy        printf("%20s %d\n", aLimit[i].zLimitName,
18671286510Speter               sqlite3_limit(p->db, aLimit[i].limitCode, -1));
18672286510Speter      }
18673286510Speter    }else if( nArg>3 ){
18674298161Sbapt      raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
18675286510Speter      rc = 1;
18676286510Speter      goto meta_command_exit;
18677286510Speter    }else{
18678286510Speter      int iLimit = -1;
18679286510Speter      n2 = strlen30(azArg[1]);
18680286510Speter      for(i=0; i<ArraySize(aLimit); i++){
18681286510Speter        if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
18682286510Speter          if( iLimit<0 ){
18683286510Speter            iLimit = i;
18684286510Speter          }else{
18685298161Sbapt            utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
18686286510Speter            rc = 1;
18687286510Speter            goto meta_command_exit;
18688286510Speter          }
18689286510Speter        }
18690286510Speter      }
18691286510Speter      if( iLimit<0 ){
18692298161Sbapt        utf8_printf(stderr, "unknown limit: \"%s\"\n"
18693286510Speter                        "enter \".limits\" with no arguments for a list.\n",
18694286510Speter                         azArg[1]);
18695286510Speter        rc = 1;
18696286510Speter        goto meta_command_exit;
18697286510Speter      }
18698286510Speter      if( nArg==3 ){
18699286510Speter        sqlite3_limit(p->db, aLimit[iLimit].limitCode,
18700286510Speter                      (int)integerValue(azArg[2]));
18701286510Speter      }
18702286510Speter      printf("%20s %d\n", aLimit[iLimit].zLimitName,
18703286510Speter             sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
18704286510Speter    }
18705286510Speter  }else
18706251883Speter
18707322444Speter  if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
18708322444Speter    open_db(p, 0);
18709322444Speter    lintDotCommand(p, azArg, nArg);
18710322444Speter  }else
18711322444Speter
18712251883Speter#ifndef SQLITE_OMIT_LOAD_EXTENSION
18713269851Speter  if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
18714251883Speter    const char *zFile, *zProc;
18715251883Speter    char *zErrMsg = 0;
18716269851Speter    if( nArg<2 ){
18717298161Sbapt      raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
18718269851Speter      rc = 1;
18719269851Speter      goto meta_command_exit;
18720269851Speter    }
18721251883Speter    zFile = azArg[1];
18722251883Speter    zProc = nArg>=3 ? azArg[2] : 0;
18723269851Speter    open_db(p, 0);
18724251883Speter    rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
18725251883Speter    if( rc!=SQLITE_OK ){
18726298161Sbapt      utf8_printf(stderr, "Error: %s\n", zErrMsg);
18727251883Speter      sqlite3_free(zErrMsg);
18728251883Speter      rc = 1;
18729251883Speter    }
18730251883Speter  }else
18731251883Speter#endif
18732251883Speter
18733269851Speter  if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
18734269851Speter    if( nArg!=2 ){
18735298161Sbapt      raw_printf(stderr, "Usage: .log FILENAME\n");
18736269851Speter      rc = 1;
18737269851Speter    }else{
18738269851Speter      const char *zFile = azArg[1];
18739269851Speter      output_file_close(p->pLog);
18740342292Scy      p->pLog = output_file_open(zFile, 0);
18741269851Speter    }
18742251883Speter  }else
18743251883Speter
18744269851Speter  if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
18745269851Speter    const char *zMode = nArg>=2 ? azArg[1] : "";
18746342292Scy    int n2 = strlen30(zMode);
18747269851Speter    int c2 = zMode[0];
18748269851Speter    if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){
18749251883Speter      p->mode = MODE_Line;
18750322444Speter      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
18751269851Speter    }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
18752251883Speter      p->mode = MODE_Column;
18753366076Scy      if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){
18754366076Scy        p->showHeader = 1;
18755366076Scy      }
18756322444Speter      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
18757269851Speter    }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
18758251883Speter      p->mode = MODE_List;
18759322444Speter      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
18760322444Speter      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
18761269851Speter    }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){
18762251883Speter      p->mode = MODE_Html;
18763269851Speter    }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
18764251883Speter      p->mode = MODE_Tcl;
18765282328Sbapt      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
18766322444Speter      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
18767269851Speter    }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
18768251883Speter      p->mode = MODE_Csv;
18769282328Sbapt      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
18770282328Sbapt      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
18771269851Speter    }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
18772251883Speter      p->mode = MODE_List;
18773282328Sbapt      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
18774269851Speter    }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
18775251883Speter      p->mode = MODE_Insert;
18776269851Speter      set_table_name(p, nArg>=3 ? azArg[2] : "table");
18777322444Speter    }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
18778322444Speter      p->mode = MODE_Quote;
18779366076Scy      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
18780366076Scy      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
18781282328Sbapt    }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
18782282328Sbapt      p->mode = MODE_Ascii;
18783282328Sbapt      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
18784282328Sbapt      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
18785366076Scy    }else if( c2=='m' && strncmp(azArg[1],"markdown",n2)==0 ){
18786366076Scy      p->mode = MODE_Markdown;
18787366076Scy    }else if( c2=='t' && strncmp(azArg[1],"table",n2)==0 ){
18788366076Scy      p->mode = MODE_Table;
18789366076Scy    }else if( c2=='b' && strncmp(azArg[1],"box",n2)==0 ){
18790366076Scy      p->mode = MODE_Box;
18791366076Scy    }else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){
18792366076Scy      p->mode = MODE_Json;
18793322444Speter    }else if( nArg==1 ){
18794322444Speter      raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
18795322444Speter    }else{
18796298161Sbapt      raw_printf(stderr, "Error: mode should be one of: "
18797366076Scy         "ascii box column csv html insert json line list markdown "
18798366076Scy         "quote table tabs tcl\n");
18799251883Speter      rc = 1;
18800251883Speter    }
18801298161Sbapt    p->cMode = p->mode;
18802251883Speter  }else
18803251883Speter
18804269851Speter  if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
18805269851Speter    if( nArg==2 ){
18806282328Sbapt      sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
18807282328Sbapt                       "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
18808269851Speter    }else{
18809298161Sbapt      raw_printf(stderr, "Usage: .nullvalue STRING\n");
18810251883Speter      rc = 1;
18811251883Speter    }
18812251883Speter  }else
18813251883Speter
18814362190Scy#ifdef SQLITE_DEBUG
18815362190Scy  if( c=='o' && strcmp(azArg[0],"oom")==0 ){
18816362190Scy    int i;
18817362190Scy    for(i=1; i<nArg; i++){
18818362190Scy      const char *z = azArg[i];
18819362190Scy      if( z[0]=='-' && z[1]=='-' ) z++;
18820362190Scy      if( strcmp(z,"-repeat")==0 ){
18821362190Scy        if( i==nArg-1 ){
18822362190Scy          raw_printf(p->out, "missing argument on \"%s\"\n", azArg[i]);
18823362190Scy          rc = 1;
18824362190Scy        }else{
18825362190Scy          oomRepeat = (int)integerValue(azArg[++i]);
18826362190Scy        }
18827362190Scy      }else if( IsDigit(z[0]) ){
18828362190Scy        oomCounter = (int)integerValue(azArg[i]);
18829362190Scy      }else{
18830362190Scy        raw_printf(p->out, "unknown argument: \"%s\"\n", azArg[i]);
18831362190Scy        raw_printf(p->out, "Usage: .oom [--repeat N] [M]\n");
18832362190Scy        rc = 1;
18833362190Scy      }
18834362190Scy    }
18835362190Scy    if( rc==0 ){
18836362190Scy      raw_printf(p->out, "oomCounter = %d\n", oomCounter);
18837362190Scy      raw_printf(p->out, "oomRepeat  = %d\n", oomRepeat);
18838362190Scy    }
18839362190Scy  }else
18840362190Scy#endif /* SQLITE_DEBUG */
18841362190Scy
18842269851Speter  if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
18843369951Scy    char *zNewFilename = 0;  /* Name of the database file to open */
18844369951Scy    int iName = 1;           /* Index in azArg[] of the filename */
18845369951Scy    int newFlag = 0;         /* True to delete file before opening */
18846322444Speter    /* Close the existing database */
18847322444Speter    session_close_all(p);
18848342292Scy    close_db(p->db);
18849269851Speter    p->db = 0;
18850322444Speter    p->zDbFilename = 0;
18851322444Speter    sqlite3_free(p->zFreeOnClose);
18852322444Speter    p->zFreeOnClose = 0;
18853342292Scy    p->openMode = SHELL_OPEN_UNSPEC;
18854361456Scy    p->openFlags = 0;
18855346442Scy    p->szMax = 0;
18856322444Speter    /* Check for command-line arguments */
18857369951Scy    for(iName=1; iName<nArg; iName++){
18858322444Speter      const char *z = azArg[iName];
18859322444Speter      if( optionMatch(z,"new") ){
18860322444Speter        newFlag = 1;
18861342292Scy#ifdef SQLITE_HAVE_ZLIB
18862342292Scy      }else if( optionMatch(z, "zip") ){
18863342292Scy        p->openMode = SHELL_OPEN_ZIPFILE;
18864342292Scy#endif
18865342292Scy      }else if( optionMatch(z, "append") ){
18866342292Scy        p->openMode = SHELL_OPEN_APPENDVFS;
18867342292Scy      }else if( optionMatch(z, "readonly") ){
18868342292Scy        p->openMode = SHELL_OPEN_READONLY;
18869361456Scy      }else if( optionMatch(z, "nofollow") ){
18870361456Scy        p->openFlags |= SQLITE_OPEN_NOFOLLOW;
18871342292Scy#ifdef SQLITE_ENABLE_DESERIALIZE
18872342292Scy      }else if( optionMatch(z, "deserialize") ){
18873342292Scy        p->openMode = SHELL_OPEN_DESERIALIZE;
18874346442Scy      }else if( optionMatch(z, "hexdb") ){
18875346442Scy        p->openMode = SHELL_OPEN_HEXDB;
18876346442Scy      }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
18877346442Scy        p->szMax = integerValue(azArg[++iName]);
18878346442Scy#endif /* SQLITE_ENABLE_DESERIALIZE */
18879322444Speter      }else if( z[0]=='-' ){
18880322444Speter        utf8_printf(stderr, "unknown option: %s\n", z);
18881322444Speter        rc = 1;
18882322444Speter        goto meta_command_exit;
18883369951Scy      }else if( zNewFilename ){
18884369951Scy        utf8_printf(stderr, "extra argument: \"%s\"\n", z);
18885369951Scy        rc = 1;
18886369951Scy        goto meta_command_exit;
18887369951Scy      }else{
18888369951Scy        zNewFilename = sqlite3_mprintf("%s", z);
18889322444Speter      }
18890269851Speter    }
18891322444Speter    /* If a filename is specified, try to open it first */
18892346442Scy    if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
18893322444Speter      if( newFlag ) shellDeleteFile(zNewFilename);
18894322444Speter      p->zDbFilename = zNewFilename;
18895342292Scy      open_db(p, OPEN_DB_KEEPALIVE);
18896322444Speter      if( p->db==0 ){
18897322444Speter        utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
18898322444Speter        sqlite3_free(zNewFilename);
18899322444Speter      }else{
18900322444Speter        p->zFreeOnClose = zNewFilename;
18901322444Speter      }
18902322444Speter    }
18903322444Speter    if( p->db==0 ){
18904322444Speter      /* As a fall-back open a TEMP database */
18905322444Speter      p->zDbFilename = 0;
18906322444Speter      open_db(p, 0);
18907322444Speter    }
18908251883Speter  }else
18909251883Speter
18910342292Scy  if( (c=='o'
18911342292Scy        && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
18912342292Scy   || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
18913269851Speter  ){
18914369951Scy    char *zFile = 0;
18915342292Scy    int bTxtMode = 0;
18916362190Scy    int i;
18917362190Scy    int eMode = 0;
18918362190Scy    int bBOM = 0;
18919362190Scy    int bOnce = 0;  /* 0: .output, 1: .once, 2: .excel */
18920362190Scy
18921362190Scy    if( c=='e' ){
18922362190Scy      eMode = 'x';
18923362190Scy      bOnce = 2;
18924362190Scy    }else if( strncmp(azArg[0],"once",n)==0 ){
18925362190Scy      bOnce = 1;
18926342292Scy    }
18927362190Scy    for(i=1; i<nArg; i++){
18928362190Scy      char *z = azArg[i];
18929362190Scy      if( z[0]=='-' ){
18930362190Scy        if( z[1]=='-' ) z++;
18931362190Scy        if( strcmp(z,"-bom")==0 ){
18932362190Scy          bBOM = 1;
18933362190Scy        }else if( c!='e' && strcmp(z,"-x")==0 ){
18934362190Scy          eMode = 'x';  /* spreadsheet */
18935362190Scy        }else if( c!='e' && strcmp(z,"-e")==0 ){
18936362190Scy          eMode = 'e';  /* text editor */
18937362190Scy        }else{
18938362190Scy          utf8_printf(p->out, "ERROR: unknown option: \"%s\".  Usage:\n",
18939362190Scy                      azArg[i]);
18940362190Scy          showHelp(p->out, azArg[0]);
18941362190Scy          rc = 1;
18942362190Scy          goto meta_command_exit;
18943362190Scy        }
18944369951Scy      }else if( zFile==0 && eMode!='e' && eMode!='x' ){
18945369951Scy        zFile = sqlite3_mprintf("%s", z);
18946369951Scy        if( zFile[0]=='|' ){
18947369951Scy          while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]);
18948369951Scy          break;
18949369951Scy        }
18950362190Scy      }else{
18951362190Scy        utf8_printf(p->out,"ERROR: extra parameter: \"%s\".  Usage:\n",
18952362190Scy                    azArg[i]);
18953362190Scy        showHelp(p->out, azArg[0]);
18954269851Speter        rc = 1;
18955369951Scy        sqlite3_free(zFile);
18956269851Speter        goto meta_command_exit;
18957269851Speter      }
18958362190Scy    }
18959369951Scy    if( zFile==0 ) zFile = sqlite3_mprintf("stdout");
18960362190Scy    if( bOnce ){
18961269851Speter      p->outCount = 2;
18962251883Speter    }else{
18963269851Speter      p->outCount = 0;
18964251883Speter    }
18965269851Speter    output_reset(p);
18966342292Scy#ifndef SQLITE_NOHAVE_SYSTEM
18967362190Scy    if( eMode=='e' || eMode=='x' ){
18968342292Scy      p->doXdgOpen = 1;
18969342292Scy      outputModePush(p);
18970362190Scy      if( eMode=='x' ){
18971362190Scy        /* spreadsheet mode.  Output as CSV. */
18972342292Scy        newTempFile(p, "csv");
18973362190Scy        ShellClearFlag(p, SHFLG_Echo);
18974342292Scy        p->mode = MODE_Csv;
18975342292Scy        sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
18976342292Scy        sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
18977342292Scy      }else{
18978362190Scy        /* text editor mode */
18979342292Scy        newTempFile(p, "txt");
18980342292Scy        bTxtMode = 1;
18981342292Scy      }
18982369951Scy      sqlite3_free(zFile);
18983369951Scy      zFile = sqlite3_mprintf("%s", p->zTempFile);
18984342292Scy    }
18985342292Scy#endif /* SQLITE_NOHAVE_SYSTEM */
18986269851Speter    if( zFile[0]=='|' ){
18987282328Sbapt#ifdef SQLITE_OMIT_POPEN
18988298161Sbapt      raw_printf(stderr, "Error: pipes are not supported in this OS\n");
18989282328Sbapt      rc = 1;
18990282328Sbapt      p->out = stdout;
18991282328Sbapt#else
18992269851Speter      p->out = popen(zFile + 1, "w");
18993251883Speter      if( p->out==0 ){
18994298161Sbapt        utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
18995251883Speter        p->out = stdout;
18996251883Speter        rc = 1;
18997251883Speter      }else{
18998362190Scy        if( bBOM ) fprintf(p->out,"\357\273\277");
18999269851Speter        sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
19000251883Speter      }
19001282328Sbapt#endif
19002251883Speter    }else{
19003342292Scy      p->out = output_file_open(zFile, bTxtMode);
19004251883Speter      if( p->out==0 ){
19005269851Speter        if( strcmp(zFile,"off")!=0 ){
19006298161Sbapt          utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
19007251883Speter        }
19008251883Speter        p->out = stdout;
19009251883Speter        rc = 1;
19010251883Speter      } else {
19011362190Scy        if( bBOM ) fprintf(p->out,"\357\273\277");
19012269851Speter        sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
19013251883Speter      }
19014251883Speter    }
19015369951Scy    sqlite3_free(zFile);
19016251883Speter  }else
19017251883Speter
19018347347Scy  if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
19019347347Scy    open_db(p,0);
19020347347Scy    if( nArg<=1 ) goto parameter_syntax_error;
19021347347Scy
19022347347Scy    /* .parameter clear
19023347347Scy    ** Clear all bind parameters by dropping the TEMP table that holds them.
19024347347Scy    */
19025347347Scy    if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
19026347347Scy      sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
19027347347Scy                   0, 0, 0);
19028347347Scy    }else
19029347347Scy
19030347347Scy    /* .parameter list
19031347347Scy    ** List all bind parameters.
19032347347Scy    */
19033347347Scy    if( nArg==2 && strcmp(azArg[1],"list")==0 ){
19034347347Scy      sqlite3_stmt *pStmt = 0;
19035347347Scy      int rx;
19036347347Scy      int len = 0;
19037347347Scy      rx = sqlite3_prepare_v2(p->db,
19038347347Scy             "SELECT max(length(key)) "
19039347347Scy             "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
19040347347Scy      if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
19041347347Scy        len = sqlite3_column_int(pStmt, 0);
19042347347Scy        if( len>40 ) len = 40;
19043347347Scy      }
19044347347Scy      sqlite3_finalize(pStmt);
19045347347Scy      pStmt = 0;
19046347347Scy      if( len ){
19047347347Scy        rx = sqlite3_prepare_v2(p->db,
19048347347Scy             "SELECT key, quote(value) "
19049347347Scy             "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
19050347347Scy        while( sqlite3_step(pStmt)==SQLITE_ROW ){
19051347347Scy          utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
19052347347Scy                      sqlite3_column_text(pStmt,1));
19053347347Scy        }
19054347347Scy        sqlite3_finalize(pStmt);
19055347347Scy      }
19056347347Scy    }else
19057347347Scy
19058347347Scy    /* .parameter init
19059347347Scy    ** Make sure the TEMP table used to hold bind parameters exists.
19060347347Scy    ** Create it if necessary.
19061347347Scy    */
19062347347Scy    if( nArg==2 && strcmp(azArg[1],"init")==0 ){
19063347347Scy      bind_table_init(p);
19064347347Scy    }else
19065347347Scy
19066347347Scy    /* .parameter set NAME VALUE
19067347347Scy    ** Set or reset a bind parameter.  NAME should be the full parameter
19068347347Scy    ** name exactly as it appears in the query.  (ex: $abc, @def).  The
19069347347Scy    ** VALUE can be in either SQL literal notation, or if not it will be
19070347347Scy    ** understood to be a text string.
19071347347Scy    */
19072347347Scy    if( nArg==4 && strcmp(azArg[1],"set")==0 ){
19073347347Scy      int rx;
19074347347Scy      char *zSql;
19075347347Scy      sqlite3_stmt *pStmt;
19076347347Scy      const char *zKey = azArg[2];
19077347347Scy      const char *zValue = azArg[3];
19078347347Scy      bind_table_init(p);
19079347347Scy      zSql = sqlite3_mprintf(
19080347347Scy                  "REPLACE INTO temp.sqlite_parameters(key,value)"
19081347347Scy                  "VALUES(%Q,%s);", zKey, zValue);
19082347347Scy      if( zSql==0 ) shell_out_of_memory();
19083347347Scy      pStmt = 0;
19084347347Scy      rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
19085347347Scy      sqlite3_free(zSql);
19086347347Scy      if( rx!=SQLITE_OK ){
19087347347Scy        sqlite3_finalize(pStmt);
19088347347Scy        pStmt = 0;
19089347347Scy        zSql = sqlite3_mprintf(
19090347347Scy                   "REPLACE INTO temp.sqlite_parameters(key,value)"
19091347347Scy                   "VALUES(%Q,%Q);", zKey, zValue);
19092347347Scy        if( zSql==0 ) shell_out_of_memory();
19093347347Scy        rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
19094347347Scy        sqlite3_free(zSql);
19095347347Scy        if( rx!=SQLITE_OK ){
19096347347Scy          utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
19097347347Scy          sqlite3_finalize(pStmt);
19098347347Scy          pStmt = 0;
19099347347Scy          rc = 1;
19100347347Scy        }
19101347347Scy      }
19102347347Scy      sqlite3_step(pStmt);
19103347347Scy      sqlite3_finalize(pStmt);
19104347347Scy    }else
19105347347Scy
19106347347Scy    /* .parameter unset NAME
19107347347Scy    ** Remove the NAME binding from the parameter binding table, if it
19108347347Scy    ** exists.
19109347347Scy    */
19110347347Scy    if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
19111347347Scy      char *zSql = sqlite3_mprintf(
19112347347Scy          "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
19113347347Scy      if( zSql==0 ) shell_out_of_memory();
19114347347Scy      sqlite3_exec(p->db, zSql, 0, 0, 0);
19115347347Scy      sqlite3_free(zSql);
19116347347Scy    }else
19117347347Scy    /* If no command name matches, show a syntax error */
19118347347Scy    parameter_syntax_error:
19119347347Scy    showHelp(p->out, "parameter");
19120347347Scy  }else
19121347347Scy
19122251883Speter  if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
19123251883Speter    int i;
19124251883Speter    for(i=1; i<nArg; i++){
19125298161Sbapt      if( i>1 ) raw_printf(p->out, " ");
19126298161Sbapt      utf8_printf(p->out, "%s", azArg[i]);
19127251883Speter    }
19128298161Sbapt    raw_printf(p->out, "\n");
19129251883Speter  }else
19130251883Speter
19131346442Scy#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
19132346442Scy  if( c=='p' && n>=3 && strncmp(azArg[0], "progress", n)==0 ){
19133346442Scy    int i;
19134346442Scy    int nn = 0;
19135346442Scy    p->flgProgress = 0;
19136346442Scy    p->mxProgress = 0;
19137346442Scy    p->nProgress = 0;
19138346442Scy    for(i=1; i<nArg; i++){
19139346442Scy      const char *z = azArg[i];
19140346442Scy      if( z[0]=='-' ){
19141346442Scy        z++;
19142346442Scy        if( z[0]=='-' ) z++;
19143346442Scy        if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
19144346442Scy          p->flgProgress |= SHELL_PROGRESS_QUIET;
19145346442Scy          continue;
19146346442Scy        }
19147346442Scy        if( strcmp(z,"reset")==0 ){
19148346442Scy          p->flgProgress |= SHELL_PROGRESS_RESET;
19149346442Scy          continue;
19150346442Scy        }
19151346442Scy        if( strcmp(z,"once")==0 ){
19152346442Scy          p->flgProgress |= SHELL_PROGRESS_ONCE;
19153346442Scy          continue;
19154346442Scy        }
19155346442Scy        if( strcmp(z,"limit")==0 ){
19156346442Scy          if( i+1>=nArg ){
19157346442Scy            utf8_printf(stderr, "Error: missing argument on --limit\n");
19158346442Scy            rc = 1;
19159346442Scy            goto meta_command_exit;
19160346442Scy          }else{
19161346442Scy            p->mxProgress = (int)integerValue(azArg[++i]);
19162346442Scy          }
19163346442Scy          continue;
19164346442Scy        }
19165346442Scy        utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
19166346442Scy        rc = 1;
19167346442Scy        goto meta_command_exit;
19168346442Scy      }else{
19169346442Scy        nn = (int)integerValue(z);
19170346442Scy      }
19171346442Scy    }
19172346442Scy    open_db(p, 0);
19173346442Scy    sqlite3_progress_handler(p->db, nn, progress_handler, p);
19174346442Scy  }else
19175346442Scy#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
19176346442Scy
19177269851Speter  if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
19178251883Speter    if( nArg >= 2) {
19179251883Speter      strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
19180251883Speter    }
19181251883Speter    if( nArg >= 3) {
19182251883Speter      strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
19183251883Speter    }
19184251883Speter  }else
19185251883Speter
19186269851Speter  if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
19187251883Speter    rc = 2;
19188251883Speter  }else
19189251883Speter
19190269851Speter  if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
19191346442Scy    FILE *inSaved = p->in;
19192346442Scy    int savedLineno = p->lineno;
19193269851Speter    if( nArg!=2 ){
19194298161Sbapt      raw_printf(stderr, "Usage: .read FILE\n");
19195269851Speter      rc = 1;
19196269851Speter      goto meta_command_exit;
19197269851Speter    }
19198369950Scy    if( azArg[1][0]=='|' ){
19199369951Scy#ifdef SQLITE_OMIT_POPEN
19200369951Scy      raw_printf(stderr, "Error: pipes are not supported in this OS\n");
19201369951Scy      rc = 1;
19202369951Scy      p->out = stdout;
19203369951Scy#else
19204369950Scy      p->in = popen(azArg[1]+1, "r");
19205369950Scy      if( p->in==0 ){
19206369950Scy        utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
19207369950Scy        rc = 1;
19208369950Scy      }else{
19209369950Scy        rc = process_input(p);
19210369950Scy        pclose(p->in);
19211369950Scy      }
19212369951Scy#endif
19213369950Scy    }else if( notNormalFile(azArg[1]) || (p->in = fopen(azArg[1], "rb"))==0 ){
19214298161Sbapt      utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
19215251883Speter      rc = 1;
19216251883Speter    }else{
19217346442Scy      rc = process_input(p);
19218346442Scy      fclose(p->in);
19219251883Speter    }
19220346442Scy    p->in = inSaved;
19221346442Scy    p->lineno = savedLineno;
19222251883Speter  }else
19223251883Speter
19224269851Speter  if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
19225251883Speter    const char *zSrcFile;
19226251883Speter    const char *zDb;
19227251883Speter    sqlite3 *pSrc;
19228251883Speter    sqlite3_backup *pBackup;
19229251883Speter    int nTimeout = 0;
19230251883Speter
19231251883Speter    if( nArg==2 ){
19232251883Speter      zSrcFile = azArg[1];
19233251883Speter      zDb = "main";
19234269851Speter    }else if( nArg==3 ){
19235251883Speter      zSrcFile = azArg[2];
19236251883Speter      zDb = azArg[1];
19237269851Speter    }else{
19238298161Sbapt      raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
19239269851Speter      rc = 1;
19240269851Speter      goto meta_command_exit;
19241251883Speter    }
19242251883Speter    rc = sqlite3_open(zSrcFile, &pSrc);
19243251883Speter    if( rc!=SQLITE_OK ){
19244298161Sbapt      utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
19245342292Scy      close_db(pSrc);
19246251883Speter      return 1;
19247251883Speter    }
19248269851Speter    open_db(p, 0);
19249251883Speter    pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
19250251883Speter    if( pBackup==0 ){
19251298161Sbapt      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
19252342292Scy      close_db(pSrc);
19253251883Speter      return 1;
19254251883Speter    }
19255251883Speter    while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
19256251883Speter          || rc==SQLITE_BUSY  ){
19257251883Speter      if( rc==SQLITE_BUSY ){
19258251883Speter        if( nTimeout++ >= 3 ) break;
19259251883Speter        sqlite3_sleep(100);
19260251883Speter      }
19261251883Speter    }
19262251883Speter    sqlite3_backup_finish(pBackup);
19263251883Speter    if( rc==SQLITE_DONE ){
19264251883Speter      rc = 0;
19265251883Speter    }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
19266298161Sbapt      raw_printf(stderr, "Error: source database is busy\n");
19267251883Speter      rc = 1;
19268251883Speter    }else{
19269298161Sbapt      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
19270251883Speter      rc = 1;
19271251883Speter    }
19272342292Scy    close_db(pSrc);
19273251883Speter  }else
19274251883Speter
19275282328Sbapt  if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
19276282328Sbapt    if( nArg==2 ){
19277342292Scy      p->scanstatsOn = (u8)booleanValue(azArg[1]);
19278282328Sbapt#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
19279298161Sbapt      raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
19280282328Sbapt#endif
19281282328Sbapt    }else{
19282298161Sbapt      raw_printf(stderr, "Usage: .scanstats on|off\n");
19283282328Sbapt      rc = 1;
19284282328Sbapt    }
19285282328Sbapt  }else
19286282328Sbapt
19287269851Speter  if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
19288322444Speter    ShellText sSelect;
19289274884Sbapt    ShellState data;
19290251883Speter    char *zErrMsg = 0;
19291342292Scy    const char *zDiv = "(";
19292342292Scy    const char *zName = 0;
19293322444Speter    int iSchema = 0;
19294342292Scy    int bDebug = 0;
19295369950Scy    int bNoSystemTabs = 0;
19296342292Scy    int ii;
19297322444Speter
19298269851Speter    open_db(p, 0);
19299251883Speter    memcpy(&data, p, sizeof(data));
19300251883Speter    data.showHeader = 0;
19301298161Sbapt    data.cMode = data.mode = MODE_Semi;
19302322444Speter    initText(&sSelect);
19303342292Scy    for(ii=1; ii<nArg; ii++){
19304342292Scy      if( optionMatch(azArg[ii],"indent") ){
19305342292Scy        data.cMode = data.mode = MODE_Pretty;
19306342292Scy      }else if( optionMatch(azArg[ii],"debug") ){
19307342292Scy        bDebug = 1;
19308369950Scy      }else if( optionMatch(azArg[ii],"nosys") ){
19309369950Scy        bNoSystemTabs = 1;
19310369950Scy      }else if( azArg[ii][0]=='-' ){
19311369950Scy        utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
19312369950Scy        rc = 1;
19313369950Scy        goto meta_command_exit;
19314342292Scy      }else if( zName==0 ){
19315342292Scy        zName = azArg[ii];
19316342292Scy      }else{
19317369950Scy        raw_printf(stderr, "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
19318342292Scy        rc = 1;
19319342292Scy        goto meta_command_exit;
19320342292Scy      }
19321305002Scy    }
19322342292Scy    if( zName!=0 ){
19323366076Scy      int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0
19324366076Scy                  || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
19325366076Scy                  || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
19326366076Scy                  || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
19327366076Scy      if( isSchema ){
19328251883Speter        char *new_argv[2], *new_colv[2];
19329342292Scy        new_argv[0] = sqlite3_mprintf(
19330342292Scy                      "CREATE TABLE %s (\n"
19331251883Speter                      "  type text,\n"
19332251883Speter                      "  name text,\n"
19333251883Speter                      "  tbl_name text,\n"
19334251883Speter                      "  rootpage integer,\n"
19335251883Speter                      "  sql text\n"
19336366076Scy                      ")", zName);
19337251883Speter        new_argv[1] = 0;
19338251883Speter        new_colv[0] = "sql";
19339251883Speter        new_colv[1] = 0;
19340251883Speter        callback(&data, 1, new_argv, new_colv);
19341342292Scy        sqlite3_free(new_argv[0]);
19342251883Speter      }
19343251883Speter    }
19344322444Speter    if( zDiv ){
19345322444Speter      sqlite3_stmt *pStmt = 0;
19346322444Speter      rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
19347322444Speter                              -1, &pStmt, 0);
19348322444Speter      if( rc ){
19349322444Speter        utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
19350322444Speter        sqlite3_finalize(pStmt);
19351322444Speter        rc = 1;
19352322444Speter        goto meta_command_exit;
19353322444Speter      }
19354322444Speter      appendText(&sSelect, "SELECT sql FROM", 0);
19355322444Speter      iSchema = 0;
19356322444Speter      while( sqlite3_step(pStmt)==SQLITE_ROW ){
19357322444Speter        const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
19358322444Speter        char zScNum[30];
19359322444Speter        sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
19360322444Speter        appendText(&sSelect, zDiv, 0);
19361322444Speter        zDiv = " UNION ALL ";
19362342292Scy        appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
19363342292Scy        if( sqlite3_stricmp(zDb, "main")!=0 ){
19364355326Scy          appendText(&sSelect, zDb, '\'');
19365322444Speter        }else{
19366342292Scy          appendText(&sSelect, "NULL", 0);
19367322444Speter        }
19368342292Scy        appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0);
19369342292Scy        appendText(&sSelect, zScNum, 0);
19370342292Scy        appendText(&sSelect, " AS snum, ", 0);
19371342292Scy        appendText(&sSelect, zDb, '\'');
19372342292Scy        appendText(&sSelect, " AS sname FROM ", 0);
19373355326Scy        appendText(&sSelect, zDb, quoteChar(zDb));
19374366076Scy        appendText(&sSelect, ".sqlite_schema", 0);
19375322444Speter      }
19376322444Speter      sqlite3_finalize(pStmt);
19377355326Scy#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
19378342292Scy      if( zName ){
19379342292Scy        appendText(&sSelect,
19380342292Scy           " UNION ALL SELECT shell_module_schema(name),"
19381355326Scy           " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
19382355326Scy        0);
19383342292Scy      }
19384342292Scy#endif
19385322444Speter      appendText(&sSelect, ") WHERE ", 0);
19386342292Scy      if( zName ){
19387342292Scy        char *zQarg = sqlite3_mprintf("%Q", zName);
19388342292Scy        int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
19389342292Scy                    strchr(zName, '[') != 0;
19390342292Scy        if( strchr(zName, '.') ){
19391322444Speter          appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
19392322444Speter        }else{
19393322444Speter          appendText(&sSelect, "lower(tbl_name)", 0);
19394322444Speter        }
19395342292Scy        appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0);
19396322444Speter        appendText(&sSelect, zQarg, 0);
19397342292Scy        if( !bGlob ){
19398342292Scy          appendText(&sSelect, " ESCAPE '\\' ", 0);
19399342292Scy        }
19400322444Speter        appendText(&sSelect, " AND ", 0);
19401322444Speter        sqlite3_free(zQarg);
19402322444Speter      }
19403369950Scy      if( bNoSystemTabs ){
19404369950Scy        appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
19405369950Scy      }
19406369950Scy      appendText(&sSelect, "sql IS NOT NULL"
19407322444Speter                           " ORDER BY snum, rowid", 0);
19408342292Scy      if( bDebug ){
19409342292Scy        utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
19410342292Scy      }else{
19411342292Scy        rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
19412342292Scy      }
19413322444Speter      freeText(&sSelect);
19414322444Speter    }
19415251883Speter    if( zErrMsg ){
19416298161Sbapt      utf8_printf(stderr,"Error: %s\n", zErrMsg);
19417251883Speter      sqlite3_free(zErrMsg);
19418251883Speter      rc = 1;
19419251883Speter    }else if( rc != SQLITE_OK ){
19420298161Sbapt      raw_printf(stderr,"Error: querying schema information\n");
19421251883Speter      rc = 1;
19422251883Speter    }else{
19423251883Speter      rc = 0;
19424251883Speter    }
19425251883Speter  }else
19426251883Speter
19427274884Sbapt  if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
19428369951Scy    unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
19429369951Scy    sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
19430274884Sbapt  }else
19431274884Sbapt
19432305002Scy#if defined(SQLITE_ENABLE_SESSION)
19433305002Scy  if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
19434305002Scy    OpenSession *pSession = &p->aSession[0];
19435305002Scy    char **azCmd = &azArg[1];
19436305002Scy    int iSes = 0;
19437305002Scy    int nCmd = nArg - 1;
19438305002Scy    int i;
19439305002Scy    if( nArg<=1 ) goto session_syntax_error;
19440305002Scy    open_db(p, 0);
19441305002Scy    if( nArg>=3 ){
19442305002Scy      for(iSes=0; iSes<p->nSession; iSes++){
19443305002Scy        if( strcmp(p->aSession[iSes].zName, azArg[1])==0 ) break;
19444305002Scy      }
19445305002Scy      if( iSes<p->nSession ){
19446305002Scy        pSession = &p->aSession[iSes];
19447305002Scy        azCmd++;
19448305002Scy        nCmd--;
19449305002Scy      }else{
19450305002Scy        pSession = &p->aSession[0];
19451305002Scy        iSes = 0;
19452305002Scy      }
19453305002Scy    }
19454274884Sbapt
19455305002Scy    /* .session attach TABLE
19456305002Scy    ** Invoke the sqlite3session_attach() interface to attach a particular
19457305002Scy    ** table so that it is never filtered.
19458305002Scy    */
19459305002Scy    if( strcmp(azCmd[0],"attach")==0 ){
19460305002Scy      if( nCmd!=2 ) goto session_syntax_error;
19461305002Scy      if( pSession->p==0 ){
19462305002Scy        session_not_open:
19463305002Scy        raw_printf(stderr, "ERROR: No sessions are open\n");
19464305002Scy      }else{
19465305002Scy        rc = sqlite3session_attach(pSession->p, azCmd[1]);
19466305002Scy        if( rc ){
19467305002Scy          raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
19468305002Scy          rc = 0;
19469305002Scy        }
19470305002Scy      }
19471305002Scy    }else
19472305002Scy
19473305002Scy    /* .session changeset FILE
19474305002Scy    ** .session patchset FILE
19475305002Scy    ** Write a changeset or patchset into a file.  The file is overwritten.
19476305002Scy    */
19477305002Scy    if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
19478305002Scy      FILE *out = 0;
19479305002Scy      if( nCmd!=2 ) goto session_syntax_error;
19480305002Scy      if( pSession->p==0 ) goto session_not_open;
19481305002Scy      out = fopen(azCmd[1], "wb");
19482305002Scy      if( out==0 ){
19483355326Scy        utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
19484355326Scy                    azCmd[1]);
19485305002Scy      }else{
19486305002Scy        int szChng;
19487305002Scy        void *pChng;
19488305002Scy        if( azCmd[0][0]=='c' ){
19489305002Scy          rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
19490305002Scy        }else{
19491305002Scy          rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
19492305002Scy        }
19493305002Scy        if( rc ){
19494305002Scy          printf("Error: error code %d\n", rc);
19495305002Scy          rc = 0;
19496305002Scy        }
19497305002Scy        if( pChng
19498305002Scy          && fwrite(pChng, szChng, 1, out)!=1 ){
19499305002Scy          raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
19500305002Scy                  szChng);
19501305002Scy        }
19502305002Scy        sqlite3_free(pChng);
19503305002Scy        fclose(out);
19504305002Scy      }
19505305002Scy    }else
19506305002Scy
19507305002Scy    /* .session close
19508305002Scy    ** Close the identified session
19509305002Scy    */
19510305002Scy    if( strcmp(azCmd[0], "close")==0 ){
19511305002Scy      if( nCmd!=1 ) goto session_syntax_error;
19512305002Scy      if( p->nSession ){
19513305002Scy        session_close(pSession);
19514305002Scy        p->aSession[iSes] = p->aSession[--p->nSession];
19515305002Scy      }
19516305002Scy    }else
19517305002Scy
19518305002Scy    /* .session enable ?BOOLEAN?
19519305002Scy    ** Query or set the enable flag
19520305002Scy    */
19521305002Scy    if( strcmp(azCmd[0], "enable")==0 ){
19522305002Scy      int ii;
19523305002Scy      if( nCmd>2 ) goto session_syntax_error;
19524305002Scy      ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
19525305002Scy      if( p->nSession ){
19526305002Scy        ii = sqlite3session_enable(pSession->p, ii);
19527305002Scy        utf8_printf(p->out, "session %s enable flag = %d\n",
19528305002Scy                    pSession->zName, ii);
19529305002Scy      }
19530305002Scy    }else
19531305002Scy
19532305002Scy    /* .session filter GLOB ....
19533305002Scy    ** Set a list of GLOB patterns of table names to be excluded.
19534305002Scy    */
19535305002Scy    if( strcmp(azCmd[0], "filter")==0 ){
19536305002Scy      int ii, nByte;
19537305002Scy      if( nCmd<2 ) goto session_syntax_error;
19538305002Scy      if( p->nSession ){
19539305002Scy        for(ii=0; ii<pSession->nFilter; ii++){
19540305002Scy          sqlite3_free(pSession->azFilter[ii]);
19541305002Scy        }
19542305002Scy        sqlite3_free(pSession->azFilter);
19543305002Scy        nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
19544305002Scy        pSession->azFilter = sqlite3_malloc( nByte );
19545305002Scy        if( pSession->azFilter==0 ){
19546305002Scy          raw_printf(stderr, "Error: out or memory\n");
19547305002Scy          exit(1);
19548305002Scy        }
19549305002Scy        for(ii=1; ii<nCmd; ii++){
19550305002Scy          pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
19551305002Scy        }
19552305002Scy        pSession->nFilter = ii-1;
19553305002Scy      }
19554305002Scy    }else
19555305002Scy
19556305002Scy    /* .session indirect ?BOOLEAN?
19557305002Scy    ** Query or set the indirect flag
19558305002Scy    */
19559305002Scy    if( strcmp(azCmd[0], "indirect")==0 ){
19560305002Scy      int ii;
19561305002Scy      if( nCmd>2 ) goto session_syntax_error;
19562305002Scy      ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
19563305002Scy      if( p->nSession ){
19564305002Scy        ii = sqlite3session_indirect(pSession->p, ii);
19565305002Scy        utf8_printf(p->out, "session %s indirect flag = %d\n",
19566305002Scy                    pSession->zName, ii);
19567305002Scy      }
19568305002Scy    }else
19569305002Scy
19570305002Scy    /* .session isempty
19571305002Scy    ** Determine if the session is empty
19572305002Scy    */
19573305002Scy    if( strcmp(azCmd[0], "isempty")==0 ){
19574305002Scy      int ii;
19575305002Scy      if( nCmd!=1 ) goto session_syntax_error;
19576305002Scy      if( p->nSession ){
19577305002Scy        ii = sqlite3session_isempty(pSession->p);
19578305002Scy        utf8_printf(p->out, "session %s isempty flag = %d\n",
19579305002Scy                    pSession->zName, ii);
19580305002Scy      }
19581305002Scy    }else
19582305002Scy
19583305002Scy    /* .session list
19584305002Scy    ** List all currently open sessions
19585305002Scy    */
19586305002Scy    if( strcmp(azCmd[0],"list")==0 ){
19587305002Scy      for(i=0; i<p->nSession; i++){
19588305002Scy        utf8_printf(p->out, "%d %s\n", i, p->aSession[i].zName);
19589305002Scy      }
19590305002Scy    }else
19591305002Scy
19592305002Scy    /* .session open DB NAME
19593305002Scy    ** Open a new session called NAME on the attached database DB.
19594305002Scy    ** DB is normally "main".
19595305002Scy    */
19596305002Scy    if( strcmp(azCmd[0],"open")==0 ){
19597305002Scy      char *zName;
19598305002Scy      if( nCmd!=3 ) goto session_syntax_error;
19599305002Scy      zName = azCmd[2];
19600305002Scy      if( zName[0]==0 ) goto session_syntax_error;
19601305002Scy      for(i=0; i<p->nSession; i++){
19602305002Scy        if( strcmp(p->aSession[i].zName,zName)==0 ){
19603305002Scy          utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
19604305002Scy          goto meta_command_exit;
19605305002Scy        }
19606305002Scy      }
19607305002Scy      if( p->nSession>=ArraySize(p->aSession) ){
19608305002Scy        raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(p->aSession));
19609305002Scy        goto meta_command_exit;
19610305002Scy      }
19611305002Scy      pSession = &p->aSession[p->nSession];
19612305002Scy      rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
19613305002Scy      if( rc ){
19614305002Scy        raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
19615305002Scy        rc = 0;
19616305002Scy        goto meta_command_exit;
19617305002Scy      }
19618305002Scy      pSession->nFilter = 0;
19619305002Scy      sqlite3session_table_filter(pSession->p, session_filter, pSession);
19620305002Scy      p->nSession++;
19621305002Scy      pSession->zName = sqlite3_mprintf("%s", zName);
19622305002Scy    }else
19623305002Scy    /* If no command name matches, show a syntax error */
19624305002Scy    session_syntax_error:
19625342292Scy    showHelp(p->out, "session");
19626305002Scy  }else
19627305002Scy#endif
19628305002Scy
19629269851Speter#ifdef SQLITE_DEBUG
19630269851Speter  /* Undocumented commands for internal testing.  Subject to change
19631269851Speter  ** without notice. */
19632269851Speter  if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
19633269851Speter    if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
19634269851Speter      int i, v;
19635269851Speter      for(i=1; i<nArg; i++){
19636269851Speter        v = booleanValue(azArg[i]);
19637298161Sbapt        utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
19638269851Speter      }
19639269851Speter    }
19640269851Speter    if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
19641269851Speter      int i; sqlite3_int64 v;
19642269851Speter      for(i=1; i<nArg; i++){
19643269851Speter        char zBuf[200];
19644269851Speter        v = integerValue(azArg[i]);
19645269851Speter        sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
19646298161Sbapt        utf8_printf(p->out, "%s", zBuf);
19647269851Speter      }
19648269851Speter    }
19649251883Speter  }else
19650269851Speter#endif
19651251883Speter
19652322444Speter  if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){
19653322444Speter    int bIsInit = 0;         /* True to initialize the SELFTEST table */
19654322444Speter    int bVerbose = 0;        /* Verbose output */
19655322444Speter    int bSelftestExists;     /* True if SELFTEST already exists */
19656322444Speter    int i, k;                /* Loop counters */
19657322444Speter    int nTest = 0;           /* Number of tests runs */
19658322444Speter    int nErr = 0;            /* Number of errors seen */
19659322444Speter    ShellText str;           /* Answer for a query */
19660322444Speter    sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
19661322444Speter
19662322444Speter    open_db(p,0);
19663322444Speter    for(i=1; i<nArg; i++){
19664322444Speter      const char *z = azArg[i];
19665322444Speter      if( z[0]=='-' && z[1]=='-' ) z++;
19666322444Speter      if( strcmp(z,"-init")==0 ){
19667322444Speter        bIsInit = 1;
19668322444Speter      }else
19669322444Speter      if( strcmp(z,"-v")==0 ){
19670322444Speter        bVerbose++;
19671322444Speter      }else
19672322444Speter      {
19673322444Speter        utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
19674322444Speter                    azArg[i], azArg[0]);
19675322444Speter        raw_printf(stderr, "Should be one of: --init -v\n");
19676322444Speter        rc = 1;
19677322444Speter        goto meta_command_exit;
19678322444Speter      }
19679322444Speter    }
19680322444Speter    if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
19681322444Speter           != SQLITE_OK ){
19682322444Speter      bSelftestExists = 0;
19683322444Speter    }else{
19684322444Speter      bSelftestExists = 1;
19685322444Speter    }
19686322444Speter    if( bIsInit ){
19687322444Speter      createSelftestTable(p);
19688322444Speter      bSelftestExists = 1;
19689322444Speter    }
19690322444Speter    initText(&str);
19691322444Speter    appendText(&str, "x", 0);
19692322444Speter    for(k=bSelftestExists; k>=0; k--){
19693322444Speter      if( k==1 ){
19694322444Speter        rc = sqlite3_prepare_v2(p->db,
19695322444Speter            "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
19696322444Speter            -1, &pStmt, 0);
19697322444Speter      }else{
19698322444Speter        rc = sqlite3_prepare_v2(p->db,
19699322444Speter          "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
19700322444Speter          "      (1,'run','PRAGMA integrity_check','ok')",
19701322444Speter          -1, &pStmt, 0);
19702322444Speter      }
19703322444Speter      if( rc ){
19704322444Speter        raw_printf(stderr, "Error querying the selftest table\n");
19705322444Speter        rc = 1;
19706322444Speter        sqlite3_finalize(pStmt);
19707322444Speter        goto meta_command_exit;
19708322444Speter      }
19709322444Speter      for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
19710322444Speter        int tno = sqlite3_column_int(pStmt, 0);
19711322444Speter        const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
19712322444Speter        const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
19713322444Speter        const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
19714322444Speter
19715322444Speter        k = 0;
19716322444Speter        if( bVerbose>0 ){
19717322444Speter          char *zQuote = sqlite3_mprintf("%q", zSql);
19718322444Speter          printf("%d: %s %s\n", tno, zOp, zSql);
19719322444Speter          sqlite3_free(zQuote);
19720322444Speter        }
19721322444Speter        if( strcmp(zOp,"memo")==0 ){
19722322444Speter          utf8_printf(p->out, "%s\n", zSql);
19723322444Speter        }else
19724322444Speter        if( strcmp(zOp,"run")==0 ){
19725322444Speter          char *zErrMsg = 0;
19726322444Speter          str.n = 0;
19727322444Speter          str.z[0] = 0;
19728322444Speter          rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
19729322444Speter          nTest++;
19730322444Speter          if( bVerbose ){
19731322444Speter            utf8_printf(p->out, "Result: %s\n", str.z);
19732322444Speter          }
19733322444Speter          if( rc || zErrMsg ){
19734322444Speter            nErr++;
19735322444Speter            rc = 1;
19736322444Speter            utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
19737322444Speter            sqlite3_free(zErrMsg);
19738322444Speter          }else if( strcmp(zAns,str.z)!=0 ){
19739322444Speter            nErr++;
19740322444Speter            rc = 1;
19741322444Speter            utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
19742322444Speter            utf8_printf(p->out, "%d:      Got: [%s]\n", tno, str.z);
19743322444Speter          }
19744322444Speter        }else
19745322444Speter        {
19746322444Speter          utf8_printf(stderr,
19747322444Speter            "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
19748322444Speter          rc = 1;
19749322444Speter          break;
19750322444Speter        }
19751322444Speter      } /* End loop over rows of content from SELFTEST */
19752322444Speter      sqlite3_finalize(pStmt);
19753322444Speter    } /* End loop over k */
19754322444Speter    freeText(&str);
19755322444Speter    utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
19756322444Speter  }else
19757322444Speter
19758269851Speter  if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
19759274884Sbapt    if( nArg<2 || nArg>3 ){
19760298161Sbapt      raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
19761269851Speter      rc = 1;
19762269851Speter    }
19763274884Sbapt    if( nArg>=2 ){
19764282328Sbapt      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
19765282328Sbapt                       "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
19766274884Sbapt    }
19767274884Sbapt    if( nArg>=3 ){
19768282328Sbapt      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator,
19769282328Sbapt                       "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]);
19770274884Sbapt    }
19771269851Speter  }else
19772269851Speter
19773322444Speter  if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){
19774322444Speter    const char *zLike = 0;   /* Which table to checksum. 0 means everything */
19775322444Speter    int i;                   /* Loop counter */
19776322444Speter    int bSchema = 0;         /* Also hash the schema */
19777322444Speter    int bSeparate = 0;       /* Hash each table separately */
19778322444Speter    int iSize = 224;         /* Hash algorithm to use */
19779322444Speter    int bDebug = 0;          /* Only show the query that would have run */
19780322444Speter    sqlite3_stmt *pStmt;     /* For querying tables names */
19781322444Speter    char *zSql;              /* SQL to be run */
19782322444Speter    char *zSep;              /* Separator */
19783322444Speter    ShellText sSql;          /* Complete SQL for the query to run the hash */
19784322444Speter    ShellText sQuery;        /* Set of queries used to read all content */
19785322444Speter    open_db(p, 0);
19786322444Speter    for(i=1; i<nArg; i++){
19787322444Speter      const char *z = azArg[i];
19788322444Speter      if( z[0]=='-' ){
19789322444Speter        z++;
19790322444Speter        if( z[0]=='-' ) z++;
19791322444Speter        if( strcmp(z,"schema")==0 ){
19792322444Speter          bSchema = 1;
19793322444Speter        }else
19794322444Speter        if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
19795322444Speter         || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
19796322444Speter        ){
19797322444Speter          iSize = atoi(&z[5]);
19798322444Speter        }else
19799322444Speter        if( strcmp(z,"debug")==0 ){
19800322444Speter          bDebug = 1;
19801322444Speter        }else
19802322444Speter        {
19803322444Speter          utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
19804322444Speter                      azArg[i], azArg[0]);
19805355326Scy          showHelp(p->out, azArg[0]);
19806322444Speter          rc = 1;
19807322444Speter          goto meta_command_exit;
19808322444Speter        }
19809322444Speter      }else if( zLike ){
19810322444Speter        raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
19811322444Speter        rc = 1;
19812322444Speter        goto meta_command_exit;
19813322444Speter      }else{
19814322444Speter        zLike = z;
19815322444Speter        bSeparate = 1;
19816342292Scy        if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1;
19817322444Speter      }
19818322444Speter    }
19819322444Speter    if( bSchema ){
19820366076Scy      zSql = "SELECT lower(name) FROM sqlite_schema"
19821322444Speter             " WHERE type='table' AND coalesce(rootpage,0)>1"
19822366076Scy             " UNION ALL SELECT 'sqlite_schema'"
19823322444Speter             " ORDER BY 1 collate nocase";
19824322444Speter    }else{
19825366076Scy      zSql = "SELECT lower(name) FROM sqlite_schema"
19826322444Speter             " WHERE type='table' AND coalesce(rootpage,0)>1"
19827322444Speter             " AND name NOT LIKE 'sqlite_%'"
19828322444Speter             " ORDER BY 1 collate nocase";
19829322444Speter    }
19830322444Speter    sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
19831322444Speter    initText(&sQuery);
19832322444Speter    initText(&sSql);
19833322444Speter    appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
19834322444Speter    zSep = "VALUES(";
19835322444Speter    while( SQLITE_ROW==sqlite3_step(pStmt) ){
19836322444Speter      const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
19837322444Speter      if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
19838322444Speter      if( strncmp(zTab, "sqlite_",7)!=0 ){
19839322444Speter        appendText(&sQuery,"SELECT * FROM ", 0);
19840322444Speter        appendText(&sQuery,zTab,'"');
19841322444Speter        appendText(&sQuery," NOT INDEXED;", 0);
19842366076Scy      }else if( strcmp(zTab, "sqlite_schema")==0 ){
19843366076Scy        appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema"
19844322444Speter                           " ORDER BY name;", 0);
19845322444Speter      }else if( strcmp(zTab, "sqlite_sequence")==0 ){
19846322444Speter        appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
19847322444Speter                           " ORDER BY name;", 0);
19848322444Speter      }else if( strcmp(zTab, "sqlite_stat1")==0 ){
19849322444Speter        appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
19850322444Speter                           " ORDER BY tbl,idx;", 0);
19851355326Scy      }else if( strcmp(zTab, "sqlite_stat4")==0 ){
19852322444Speter        appendText(&sQuery, "SELECT * FROM ", 0);
19853322444Speter        appendText(&sQuery, zTab, 0);
19854322444Speter        appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
19855322444Speter      }
19856322444Speter      appendText(&sSql, zSep, 0);
19857322444Speter      appendText(&sSql, sQuery.z, '\'');
19858322444Speter      sQuery.n = 0;
19859322444Speter      appendText(&sSql, ",", 0);
19860322444Speter      appendText(&sSql, zTab, '\'');
19861322444Speter      zSep = "),(";
19862322444Speter    }
19863322444Speter    sqlite3_finalize(pStmt);
19864322444Speter    if( bSeparate ){
19865322444Speter      zSql = sqlite3_mprintf(
19866322444Speter          "%s))"
19867322444Speter          " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
19868322444Speter          "   FROM [sha3sum$query]",
19869322444Speter          sSql.z, iSize);
19870322444Speter    }else{
19871322444Speter      zSql = sqlite3_mprintf(
19872322444Speter          "%s))"
19873322444Speter          " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
19874322444Speter          "   FROM [sha3sum$query]",
19875322444Speter          sSql.z, iSize);
19876322444Speter    }
19877322444Speter    freeText(&sQuery);
19878322444Speter    freeText(&sSql);
19879322444Speter    if( bDebug ){
19880322444Speter      utf8_printf(p->out, "%s\n", zSql);
19881322444Speter    }else{
19882342292Scy      shell_exec(p, zSql, 0);
19883322444Speter    }
19884322444Speter    sqlite3_free(zSql);
19885322444Speter  }else
19886322444Speter
19887342292Scy#ifndef SQLITE_NOHAVE_SYSTEM
19888269851Speter  if( c=='s'
19889269851Speter   && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
19890269851Speter  ){
19891269851Speter    char *zCmd;
19892274884Sbapt    int i, x;
19893269851Speter    if( nArg<2 ){
19894298161Sbapt      raw_printf(stderr, "Usage: .system COMMAND\n");
19895269851Speter      rc = 1;
19896269851Speter      goto meta_command_exit;
19897269851Speter    }
19898269851Speter    zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
19899269851Speter    for(i=2; i<nArg; i++){
19900269851Speter      zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
19901269851Speter                             zCmd, azArg[i]);
19902269851Speter    }
19903274884Sbapt    x = system(zCmd);
19904269851Speter    sqlite3_free(zCmd);
19905298161Sbapt    if( x ) raw_printf(stderr, "System command returns %d\n", x);
19906269851Speter  }else
19907342292Scy#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
19908269851Speter
19909269851Speter  if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
19910342292Scy    static const char *azBool[] = { "off", "on", "trigger", "full"};
19911369951Scy    const char *zOut;
19912269851Speter    int i;
19913269851Speter    if( nArg!=1 ){
19914298161Sbapt      raw_printf(stderr, "Usage: .show\n");
19915269851Speter      rc = 1;
19916269851Speter      goto meta_command_exit;
19917269851Speter    }
19918322444Speter    utf8_printf(p->out, "%12.12s: %s\n","echo",
19919322444Speter                                  azBool[ShellHasFlag(p, SHFLG_Echo)]);
19920305002Scy    utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
19921298161Sbapt    utf8_printf(p->out, "%12.12s: %s\n","explain",
19922298161Sbapt         p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
19923305002Scy    utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
19924298161Sbapt    utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
19925298161Sbapt    utf8_printf(p->out, "%12.12s: ", "nullvalue");
19926282328Sbapt      output_c_string(p->out, p->nullValue);
19927298161Sbapt      raw_printf(p->out, "\n");
19928298161Sbapt    utf8_printf(p->out,"%12.12s: %s\n","output",
19929251883Speter            strlen30(p->outfile) ? p->outfile : "stdout");
19930298161Sbapt    utf8_printf(p->out,"%12.12s: ", "colseparator");
19931282328Sbapt      output_c_string(p->out, p->colSeparator);
19932298161Sbapt      raw_printf(p->out, "\n");
19933298161Sbapt    utf8_printf(p->out,"%12.12s: ", "rowseparator");
19934282328Sbapt      output_c_string(p->out, p->rowSeparator);
19935298161Sbapt      raw_printf(p->out, "\n");
19936369951Scy    switch( p->statsOn ){
19937369951Scy      case 0:  zOut = "off";     break;
19938369951Scy      default: zOut = "on";      break;
19939369951Scy      case 2:  zOut = "stmt";    break;
19940369951Scy      case 3:  zOut = "vmstep";  break;
19941369951Scy    }
19942369951Scy    utf8_printf(p->out, "%12.12s: %s\n","stats", zOut);
19943298161Sbapt    utf8_printf(p->out, "%12.12s: ", "width");
19944366076Scy    for (i=0;i<p->nWidth;i++) {
19945298161Sbapt      raw_printf(p->out, "%d ", p->colWidth[i]);
19946251883Speter    }
19947298161Sbapt    raw_printf(p->out, "\n");
19948322444Speter    utf8_printf(p->out, "%12.12s: %s\n", "filename",
19949322444Speter                p->zDbFilename ? p->zDbFilename : "");
19950251883Speter  }else
19951251883Speter
19952269851Speter  if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
19953269851Speter    if( nArg==2 ){
19954369951Scy      if( strcmp(azArg[1],"stmt")==0 ){
19955369951Scy        p->statsOn = 2;
19956369951Scy      }else if( strcmp(azArg[1],"vmstep")==0 ){
19957369951Scy        p->statsOn = 3;
19958369951Scy      }else{
19959369951Scy        p->statsOn = (u8)booleanValue(azArg[1]);
19960369951Scy      }
19961298161Sbapt    }else if( nArg==1 ){
19962298161Sbapt      display_stats(p->db, p, 0);
19963269851Speter    }else{
19964369951Scy      raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n");
19965269851Speter      rc = 1;
19966269851Speter    }
19967251883Speter  }else
19968251883Speter
19969322444Speter  if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0)
19970322444Speter   || (c=='i' && (strncmp(azArg[0], "indices", n)==0
19971322444Speter                 || strncmp(azArg[0], "indexes", n)==0) )
19972322444Speter  ){
19973251883Speter    sqlite3_stmt *pStmt;
19974251883Speter    char **azResult;
19975251883Speter    int nRow, nAlloc;
19976251883Speter    int ii;
19977322444Speter    ShellText s;
19978322444Speter    initText(&s);
19979269851Speter    open_db(p, 0);
19980251883Speter    rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
19981342292Scy    if( rc ){
19982342292Scy      sqlite3_finalize(pStmt);
19983342292Scy      return shellDatabaseError(p->db);
19984342292Scy    }
19985298161Sbapt
19986322444Speter    if( nArg>2 && c=='i' ){
19987322444Speter      /* It is an historical accident that the .indexes command shows an error
19988322444Speter      ** when called with the wrong number of arguments whereas the .tables
19989322444Speter      ** command does not. */
19990322444Speter      raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
19991322444Speter      rc = 1;
19992342292Scy      sqlite3_finalize(pStmt);
19993322444Speter      goto meta_command_exit;
19994322444Speter    }
19995322444Speter    for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
19996251883Speter      const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
19997322444Speter      if( zDbName==0 ) continue;
19998322444Speter      if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0);
19999322444Speter      if( sqlite3_stricmp(zDbName, "main")==0 ){
20000322444Speter        appendText(&s, "SELECT name FROM ", 0);
20001251883Speter      }else{
20002322444Speter        appendText(&s, "SELECT ", 0);
20003322444Speter        appendText(&s, zDbName, '\'');
20004322444Speter        appendText(&s, "||'.'||name FROM ", 0);
20005251883Speter      }
20006322444Speter      appendText(&s, zDbName, '"');
20007366076Scy      appendText(&s, ".sqlite_schema ", 0);
20008322444Speter      if( c=='t' ){
20009322444Speter        appendText(&s," WHERE type IN ('table','view')"
20010322444Speter                      "   AND name NOT LIKE 'sqlite_%'"
20011322444Speter                      "   AND name LIKE ?1", 0);
20012322444Speter      }else{
20013322444Speter        appendText(&s," WHERE type='index'"
20014322444Speter                      "   AND tbl_name LIKE ?1", 0);
20015322444Speter      }
20016251883Speter    }
20017298161Sbapt    rc = sqlite3_finalize(pStmt);
20018322444Speter    appendText(&s, " ORDER BY 1", 0);
20019322444Speter    rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
20020322444Speter    freeText(&s);
20021298161Sbapt    if( rc ) return shellDatabaseError(p->db);
20022298161Sbapt
20023298161Sbapt    /* Run the SQL statement prepared by the above block. Store the results
20024298161Sbapt    ** as an array of nul-terminated strings in azResult[].  */
20025251883Speter    nRow = nAlloc = 0;
20026251883Speter    azResult = 0;
20027251883Speter    if( nArg>1 ){
20028251883Speter      sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
20029251883Speter    }else{
20030251883Speter      sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
20031251883Speter    }
20032251883Speter    while( sqlite3_step(pStmt)==SQLITE_ROW ){
20033251883Speter      if( nRow>=nAlloc ){
20034251883Speter        char **azNew;
20035286510Speter        int n2 = nAlloc*2 + 10;
20036286510Speter        azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
20037342292Scy        if( azNew==0 ) shell_out_of_memory();
20038286510Speter        nAlloc = n2;
20039251883Speter        azResult = azNew;
20040251883Speter      }
20041251883Speter      azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
20042342292Scy      if( 0==azResult[nRow] ) shell_out_of_memory();
20043298161Sbapt      nRow++;
20044251883Speter    }
20045298161Sbapt    if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
20046298161Sbapt      rc = shellDatabaseError(p->db);
20047298161Sbapt    }
20048298161Sbapt
20049298161Sbapt    /* Pretty-print the contents of array azResult[] to the output */
20050298161Sbapt    if( rc==0 && nRow>0 ){
20051251883Speter      int len, maxlen = 0;
20052251883Speter      int i, j;
20053251883Speter      int nPrintCol, nPrintRow;
20054251883Speter      for(i=0; i<nRow; i++){
20055251883Speter        len = strlen30(azResult[i]);
20056251883Speter        if( len>maxlen ) maxlen = len;
20057251883Speter      }
20058251883Speter      nPrintCol = 80/(maxlen+2);
20059251883Speter      if( nPrintCol<1 ) nPrintCol = 1;
20060251883Speter      nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
20061251883Speter      for(i=0; i<nPrintRow; i++){
20062251883Speter        for(j=i; j<nRow; j+=nPrintRow){
20063251883Speter          char *zSp = j<nPrintRow ? "" : "  ";
20064298161Sbapt          utf8_printf(p->out, "%s%-*s", zSp, maxlen,
20065298161Sbapt                      azResult[j] ? azResult[j]:"");
20066251883Speter        }
20067298161Sbapt        raw_printf(p->out, "\n");
20068251883Speter      }
20069251883Speter    }
20070298161Sbapt
20071251883Speter    for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
20072251883Speter    sqlite3_free(azResult);
20073251883Speter  }else
20074251883Speter
20075322444Speter  /* Begin redirecting output to the file "testcase-out.txt" */
20076322444Speter  if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
20077322444Speter    output_reset(p);
20078342292Scy    p->out = output_file_open("testcase-out.txt", 0);
20079322444Speter    if( p->out==0 ){
20080322444Speter      raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
20081322444Speter    }
20082322444Speter    if( nArg>=2 ){
20083322444Speter      sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
20084322444Speter    }else{
20085322444Speter      sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
20086322444Speter    }
20087322444Speter  }else
20088322444Speter
20089322444Speter#ifndef SQLITE_UNTESTABLE
20090342292Scy  if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
20091251883Speter    static const struct {
20092251883Speter       const char *zCtrlName;   /* Name of a test-control option */
20093251883Speter       int ctrlCode;            /* Integer code for that option */
20094342292Scy       const char *zUsage;      /* Usage notes */
20095251883Speter    } aCtrl[] = {
20096355326Scy      { "always",             SQLITE_TESTCTRL_ALWAYS,        "BOOLEAN"        },
20097355326Scy      { "assert",             SQLITE_TESTCTRL_ASSERT,        "BOOLEAN"        },
20098355326Scy    /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, ""       },*/
20099355326Scy    /*{ "bitvec_test",        SQLITE_TESTCTRL_BITVEC_TEST,   ""             },*/
20100355326Scy      { "byteorder",          SQLITE_TESTCTRL_BYTEORDER,     ""               },
20101355326Scy      { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN"   },
20102355326Scy    /*{ "fault_install",      SQLITE_TESTCTRL_FAULT_INSTALL, ""             },*/
20103355326Scy      { "imposter",         SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
20104361456Scy      { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "" },
20105355326Scy      { "localtime_fault",    SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN"       },
20106355326Scy      { "never_corrupt",      SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN"        },
20107355326Scy      { "optimizations",      SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK"   },
20108342292Scy#ifdef YYCOVERAGE
20109355326Scy      { "parser_coverage",    SQLITE_TESTCTRL_PARSER_COVERAGE, ""             },
20110342292Scy#endif
20111355326Scy      { "pending_byte",       SQLITE_TESTCTRL_PENDING_BYTE,  "OFFSET  "       },
20112355326Scy      { "prng_restore",       SQLITE_TESTCTRL_PRNG_RESTORE,  ""               },
20113355326Scy      { "prng_save",          SQLITE_TESTCTRL_PRNG_SAVE,     ""               },
20114355326Scy      { "prng_seed",          SQLITE_TESTCTRL_PRNG_SEED,     "SEED ?db?"      },
20115369950Scy      { "seek_count",         SQLITE_TESTCTRL_SEEK_COUNT,    ""               },
20116251883Speter    };
20117251883Speter    int testctrl = -1;
20118342292Scy    int iCtrl = -1;
20119342292Scy    int rc2 = 0;    /* 0: usage.  1: %d  2: %x  3: no-output */
20120342292Scy    int isOk = 0;
20121286510Speter    int i, n2;
20122342292Scy    const char *zCmd = 0;
20123342292Scy
20124269851Speter    open_db(p, 0);
20125342292Scy    zCmd = nArg>=2 ? azArg[1] : "help";
20126251883Speter
20127342292Scy    /* The argument can optionally begin with "-" or "--" */
20128342292Scy    if( zCmd[0]=='-' && zCmd[1] ){
20129342292Scy      zCmd++;
20130342292Scy      if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
20131342292Scy    }
20132342292Scy
20133342292Scy    /* --help lists all test-controls */
20134342292Scy    if( strcmp(zCmd,"help")==0 ){
20135342292Scy      utf8_printf(p->out, "Available test-controls:\n");
20136342292Scy      for(i=0; i<ArraySize(aCtrl); i++){
20137342292Scy        utf8_printf(p->out, "  .testctrl %s %s\n",
20138342292Scy                    aCtrl[i].zCtrlName, aCtrl[i].zUsage);
20139342292Scy      }
20140342292Scy      rc = 1;
20141342292Scy      goto meta_command_exit;
20142342292Scy    }
20143342292Scy
20144251883Speter    /* convert testctrl text option to value. allow any unique prefix
20145251883Speter    ** of the option name, or a numerical value. */
20146342292Scy    n2 = strlen30(zCmd);
20147286510Speter    for(i=0; i<ArraySize(aCtrl); i++){
20148342292Scy      if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
20149251883Speter        if( testctrl<0 ){
20150251883Speter          testctrl = aCtrl[i].ctrlCode;
20151342292Scy          iCtrl = i;
20152251883Speter        }else{
20153342292Scy          utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
20154342292Scy                              "Use \".testctrl --help\" for help\n", zCmd);
20155342292Scy          rc = 1;
20156342292Scy          goto meta_command_exit;
20157251883Speter        }
20158251883Speter      }
20159251883Speter    }
20160342292Scy    if( testctrl<0 ){
20161342292Scy      utf8_printf(stderr,"Error: unknown test-control: %s\n"
20162342292Scy                         "Use \".testctrl --help\" for help\n", zCmd);
20163251883Speter    }else{
20164251883Speter      switch(testctrl){
20165251883Speter
20166251883Speter        /* sqlite3_test_control(int, db, int) */
20167251883Speter        case SQLITE_TESTCTRL_OPTIMIZATIONS:
20168251883Speter          if( nArg==3 ){
20169369951Scy            unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
20170286510Speter            rc2 = sqlite3_test_control(testctrl, p->db, opt);
20171342292Scy            isOk = 3;
20172251883Speter          }
20173251883Speter          break;
20174251883Speter
20175251883Speter        /* sqlite3_test_control(int) */
20176269851Speter        case SQLITE_TESTCTRL_PRNG_SAVE:
20177269851Speter        case SQLITE_TESTCTRL_PRNG_RESTORE:
20178269851Speter        case SQLITE_TESTCTRL_BYTEORDER:
20179251883Speter          if( nArg==2 ){
20180286510Speter            rc2 = sqlite3_test_control(testctrl);
20181342292Scy            isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
20182251883Speter          }
20183251883Speter          break;
20184251883Speter
20185251883Speter        /* sqlite3_test_control(int, uint) */
20186305002Scy        case SQLITE_TESTCTRL_PENDING_BYTE:
20187251883Speter          if( nArg==3 ){
20188269851Speter            unsigned int opt = (unsigned int)integerValue(azArg[2]);
20189286510Speter            rc2 = sqlite3_test_control(testctrl, opt);
20190342292Scy            isOk = 3;
20191251883Speter          }
20192251883Speter          break;
20193305002Scy
20194355326Scy        /* sqlite3_test_control(int, int, sqlite3*) */
20195355326Scy        case SQLITE_TESTCTRL_PRNG_SEED:
20196355326Scy          if( nArg==3 || nArg==4 ){
20197355326Scy            int ii = (int)integerValue(azArg[2]);
20198355326Scy            sqlite3 *db;
20199355326Scy            if( ii==0 && strcmp(azArg[2],"random")==0 ){
20200355326Scy              sqlite3_randomness(sizeof(ii),&ii);
20201355326Scy              printf("-- random seed: %d\n", ii);
20202355326Scy            }
20203355326Scy            if( nArg==3 ){
20204355326Scy              db = 0;
20205355326Scy            }else{
20206355326Scy              db = p->db;
20207355326Scy              /* Make sure the schema has been loaded */
20208355326Scy              sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);
20209355326Scy            }
20210355326Scy            rc2 = sqlite3_test_control(testctrl, ii, db);
20211355326Scy            isOk = 3;
20212355326Scy          }
20213355326Scy          break;
20214355326Scy
20215251883Speter        /* sqlite3_test_control(int, int) */
20216305002Scy        case SQLITE_TESTCTRL_ASSERT:
20217305002Scy        case SQLITE_TESTCTRL_ALWAYS:
20218251883Speter          if( nArg==3 ){
20219305002Scy            int opt = booleanValue(azArg[2]);
20220286510Speter            rc2 = sqlite3_test_control(testctrl, opt);
20221342292Scy            isOk = 1;
20222251883Speter          }
20223251883Speter          break;
20224251883Speter
20225342292Scy        /* sqlite3_test_control(int, int) */
20226342292Scy        case SQLITE_TESTCTRL_LOCALTIME_FAULT:
20227342292Scy        case SQLITE_TESTCTRL_NEVER_CORRUPT:
20228251883Speter          if( nArg==3 ){
20229342292Scy            int opt = booleanValue(azArg[2]);
20230286510Speter            rc2 = sqlite3_test_control(testctrl, opt);
20231342292Scy            isOk = 3;
20232251883Speter          }
20233251883Speter          break;
20234251883Speter
20235361456Scy        /* sqlite3_test_control(sqlite3*) */
20236361456Scy        case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
20237361456Scy          rc2 = sqlite3_test_control(testctrl, p->db);
20238361456Scy          isOk = 3;
20239361456Scy          break;
20240361456Scy
20241282328Sbapt        case SQLITE_TESTCTRL_IMPOSTER:
20242282328Sbapt          if( nArg==5 ){
20243305002Scy            rc2 = sqlite3_test_control(testctrl, p->db,
20244282328Sbapt                          azArg[2],
20245282328Sbapt                          integerValue(azArg[3]),
20246282328Sbapt                          integerValue(azArg[4]));
20247342292Scy            isOk = 3;
20248282328Sbapt          }
20249282328Sbapt          break;
20250282328Sbapt
20251369950Scy        case SQLITE_TESTCTRL_SEEK_COUNT: {
20252369950Scy          u64 x = 0;
20253369950Scy          rc2 = sqlite3_test_control(testctrl, p->db, &x);
20254369950Scy          utf8_printf(p->out, "%llu\n", x);
20255369950Scy          isOk = 3;
20256369950Scy          break;
20257369950Scy        }
20258369950Scy
20259342292Scy#ifdef YYCOVERAGE
20260342292Scy        case SQLITE_TESTCTRL_PARSER_COVERAGE:
20261342292Scy          if( nArg==2 ){
20262342292Scy            sqlite3_test_control(testctrl, p->out);
20263342292Scy            isOk = 3;
20264342292Scy          }
20265342292Scy#endif
20266251883Speter      }
20267251883Speter    }
20268342292Scy    if( isOk==0 && iCtrl>=0 ){
20269355326Scy      utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
20270342292Scy      rc = 1;
20271342292Scy    }else if( isOk==1 ){
20272342292Scy      raw_printf(p->out, "%d\n", rc2);
20273342292Scy    }else if( isOk==2 ){
20274342292Scy      raw_printf(p->out, "0x%08x\n", rc2);
20275342292Scy    }
20276251883Speter  }else
20277322444Speter#endif /* !defined(SQLITE_UNTESTABLE) */
20278251883Speter
20279269851Speter  if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
20280269851Speter    open_db(p, 0);
20281269851Speter    sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
20282251883Speter  }else
20283305002Scy
20284269851Speter  if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
20285269851Speter    if( nArg==2 ){
20286269851Speter      enableTimer = booleanValue(azArg[1]);
20287269851Speter      if( enableTimer && !HAS_TIMER ){
20288298161Sbapt        raw_printf(stderr, "Error: timer not available on this system.\n");
20289269851Speter        enableTimer = 0;
20290269851Speter      }
20291269851Speter    }else{
20292298161Sbapt      raw_printf(stderr, "Usage: .timer on|off\n");
20293269851Speter      rc = 1;
20294269851Speter    }
20295251883Speter  }else
20296305002Scy
20297346442Scy#ifndef SQLITE_OMIT_TRACE
20298269851Speter  if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
20299346442Scy    int mType = 0;
20300346442Scy    int jj;
20301269851Speter    open_db(p, 0);
20302346442Scy    for(jj=1; jj<nArg; jj++){
20303346442Scy      const char *z = azArg[jj];
20304346442Scy      if( z[0]=='-' ){
20305346442Scy        if( optionMatch(z, "expanded") ){
20306346442Scy          p->eTraceType = SHELL_TRACE_EXPANDED;
20307346442Scy        }
20308346442Scy#ifdef SQLITE_ENABLE_NORMALIZE
20309346442Scy        else if( optionMatch(z, "normalized") ){
20310346442Scy          p->eTraceType = SHELL_TRACE_NORMALIZED;
20311346442Scy        }
20312346442Scy#endif
20313346442Scy        else if( optionMatch(z, "plain") ){
20314346442Scy          p->eTraceType = SHELL_TRACE_PLAIN;
20315346442Scy        }
20316346442Scy        else if( optionMatch(z, "profile") ){
20317346442Scy          mType |= SQLITE_TRACE_PROFILE;
20318346442Scy        }
20319346442Scy        else if( optionMatch(z, "row") ){
20320346442Scy          mType |= SQLITE_TRACE_ROW;
20321346442Scy        }
20322346442Scy        else if( optionMatch(z, "stmt") ){
20323346442Scy          mType |= SQLITE_TRACE_STMT;
20324346442Scy        }
20325346442Scy        else if( optionMatch(z, "close") ){
20326346442Scy          mType |= SQLITE_TRACE_CLOSE;
20327346442Scy        }
20328346442Scy        else {
20329346442Scy          raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
20330346442Scy          rc = 1;
20331346442Scy          goto meta_command_exit;
20332346442Scy        }
20333346442Scy      }else{
20334346442Scy        output_file_close(p->traceOut);
20335346442Scy        p->traceOut = output_file_open(azArg[1], 0);
20336346442Scy      }
20337269851Speter    }
20338251883Speter    if( p->traceOut==0 ){
20339305002Scy      sqlite3_trace_v2(p->db, 0, 0, 0);
20340251883Speter    }else{
20341346442Scy      if( mType==0 ) mType = SQLITE_TRACE_STMT;
20342346442Scy      sqlite3_trace_v2(p->db, mType, sql_trace_callback, p);
20343251883Speter    }
20344251883Speter  }else
20345346442Scy#endif /* !defined(SQLITE_OMIT_TRACE) */
20346251883Speter
20347355326Scy#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
20348355326Scy  if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){
20349355326Scy    int ii;
20350355326Scy    int lenOpt;
20351355326Scy    char *zOpt;
20352355326Scy    if( nArg<2 ){
20353355326Scy      raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
20354355326Scy      rc = 1;
20355355326Scy      goto meta_command_exit;
20356355326Scy    }
20357355326Scy    open_db(p, 0);
20358355326Scy    zOpt = azArg[1];
20359355326Scy    if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
20360355326Scy    lenOpt = (int)strlen(zOpt);
20361355326Scy    if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){
20362355326Scy      assert( azArg[nArg]==0 );
20363355326Scy      sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0);
20364355326Scy    }else{
20365355326Scy      for(ii=1; ii<nArg; ii++){
20366355326Scy        sqlite3_create_module(p->db, azArg[ii], 0, 0);
20367355326Scy      }
20368355326Scy    }
20369355326Scy  }else
20370355326Scy#endif
20371355326Scy
20372274884Sbapt#if SQLITE_USER_AUTHENTICATION
20373274884Sbapt  if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
20374274884Sbapt    if( nArg<2 ){
20375298161Sbapt      raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
20376274884Sbapt      rc = 1;
20377274884Sbapt      goto meta_command_exit;
20378274884Sbapt    }
20379274884Sbapt    open_db(p, 0);
20380274884Sbapt    if( strcmp(azArg[1],"login")==0 ){
20381274884Sbapt      if( nArg!=4 ){
20382298161Sbapt        raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
20383274884Sbapt        rc = 1;
20384274884Sbapt        goto meta_command_exit;
20385274884Sbapt      }
20386355326Scy      rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
20387355326Scy                                     strlen30(azArg[3]));
20388274884Sbapt      if( rc ){
20389298161Sbapt        utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
20390274884Sbapt        rc = 1;
20391274884Sbapt      }
20392274884Sbapt    }else if( strcmp(azArg[1],"add")==0 ){
20393274884Sbapt      if( nArg!=5 ){
20394298161Sbapt        raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
20395274884Sbapt        rc = 1;
20396274884Sbapt        goto meta_command_exit;
20397274884Sbapt      }
20398342292Scy      rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
20399274884Sbapt                            booleanValue(azArg[4]));
20400274884Sbapt      if( rc ){
20401298161Sbapt        raw_printf(stderr, "User-Add failed: %d\n", rc);
20402274884Sbapt        rc = 1;
20403274884Sbapt      }
20404274884Sbapt    }else if( strcmp(azArg[1],"edit")==0 ){
20405274884Sbapt      if( nArg!=5 ){
20406298161Sbapt        raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
20407274884Sbapt        rc = 1;
20408274884Sbapt        goto meta_command_exit;
20409274884Sbapt      }
20410342292Scy      rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
20411274884Sbapt                              booleanValue(azArg[4]));
20412274884Sbapt      if( rc ){
20413298161Sbapt        raw_printf(stderr, "User-Edit failed: %d\n", rc);
20414274884Sbapt        rc = 1;
20415274884Sbapt      }
20416274884Sbapt    }else if( strcmp(azArg[1],"delete")==0 ){
20417274884Sbapt      if( nArg!=3 ){
20418298161Sbapt        raw_printf(stderr, "Usage: .user delete USER\n");
20419274884Sbapt        rc = 1;
20420274884Sbapt        goto meta_command_exit;
20421274884Sbapt      }
20422274884Sbapt      rc = sqlite3_user_delete(p->db, azArg[2]);
20423274884Sbapt      if( rc ){
20424298161Sbapt        raw_printf(stderr, "User-Delete failed: %d\n", rc);
20425274884Sbapt        rc = 1;
20426274884Sbapt      }
20427274884Sbapt    }else{
20428298161Sbapt      raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
20429274884Sbapt      rc = 1;
20430274884Sbapt      goto meta_command_exit;
20431305002Scy    }
20432274884Sbapt  }else
20433274884Sbapt#endif /* SQLITE_USER_AUTHENTICATION */
20434274884Sbapt
20435251883Speter  if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
20436298161Sbapt    utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
20437251883Speter        sqlite3_libversion(), sqlite3_sourceid());
20438342292Scy#if SQLITE_HAVE_ZLIB
20439342292Scy    utf8_printf(p->out, "zlib version %s\n", zlibVersion());
20440342292Scy#endif
20441342292Scy#define CTIMEOPT_VAL_(opt) #opt
20442342292Scy#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
20443342292Scy#if defined(__clang__) && defined(__clang_major__)
20444342292Scy    utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
20445342292Scy                    CTIMEOPT_VAL(__clang_minor__) "."
20446342292Scy                    CTIMEOPT_VAL(__clang_patchlevel__) "\n");
20447342292Scy#elif defined(_MSC_VER)
20448342292Scy    utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n");
20449342292Scy#elif defined(__GNUC__) && defined(__VERSION__)
20450342292Scy    utf8_printf(p->out, "gcc-" __VERSION__ "\n");
20451342292Scy#endif
20452251883Speter  }else
20453251883Speter
20454298161Sbapt  if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
20455298161Sbapt    const char *zDbName = nArg==2 ? azArg[1] : "main";
20456322444Speter    sqlite3_vfs *pVfs = 0;
20457298161Sbapt    if( p->db ){
20458298161Sbapt      sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
20459298161Sbapt      if( pVfs ){
20460298161Sbapt        utf8_printf(p->out, "vfs.zName      = \"%s\"\n", pVfs->zName);
20461298161Sbapt        raw_printf(p->out, "vfs.iVersion   = %d\n", pVfs->iVersion);
20462298161Sbapt        raw_printf(p->out, "vfs.szOsFile   = %d\n", pVfs->szOsFile);
20463298161Sbapt        raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
20464298161Sbapt      }
20465298161Sbapt    }
20466298161Sbapt  }else
20467298161Sbapt
20468298161Sbapt  if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){
20469298161Sbapt    sqlite3_vfs *pVfs;
20470298161Sbapt    sqlite3_vfs *pCurrent = 0;
20471298161Sbapt    if( p->db ){
20472298161Sbapt      sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
20473298161Sbapt    }
20474298161Sbapt    for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
20475298161Sbapt      utf8_printf(p->out, "vfs.zName      = \"%s\"%s\n", pVfs->zName,
20476298161Sbapt           pVfs==pCurrent ? "  <--- CURRENT" : "");
20477298161Sbapt      raw_printf(p->out, "vfs.iVersion   = %d\n", pVfs->iVersion);
20478298161Sbapt      raw_printf(p->out, "vfs.szOsFile   = %d\n", pVfs->szOsFile);
20479298161Sbapt      raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
20480298161Sbapt      if( pVfs->pNext ){
20481298161Sbapt        raw_printf(p->out, "-----------------------------------\n");
20482298161Sbapt      }
20483298161Sbapt    }
20484298161Sbapt  }else
20485298161Sbapt
20486251883Speter  if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
20487251883Speter    const char *zDbName = nArg==2 ? azArg[1] : "main";
20488251883Speter    char *zVfsName = 0;
20489251883Speter    if( p->db ){
20490251883Speter      sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
20491251883Speter      if( zVfsName ){
20492298161Sbapt        utf8_printf(p->out, "%s\n", zVfsName);
20493251883Speter        sqlite3_free(zVfsName);
20494251883Speter      }
20495251883Speter    }
20496251883Speter  }else
20497251883Speter
20498251883Speter  if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
20499369951Scy    unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
20500369951Scy    sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x);
20501251883Speter  }else
20502251883Speter
20503269851Speter  if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
20504251883Speter    int j;
20505251883Speter    assert( nArg<=ArraySize(azArg) );
20506366076Scy    p->nWidth = nArg-1;
20507366076Scy    p->colWidth = realloc(p->colWidth, p->nWidth*sizeof(int)*2);
20508366076Scy    if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory();
20509366076Scy    if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
20510366076Scy    for(j=1; j<nArg; j++){
20511269851Speter      p->colWidth[j-1] = (int)integerValue(azArg[j]);
20512251883Speter    }
20513251883Speter  }else
20514251883Speter
20515251883Speter  {
20516298161Sbapt    utf8_printf(stderr, "Error: unknown command or invalid arguments: "
20517251883Speter      " \"%s\". Enter \".help\" for help\n", azArg[0]);
20518251883Speter    rc = 1;
20519251883Speter  }
20520251883Speter
20521269851Spetermeta_command_exit:
20522269851Speter  if( p->outCount ){
20523269851Speter    p->outCount--;
20524269851Speter    if( p->outCount==0 ) output_reset(p);
20525269851Speter  }
20526251883Speter  return rc;
20527251883Speter}
20528251883Speter
20529251883Speter/*
20530251883Speter** Return TRUE if a semicolon occurs anywhere in the first N characters
20531251883Speter** of string z[].
20532251883Speter*/
20533269851Speterstatic int line_contains_semicolon(const char *z, int N){
20534251883Speter  int i;
20535251883Speter  for(i=0; i<N; i++){  if( z[i]==';' ) return 1; }
20536251883Speter  return 0;
20537251883Speter}
20538251883Speter
20539251883Speter/*
20540251883Speter** Test to see if a line consists entirely of whitespace.
20541251883Speter*/
20542251883Speterstatic int _all_whitespace(const char *z){
20543251883Speter  for(; *z; z++){
20544251883Speter    if( IsSpace(z[0]) ) continue;
20545251883Speter    if( *z=='/' && z[1]=='*' ){
20546251883Speter      z += 2;
20547251883Speter      while( *z && (*z!='*' || z[1]!='/') ){ z++; }
20548251883Speter      if( *z==0 ) return 0;
20549251883Speter      z++;
20550251883Speter      continue;
20551251883Speter    }
20552251883Speter    if( *z=='-' && z[1]=='-' ){
20553251883Speter      z += 2;
20554251883Speter      while( *z && *z!='\n' ){ z++; }
20555251883Speter      if( *z==0 ) return 1;
20556251883Speter      continue;
20557251883Speter    }
20558251883Speter    return 0;
20559251883Speter  }
20560251883Speter  return 1;
20561251883Speter}
20562251883Speter
20563251883Speter/*
20564251883Speter** Return TRUE if the line typed in is an SQL command terminator other
20565251883Speter** than a semi-colon.  The SQL Server style "go" command is understood
20566251883Speter** as is the Oracle "/".
20567251883Speter*/
20568269851Speterstatic int line_is_command_terminator(const char *zLine){
20569251883Speter  while( IsSpace(zLine[0]) ){ zLine++; };
20570251883Speter  if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ){
20571251883Speter    return 1;  /* Oracle */
20572251883Speter  }
20573251883Speter  if( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o'
20574251883Speter         && _all_whitespace(&zLine[2]) ){
20575251883Speter    return 1;  /* SQL Server */
20576251883Speter  }
20577251883Speter  return 0;
20578251883Speter}
20579251883Speter
20580251883Speter/*
20581342292Scy** We need a default sqlite3_complete() implementation to use in case
20582342292Scy** the shell is compiled with SQLITE_OMIT_COMPLETE.  The default assumes
20583342292Scy** any arbitrary text is a complete SQL statement.  This is not very
20584342292Scy** user-friendly, but it does seem to work.
20585342292Scy*/
20586342292Scy#ifdef SQLITE_OMIT_COMPLETE
20587342292Scy#define sqlite3_complete(x) 1
20588342292Scy#endif
20589342292Scy
20590342292Scy/*
20591251883Speter** Return true if zSql is a complete SQL statement.  Return false if it
20592251883Speter** ends in the middle of a string literal or C-style comment.
20593251883Speter*/
20594269851Speterstatic int line_is_complete(char *zSql, int nSql){
20595251883Speter  int rc;
20596251883Speter  if( zSql==0 ) return 1;
20597251883Speter  zSql[nSql] = ';';
20598251883Speter  zSql[nSql+1] = 0;
20599251883Speter  rc = sqlite3_complete(zSql);
20600251883Speter  zSql[nSql] = 0;
20601251883Speter  return rc;
20602251883Speter}
20603251883Speter
20604251883Speter/*
20605342292Scy** Run a single line of SQL.  Return the number of errors.
20606322444Speter*/
20607322444Speterstatic int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
20608322444Speter  int rc;
20609322444Speter  char *zErrMsg = 0;
20610322444Speter
20611322444Speter  open_db(p, 0);
20612322444Speter  if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
20613346442Scy  if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
20614322444Speter  BEGIN_TIMER;
20615342292Scy  rc = shell_exec(p, zSql, &zErrMsg);
20616322444Speter  END_TIMER;
20617322444Speter  if( rc || zErrMsg ){
20618322444Speter    char zPrefix[100];
20619322444Speter    if( in!=0 || !stdin_is_interactive ){
20620322444Speter      sqlite3_snprintf(sizeof(zPrefix), zPrefix,
20621322444Speter                       "Error: near line %d:", startline);
20622322444Speter    }else{
20623322444Speter      sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
20624322444Speter    }
20625322444Speter    if( zErrMsg!=0 ){
20626322444Speter      utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
20627322444Speter      sqlite3_free(zErrMsg);
20628322444Speter      zErrMsg = 0;
20629322444Speter    }else{
20630322444Speter      utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
20631322444Speter    }
20632322444Speter    return 1;
20633322444Speter  }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
20634322444Speter    raw_printf(p->out, "changes: %3d   total_changes: %d\n",
20635322444Speter            sqlite3_changes(p->db), sqlite3_total_changes(p->db));
20636322444Speter  }
20637322444Speter  return 0;
20638322444Speter}
20639322444Speter
20640322444Speter
20641322444Speter/*
20642251883Speter** Read input from *in and process it.  If *in==0 then input
20643251883Speter** is interactive - the user is typing it it.  Otherwise, input
20644251883Speter** is coming from a file or device.  A prompt is issued and history
20645251883Speter** is saved only if input is interactive.  An interrupt signal will
20646251883Speter** cause this routine to exit immediately, unless input is interactive.
20647251883Speter**
20648251883Speter** Return the number of errors.
20649251883Speter*/
20650346442Scystatic int process_input(ShellState *p){
20651269851Speter  char *zLine = 0;          /* A single input line */
20652269851Speter  char *zSql = 0;           /* Accumulated SQL text */
20653269851Speter  int nLine;                /* Length of current line */
20654269851Speter  int nSql = 0;             /* Bytes of zSql[] used */
20655269851Speter  int nAlloc = 0;           /* Allocated zSql[] space */
20656269851Speter  int nSqlPrior = 0;        /* Bytes of zSql[] used by prior line */
20657269851Speter  int rc;                   /* Error code */
20658269851Speter  int errCnt = 0;           /* Number of errors seen */
20659269851Speter  int startline = 0;        /* Line number for start of current input */
20660251883Speter
20661346442Scy  p->lineno = 0;
20662346442Scy  while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
20663251883Speter    fflush(p->out);
20664346442Scy    zLine = one_input_line(p->in, zLine, nSql>0);
20665251883Speter    if( zLine==0 ){
20666251883Speter      /* End of input */
20667346442Scy      if( p->in==0 && stdin_is_interactive ) printf("\n");
20668251883Speter      break;
20669251883Speter    }
20670251883Speter    if( seenInterrupt ){
20671346442Scy      if( p->in!=0 ) break;
20672251883Speter      seenInterrupt = 0;
20673251883Speter    }
20674346442Scy    p->lineno++;
20675269851Speter    if( nSql==0 && _all_whitespace(zLine) ){
20676322444Speter      if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
20677269851Speter      continue;
20678269851Speter    }
20679342292Scy    if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
20680322444Speter      if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
20681342292Scy      if( zLine[0]=='.' ){
20682342292Scy        rc = do_meta_command(zLine, p);
20683342292Scy        if( rc==2 ){ /* exit requested */
20684342292Scy          break;
20685342292Scy        }else if( rc ){
20686342292Scy          errCnt++;
20687342292Scy        }
20688251883Speter      }
20689251883Speter      continue;
20690251883Speter    }
20691269851Speter    if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){
20692251883Speter      memcpy(zLine,";",2);
20693251883Speter    }
20694269851Speter    nLine = strlen30(zLine);
20695269851Speter    if( nSql+nLine+2>=nAlloc ){
20696269851Speter      nAlloc = nSql+nLine+100;
20697269851Speter      zSql = realloc(zSql, nAlloc);
20698342292Scy      if( zSql==0 ) shell_out_of_memory();
20699269851Speter    }
20700251883Speter    nSqlPrior = nSql;
20701269851Speter    if( nSql==0 ){
20702251883Speter      int i;
20703251883Speter      for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
20704269851Speter      assert( nAlloc>0 && zSql!=0 );
20705269851Speter      memcpy(zSql, zLine+i, nLine+1-i);
20706346442Scy      startline = p->lineno;
20707269851Speter      nSql = nLine-i;
20708251883Speter    }else{
20709251883Speter      zSql[nSql++] = '\n';
20710269851Speter      memcpy(zSql+nSql, zLine, nLine+1);
20711269851Speter      nSql += nLine;
20712251883Speter    }
20713269851Speter    if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
20714251883Speter                && sqlite3_complete(zSql) ){
20715346442Scy      errCnt += runOneSqlLine(p, zSql, p->in, startline);
20716251883Speter      nSql = 0;
20717269851Speter      if( p->outCount ){
20718269851Speter        output_reset(p);
20719269851Speter        p->outCount = 0;
20720342292Scy      }else{
20721342292Scy        clearTempFile(p);
20722269851Speter      }
20723269851Speter    }else if( nSql && _all_whitespace(zSql) ){
20724322444Speter      if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
20725251883Speter      nSql = 0;
20726251883Speter    }
20727251883Speter  }
20728322444Speter  if( nSql && !_all_whitespace(zSql) ){
20729346442Scy    errCnt += runOneSqlLine(p, zSql, p->in, startline);
20730251883Speter  }
20731298161Sbapt  free(zSql);
20732251883Speter  free(zLine);
20733251883Speter  return errCnt>0;
20734251883Speter}
20735251883Speter
20736251883Speter/*
20737251883Speter** Return a pathname which is the user's home directory.  A
20738251883Speter** 0 return indicates an error of some kind.
20739251883Speter*/
20740322444Speterstatic char *find_home_dir(int clearFlag){
20741251883Speter  static char *home_dir = NULL;
20742322444Speter  if( clearFlag ){
20743322444Speter    free(home_dir);
20744322444Speter    home_dir = 0;
20745322444Speter    return 0;
20746322444Speter  }
20747251883Speter  if( home_dir ) return home_dir;
20748251883Speter
20749282328Sbapt#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
20750282328Sbapt     && !defined(__RTP__) && !defined(_WRS_KERNEL)
20751251883Speter  {
20752251883Speter    struct passwd *pwent;
20753251883Speter    uid_t uid = getuid();
20754251883Speter    if( (pwent=getpwuid(uid)) != NULL) {
20755251883Speter      home_dir = pwent->pw_dir;
20756251883Speter    }
20757251883Speter  }
20758251883Speter#endif
20759251883Speter
20760251883Speter#if defined(_WIN32_WCE)
20761251883Speter  /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
20762251883Speter   */
20763251883Speter  home_dir = "/";
20764251883Speter#else
20765251883Speter
20766251883Speter#if defined(_WIN32) || defined(WIN32)
20767251883Speter  if (!home_dir) {
20768251883Speter    home_dir = getenv("USERPROFILE");
20769251883Speter  }
20770251883Speter#endif
20771251883Speter
20772251883Speter  if (!home_dir) {
20773251883Speter    home_dir = getenv("HOME");
20774251883Speter  }
20775251883Speter
20776251883Speter#if defined(_WIN32) || defined(WIN32)
20777251883Speter  if (!home_dir) {
20778251883Speter    char *zDrive, *zPath;
20779251883Speter    int n;
20780251883Speter    zDrive = getenv("HOMEDRIVE");
20781251883Speter    zPath = getenv("HOMEPATH");
20782251883Speter    if( zDrive && zPath ){
20783251883Speter      n = strlen30(zDrive) + strlen30(zPath) + 1;
20784251883Speter      home_dir = malloc( n );
20785251883Speter      if( home_dir==0 ) return 0;
20786251883Speter      sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
20787251883Speter      return home_dir;
20788251883Speter    }
20789251883Speter    home_dir = "c:\\";
20790251883Speter  }
20791251883Speter#endif
20792251883Speter
20793251883Speter#endif /* !_WIN32_WCE */
20794251883Speter
20795251883Speter  if( home_dir ){
20796251883Speter    int n = strlen30(home_dir) + 1;
20797251883Speter    char *z = malloc( n );
20798251883Speter    if( z ) memcpy(z, home_dir, n);
20799251883Speter    home_dir = z;
20800251883Speter  }
20801251883Speter
20802251883Speter  return home_dir;
20803251883Speter}
20804251883Speter
20805251883Speter/*
20806251883Speter** Read input from the file given by sqliterc_override.  Or if that
20807251883Speter** parameter is NULL, take input from ~/.sqliterc
20808251883Speter**
20809251883Speter** Returns the number of errors.
20810251883Speter*/
20811282328Sbaptstatic void process_sqliterc(
20812274884Sbapt  ShellState *p,                  /* Configuration data */
20813251883Speter  const char *sqliterc_override   /* Name of config file. NULL to use default */
20814251883Speter){
20815251883Speter  char *home_dir = NULL;
20816251883Speter  const char *sqliterc = sqliterc_override;
20817251883Speter  char *zBuf = 0;
20818346442Scy  FILE *inSaved = p->in;
20819346442Scy  int savedLineno = p->lineno;
20820251883Speter
20821251883Speter  if (sqliterc == NULL) {
20822322444Speter    home_dir = find_home_dir(0);
20823251883Speter    if( home_dir==0 ){
20824298161Sbapt      raw_printf(stderr, "-- warning: cannot find home directory;"
20825282328Sbapt                      " cannot read ~/.sqliterc\n");
20826282328Sbapt      return;
20827251883Speter    }
20828251883Speter    zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
20829251883Speter    sqliterc = zBuf;
20830251883Speter  }
20831346442Scy  p->in = fopen(sqliterc,"rb");
20832346442Scy  if( p->in ){
20833251883Speter    if( stdin_is_interactive ){
20834298161Sbapt      utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
20835251883Speter    }
20836369950Scy    if( process_input(p) && bail_on_error ) exit(1);
20837346442Scy    fclose(p->in);
20838369950Scy  }else if( sqliterc_override!=0 ){
20839369950Scy    utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
20840369950Scy    if( bail_on_error ) exit(1);
20841251883Speter  }
20842346442Scy  p->in = inSaved;
20843346442Scy  p->lineno = savedLineno;
20844251883Speter  sqlite3_free(zBuf);
20845251883Speter}
20846251883Speter
20847251883Speter/*
20848251883Speter** Show available command line options
20849251883Speter*/
20850305002Scystatic const char zOptions[] =
20851342292Scy#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
20852342292Scy  "   -A ARGS...           run \".archive ARGS\" and exit\n"
20853342292Scy#endif
20854342292Scy  "   -append              append the database to the end of the file\n"
20855282328Sbapt  "   -ascii               set output mode to 'ascii'\n"
20856251883Speter  "   -bail                stop after hitting an error\n"
20857251883Speter  "   -batch               force batch I/O\n"
20858366076Scy  "   -box                 set output mode to 'box'\n"
20859251883Speter  "   -column              set output mode to 'column'\n"
20860251883Speter  "   -cmd COMMAND         run \"COMMAND\" before reading stdin\n"
20861251883Speter  "   -csv                 set output mode to 'csv'\n"
20862346442Scy#if defined(SQLITE_ENABLE_DESERIALIZE)
20863346442Scy  "   -deserialize         open the database using sqlite3_deserialize()\n"
20864346442Scy#endif
20865251883Speter  "   -echo                print commands before execution\n"
20866251883Speter  "   -init FILENAME       read/process named file\n"
20867251883Speter  "   -[no]header          turn headers on or off\n"
20868251883Speter#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
20869251883Speter  "   -heap SIZE           Size of heap for memsys3 or memsys5\n"
20870251883Speter#endif
20871251883Speter  "   -help                show this message\n"
20872251883Speter  "   -html                set output mode to HTML\n"
20873251883Speter  "   -interactive         force interactive I/O\n"
20874366076Scy  "   -json                set output mode to 'json'\n"
20875251883Speter  "   -line                set output mode to 'line'\n"
20876251883Speter  "   -list                set output mode to 'list'\n"
20877274884Sbapt  "   -lookaside SIZE N    use N entries of SZ bytes for lookaside memory\n"
20878366076Scy  "   -markdown            set output mode to 'markdown'\n"
20879346442Scy#if defined(SQLITE_ENABLE_DESERIALIZE)
20880346442Scy  "   -maxsize N           maximum size for a --deserialize database\n"
20881346442Scy#endif
20882346442Scy  "   -memtrace            trace all memory allocations and deallocations\n"
20883251883Speter  "   -mmap N              default mmap size set to N\n"
20884251883Speter#ifdef SQLITE_ENABLE_MULTIPLEX
20885251883Speter  "   -multiplex           enable the multiplexor VFS\n"
20886251883Speter#endif
20887282328Sbapt  "   -newline SEP         set output row separator. Default: '\\n'\n"
20888361456Scy  "   -nofollow            refuse to open symbolic links to database files\n"
20889251883Speter  "   -nullvalue TEXT      set text string for NULL values. Default ''\n"
20890274884Sbapt  "   -pagecache SIZE N    use N slots of SZ bytes each for page cache memory\n"
20891322444Speter  "   -quote               set output mode to 'quote'\n"
20892342292Scy  "   -readonly            open the database read-only\n"
20893282328Sbapt  "   -separator SEP       set output column separator. Default: '|'\n"
20894342292Scy#ifdef SQLITE_ENABLE_SORTER_REFERENCES
20895342292Scy  "   -sorterref SIZE      sorter references threshold size\n"
20896342292Scy#endif
20897251883Speter  "   -stats               print memory stats before each finalize\n"
20898366076Scy  "   -table               set output mode to 'table'\n"
20899369950Scy  "   -tabs                set output mode to 'tabs'\n"
20900251883Speter  "   -version             show SQLite version\n"
20901251883Speter  "   -vfs NAME            use NAME as the default VFS\n"
20902251883Speter#ifdef SQLITE_ENABLE_VFSTRACE
20903251883Speter  "   -vfstrace            enable tracing of all VFS calls\n"
20904251883Speter#endif
20905342292Scy#ifdef SQLITE_HAVE_ZLIB
20906342292Scy  "   -zip                 open the file as a ZIP Archive\n"
20907342292Scy#endif
20908251883Speter;
20909251883Speterstatic void usage(int showDetail){
20910298161Sbapt  utf8_printf(stderr,
20911305002Scy      "Usage: %s [OPTIONS] FILENAME [SQL]\n"
20912251883Speter      "FILENAME is the name of an SQLite database. A new database is created\n"
20913251883Speter      "if the file does not previously exist.\n", Argv0);
20914251883Speter  if( showDetail ){
20915298161Sbapt    utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
20916251883Speter  }else{
20917298161Sbapt    raw_printf(stderr, "Use the -help option for additional information\n");
20918251883Speter  }
20919251883Speter  exit(1);
20920251883Speter}
20921251883Speter
20922251883Speter/*
20923342292Scy** Internal check:  Verify that the SQLite is uninitialized.  Print a
20924342292Scy** error message if it is initialized.
20925342292Scy*/
20926342292Scystatic void verify_uninitialized(void){
20927342292Scy  if( sqlite3_config(-1)==SQLITE_MISUSE ){
20928342292Scy    utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
20929342292Scy                        " initialization.\n");
20930342292Scy  }
20931342292Scy}
20932342292Scy
20933342292Scy/*
20934251883Speter** Initialize the state information in data
20935251883Speter*/
20936274884Sbaptstatic void main_init(ShellState *data) {
20937251883Speter  memset(data, 0, sizeof(*data));
20938298161Sbapt  data->normalMode = data->cMode = data->mode = MODE_List;
20939298161Sbapt  data->autoExplain = 1;
20940282328Sbapt  memcpy(data->colSeparator,SEP_Column, 2);
20941282328Sbapt  memcpy(data->rowSeparator,SEP_Row, 2);
20942251883Speter  data->showHeader = 0;
20943274884Sbapt  data->shellFlgs = SHFLG_Lookaside;
20944342292Scy  verify_uninitialized();
20945251883Speter  sqlite3_config(SQLITE_CONFIG_URI, 1);
20946251883Speter  sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
20947274884Sbapt  sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
20948251883Speter  sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
20949251883Speter  sqlite3_snprintf(sizeof(continuePrompt), continuePrompt,"   ...> ");
20950251883Speter}
20951251883Speter
20952251883Speter/*
20953269851Speter** Output text to the console in a font that attracts extra attention.
20954269851Speter*/
20955269851Speter#ifdef _WIN32
20956269851Speterstatic void printBold(const char *zText){
20957362190Scy#if !SQLITE_OS_WINRT
20958269851Speter  HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
20959269851Speter  CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
20960269851Speter  GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
20961269851Speter  SetConsoleTextAttribute(out,
20962269851Speter         FOREGROUND_RED|FOREGROUND_INTENSITY
20963269851Speter  );
20964362190Scy#endif
20965269851Speter  printf("%s", zText);
20966362190Scy#if !SQLITE_OS_WINRT
20967269851Speter  SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
20968362190Scy#endif
20969269851Speter}
20970269851Speter#else
20971269851Speterstatic void printBold(const char *zText){
20972269851Speter  printf("\033[1m%s\033[0m", zText);
20973269851Speter}
20974269851Speter#endif
20975269851Speter
20976269851Speter/*
20977251883Speter** Get the argument to an --option.  Throw an error and die if no argument
20978251883Speter** is available.
20979251883Speter*/
20980251883Speterstatic char *cmdline_option_value(int argc, char **argv, int i){
20981251883Speter  if( i==argc ){
20982298161Sbapt    utf8_printf(stderr, "%s: Error: missing argument to %s\n",
20983251883Speter            argv[0], argv[argc-1]);
20984251883Speter    exit(1);
20985251883Speter  }
20986251883Speter  return argv[i];
20987251883Speter}
20988251883Speter
20989305002Scy#ifndef SQLITE_SHELL_IS_UTF8
20990369951Scy#  if (defined(_WIN32) || defined(WIN32)) \
20991369951Scy   && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
20992305002Scy#    define SQLITE_SHELL_IS_UTF8          (0)
20993305002Scy#  else
20994305002Scy#    define SQLITE_SHELL_IS_UTF8          (1)
20995305002Scy#  endif
20996305002Scy#endif
20997305002Scy
20998305002Scy#if SQLITE_SHELL_IS_UTF8
20999282328Sbaptint SQLITE_CDECL main(int argc, char **argv){
21000305002Scy#else
21001305002Scyint SQLITE_CDECL wmain(int argc, wchar_t **wargv){
21002305002Scy  char **argv;
21003305002Scy#endif
21004251883Speter  char *zErrMsg = 0;
21005274884Sbapt  ShellState data;
21006251883Speter  const char *zInitFile = 0;
21007251883Speter  int i;
21008251883Speter  int rc = 0;
21009269851Speter  int warnInmemoryDb = 0;
21010282328Sbapt  int readStdin = 1;
21011282328Sbapt  int nCmd = 0;
21012282328Sbapt  char **azCmd = 0;
21013342292Scy  const char *zVfs = 0;           /* Value of -vfs command-line option */
21014342292Scy#if !SQLITE_SHELL_IS_UTF8
21015342292Scy  char **argvToFree = 0;
21016342292Scy  int argcToFree = 0;
21017342292Scy#endif
21018251883Speter
21019305002Scy  setBinaryMode(stdin, 0);
21020305002Scy  setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
21021305002Scy  stdin_is_interactive = isatty(0);
21022305002Scy  stdout_is_console = isatty(1);
21023305002Scy
21024362190Scy#ifdef SQLITE_DEBUG
21025362190Scy  registerOomSimulator();
21026362190Scy#endif
21027362190Scy
21028342292Scy#if !defined(_WIN32_WCE)
21029342292Scy  if( getenv("SQLITE_DEBUG_BREAK") ){
21030342292Scy    if( isatty(0) && isatty(2) ){
21031342292Scy      fprintf(stderr,
21032342292Scy          "attach debugger to process %d and press any key to continue.\n",
21033342292Scy          GETPID());
21034342292Scy      fgetc(stdin);
21035342292Scy    }else{
21036342292Scy#if defined(_WIN32) || defined(WIN32)
21037362190Scy#if SQLITE_OS_WINRT
21038362190Scy      __debugbreak();
21039362190Scy#else
21040342292Scy      DebugBreak();
21041362190Scy#endif
21042342292Scy#elif defined(SIGTRAP)
21043342292Scy      raise(SIGTRAP);
21044342292Scy#endif
21045342292Scy    }
21046342292Scy  }
21047342292Scy#endif
21048342292Scy
21049269851Speter#if USE_SYSTEM_SQLITE+0!=1
21050342292Scy  if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
21051298161Sbapt    utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
21052251883Speter            sqlite3_sourceid(), SQLITE_SOURCE_ID);
21053251883Speter    exit(1);
21054251883Speter  }
21055269851Speter#endif
21056305002Scy  main_init(&data);
21057342292Scy
21058342292Scy  /* On Windows, we must translate command-line arguments into UTF-8.
21059342292Scy  ** The SQLite memory allocator subsystem has to be enabled in order to
21060342292Scy  ** do this.  But we want to run an sqlite3_shutdown() afterwards so that
21061342292Scy  ** subsequent sqlite3_config() calls will work.  So copy all results into
21062342292Scy  ** memory that does not come from the SQLite memory allocator.
21063342292Scy  */
21064305002Scy#if !SQLITE_SHELL_IS_UTF8
21065305002Scy  sqlite3_initialize();
21066342292Scy  argvToFree = malloc(sizeof(argv[0])*argc*2);
21067342292Scy  argcToFree = argc;
21068342292Scy  argv = argvToFree + argc;
21069342292Scy  if( argv==0 ) shell_out_of_memory();
21070305002Scy  for(i=0; i<argc; i++){
21071342292Scy    char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
21072342292Scy    int n;
21073342292Scy    if( z==0 ) shell_out_of_memory();
21074342292Scy    n = (int)strlen(z);
21075342292Scy    argv[i] = malloc( n+1 );
21076342292Scy    if( argv[i]==0 ) shell_out_of_memory();
21077342292Scy    memcpy(argv[i], z, n+1);
21078342292Scy    argvToFree[i] = argv[i];
21079342292Scy    sqlite3_free(z);
21080305002Scy  }
21081342292Scy  sqlite3_shutdown();
21082305002Scy#endif
21083342292Scy
21084305002Scy  assert( argc>=1 && argv && argv[0] );
21085251883Speter  Argv0 = argv[0];
21086251883Speter
21087251883Speter  /* Make sure we have a valid signal handler early, before anything
21088251883Speter  ** else is done.
21089251883Speter  */
21090251883Speter#ifdef SIGINT
21091251883Speter  signal(SIGINT, interrupt_handler);
21092342292Scy#elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
21093342292Scy  SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
21094251883Speter#endif
21095251883Speter
21096282328Sbapt#ifdef SQLITE_SHELL_DBNAME_PROC
21097282328Sbapt  {
21098282328Sbapt    /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
21099282328Sbapt    ** of a C-function that will provide the name of the database file.  Use
21100282328Sbapt    ** this compile-time option to embed this shell program in larger
21101282328Sbapt    ** applications. */
21102282328Sbapt    extern void SQLITE_SHELL_DBNAME_PROC(const char**);
21103282328Sbapt    SQLITE_SHELL_DBNAME_PROC(&data.zDbFilename);
21104282328Sbapt    warnInmemoryDb = 0;
21105282328Sbapt  }
21106282328Sbapt#endif
21107282328Sbapt
21108251883Speter  /* Do an initial pass through the command-line argument to locate
21109251883Speter  ** the name of the database file, the name of the initialization file,
21110251883Speter  ** the size of the alternative malloc heap,
21111251883Speter  ** and the first command to execute.
21112251883Speter  */
21113342292Scy  verify_uninitialized();
21114251883Speter  for(i=1; i<argc; i++){
21115251883Speter    char *z;
21116251883Speter    z = argv[i];
21117251883Speter    if( z[0]!='-' ){
21118251883Speter      if( data.zDbFilename==0 ){
21119251883Speter        data.zDbFilename = z;
21120282328Sbapt      }else{
21121282328Sbapt        /* Excesss arguments are interpreted as SQL (or dot-commands) and
21122282328Sbapt        ** mean that nothing is read from stdin */
21123282328Sbapt        readStdin = 0;
21124282328Sbapt        nCmd++;
21125282328Sbapt        azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
21126342292Scy        if( azCmd==0 ) shell_out_of_memory();
21127282328Sbapt        azCmd[nCmd-1] = z;
21128251883Speter      }
21129251883Speter    }
21130251883Speter    if( z[1]=='-' ) z++;
21131251883Speter    if( strcmp(z,"-separator")==0
21132251883Speter     || strcmp(z,"-nullvalue")==0
21133274884Sbapt     || strcmp(z,"-newline")==0
21134251883Speter     || strcmp(z,"-cmd")==0
21135251883Speter    ){
21136251883Speter      (void)cmdline_option_value(argc, argv, ++i);
21137251883Speter    }else if( strcmp(z,"-init")==0 ){
21138251883Speter      zInitFile = cmdline_option_value(argc, argv, ++i);
21139251883Speter    }else if( strcmp(z,"-batch")==0 ){
21140251883Speter      /* Need to check for batch mode here to so we can avoid printing
21141305002Scy      ** informational messages (like from process_sqliterc) before
21142251883Speter      ** we do the actual processing of arguments later in a second pass.
21143251883Speter      */
21144251883Speter      stdin_is_interactive = 0;
21145251883Speter    }else if( strcmp(z,"-heap")==0 ){
21146251883Speter#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
21147251883Speter      const char *zSize;
21148251883Speter      sqlite3_int64 szHeap;
21149251883Speter
21150251883Speter      zSize = cmdline_option_value(argc, argv, ++i);
21151251883Speter      szHeap = integerValue(zSize);
21152251883Speter      if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
21153251883Speter      sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
21154305002Scy#else
21155305002Scy      (void)cmdline_option_value(argc, argv, ++i);
21156251883Speter#endif
21157274884Sbapt    }else if( strcmp(z,"-pagecache")==0 ){
21158369950Scy      sqlite3_int64 n, sz;
21159369950Scy      sz = integerValue(cmdline_option_value(argc,argv,++i));
21160274884Sbapt      if( sz>70000 ) sz = 70000;
21161298161Sbapt      if( sz<0 ) sz = 0;
21162369950Scy      n = integerValue(cmdline_option_value(argc,argv,++i));
21163369950Scy      if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
21164369950Scy        n = 0xffffffffffffLL/sz;
21165369950Scy      }
21166298161Sbapt      sqlite3_config(SQLITE_CONFIG_PAGECACHE,
21167298161Sbapt                    (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
21168274884Sbapt      data.shellFlgs |= SHFLG_Pagecache;
21169274884Sbapt    }else if( strcmp(z,"-lookaside")==0 ){
21170274884Sbapt      int n, sz;
21171274884Sbapt      sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
21172274884Sbapt      if( sz<0 ) sz = 0;
21173274884Sbapt      n = (int)integerValue(cmdline_option_value(argc,argv,++i));
21174274884Sbapt      if( n<0 ) n = 0;
21175274884Sbapt      sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
21176274884Sbapt      if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
21177251883Speter#ifdef SQLITE_ENABLE_VFSTRACE
21178251883Speter    }else if( strcmp(z,"-vfstrace")==0 ){
21179251883Speter      extern int vfstrace_register(
21180251883Speter         const char *zTraceName,
21181251883Speter         const char *zOldVfsName,
21182251883Speter         int (*xOut)(const char*,void*),
21183251883Speter         void *pOutArg,
21184251883Speter         int makeDefault
21185251883Speter      );
21186251883Speter      vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
21187251883Speter#endif
21188251883Speter#ifdef SQLITE_ENABLE_MULTIPLEX
21189251883Speter    }else if( strcmp(z,"-multiplex")==0 ){
21190251883Speter      extern int sqlite3_multiple_initialize(const char*,int);
21191251883Speter      sqlite3_multiplex_initialize(0, 1);
21192251883Speter#endif
21193251883Speter    }else if( strcmp(z,"-mmap")==0 ){
21194251883Speter      sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
21195251883Speter      sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
21196342292Scy#ifdef SQLITE_ENABLE_SORTER_REFERENCES
21197342292Scy    }else if( strcmp(z,"-sorterref")==0 ){
21198342292Scy      sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
21199342292Scy      sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz);
21200342292Scy#endif
21201251883Speter    }else if( strcmp(z,"-vfs")==0 ){
21202342292Scy      zVfs = cmdline_option_value(argc, argv, ++i);
21203342292Scy#ifdef SQLITE_HAVE_ZLIB
21204342292Scy    }else if( strcmp(z,"-zip")==0 ){
21205342292Scy      data.openMode = SHELL_OPEN_ZIPFILE;
21206342292Scy#endif
21207342292Scy    }else if( strcmp(z,"-append")==0 ){
21208342292Scy      data.openMode = SHELL_OPEN_APPENDVFS;
21209342292Scy#ifdef SQLITE_ENABLE_DESERIALIZE
21210342292Scy    }else if( strcmp(z,"-deserialize")==0 ){
21211342292Scy      data.openMode = SHELL_OPEN_DESERIALIZE;
21212346442Scy    }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
21213346442Scy      data.szMax = integerValue(argv[++i]);
21214342292Scy#endif
21215342292Scy    }else if( strcmp(z,"-readonly")==0 ){
21216342292Scy      data.openMode = SHELL_OPEN_READONLY;
21217361456Scy    }else if( strcmp(z,"-nofollow")==0 ){
21218361456Scy      data.openFlags = SQLITE_OPEN_NOFOLLOW;
21219342292Scy#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
21220342292Scy    }else if( strncmp(z, "-A",2)==0 ){
21221342292Scy      /* All remaining command-line arguments are passed to the ".archive"
21222342292Scy      ** command, so ignore them */
21223342292Scy      break;
21224342292Scy#endif
21225346442Scy    }else if( strcmp(z, "-memtrace")==0 ){
21226346442Scy      sqlite3MemTraceActivate(stderr);
21227369950Scy    }else if( strcmp(z,"-bail")==0 ){
21228369950Scy      bail_on_error = 1;
21229251883Speter    }
21230251883Speter  }
21231342292Scy  verify_uninitialized();
21232342292Scy
21233342292Scy
21234342292Scy#ifdef SQLITE_SHELL_INIT_PROC
21235342292Scy  {
21236342292Scy    /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name
21237342292Scy    ** of a C-function that will perform initialization actions on SQLite that
21238342292Scy    ** occur just before or after sqlite3_initialize(). Use this compile-time
21239342292Scy    ** option to embed this shell program in larger applications. */
21240342292Scy    extern void SQLITE_SHELL_INIT_PROC(void);
21241342292Scy    SQLITE_SHELL_INIT_PROC();
21242342292Scy  }
21243342292Scy#else
21244342292Scy  /* All the sqlite3_config() calls have now been made. So it is safe
21245342292Scy  ** to call sqlite3_initialize() and process any command line -vfs option. */
21246342292Scy  sqlite3_initialize();
21247342292Scy#endif
21248342292Scy
21249342292Scy  if( zVfs ){
21250342292Scy    sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
21251342292Scy    if( pVfs ){
21252342292Scy      sqlite3_vfs_register(pVfs, 1);
21253342292Scy    }else{
21254342292Scy      utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
21255342292Scy      exit(1);
21256342292Scy    }
21257342292Scy  }
21258342292Scy
21259251883Speter  if( data.zDbFilename==0 ){
21260251883Speter#ifndef SQLITE_OMIT_MEMORYDB
21261251883Speter    data.zDbFilename = ":memory:";
21262269851Speter    warnInmemoryDb = argc==1;
21263251883Speter#else
21264298161Sbapt    utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
21265251883Speter    return 1;
21266251883Speter#endif
21267251883Speter  }
21268251883Speter  data.out = stdout;
21269342292Scy  sqlite3_appendvfs_init(0,0,0);
21270251883Speter
21271251883Speter  /* Go ahead and open the database file if it already exists.  If the
21272251883Speter  ** file does not exist, delay opening it.  This prevents empty database
21273251883Speter  ** files from being created if a user mistypes the database name argument
21274251883Speter  ** to the sqlite command-line tool.
21275251883Speter  */
21276251883Speter  if( access(data.zDbFilename, 0)==0 ){
21277269851Speter    open_db(&data, 0);
21278251883Speter  }
21279251883Speter
21280251883Speter  /* Process the initialization file if there is one.  If no -init option
21281251883Speter  ** is given on the command line, look for a file named ~/.sqliterc and
21282251883Speter  ** try to process it.
21283251883Speter  */
21284282328Sbapt  process_sqliterc(&data,zInitFile);
21285251883Speter
21286251883Speter  /* Make a second pass through the command-line argument and set
21287251883Speter  ** options.  This second pass is delayed until after the initialization
21288251883Speter  ** file is processed so that the command-line arguments will override
21289251883Speter  ** settings in the initialization file.
21290251883Speter  */
21291251883Speter  for(i=1; i<argc; i++){
21292251883Speter    char *z = argv[i];
21293251883Speter    if( z[0]!='-' ) continue;
21294251883Speter    if( z[1]=='-' ){ z++; }
21295251883Speter    if( strcmp(z,"-init")==0 ){
21296251883Speter      i++;
21297251883Speter    }else if( strcmp(z,"-html")==0 ){
21298251883Speter      data.mode = MODE_Html;
21299251883Speter    }else if( strcmp(z,"-list")==0 ){
21300251883Speter      data.mode = MODE_List;
21301322444Speter    }else if( strcmp(z,"-quote")==0 ){
21302322444Speter      data.mode = MODE_Quote;
21303369950Scy      sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma);
21304369950Scy      sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
21305251883Speter    }else if( strcmp(z,"-line")==0 ){
21306251883Speter      data.mode = MODE_Line;
21307251883Speter    }else if( strcmp(z,"-column")==0 ){
21308251883Speter      data.mode = MODE_Column;
21309366076Scy    }else if( strcmp(z,"-json")==0 ){
21310366076Scy      data.mode = MODE_Json;
21311366076Scy    }else if( strcmp(z,"-markdown")==0 ){
21312366076Scy      data.mode = MODE_Markdown;
21313366076Scy    }else if( strcmp(z,"-table")==0 ){
21314366076Scy      data.mode = MODE_Table;
21315366076Scy    }else if( strcmp(z,"-box")==0 ){
21316366076Scy      data.mode = MODE_Box;
21317251883Speter    }else if( strcmp(z,"-csv")==0 ){
21318251883Speter      data.mode = MODE_Csv;
21319282328Sbapt      memcpy(data.colSeparator,",",2);
21320342292Scy#ifdef SQLITE_HAVE_ZLIB
21321342292Scy    }else if( strcmp(z,"-zip")==0 ){
21322342292Scy      data.openMode = SHELL_OPEN_ZIPFILE;
21323342292Scy#endif
21324342292Scy    }else if( strcmp(z,"-append")==0 ){
21325342292Scy      data.openMode = SHELL_OPEN_APPENDVFS;
21326342292Scy#ifdef SQLITE_ENABLE_DESERIALIZE
21327342292Scy    }else if( strcmp(z,"-deserialize")==0 ){
21328342292Scy      data.openMode = SHELL_OPEN_DESERIALIZE;
21329346442Scy    }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
21330346442Scy      data.szMax = integerValue(argv[++i]);
21331342292Scy#endif
21332342292Scy    }else if( strcmp(z,"-readonly")==0 ){
21333342292Scy      data.openMode = SHELL_OPEN_READONLY;
21334361456Scy    }else if( strcmp(z,"-nofollow")==0 ){
21335361456Scy      data.openFlags |= SQLITE_OPEN_NOFOLLOW;
21336282328Sbapt    }else if( strcmp(z,"-ascii")==0 ){
21337282328Sbapt      data.mode = MODE_Ascii;
21338369950Scy      sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit);
21339369950Scy      sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record);
21340369950Scy    }else if( strcmp(z,"-tabs")==0 ){
21341369950Scy      data.mode = MODE_List;
21342369950Scy      sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Tab);
21343369950Scy      sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
21344251883Speter    }else if( strcmp(z,"-separator")==0 ){
21345282328Sbapt      sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
21346251883Speter                       "%s",cmdline_option_value(argc,argv,++i));
21347274884Sbapt    }else if( strcmp(z,"-newline")==0 ){
21348282328Sbapt      sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
21349274884Sbapt                       "%s",cmdline_option_value(argc,argv,++i));
21350251883Speter    }else if( strcmp(z,"-nullvalue")==0 ){
21351282328Sbapt      sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
21352251883Speter                       "%s",cmdline_option_value(argc,argv,++i));
21353251883Speter    }else if( strcmp(z,"-header")==0 ){
21354251883Speter      data.showHeader = 1;
21355251883Speter    }else if( strcmp(z,"-noheader")==0 ){
21356251883Speter      data.showHeader = 0;
21357251883Speter    }else if( strcmp(z,"-echo")==0 ){
21358322444Speter      ShellSetFlag(&data, SHFLG_Echo);
21359269851Speter    }else if( strcmp(z,"-eqp")==0 ){
21360342292Scy      data.autoEQP = AUTOEQP_on;
21361305002Scy    }else if( strcmp(z,"-eqpfull")==0 ){
21362342292Scy      data.autoEQP = AUTOEQP_full;
21363251883Speter    }else if( strcmp(z,"-stats")==0 ){
21364251883Speter      data.statsOn = 1;
21365282328Sbapt    }else if( strcmp(z,"-scanstats")==0 ){
21366282328Sbapt      data.scanstatsOn = 1;
21367286510Speter    }else if( strcmp(z,"-backslash")==0 ){
21368286510Speter      /* Undocumented command-line option: -backslash
21369286510Speter      ** Causes C-style backslash escapes to be evaluated in SQL statements
21370286510Speter      ** prior to sending the SQL into SQLite.  Useful for injecting
21371286510Speter      ** crazy bytes in the middle of SQL statements for testing and debugging.
21372286510Speter      */
21373322444Speter      ShellSetFlag(&data, SHFLG_Backslash);
21374251883Speter    }else if( strcmp(z,"-bail")==0 ){
21375369950Scy      /* No-op.  The bail_on_error flag should already be set. */
21376251883Speter    }else if( strcmp(z,"-version")==0 ){
21377251883Speter      printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
21378251883Speter      return 0;
21379251883Speter    }else if( strcmp(z,"-interactive")==0 ){
21380251883Speter      stdin_is_interactive = 1;
21381251883Speter    }else if( strcmp(z,"-batch")==0 ){
21382251883Speter      stdin_is_interactive = 0;
21383251883Speter    }else if( strcmp(z,"-heap")==0 ){
21384251883Speter      i++;
21385274884Sbapt    }else if( strcmp(z,"-pagecache")==0 ){
21386274884Sbapt      i+=2;
21387274884Sbapt    }else if( strcmp(z,"-lookaside")==0 ){
21388274884Sbapt      i+=2;
21389251883Speter    }else if( strcmp(z,"-mmap")==0 ){
21390251883Speter      i++;
21391346442Scy    }else if( strcmp(z,"-memtrace")==0 ){
21392346442Scy      i++;
21393342292Scy#ifdef SQLITE_ENABLE_SORTER_REFERENCES
21394342292Scy    }else if( strcmp(z,"-sorterref")==0 ){
21395342292Scy      i++;
21396342292Scy#endif
21397251883Speter    }else if( strcmp(z,"-vfs")==0 ){
21398251883Speter      i++;
21399251883Speter#ifdef SQLITE_ENABLE_VFSTRACE
21400251883Speter    }else if( strcmp(z,"-vfstrace")==0 ){
21401251883Speter      i++;
21402251883Speter#endif
21403251883Speter#ifdef SQLITE_ENABLE_MULTIPLEX
21404251883Speter    }else if( strcmp(z,"-multiplex")==0 ){
21405251883Speter      i++;
21406251883Speter#endif
21407251883Speter    }else if( strcmp(z,"-help")==0 ){
21408251883Speter      usage(1);
21409251883Speter    }else if( strcmp(z,"-cmd")==0 ){
21410282328Sbapt      /* Run commands that follow -cmd first and separately from commands
21411282328Sbapt      ** that simply appear on the command-line.  This seems goofy.  It would
21412282328Sbapt      ** be better if all commands ran in the order that they appear.  But
21413282328Sbapt      ** we retain the goofy behavior for historical compatibility. */
21414251883Speter      if( i==argc-1 ) break;
21415251883Speter      z = cmdline_option_value(argc,argv,++i);
21416251883Speter      if( z[0]=='.' ){
21417251883Speter        rc = do_meta_command(z, &data);
21418251883Speter        if( rc && bail_on_error ) return rc==2 ? 0 : rc;
21419251883Speter      }else{
21420269851Speter        open_db(&data, 0);
21421342292Scy        rc = shell_exec(&data, z, &zErrMsg);
21422251883Speter        if( zErrMsg!=0 ){
21423298161Sbapt          utf8_printf(stderr,"Error: %s\n", zErrMsg);
21424251883Speter          if( bail_on_error ) return rc!=0 ? rc : 1;
21425251883Speter        }else if( rc!=0 ){
21426298161Sbapt          utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
21427251883Speter          if( bail_on_error ) return rc;
21428251883Speter        }
21429251883Speter      }
21430342292Scy#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
21431342292Scy    }else if( strncmp(z, "-A", 2)==0 ){
21432342292Scy      if( nCmd>0 ){
21433342292Scy        utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
21434342292Scy                            " with \"%s\"\n", z);
21435342292Scy        return 1;
21436342292Scy      }
21437342292Scy      open_db(&data, OPEN_DB_ZIPFILE);
21438342292Scy      if( z[2] ){
21439342292Scy        argv[i] = &z[2];
21440342292Scy        arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
21441342292Scy      }else{
21442342292Scy        arDotCommand(&data, 1, argv+i, argc-i);
21443342292Scy      }
21444342292Scy      readStdin = 0;
21445342292Scy      break;
21446342292Scy#endif
21447251883Speter    }else{
21448298161Sbapt      utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
21449298161Sbapt      raw_printf(stderr,"Use -help for a list of options.\n");
21450251883Speter      return 1;
21451251883Speter    }
21452298161Sbapt    data.cMode = data.mode;
21453251883Speter  }
21454251883Speter
21455282328Sbapt  if( !readStdin ){
21456282328Sbapt    /* Run all arguments that do not begin with '-' as if they were separate
21457282328Sbapt    ** command-line inputs, except for the argToSkip argument which contains
21458282328Sbapt    ** the database filename.
21459251883Speter    */
21460282328Sbapt    for(i=0; i<nCmd; i++){
21461282328Sbapt      if( azCmd[i][0]=='.' ){
21462282328Sbapt        rc = do_meta_command(azCmd[i], &data);
21463369950Scy        if( rc ){
21464369950Scy          free(azCmd);
21465369950Scy          return rc==2 ? 0 : rc;
21466369950Scy        }
21467282328Sbapt      }else{
21468282328Sbapt        open_db(&data, 0);
21469342292Scy        rc = shell_exec(&data, azCmd[i], &zErrMsg);
21470369950Scy        if( zErrMsg || rc ){
21471369950Scy          if( zErrMsg!=0 ){
21472369950Scy            utf8_printf(stderr,"Error: %s\n", zErrMsg);
21473369950Scy          }else{
21474369950Scy            utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
21475369950Scy          }
21476369950Scy          sqlite3_free(zErrMsg);
21477369950Scy          free(azCmd);
21478282328Sbapt          return rc!=0 ? rc : 1;
21479282328Sbapt        }
21480251883Speter      }
21481251883Speter    }
21482251883Speter  }else{
21483251883Speter    /* Run commands received from standard input
21484251883Speter    */
21485251883Speter    if( stdin_is_interactive ){
21486251883Speter      char *zHome;
21487342292Scy      char *zHistory;
21488251883Speter      int nHistory;
21489251883Speter      printf(
21490251883Speter        "SQLite version %s %.19s\n" /*extra-version-info*/
21491269851Speter        "Enter \".help\" for usage hints.\n",
21492251883Speter        sqlite3_libversion(), sqlite3_sourceid()
21493251883Speter      );
21494269851Speter      if( warnInmemoryDb ){
21495269851Speter        printf("Connected to a ");
21496269851Speter        printBold("transient in-memory database");
21497269851Speter        printf(".\nUse \".open FILENAME\" to reopen on a "
21498269851Speter               "persistent database.\n");
21499269851Speter      }
21500342292Scy      zHistory = getenv("SQLITE_HISTORY");
21501342292Scy      if( zHistory ){
21502342292Scy        zHistory = strdup(zHistory);
21503342292Scy      }else if( (zHome = find_home_dir(0))!=0 ){
21504251883Speter        nHistory = strlen30(zHome) + 20;
21505251883Speter        if( (zHistory = malloc(nHistory))!=0 ){
21506251883Speter          sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
21507251883Speter        }
21508251883Speter      }
21509286510Speter      if( zHistory ){ shell_read_history(zHistory); }
21510322444Speter#if HAVE_READLINE || HAVE_EDITLINE
21511322444Speter      rl_attempted_completion_function = readline_completion;
21512322444Speter#elif HAVE_LINENOISE
21513322444Speter      linenoiseSetCompletionCallback(linenoise_completion);
21514322444Speter#endif
21515346442Scy      data.in = 0;
21516346442Scy      rc = process_input(&data);
21517251883Speter      if( zHistory ){
21518322444Speter        shell_stifle_history(2000);
21519282328Sbapt        shell_write_history(zHistory);
21520251883Speter        free(zHistory);
21521251883Speter      }
21522251883Speter    }else{
21523346442Scy      data.in = stdin;
21524346442Scy      rc = process_input(&data);
21525251883Speter    }
21526251883Speter  }
21527369950Scy  free(azCmd);
21528251883Speter  set_table_name(&data, 0);
21529251883Speter  if( data.db ){
21530305002Scy    session_close_all(&data);
21531342292Scy    close_db(data.db);
21532251883Speter  }
21533305002Scy  sqlite3_free(data.zFreeOnClose);
21534322444Speter  find_home_dir(1);
21535342292Scy  output_reset(&data);
21536342292Scy  data.doXdgOpen = 0;
21537342292Scy  clearTempFile(&data);
21538305002Scy#if !SQLITE_SHELL_IS_UTF8
21539342292Scy  for(i=0; i<argcToFree; i++) free(argvToFree[i]);
21540342292Scy  free(argvToFree);
21541305002Scy#endif
21542366076Scy  free(data.colWidth);
21543342292Scy  /* Clear the global data structure so that valgrind will detect memory
21544342292Scy  ** leaks */
21545342292Scy  memset(&data, 0, sizeof(data));
21546251883Speter  return rc;
21547251883Speter}
21548