blob: 237710344205658163b0b8c87b74d5e63145a698 [file] [log] [blame]
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001/* DO NOT EDIT!
2** This file is automatically generated by the script in the canonical
3** SQLite source tree at tool/mkshellc.tcl. That script combines source
4** code from various constituent source files of SQLite into this single
5** "shell.c" file used to implement the SQLite command-line shell.
6**
7** Most of the code found below comes from the "src/shell.c.in" file in
8** the canonical SQLite source tree. That main file contains "INCLUDE"
9** lines that specify other files in the canonical source tree that are
10** inserted to getnerate this complete program source file.
11**
12** The code from multiple files is combined into this single "shell.c"
13** source file to help make the command-line program easier to compile.
14**
15** To modify this program, get a copy of the canonical SQLite source tree,
16** edit the src/shell.c.in" and/or some of the other files that are included
17** by "src/shell.c.in", then rerun the tool/mkshellc.tcl script.
18*/
The Android Open Source Project7790ef52009-03-03 19:30:40 -080019/*
20** 2001 September 15
21**
22** The author disclaims copyright to this source code. In place of
23** a legal notice, here is a blessing:
24**
25** May you do good and not evil.
26** May you find forgiveness for yourself and forgive others.
27** May you share freely, never taking more than you give.
28**
29*************************************************************************
30** This file contains code to implement the "sqlite" command line
31** utility for accessing SQLite databases.
The Android Open Source Project7790ef52009-03-03 19:30:40 -080032*/
Jeff Brown90ed05d2012-01-19 16:35:19 -080033#if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
Vasu Noria4356a02010-01-20 15:10:57 -080034/* This needs to come before any includes for MSVC compiler */
35#define _CRT_SECURE_NO_WARNINGS
The Android Open Source Project7790ef52009-03-03 19:30:40 -080036#endif
37
Jeff Brown90ed05d2012-01-19 16:35:19 -080038/*
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080039** Warning pragmas copied from msvc.h in the core.
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070040*/
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080041#if defined(_MSC_VER)
42#pragma warning(disable : 4054)
43#pragma warning(disable : 4055)
44#pragma warning(disable : 4100)
45#pragma warning(disable : 4127)
46#pragma warning(disable : 4130)
47#pragma warning(disable : 4152)
48#pragma warning(disable : 4189)
49#pragma warning(disable : 4206)
50#pragma warning(disable : 4210)
51#pragma warning(disable : 4232)
52#pragma warning(disable : 4244)
53#pragma warning(disable : 4305)
54#pragma warning(disable : 4306)
55#pragma warning(disable : 4702)
56#pragma warning(disable : 4706)
57#endif /* defined(_MSC_VER) */
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070058
59/*
60** No support for loadable extensions in VxWorks.
61*/
62#if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION
63# define SQLITE_OMIT_LOAD_EXTENSION 1
64#endif
65
66/*
Jeff Brown90ed05d2012-01-19 16:35:19 -080067** Enable large-file support for fopen() and friends on unix.
68*/
69#ifndef SQLITE_DISABLE_LFS
70# define _LARGE_FILE 1
71# ifndef _FILE_OFFSET_BITS
72# define _FILE_OFFSET_BITS 64
73# endif
74# define _LARGEFILE_SOURCE 1
75#endif
76
The Android Open Source Project7790ef52009-03-03 19:30:40 -080077#include <stdlib.h>
78#include <string.h>
79#include <stdio.h>
80#include <assert.h>
81#include "sqlite3.h"
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080082typedef sqlite3_int64 i64;
83typedef sqlite3_uint64 u64;
84typedef unsigned char u8;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070085#if SQLITE_USER_AUTHENTICATION
86# include "sqlite3userauth.h"
87#endif
The Android Open Source Project7790ef52009-03-03 19:30:40 -080088#include <ctype.h>
89#include <stdarg.h>
Vasu Noric296bf92010-06-15 14:06:10 -070090// Begin Android Add
91#ifndef NO_ANDROID_FUNCS
Neil Fuller84c2f242019-03-11 19:31:59 +000092#include <aicu/AIcu.h>
Vasu Noric296bf92010-06-15 14:06:10 -070093#include <sqlite3_android.h>
94#endif
95// End Android Add
96
Nick Kralevich8fecf562014-05-29 16:56:33 -070097#if !defined(_WIN32) && !defined(WIN32)
The Android Open Source Project7790ef52009-03-03 19:30:40 -080098# include <signal.h>
Vasu Noria4356a02010-01-20 15:10:57 -080099# if !defined(__RTP__) && !defined(_WRS_KERNEL)
100# include <pwd.h>
101# endif
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800102#endif
Fyodor Kupolov0181ec22018-02-13 16:45:16 -0800103#if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__)
104# include <unistd.h>
105# include <dirent.h>
mydongistiny63ee58c2019-09-21 18:04:30 -0700106# define GETPID getpid
Fyodor Kupolov0181ec22018-02-13 16:45:16 -0800107# if defined(__MINGW32__)
108# define DIRENT dirent
109# ifndef S_ISLNK
110# define S_ISLNK(mode) (0)
111# endif
112# endif
mydongistiny63ee58c2019-09-21 18:04:30 -0700113#else
114# define GETPID (int)GetCurrentProcessId
Fyodor Kupolov0181ec22018-02-13 16:45:16 -0800115#endif
116#include <sys/types.h>
117#include <sys/stat.h>
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800118
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700119#if HAVE_READLINE
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800120# include <readline/readline.h>
121# include <readline/history.h>
Jeff Brown90ed05d2012-01-19 16:35:19 -0800122#endif
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700123
124#if HAVE_EDITLINE
Nick Kralevich8fecf562014-05-29 16:56:33 -0700125# include <editline/readline.h>
126#endif
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700127
128#if HAVE_EDITLINE || HAVE_READLINE
129
130# define shell_add_history(X) add_history(X)
131# define shell_read_history(X) read_history(X)
132# define shell_write_history(X) write_history(X)
133# define shell_stifle_history(X) stifle_history(X)
134# define shell_readline(X) readline(X)
135
136#elif HAVE_LINENOISE
137
138# include "linenoise.h"
139# define shell_add_history(X) linenoiseHistoryAdd(X)
140# define shell_read_history(X) linenoiseHistoryLoad(X)
141# define shell_write_history(X) linenoiseHistorySave(X)
142# define shell_stifle_history(X) linenoiseHistorySetMaxLen(X)
143# define shell_readline(X) linenoise(X)
144
145#else
146
Alex Naidis60fa6fd2016-07-10 14:13:38 +0200147# define shell_read_history(X)
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700148# define shell_write_history(X)
149# define shell_stifle_history(X)
150
151# define SHELL_USE_LOCAL_GETLINE 1
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800152#endif
153
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700154
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800155#if defined(_WIN32) || defined(WIN32)
156# include <io.h>
Jeff Brown9bee60b2014-08-20 16:41:25 -0700157# include <fcntl.h>
Nick Kralevich253ed642015-12-23 10:07:58 -0800158# define isatty(h) _isatty(h)
159# ifndef access
160# define access(f,m) _access((f),(m))
161# endif
mydongistiny63ee58c2019-09-21 18:04:30 -0700162# ifndef unlink
163# define unlink _unlink
164# endif
165# ifndef strdup
166# define strdup _strdup
167# endif
Nick Kralevich253ed642015-12-23 10:07:58 -0800168# undef popen
169# define popen _popen
170# undef pclose
171# define pclose _pclose
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800172#else
Nick Kralevich253ed642015-12-23 10:07:58 -0800173 /* Make sure isatty() has a prototype. */
174 extern int isatty(int);
Nick Kralevich8fecf562014-05-29 16:56:33 -0700175
Nick Kralevich253ed642015-12-23 10:07:58 -0800176# if !defined(__RTP__) && !defined(_WRS_KERNEL)
177 /* popen and pclose are not C89 functions and so are
178 ** sometimes omitted from the <stdio.h> header */
179 extern FILE *popen(const char*,const char*);
180 extern int pclose(FILE*);
181# else
182# define SQLITE_OMIT_POPEN 1
183# endif
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800184#endif
185
186#if defined(_WIN32_WCE)
187/* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty()
188 * thus we always assume that we have a console. That can be
189 * overridden with the -batch command line option.
190 */
191#define isatty(x) 1
192#endif
193
Jeff Brown90ed05d2012-01-19 16:35:19 -0800194/* ctype macros that work with signed characters */
195#define IsSpace(X) isspace((unsigned char)X)
196#define IsDigit(X) isdigit((unsigned char)X)
197#define ToLower(X) (char)tolower((unsigned char)X)
198
Alex Naidis60fa6fd2016-07-10 14:13:38 +0200199#if defined(_WIN32) || defined(WIN32)
200#include <windows.h>
201
202/* string conversion routines only needed on Win32 */
203extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
204extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int);
205extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int);
Alex Naidis08f78cb2016-10-14 15:52:08 +0200206extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
Alex Naidis60fa6fd2016-07-10 14:13:38 +0200207#endif
208
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700209/* On Windows, we normally run with output mode of TEXT so that \n characters
210** are automatically translated into \r\n. However, this behavior needs
211** to be disabled in some cases (ex: when generating CSV output and when
212** rendering quoted strings that contain \n characters). The following
213** routines take care of that.
214*/
215#if defined(_WIN32) || defined(WIN32)
Alex Naidis60fa6fd2016-07-10 14:13:38 +0200216static void setBinaryMode(FILE *file, int isOutput){
217 if( isOutput ) fflush(file);
218 _setmode(_fileno(file), _O_BINARY);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700219}
Alex Naidis60fa6fd2016-07-10 14:13:38 +0200220static void setTextMode(FILE *file, int isOutput){
221 if( isOutput ) fflush(file);
222 _setmode(_fileno(file), _O_TEXT);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700223}
224#else
Alex Naidis60fa6fd2016-07-10 14:13:38 +0200225# define setBinaryMode(X,Y)
226# define setTextMode(X,Y)
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700227#endif
228
Nick Kralevich8fecf562014-05-29 16:56:33 -0700229
230/* True if the timer is enabled */
231static int enableTimer = 0;
232
233/* Return the current wall-clock time */
234static sqlite3_int64 timeOfDay(void){
235 static sqlite3_vfs *clockVfs = 0;
236 sqlite3_int64 t;
237 if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
Alex Naidis60fa6fd2016-07-10 14:13:38 +0200238 if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
Nick Kralevich8fecf562014-05-29 16:56:33 -0700239 clockVfs->xCurrentTimeInt64(clockVfs, &t);
240 }else{
241 double r;
242 clockVfs->xCurrentTime(clockVfs, &r);
243 t = (sqlite3_int64)(r*86400000.0);
244 }
245 return t;
246}
247
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700248#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800249#include <sys/time.h>
250#include <sys/resource.h>
251
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700252/* VxWorks does not support getrusage() as far as we can determine */
253#if defined(_WRS_KERNEL) || defined(__RTP__)
254struct rusage {
255 struct timeval ru_utime; /* user CPU time used */
256 struct timeval ru_stime; /* system CPU time used */
257};
258#define getrusage(A,B) memset(B,0,sizeof(*B))
259#endif
260
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800261/* Saved resource information for the beginning of an operation */
Nick Kralevich8fecf562014-05-29 16:56:33 -0700262static struct rusage sBegin; /* CPU time at start */
263static sqlite3_int64 iBegin; /* Wall-clock time at start */
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800264
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800265/*
266** Begin timing an operation
267*/
268static void beginTimer(void){
269 if( enableTimer ){
270 getrusage(RUSAGE_SELF, &sBegin);
Nick Kralevich8fecf562014-05-29 16:56:33 -0700271 iBegin = timeOfDay();
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800272 }
273}
274
Vasu Noria4356a02010-01-20 15:10:57 -0800275/* Return the difference of two time_structs in seconds */
276static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
Alex Naidis60fa6fd2016-07-10 14:13:38 +0200277 return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
Vasu Noria4356a02010-01-20 15:10:57 -0800278 (double)(pEnd->tv_sec - pStart->tv_sec);
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800279}
280
281/*
282** Print the timing results.
283*/
284static void endTimer(void){
285 if( enableTimer ){
Nick Kralevich8fecf562014-05-29 16:56:33 -0700286 sqlite3_int64 iEnd = timeOfDay();
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700287 struct rusage sEnd;
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800288 getrusage(RUSAGE_SELF, &sEnd);
Nick Kralevich8fecf562014-05-29 16:56:33 -0700289 printf("Run Time: real %.3f user %f sys %f\n",
290 (iEnd - iBegin)*0.001,
Vasu Noria4356a02010-01-20 15:10:57 -0800291 timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
292 timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800293 }
294}
Vasu Noria4356a02010-01-20 15:10:57 -0800295
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800296#define BEGIN_TIMER beginTimer()
297#define END_TIMER endTimer()
298#define HAS_TIMER 1
Vasu Noria4356a02010-01-20 15:10:57 -0800299
300#elif (defined(_WIN32) || defined(WIN32))
301
Vasu Noria4356a02010-01-20 15:10:57 -0800302/* Saved resource information for the beginning of an operation */
303static HANDLE hProcess;
304static FILETIME ftKernelBegin;
305static FILETIME ftUserBegin;
Nick Kralevich8fecf562014-05-29 16:56:33 -0700306static sqlite3_int64 ftWallBegin;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700307typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
308 LPFILETIME, LPFILETIME);
Vasu Noria4356a02010-01-20 15:10:57 -0800309static GETPROCTIMES getProcessTimesAddr = NULL;
310
Vasu Noria4356a02010-01-20 15:10:57 -0800311/*
312** Check to see if we have timer support. Return 1 if necessary
313** support found (or found previously).
314*/
315static int hasTimer(void){
316 if( getProcessTimesAddr ){
317 return 1;
318 } else {
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700319 /* GetProcessTimes() isn't supported in WIN95 and some other Windows
320 ** versions. See if the version we are running on has it, and if it
321 ** does, save off a pointer to it and the current process handle.
Vasu Noria4356a02010-01-20 15:10:57 -0800322 */
323 hProcess = GetCurrentProcess();
324 if( hProcess ){
325 HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
326 if( NULL != hinstLib ){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700327 getProcessTimesAddr =
328 (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
Vasu Noria4356a02010-01-20 15:10:57 -0800329 if( NULL != getProcessTimesAddr ){
330 return 1;
331 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +0200332 FreeLibrary(hinstLib);
Vasu Noria4356a02010-01-20 15:10:57 -0800333 }
334 }
335 }
336 return 0;
337}
338
339/*
340** Begin timing an operation
341*/
342static void beginTimer(void){
343 if( enableTimer && getProcessTimesAddr ){
344 FILETIME ftCreation, ftExit;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700345 getProcessTimesAddr(hProcess,&ftCreation,&ftExit,
346 &ftKernelBegin,&ftUserBegin);
Nick Kralevich8fecf562014-05-29 16:56:33 -0700347 ftWallBegin = timeOfDay();
Vasu Noria4356a02010-01-20 15:10:57 -0800348 }
349}
350
351/* Return the difference of two FILETIME structs in seconds */
352static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
353 sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
354 sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
355 return (double) ((i64End - i64Start) / 10000000.0);
356}
357
358/*
359** Print the timing results.
360*/
361static void endTimer(void){
362 if( enableTimer && getProcessTimesAddr){
363 FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
Nick Kralevich8fecf562014-05-29 16:56:33 -0700364 sqlite3_int64 ftWallEnd = timeOfDay();
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700365 getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
Nick Kralevich8fecf562014-05-29 16:56:33 -0700366 printf("Run Time: real %.3f user %f sys %f\n",
367 (ftWallEnd - ftWallBegin)*0.001,
Vasu Noria4356a02010-01-20 15:10:57 -0800368 timeDiff(&ftUserBegin, &ftUserEnd),
369 timeDiff(&ftKernelBegin, &ftKernelEnd));
370 }
371}
372
373#define BEGIN_TIMER beginTimer()
374#define END_TIMER endTimer()
375#define HAS_TIMER hasTimer()
376
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800377#else
Alex Naidis60fa6fd2016-07-10 14:13:38 +0200378#define BEGIN_TIMER
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800379#define END_TIMER
380#define HAS_TIMER 0
381#endif
382
Vasu Noria4356a02010-01-20 15:10:57 -0800383/*
384** Used to prevent warnings about unused parameters
385*/
386#define UNUSED_PARAMETER(x) (void)(x)
387
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800388/*
Fyodor Kupolov0181ec22018-02-13 16:45:16 -0800389** Number of elements in an array
390*/
391#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
392
393/*
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800394** If the following flag is set, then command execution stops
395** at an error if we are not interactive.
396*/
397static int bail_on_error = 0;
398
399/*
400** Threat stdin as an interactive input if the following variable
401** is true. Otherwise, assume stdin is connected to a file or pipe.
402*/
403static int stdin_is_interactive = 1;
404
405/*
Alex Naidis60fa6fd2016-07-10 14:13:38 +0200406** On Windows systems we have to know if standard output is a console
407** in order to translate UTF-8 into MBCS. The following variable is
408** true if translation is required.
409*/
410static int stdout_is_console = 1;
411
412/*
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800413** The following is the open SQLite database. We make a pointer
414** to this database a static variable so that it can be accessed
415** by the SIGINT handler to interrupt database processing.
416*/
Nick Kralevich3a6c79f2015-05-08 11:25:07 -0700417static sqlite3 *globalDb = 0;
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800418
419/*
420** True if an interrupt (Control-C) has been received.
421*/
422static volatile int seenInterrupt = 0;
423
424/*
425** This is the name of our program. It is set in main(), used
426** in a number of other places, mostly for error messages.
427*/
428static char *Argv0;
429
430/*
431** Prompt strings. Initialized in main. Settable with
432** .prompt main continue
433*/
434static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/
435static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */
436
437/*
Alex Naidis60fa6fd2016-07-10 14:13:38 +0200438** Render output like fprintf(). Except, if the output is going to the
439** console and if this is running on a Windows machine, translate the
440** output from UTF-8 into MBCS.
441*/
442#if defined(_WIN32) || defined(WIN32)
443void utf8_printf(FILE *out, const char *zFormat, ...){
444 va_list ap;
445 va_start(ap, zFormat);
446 if( stdout_is_console && (out==stdout || out==stderr) ){
447 char *z1 = sqlite3_vmprintf(zFormat, ap);
448 char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0);
449 sqlite3_free(z1);
450 fputs(z2, out);
451 sqlite3_free(z2);
452 }else{
453 vfprintf(out, zFormat, ap);
454 }
455 va_end(ap);
456}
457#elif !defined(utf8_printf)
458# define utf8_printf fprintf
459#endif
460
461/*
462** Render output like fprintf(). This should not be used on anything that
463** includes string formatting (e.g. "%s").
464*/
465#if !defined(raw_printf)
466# define raw_printf fprintf
467#endif
468
mydongistiny63ee58c2019-09-21 18:04:30 -0700469/* Indicate out-of-memory and exit. */
470static void shell_out_of_memory(void){
471 raw_printf(stderr,"Error: out of memory\n");
472 exit(1);
473}
474
Alex Naidis60fa6fd2016-07-10 14:13:38 +0200475/*
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800476** Write I/O traces to the following stream.
477*/
478#ifdef SQLITE_ENABLE_IOTRACE
479static FILE *iotrace = 0;
480#endif
481
482/*
483** This routine works like printf in that its first argument is a
484** format string and subsequent arguments are values to be substituted
485** in place of % fields. The result of formatting this string
486** is written to iotrace.
487*/
488#ifdef SQLITE_ENABLE_IOTRACE
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700489static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800490 va_list ap;
491 char *z;
492 if( iotrace==0 ) return;
493 va_start(ap, zFormat);
494 z = sqlite3_vmprintf(zFormat, ap);
495 va_end(ap);
Alex Naidis60fa6fd2016-07-10 14:13:38 +0200496 utf8_printf(iotrace, "%s", z);
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800497 sqlite3_free(z);
498}
499#endif
500
Alex Naidisb94ea7b2017-05-24 19:25:14 +0200501/*
502** Output string zUtf to stream pOut as w characters. If w is negative,
503** then right-justify the text. W is the width in UTF-8 characters, not
504** in bytes. This is different from the %*.*s specification in printf
505** since with %*.*s the width is measured in bytes, not characters.
506*/
507static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
508 int i;
509 int n;
510 int aw = w<0 ? -w : w;
511 char zBuf[1000];
512 if( aw>(int)sizeof(zBuf)/3 ) aw = (int)sizeof(zBuf)/3;
513 for(i=n=0; zUtf[i]; i++){
514 if( (zUtf[i]&0xc0)!=0x80 ){
515 n++;
516 if( n==aw ){
517 do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
518 break;
519 }
520 }
521 }
522 if( n>=aw ){
523 utf8_printf(pOut, "%.*s", i, zUtf);
524 }else if( w<0 ){
525 utf8_printf(pOut, "%*s%s", aw-n, "", zUtf);
526 }else{
527 utf8_printf(pOut, "%s%*s", zUtf, aw-n, "");
528 }
529}
530
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800531
532/*
533** Determines if a string is a number of not.
534*/
535static int isNumber(const char *z, int *realnum){
536 if( *z=='-' || *z=='+' ) z++;
Jeff Brown90ed05d2012-01-19 16:35:19 -0800537 if( !IsDigit(*z) ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800538 return 0;
539 }
540 z++;
541 if( realnum ) *realnum = 0;
Jeff Brown90ed05d2012-01-19 16:35:19 -0800542 while( IsDigit(*z) ){ z++; }
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800543 if( *z=='.' ){
544 z++;
Jeff Brown90ed05d2012-01-19 16:35:19 -0800545 if( !IsDigit(*z) ) return 0;
546 while( IsDigit(*z) ){ z++; }
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800547 if( realnum ) *realnum = 1;
548 }
549 if( *z=='e' || *z=='E' ){
550 z++;
551 if( *z=='+' || *z=='-' ) z++;
Jeff Brown90ed05d2012-01-19 16:35:19 -0800552 if( !IsDigit(*z) ) return 0;
553 while( IsDigit(*z) ){ z++; }
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800554 if( realnum ) *realnum = 1;
555 }
556 return *z==0;
557}
558
559/*
Alex Naidis60fa6fd2016-07-10 14:13:38 +0200560** Compute a string length that is limited to what can be stored in
561** lower 30 bits of a 32-bit signed integer.
562*/
563static int strlen30(const char *z){
564 const char *z2 = z;
565 while( *z2 ){ z2++; }
566 return 0x3fffffff & (int)(z2 - z);
567}
568
569/*
Fyodor Kupolov0181ec22018-02-13 16:45:16 -0800570** Return the length of a string in characters. Multibyte UTF8 characters
571** count as a single character.
572*/
573static int strlenChar(const char *z){
574 int n = 0;
575 while( *z ){
576 if( (0xc0&*(z++))!=0x80 ) n++;
577 }
578 return n;
579}
580
581/*
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800582** This routine reads a line of text from FILE in, stores
583** the text in memory obtained from malloc() and returns a pointer
584** to the text. NULL is returned at end of file, or if malloc()
585** fails.
586**
Nick Kralevich8fecf562014-05-29 16:56:33 -0700587** If zLine is not NULL then it is a malloced buffer returned from
588** a previous call to this routine that may be reused.
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800589*/
Nick Kralevich8fecf562014-05-29 16:56:33 -0700590static char *local_getline(char *zLine, FILE *in){
591 int nLine = zLine==0 ? 0 : 100;
592 int n = 0;
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800593
Jeff Brown90ed05d2012-01-19 16:35:19 -0800594 while( 1 ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800595 if( n+100>nLine ){
596 nLine = nLine*2 + 100;
597 zLine = realloc(zLine, nLine);
mydongistiny63ee58c2019-09-21 18:04:30 -0700598 if( zLine==0 ) shell_out_of_memory();
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800599 }
600 if( fgets(&zLine[n], nLine - n, in)==0 ){
601 if( n==0 ){
602 free(zLine);
603 return 0;
604 }
605 zLine[n] = 0;
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800606 break;
607 }
Nick Kralevich8fecf562014-05-29 16:56:33 -0700608 while( zLine[n] ) n++;
609 if( n>0 && zLine[n-1]=='\n' ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800610 n--;
Vasu Noria4356a02010-01-20 15:10:57 -0800611 if( n>0 && zLine[n-1]=='\r' ) n--;
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800612 zLine[n] = 0;
Jeff Brown90ed05d2012-01-19 16:35:19 -0800613 break;
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800614 }
615 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +0200616#if defined(_WIN32) || defined(WIN32)
617 /* For interactive input on Windows systems, translate the
618 ** multi-byte characterset characters into UTF-8. */
Alex Naidis08f78cb2016-10-14 15:52:08 +0200619 if( stdin_is_interactive && in==stdin ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +0200620 char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
621 if( zTrans ){
622 int nTrans = strlen30(zTrans)+1;
623 if( nTrans>nLine ){
624 zLine = realloc(zLine, nTrans);
mydongistiny63ee58c2019-09-21 18:04:30 -0700625 if( zLine==0 ) shell_out_of_memory();
Alex Naidis60fa6fd2016-07-10 14:13:38 +0200626 }
627 memcpy(zLine, zTrans, nTrans);
628 sqlite3_free(zTrans);
629 }
630 }
631#endif /* defined(_WIN32) || defined(WIN32) */
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800632 return zLine;
633}
634
635/*
636** Retrieve a single line of input text.
637**
Nick Kralevich8fecf562014-05-29 16:56:33 -0700638** If in==0 then read from standard input and prompt before each line.
639** If isContinuation is true, then a continuation prompt is appropriate.
640** If isContinuation is zero, then the main prompt should be used.
641**
642** If zPrior is not NULL then it is a buffer from a prior call to this
643** routine that can be reused.
644**
645** The result is stored in space obtained from malloc() and must either
646** be freed by the caller or else passed back into this routine via the
647** zPrior argument for reuse.
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800648*/
Nick Kralevich8fecf562014-05-29 16:56:33 -0700649static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800650 char *zPrompt;
651 char *zResult;
652 if( in!=0 ){
Nick Kralevich8fecf562014-05-29 16:56:33 -0700653 zResult = local_getline(zPrior, in);
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800654 }else{
Nick Kralevich8fecf562014-05-29 16:56:33 -0700655 zPrompt = isContinuation ? continuePrompt : mainPrompt;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700656#if SHELL_USE_LOCAL_GETLINE
Nick Kralevich8fecf562014-05-29 16:56:33 -0700657 printf("%s", zPrompt);
658 fflush(stdout);
659 zResult = local_getline(zPrior, stdin);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -0700660#else
661 free(zPrior);
662 zResult = shell_readline(zPrompt);
663 if( zResult && *zResult ) shell_add_history(zResult);
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800664#endif
Nick Kralevich8fecf562014-05-29 16:56:33 -0700665 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -0800666 return zResult;
667}
Fyodor Kupolov0181ec22018-02-13 16:45:16 -0800668
669
670/*
671** Return the value of a hexadecimal digit. Return -1 if the input
672** is not a hex digit.
673*/
674static int hexDigitValue(char c){
675 if( c>='0' && c<='9' ) return c - '0';
676 if( c>='a' && c<='f' ) return c - 'a' + 10;
677 if( c>='A' && c<='F' ) return c - 'A' + 10;
678 return -1;
679}
680
681/*
682** Interpret zArg as an integer value, possibly with suffixes.
683*/
684static sqlite3_int64 integerValue(const char *zArg){
685 sqlite3_int64 v = 0;
686 static const struct { char *zSuffix; int iMult; } aMult[] = {
687 { "KiB", 1024 },
688 { "MiB", 1024*1024 },
689 { "GiB", 1024*1024*1024 },
690 { "KB", 1000 },
691 { "MB", 1000000 },
692 { "GB", 1000000000 },
693 { "K", 1000 },
694 { "M", 1000000 },
695 { "G", 1000000000 },
696 };
697 int i;
698 int isNeg = 0;
699 if( zArg[0]=='-' ){
700 isNeg = 1;
701 zArg++;
702 }else if( zArg[0]=='+' ){
703 zArg++;
704 }
705 if( zArg[0]=='0' && zArg[1]=='x' ){
706 int x;
707 zArg += 2;
708 while( (x = hexDigitValue(zArg[0]))>=0 ){
709 v = (v<<4) + x;
710 zArg++;
711 }
712 }else{
713 while( IsDigit(zArg[0]) ){
714 v = v*10 + zArg[0] - '0';
715 zArg++;
716 }
717 }
718 for(i=0; i<ArraySize(aMult); i++){
719 if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
720 v *= aMult[i].iMult;
721 break;
722 }
723 }
724 return isNeg? -v : v;
725}
726
Alex Naidisb86c0cf2017-03-31 14:12:35 +0200727/*
728** A variable length string to which one can append text.
729*/
730typedef struct ShellText ShellText;
731struct ShellText {
732 char *z;
733 int n;
734 int nAlloc;
735};
736
737/*
738** Initialize and destroy a ShellText object
739*/
740static void initText(ShellText *p){
741 memset(p, 0, sizeof(*p));
742}
743static void freeText(ShellText *p){
744 free(p->z);
745 initText(p);
746}
747
748/* zIn is either a pointer to a NULL-terminated string in memory obtained
749** from malloc(), or a NULL pointer. The string pointed to by zAppend is
750** added to zIn, and the result returned in memory obtained from malloc().
751** zIn, if it was not NULL, is freed.
752**
753** If the third argument, quote, is not '\0', then it is used as a
754** quote character for zAppend.
755*/
756static void appendText(ShellText *p, char const *zAppend, char quote){
757 int len;
758 int i;
759 int nAppend = strlen30(zAppend);
760
761 len = nAppend+p->n+1;
762 if( quote ){
763 len += 2;
764 for(i=0; i<nAppend; i++){
765 if( zAppend[i]==quote ) len++;
766 }
767 }
768
769 if( p->n+len>=p->nAlloc ){
770 p->nAlloc = p->nAlloc*2 + len + 20;
771 p->z = realloc(p->z, p->nAlloc);
mydongistiny63ee58c2019-09-21 18:04:30 -0700772 if( p->z==0 ) shell_out_of_memory();
Alex Naidisb86c0cf2017-03-31 14:12:35 +0200773 }
774
775 if( quote ){
776 char *zCsr = p->z+p->n;
777 *zCsr++ = quote;
778 for(i=0; i<nAppend; i++){
779 *zCsr++ = zAppend[i];
780 if( zAppend[i]==quote ) *zCsr++ = quote;
781 }
782 *zCsr++ = quote;
783 p->n = (int)(zCsr - p->z);
784 *zCsr = '\0';
785 }else{
786 memcpy(p->z+p->n, zAppend, nAppend);
787 p->n += nAppend;
788 p->z[p->n] = '\0';
789 }
790}
791
792/*
793** Attempt to determine if identifier zName needs to be quoted, either
794** because it contains non-alphanumeric characters, or because it is an
795** SQLite keyword. Be conservative in this estimate: When in doubt assume
796** that quoting is required.
797**
798** Return '"' if quoting is required. Return 0 if no quoting is required.
799*/
800static char quoteChar(const char *zName){
mydongistiny63ee58c2019-09-21 18:04:30 -0700801 int i;
Alex Naidisb86c0cf2017-03-31 14:12:35 +0200802 if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
803 for(i=0; zName[i]; i++){
804 if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
805 }
mydongistiny63ee58c2019-09-21 18:04:30 -0700806 return sqlite3_keyword_check(zName, i) ? '"' : 0;
Alex Naidisb86c0cf2017-03-31 14:12:35 +0200807}
808
Fyodor Kupolov0181ec22018-02-13 16:45:16 -0800809/*
810** Construct a fake object name and column list to describe the structure
811** of the view, virtual table, or table valued function zSchema.zName.
Alex Naidisb86c0cf2017-03-31 14:12:35 +0200812*/
Fyodor Kupolov0181ec22018-02-13 16:45:16 -0800813static char *shellFakeSchema(
814 sqlite3 *db, /* The database connection containing the vtab */
815 const char *zSchema, /* Schema of the database holding the vtab */
816 const char *zName /* The name of the virtual table */
817){
818 sqlite3_stmt *pStmt = 0;
819 char *zSql;
820 ShellText s;
821 char cQuote;
822 char *zDiv = "(";
823 int nRow = 0;
824
825 zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
826 zSchema ? zSchema : "main", zName);
827 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
828 sqlite3_free(zSql);
829 initText(&s);
830 if( zSchema ){
831 cQuote = quoteChar(zSchema);
832 if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0;
833 appendText(&s, zSchema, cQuote);
834 appendText(&s, ".", 0);
835 }
836 cQuote = quoteChar(zName);
837 appendText(&s, zName, cQuote);
838 while( sqlite3_step(pStmt)==SQLITE_ROW ){
839 const char *zCol = (const char*)sqlite3_column_text(pStmt, 1);
840 nRow++;
841 appendText(&s, zDiv, 0);
842 zDiv = ",";
843 cQuote = quoteChar(zCol);
844 appendText(&s, zCol, cQuote);
845 }
846 appendText(&s, ")", 0);
847 sqlite3_finalize(pStmt);
848 if( nRow==0 ){
849 freeText(&s);
850 s.z = 0;
851 }
852 return s.z;
853}
854
855/*
856** SQL function: shell_module_schema(X)
857**
858** Return a fake schema for the table-valued function or eponymous virtual
859** table X.
860*/
861static void shellModuleSchema(
862 sqlite3_context *pCtx,
863 int nVal,
864 sqlite3_value **apVal
865){
866 const char *zName = (const char*)sqlite3_value_text(apVal[0]);
867 char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName);
868 UNUSED_PARAMETER(nVal);
869 if( zFake ){
870 sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
871 -1, sqlite3_free);
872 free(zFake);
873 }
874}
875
876/*
877** SQL function: shell_add_schema(S,X)
878**
879** Add the schema name X to the CREATE statement in S and return the result.
880** Examples:
881**
882** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x);
883**
884** Also works on
885**
886** CREATE INDEX
887** CREATE UNIQUE INDEX
888** CREATE VIEW
889** CREATE TRIGGER
890** CREATE VIRTUAL TABLE
891**
892** This UDF is used by the .schema command to insert the schema name of
893** attached databases into the middle of the sqlite_master.sql field.
894*/
895static void shellAddSchemaName(
896 sqlite3_context *pCtx,
897 int nVal,
898 sqlite3_value **apVal
899){
900 static const char *aPrefix[] = {
901 "TABLE",
902 "INDEX",
903 "UNIQUE INDEX",
904 "VIEW",
905 "TRIGGER",
906 "VIRTUAL TABLE"
907 };
908 int i = 0;
909 const char *zIn = (const char*)sqlite3_value_text(apVal[0]);
910 const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
911 const char *zName = (const char*)sqlite3_value_text(apVal[2]);
912 sqlite3 *db = sqlite3_context_db_handle(pCtx);
913 UNUSED_PARAMETER(nVal);
914 if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
915 for(i=0; i<(int)(sizeof(aPrefix)/sizeof(aPrefix[0])); i++){
916 int n = strlen30(aPrefix[i]);
917 if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
918 char *z = 0;
919 char *zFake = 0;
920 if( zSchema ){
921 char cQuote = quoteChar(zSchema);
922 if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){
923 z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8);
924 }else{
925 z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8);
926 }
927 }
928 if( zName
929 && aPrefix[i][0]=='V'
930 && (zFake = shellFakeSchema(db, zSchema, zName))!=0
931 ){
932 if( z==0 ){
933 z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake);
934 }else{
935 z = sqlite3_mprintf("%z\n/* %s */", z, zFake);
936 }
937 free(zFake);
938 }
939 if( z ){
940 sqlite3_result_text(pCtx, z, -1, sqlite3_free);
941 return;
942 }
943 }
944 }
945 }
946 sqlite3_result_value(pCtx, apVal[0]);
947}
948
949/*
950** The source code for several run-time loadable extensions is inserted
951** below by the ../tool/mkshellc.tcl script. Before processing that included
952** code, we need to override some macros to make the included program code
953** work here in the middle of this regular program.
954*/
955#define SQLITE_EXTENSION_INIT1
956#define SQLITE_EXTENSION_INIT2(X) (void)(X)
957
958#if defined(_WIN32) && defined(_MSC_VER)
959/************************* Begin test_windirent.h ******************/
960/*
961** 2015 November 30
962**
963** The author disclaims copyright to this source code. In place of
964** a legal notice, here is a blessing:
965**
966** May you do good and not evil.
967** May you find forgiveness for yourself and forgive others.
968** May you share freely, never taking more than you give.
969**
970*************************************************************************
971** This file contains declarations for most of the opendir() family of
972** POSIX functions on Win32 using the MSVCRT.
973*/
974
975#if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H)
976#define SQLITE_WINDIRENT_H
977
978/*
979** We need several data types from the Windows SDK header.
980*/
981
mydongistiny63ee58c2019-09-21 18:04:30 -0700982#ifndef WIN32_LEAN_AND_MEAN
Fyodor Kupolov0181ec22018-02-13 16:45:16 -0800983#define WIN32_LEAN_AND_MEAN
mydongistiny63ee58c2019-09-21 18:04:30 -0700984#endif
985
Fyodor Kupolov0181ec22018-02-13 16:45:16 -0800986#include "windows.h"
987
988/*
989** We need several support functions from the SQLite core.
990*/
991
mydongistiny63ee58c2019-09-21 18:04:30 -0700992/* #include "sqlite3.h" */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -0800993
994/*
995** We need several things from the ANSI and MSVCRT headers.
996*/
997
998#include <stdio.h>
999#include <stdlib.h>
1000#include <errno.h>
1001#include <io.h>
1002#include <limits.h>
1003#include <sys/types.h>
1004#include <sys/stat.h>
1005
1006/*
1007** We may need several defines that should have been in "sys/stat.h".
1008*/
1009
1010#ifndef S_ISREG
1011#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
1012#endif
1013
1014#ifndef S_ISDIR
1015#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
1016#endif
1017
1018#ifndef S_ISLNK
1019#define S_ISLNK(mode) (0)
1020#endif
1021
1022/*
1023** We may need to provide the "mode_t" type.
1024*/
1025
1026#ifndef MODE_T_DEFINED
1027 #define MODE_T_DEFINED
1028 typedef unsigned short mode_t;
1029#endif
1030
1031/*
1032** We may need to provide the "ino_t" type.
1033*/
1034
1035#ifndef INO_T_DEFINED
1036 #define INO_T_DEFINED
1037 typedef unsigned short ino_t;
1038#endif
1039
1040/*
1041** We need to define "NAME_MAX" if it was not present in "limits.h".
1042*/
1043
1044#ifndef NAME_MAX
1045# ifdef FILENAME_MAX
1046# define NAME_MAX (FILENAME_MAX)
1047# else
1048# define NAME_MAX (260)
1049# endif
1050#endif
1051
1052/*
1053** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T".
1054*/
1055
1056#ifndef NULL_INTPTR_T
1057# define NULL_INTPTR_T ((intptr_t)(0))
1058#endif
1059
1060#ifndef BAD_INTPTR_T
1061# define BAD_INTPTR_T ((intptr_t)(-1))
1062#endif
1063
1064/*
1065** We need to provide the necessary structures and related types.
1066*/
1067
1068#ifndef DIRENT_DEFINED
1069#define DIRENT_DEFINED
1070typedef struct DIRENT DIRENT;
1071typedef DIRENT *LPDIRENT;
1072struct DIRENT {
1073 ino_t d_ino; /* Sequence number, do not use. */
1074 unsigned d_attributes; /* Win32 file attributes. */
1075 char d_name[NAME_MAX + 1]; /* Name within the directory. */
1076};
1077#endif
1078
1079#ifndef DIR_DEFINED
1080#define DIR_DEFINED
1081typedef struct DIR DIR;
1082typedef DIR *LPDIR;
1083struct DIR {
1084 intptr_t d_handle; /* Value returned by "_findfirst". */
1085 DIRENT d_first; /* DIRENT constructed based on "_findfirst". */
1086 DIRENT d_next; /* DIRENT constructed based on "_findnext". */
1087};
1088#endif
1089
1090/*
1091** Provide a macro, for use by the implementation, to determine if a
1092** particular directory entry should be skipped over when searching for
1093** the next directory entry that should be returned by the readdir() or
1094** readdir_r() functions.
1095*/
1096
1097#ifndef is_filtered
1098# define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM))
1099#endif
1100
1101/*
1102** Provide the function prototype for the POSIX compatiable getenv()
1103** function. This function is not thread-safe.
1104*/
1105
1106extern const char *windirent_getenv(const char *name);
1107
1108/*
1109** Finally, we can provide the function prototypes for the opendir(),
1110** readdir(), readdir_r(), and closedir() POSIX functions.
1111*/
1112
1113extern LPDIR opendir(const char *dirname);
1114extern LPDIRENT readdir(LPDIR dirp);
1115extern INT readdir_r(LPDIR dirp, LPDIRENT entry, LPDIRENT *result);
1116extern INT closedir(LPDIR dirp);
1117
1118#endif /* defined(WIN32) && defined(_MSC_VER) */
1119
1120/************************* End test_windirent.h ********************/
1121/************************* Begin test_windirent.c ******************/
1122/*
1123** 2015 November 30
1124**
1125** The author disclaims copyright to this source code. In place of
1126** a legal notice, here is a blessing:
1127**
1128** May you do good and not evil.
1129** May you find forgiveness for yourself and forgive others.
1130** May you share freely, never taking more than you give.
1131**
1132*************************************************************************
1133** This file contains code to implement most of the opendir() family of
1134** POSIX functions on Win32 using the MSVCRT.
1135*/
1136
1137#if defined(_WIN32) && defined(_MSC_VER)
1138/* #include "test_windirent.h" */
1139
1140/*
1141** Implementation of the POSIX getenv() function using the Win32 API.
1142** This function is not thread-safe.
1143*/
1144const char *windirent_getenv(
1145 const char *name
1146){
1147 static char value[32768]; /* Maximum length, per MSDN */
1148 DWORD dwSize = sizeof(value) / sizeof(char); /* Size in chars */
1149 DWORD dwRet; /* Value returned by GetEnvironmentVariableA() */
1150
1151 memset(value, 0, sizeof(value));
1152 dwRet = GetEnvironmentVariableA(name, value, dwSize);
1153 if( dwRet==0 || dwRet>dwSize ){
1154 /*
1155 ** The function call to GetEnvironmentVariableA() failed -OR-
1156 ** the buffer is not large enough. Either way, return NULL.
1157 */
1158 return 0;
1159 }else{
1160 /*
1161 ** The function call to GetEnvironmentVariableA() succeeded
1162 ** -AND- the buffer contains the entire value.
1163 */
1164 return value;
1165 }
1166}
1167
1168/*
1169** Implementation of the POSIX opendir() function using the MSVCRT.
1170*/
1171LPDIR opendir(
1172 const char *dirname
1173){
1174 struct _finddata_t data;
1175 LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR));
1176 SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]);
1177
1178 if( dirp==NULL ) return NULL;
1179 memset(dirp, 0, sizeof(DIR));
1180
1181 /* TODO: Remove this if Unix-style root paths are not used. */
1182 if( sqlite3_stricmp(dirname, "/")==0 ){
1183 dirname = windirent_getenv("SystemDrive");
1184 }
1185
1186 memset(&data, 0, sizeof(struct _finddata_t));
1187 _snprintf(data.name, namesize, "%s\\*", dirname);
1188 dirp->d_handle = _findfirst(data.name, &data);
1189
1190 if( dirp->d_handle==BAD_INTPTR_T ){
1191 closedir(dirp);
1192 return NULL;
1193 }
1194
1195 /* TODO: Remove this block to allow hidden and/or system files. */
1196 if( is_filtered(data) ){
1197next:
1198
1199 memset(&data, 0, sizeof(struct _finddata_t));
1200 if( _findnext(dirp->d_handle, &data)==-1 ){
1201 closedir(dirp);
1202 return NULL;
1203 }
1204
1205 /* TODO: Remove this block to allow hidden and/or system files. */
1206 if( is_filtered(data) ) goto next;
1207 }
1208
1209 dirp->d_first.d_attributes = data.attrib;
1210 strncpy(dirp->d_first.d_name, data.name, NAME_MAX);
1211 dirp->d_first.d_name[NAME_MAX] = '\0';
1212
1213 return dirp;
1214}
1215
1216/*
1217** Implementation of the POSIX readdir() function using the MSVCRT.
1218*/
1219LPDIRENT readdir(
1220 LPDIR dirp
1221){
1222 struct _finddata_t data;
1223
1224 if( dirp==NULL ) return NULL;
1225
1226 if( dirp->d_first.d_ino==0 ){
1227 dirp->d_first.d_ino++;
1228 dirp->d_next.d_ino++;
1229
1230 return &dirp->d_first;
1231 }
1232
1233next:
1234
1235 memset(&data, 0, sizeof(struct _finddata_t));
1236 if( _findnext(dirp->d_handle, &data)==-1 ) return NULL;
1237
1238 /* TODO: Remove this block to allow hidden and/or system files. */
1239 if( is_filtered(data) ) goto next;
1240
1241 dirp->d_next.d_ino++;
1242 dirp->d_next.d_attributes = data.attrib;
1243 strncpy(dirp->d_next.d_name, data.name, NAME_MAX);
1244 dirp->d_next.d_name[NAME_MAX] = '\0';
1245
1246 return &dirp->d_next;
1247}
1248
1249/*
1250** Implementation of the POSIX readdir_r() function using the MSVCRT.
1251*/
1252INT readdir_r(
1253 LPDIR dirp,
1254 LPDIRENT entry,
1255 LPDIRENT *result
1256){
1257 struct _finddata_t data;
1258
1259 if( dirp==NULL ) return EBADF;
1260
1261 if( dirp->d_first.d_ino==0 ){
1262 dirp->d_first.d_ino++;
1263 dirp->d_next.d_ino++;
1264
1265 entry->d_ino = dirp->d_first.d_ino;
1266 entry->d_attributes = dirp->d_first.d_attributes;
1267 strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX);
1268 entry->d_name[NAME_MAX] = '\0';
1269
1270 *result = entry;
1271 return 0;
1272 }
1273
1274next:
1275
1276 memset(&data, 0, sizeof(struct _finddata_t));
1277 if( _findnext(dirp->d_handle, &data)==-1 ){
1278 *result = NULL;
1279 return ENOENT;
1280 }
1281
1282 /* TODO: Remove this block to allow hidden and/or system files. */
1283 if( is_filtered(data) ) goto next;
1284
1285 entry->d_ino = (ino_t)-1; /* not available */
1286 entry->d_attributes = data.attrib;
1287 strncpy(entry->d_name, data.name, NAME_MAX);
1288 entry->d_name[NAME_MAX] = '\0';
1289
1290 *result = entry;
1291 return 0;
1292}
1293
1294/*
1295** Implementation of the POSIX closedir() function using the MSVCRT.
1296*/
1297INT closedir(
1298 LPDIR dirp
1299){
1300 INT result = 0;
1301
1302 if( dirp==NULL ) return EINVAL;
1303
1304 if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){
1305 result = _findclose(dirp->d_handle);
1306 }
1307
1308 sqlite3_free(dirp);
1309 return result;
1310}
1311
1312#endif /* defined(WIN32) && defined(_MSC_VER) */
1313
1314/************************* End test_windirent.c ********************/
1315#define dirent DIRENT
1316#endif
1317/************************* Begin ../ext/misc/shathree.c ******************/
1318/*
1319** 2017-03-08
1320**
1321** The author disclaims copyright to this source code. In place of
1322** a legal notice, here is a blessing:
1323**
1324** May you do good and not evil.
1325** May you find forgiveness for yourself and forgive others.
1326** May you share freely, never taking more than you give.
1327**
1328******************************************************************************
1329**
mydongistiny63ee58c2019-09-21 18:04:30 -07001330** This SQLite extension implements functions that compute SHA3 hashes.
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001331** Two SQL functions are implemented:
1332**
1333** sha3(X,SIZE)
1334** sha3_query(Y,SIZE)
1335**
1336** The sha3(X) function computes the SHA3 hash of the input X, or NULL if
1337** X is NULL.
1338**
1339** The sha3_query(Y) function evalutes all queries in the SQL statements of Y
1340** and returns a hash of their results.
1341**
1342** The SIZE argument is optional. If omitted, the SHA3-256 hash algorithm
1343** is used. If SIZE is included it must be one of the integers 224, 256,
1344** 384, or 512, to determine SHA3 hash variant that is computed.
1345*/
mydongistiny63ee58c2019-09-21 18:04:30 -07001346/* #include "sqlite3ext.h" */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001347SQLITE_EXTENSION_INIT1
1348#include <assert.h>
1349#include <string.h>
1350#include <stdarg.h>
1351/* typedef sqlite3_uint64 u64; */
1352
1353/******************************************************************************
1354** The Hash Engine
1355*/
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001356/*
1357** Macros to determine whether the machine is big or little endian,
1358** and whether or not that determination is run-time or compile-time.
1359**
1360** For best performance, an attempt is made to guess at the byte-order
1361** using C-preprocessor macros. If that is unsuccessful, or if
1362** -DSHA3_BYTEORDER=0 is set, then byte-order is determined
1363** at run-time.
1364*/
1365#ifndef SHA3_BYTEORDER
1366# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
1367 defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
1368 defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
1369 defined(__arm__)
1370# define SHA3_BYTEORDER 1234
1371# elif defined(sparc) || defined(__ppc__)
1372# define SHA3_BYTEORDER 4321
1373# else
1374# define SHA3_BYTEORDER 0
1375# endif
1376#endif
1377
1378
1379/*
1380** State structure for a SHA3 hash in progress
1381*/
1382typedef struct SHA3Context SHA3Context;
1383struct SHA3Context {
1384 union {
1385 u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */
1386 unsigned char x[1600]; /* ... or 1600 bytes */
1387 } u;
1388 unsigned nRate; /* Bytes of input accepted per Keccak iteration */
1389 unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */
1390 unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */
1391};
1392
1393/*
1394** A single step of the Keccak mixing function for a 1600-bit state
1395*/
1396static void KeccakF1600Step(SHA3Context *p){
1397 int i;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001398 u64 b0, b1, b2, b3, b4;
1399 u64 c0, c1, c2, c3, c4;
1400 u64 d0, d1, d2, d3, d4;
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001401 static const u64 RC[] = {
1402 0x0000000000000001ULL, 0x0000000000008082ULL,
1403 0x800000000000808aULL, 0x8000000080008000ULL,
1404 0x000000000000808bULL, 0x0000000080000001ULL,
1405 0x8000000080008081ULL, 0x8000000000008009ULL,
1406 0x000000000000008aULL, 0x0000000000000088ULL,
1407 0x0000000080008009ULL, 0x000000008000000aULL,
1408 0x000000008000808bULL, 0x800000000000008bULL,
1409 0x8000000000008089ULL, 0x8000000000008003ULL,
1410 0x8000000000008002ULL, 0x8000000000000080ULL,
1411 0x000000000000800aULL, 0x800000008000000aULL,
1412 0x8000000080008081ULL, 0x8000000000008080ULL,
1413 0x0000000080000001ULL, 0x8000000080008008ULL
1414 };
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001415# define a00 (p->u.s[0])
1416# define a01 (p->u.s[1])
1417# define a02 (p->u.s[2])
1418# define a03 (p->u.s[3])
1419# define a04 (p->u.s[4])
1420# define a10 (p->u.s[5])
1421# define a11 (p->u.s[6])
1422# define a12 (p->u.s[7])
1423# define a13 (p->u.s[8])
1424# define a14 (p->u.s[9])
1425# define a20 (p->u.s[10])
1426# define a21 (p->u.s[11])
1427# define a22 (p->u.s[12])
1428# define a23 (p->u.s[13])
1429# define a24 (p->u.s[14])
1430# define a30 (p->u.s[15])
1431# define a31 (p->u.s[16])
1432# define a32 (p->u.s[17])
1433# define a33 (p->u.s[18])
1434# define a34 (p->u.s[19])
1435# define a40 (p->u.s[20])
1436# define a41 (p->u.s[21])
1437# define a42 (p->u.s[22])
1438# define a43 (p->u.s[23])
1439# define a44 (p->u.s[24])
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001440# define ROL64(a,x) ((a<<x)|(a>>(64-x)))
1441
1442 for(i=0; i<24; i+=4){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001443 c0 = a00^a10^a20^a30^a40;
1444 c1 = a01^a11^a21^a31^a41;
1445 c2 = a02^a12^a22^a32^a42;
1446 c3 = a03^a13^a23^a33^a43;
1447 c4 = a04^a14^a24^a34^a44;
1448 d0 = c4^ROL64(c1, 1);
1449 d1 = c0^ROL64(c2, 1);
1450 d2 = c1^ROL64(c3, 1);
1451 d3 = c2^ROL64(c4, 1);
1452 d4 = c3^ROL64(c0, 1);
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001453
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001454 b0 = (a00^d0);
1455 b1 = ROL64((a11^d1), 44);
1456 b2 = ROL64((a22^d2), 43);
1457 b3 = ROL64((a33^d3), 21);
1458 b4 = ROL64((a44^d4), 14);
1459 a00 = b0 ^((~b1)& b2 );
1460 a00 ^= RC[i];
1461 a11 = b1 ^((~b2)& b3 );
1462 a22 = b2 ^((~b3)& b4 );
1463 a33 = b3 ^((~b4)& b0 );
1464 a44 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001465
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001466 b2 = ROL64((a20^d0), 3);
1467 b3 = ROL64((a31^d1), 45);
1468 b4 = ROL64((a42^d2), 61);
1469 b0 = ROL64((a03^d3), 28);
1470 b1 = ROL64((a14^d4), 20);
1471 a20 = b0 ^((~b1)& b2 );
1472 a31 = b1 ^((~b2)& b3 );
1473 a42 = b2 ^((~b3)& b4 );
1474 a03 = b3 ^((~b4)& b0 );
1475 a14 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001476
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001477 b4 = ROL64((a40^d0), 18);
1478 b0 = ROL64((a01^d1), 1);
1479 b1 = ROL64((a12^d2), 6);
1480 b2 = ROL64((a23^d3), 25);
1481 b3 = ROL64((a34^d4), 8);
1482 a40 = b0 ^((~b1)& b2 );
1483 a01 = b1 ^((~b2)& b3 );
1484 a12 = b2 ^((~b3)& b4 );
1485 a23 = b3 ^((~b4)& b0 );
1486 a34 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001487
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001488 b1 = ROL64((a10^d0), 36);
1489 b2 = ROL64((a21^d1), 10);
1490 b3 = ROL64((a32^d2), 15);
1491 b4 = ROL64((a43^d3), 56);
1492 b0 = ROL64((a04^d4), 27);
1493 a10 = b0 ^((~b1)& b2 );
1494 a21 = b1 ^((~b2)& b3 );
1495 a32 = b2 ^((~b3)& b4 );
1496 a43 = b3 ^((~b4)& b0 );
1497 a04 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001498
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001499 b3 = ROL64((a30^d0), 41);
1500 b4 = ROL64((a41^d1), 2);
1501 b0 = ROL64((a02^d2), 62);
1502 b1 = ROL64((a13^d3), 55);
1503 b2 = ROL64((a24^d4), 39);
1504 a30 = b0 ^((~b1)& b2 );
1505 a41 = b1 ^((~b2)& b3 );
1506 a02 = b2 ^((~b3)& b4 );
1507 a13 = b3 ^((~b4)& b0 );
1508 a24 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001509
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001510 c0 = a00^a20^a40^a10^a30;
1511 c1 = a11^a31^a01^a21^a41;
1512 c2 = a22^a42^a12^a32^a02;
1513 c3 = a33^a03^a23^a43^a13;
1514 c4 = a44^a14^a34^a04^a24;
1515 d0 = c4^ROL64(c1, 1);
1516 d1 = c0^ROL64(c2, 1);
1517 d2 = c1^ROL64(c3, 1);
1518 d3 = c2^ROL64(c4, 1);
1519 d4 = c3^ROL64(c0, 1);
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001520
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001521 b0 = (a00^d0);
1522 b1 = ROL64((a31^d1), 44);
1523 b2 = ROL64((a12^d2), 43);
1524 b3 = ROL64((a43^d3), 21);
1525 b4 = ROL64((a24^d4), 14);
1526 a00 = b0 ^((~b1)& b2 );
1527 a00 ^= RC[i+1];
1528 a31 = b1 ^((~b2)& b3 );
1529 a12 = b2 ^((~b3)& b4 );
1530 a43 = b3 ^((~b4)& b0 );
1531 a24 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001532
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001533 b2 = ROL64((a40^d0), 3);
1534 b3 = ROL64((a21^d1), 45);
1535 b4 = ROL64((a02^d2), 61);
1536 b0 = ROL64((a33^d3), 28);
1537 b1 = ROL64((a14^d4), 20);
1538 a40 = b0 ^((~b1)& b2 );
1539 a21 = b1 ^((~b2)& b3 );
1540 a02 = b2 ^((~b3)& b4 );
1541 a33 = b3 ^((~b4)& b0 );
1542 a14 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001543
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001544 b4 = ROL64((a30^d0), 18);
1545 b0 = ROL64((a11^d1), 1);
1546 b1 = ROL64((a42^d2), 6);
1547 b2 = ROL64((a23^d3), 25);
1548 b3 = ROL64((a04^d4), 8);
1549 a30 = b0 ^((~b1)& b2 );
1550 a11 = b1 ^((~b2)& b3 );
1551 a42 = b2 ^((~b3)& b4 );
1552 a23 = b3 ^((~b4)& b0 );
1553 a04 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001554
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001555 b1 = ROL64((a20^d0), 36);
1556 b2 = ROL64((a01^d1), 10);
1557 b3 = ROL64((a32^d2), 15);
1558 b4 = ROL64((a13^d3), 56);
1559 b0 = ROL64((a44^d4), 27);
1560 a20 = b0 ^((~b1)& b2 );
1561 a01 = b1 ^((~b2)& b3 );
1562 a32 = b2 ^((~b3)& b4 );
1563 a13 = b3 ^((~b4)& b0 );
1564 a44 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001565
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001566 b3 = ROL64((a10^d0), 41);
1567 b4 = ROL64((a41^d1), 2);
1568 b0 = ROL64((a22^d2), 62);
1569 b1 = ROL64((a03^d3), 55);
1570 b2 = ROL64((a34^d4), 39);
1571 a10 = b0 ^((~b1)& b2 );
1572 a41 = b1 ^((~b2)& b3 );
1573 a22 = b2 ^((~b3)& b4 );
1574 a03 = b3 ^((~b4)& b0 );
1575 a34 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001576
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001577 c0 = a00^a40^a30^a20^a10;
1578 c1 = a31^a21^a11^a01^a41;
1579 c2 = a12^a02^a42^a32^a22;
1580 c3 = a43^a33^a23^a13^a03;
1581 c4 = a24^a14^a04^a44^a34;
1582 d0 = c4^ROL64(c1, 1);
1583 d1 = c0^ROL64(c2, 1);
1584 d2 = c1^ROL64(c3, 1);
1585 d3 = c2^ROL64(c4, 1);
1586 d4 = c3^ROL64(c0, 1);
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001587
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001588 b0 = (a00^d0);
1589 b1 = ROL64((a21^d1), 44);
1590 b2 = ROL64((a42^d2), 43);
1591 b3 = ROL64((a13^d3), 21);
1592 b4 = ROL64((a34^d4), 14);
1593 a00 = b0 ^((~b1)& b2 );
1594 a00 ^= RC[i+2];
1595 a21 = b1 ^((~b2)& b3 );
1596 a42 = b2 ^((~b3)& b4 );
1597 a13 = b3 ^((~b4)& b0 );
1598 a34 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001599
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001600 b2 = ROL64((a30^d0), 3);
1601 b3 = ROL64((a01^d1), 45);
1602 b4 = ROL64((a22^d2), 61);
1603 b0 = ROL64((a43^d3), 28);
1604 b1 = ROL64((a14^d4), 20);
1605 a30 = b0 ^((~b1)& b2 );
1606 a01 = b1 ^((~b2)& b3 );
1607 a22 = b2 ^((~b3)& b4 );
1608 a43 = b3 ^((~b4)& b0 );
1609 a14 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001610
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001611 b4 = ROL64((a10^d0), 18);
1612 b0 = ROL64((a31^d1), 1);
1613 b1 = ROL64((a02^d2), 6);
1614 b2 = ROL64((a23^d3), 25);
1615 b3 = ROL64((a44^d4), 8);
1616 a10 = b0 ^((~b1)& b2 );
1617 a31 = b1 ^((~b2)& b3 );
1618 a02 = b2 ^((~b3)& b4 );
1619 a23 = b3 ^((~b4)& b0 );
1620 a44 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001621
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001622 b1 = ROL64((a40^d0), 36);
1623 b2 = ROL64((a11^d1), 10);
1624 b3 = ROL64((a32^d2), 15);
1625 b4 = ROL64((a03^d3), 56);
1626 b0 = ROL64((a24^d4), 27);
1627 a40 = b0 ^((~b1)& b2 );
1628 a11 = b1 ^((~b2)& b3 );
1629 a32 = b2 ^((~b3)& b4 );
1630 a03 = b3 ^((~b4)& b0 );
1631 a24 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001632
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001633 b3 = ROL64((a20^d0), 41);
1634 b4 = ROL64((a41^d1), 2);
1635 b0 = ROL64((a12^d2), 62);
1636 b1 = ROL64((a33^d3), 55);
1637 b2 = ROL64((a04^d4), 39);
1638 a20 = b0 ^((~b1)& b2 );
1639 a41 = b1 ^((~b2)& b3 );
1640 a12 = b2 ^((~b3)& b4 );
1641 a33 = b3 ^((~b4)& b0 );
1642 a04 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001643
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001644 c0 = a00^a30^a10^a40^a20;
1645 c1 = a21^a01^a31^a11^a41;
1646 c2 = a42^a22^a02^a32^a12;
1647 c3 = a13^a43^a23^a03^a33;
1648 c4 = a34^a14^a44^a24^a04;
1649 d0 = c4^ROL64(c1, 1);
1650 d1 = c0^ROL64(c2, 1);
1651 d2 = c1^ROL64(c3, 1);
1652 d3 = c2^ROL64(c4, 1);
1653 d4 = c3^ROL64(c0, 1);
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001654
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001655 b0 = (a00^d0);
1656 b1 = ROL64((a01^d1), 44);
1657 b2 = ROL64((a02^d2), 43);
1658 b3 = ROL64((a03^d3), 21);
1659 b4 = ROL64((a04^d4), 14);
1660 a00 = b0 ^((~b1)& b2 );
1661 a00 ^= RC[i+3];
1662 a01 = b1 ^((~b2)& b3 );
1663 a02 = b2 ^((~b3)& b4 );
1664 a03 = b3 ^((~b4)& b0 );
1665 a04 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001666
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001667 b2 = ROL64((a10^d0), 3);
1668 b3 = ROL64((a11^d1), 45);
1669 b4 = ROL64((a12^d2), 61);
1670 b0 = ROL64((a13^d3), 28);
1671 b1 = ROL64((a14^d4), 20);
1672 a10 = b0 ^((~b1)& b2 );
1673 a11 = b1 ^((~b2)& b3 );
1674 a12 = b2 ^((~b3)& b4 );
1675 a13 = b3 ^((~b4)& b0 );
1676 a14 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001677
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001678 b4 = ROL64((a20^d0), 18);
1679 b0 = ROL64((a21^d1), 1);
1680 b1 = ROL64((a22^d2), 6);
1681 b2 = ROL64((a23^d3), 25);
1682 b3 = ROL64((a24^d4), 8);
1683 a20 = b0 ^((~b1)& b2 );
1684 a21 = b1 ^((~b2)& b3 );
1685 a22 = b2 ^((~b3)& b4 );
1686 a23 = b3 ^((~b4)& b0 );
1687 a24 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001688
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001689 b1 = ROL64((a30^d0), 36);
1690 b2 = ROL64((a31^d1), 10);
1691 b3 = ROL64((a32^d2), 15);
1692 b4 = ROL64((a33^d3), 56);
1693 b0 = ROL64((a34^d4), 27);
1694 a30 = b0 ^((~b1)& b2 );
1695 a31 = b1 ^((~b2)& b3 );
1696 a32 = b2 ^((~b3)& b4 );
1697 a33 = b3 ^((~b4)& b0 );
1698 a34 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001699
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001700 b3 = ROL64((a40^d0), 41);
1701 b4 = ROL64((a41^d1), 2);
1702 b0 = ROL64((a42^d2), 62);
1703 b1 = ROL64((a43^d3), 55);
1704 b2 = ROL64((a44^d4), 39);
1705 a40 = b0 ^((~b1)& b2 );
1706 a41 = b1 ^((~b2)& b3 );
1707 a42 = b2 ^((~b3)& b4 );
1708 a43 = b3 ^((~b4)& b0 );
1709 a44 = b4 ^((~b0)& b1 );
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001710 }
1711}
1712
1713/*
1714** Initialize a new hash. iSize determines the size of the hash
1715** in bits and should be one of 224, 256, 384, or 512. Or iSize
1716** can be zero to use the default hash size of 256 bits.
1717*/
1718static void SHA3Init(SHA3Context *p, int iSize){
1719 memset(p, 0, sizeof(*p));
1720 if( iSize>=128 && iSize<=512 ){
1721 p->nRate = (1600 - ((iSize + 31)&~31)*2)/8;
1722 }else{
1723 p->nRate = (1600 - 2*256)/8;
1724 }
1725#if SHA3_BYTEORDER==1234
1726 /* Known to be little-endian at compile-time. No-op */
1727#elif SHA3_BYTEORDER==4321
1728 p->ixMask = 7; /* Big-endian */
1729#else
1730 {
1731 static unsigned int one = 1;
1732 if( 1==*(unsigned char*)&one ){
1733 /* Little endian. No byte swapping. */
1734 p->ixMask = 0;
1735 }else{
1736 /* Big endian. Byte swap. */
1737 p->ixMask = 7;
1738 }
1739 }
1740#endif
1741}
1742
1743/*
1744** Make consecutive calls to the SHA3Update function to add new content
1745** to the hash
1746*/
1747static void SHA3Update(
1748 SHA3Context *p,
1749 const unsigned char *aData,
1750 unsigned int nData
1751){
1752 unsigned int i = 0;
1753#if SHA3_BYTEORDER==1234
1754 if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
1755 for(; i+7<nData; i+=8){
1756 p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i];
1757 p->nLoaded += 8;
1758 if( p->nLoaded>=p->nRate ){
1759 KeccakF1600Step(p);
1760 p->nLoaded = 0;
1761 }
1762 }
1763 }
1764#endif
1765 for(; i<nData; i++){
1766#if SHA3_BYTEORDER==1234
1767 p->u.x[p->nLoaded] ^= aData[i];
1768#elif SHA3_BYTEORDER==4321
1769 p->u.x[p->nLoaded^0x07] ^= aData[i];
1770#else
1771 p->u.x[p->nLoaded^p->ixMask] ^= aData[i];
1772#endif
1773 p->nLoaded++;
1774 if( p->nLoaded==p->nRate ){
1775 KeccakF1600Step(p);
1776 p->nLoaded = 0;
1777 }
1778 }
1779}
1780
1781/*
1782** After all content has been added, invoke SHA3Final() to compute
1783** the final hash. The function returns a pointer to the binary
1784** hash value.
1785*/
1786static unsigned char *SHA3Final(SHA3Context *p){
1787 unsigned int i;
1788 if( p->nLoaded==p->nRate-1 ){
1789 const unsigned char c1 = 0x86;
1790 SHA3Update(p, &c1, 1);
1791 }else{
1792 const unsigned char c2 = 0x06;
1793 const unsigned char c3 = 0x80;
1794 SHA3Update(p, &c2, 1);
1795 p->nLoaded = p->nRate - 1;
1796 SHA3Update(p, &c3, 1);
1797 }
1798 for(i=0; i<p->nRate; i++){
1799 p->u.x[i+p->nRate] = p->u.x[i^p->ixMask];
1800 }
1801 return &p->u.x[p->nRate];
1802}
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08001803/* End of the hashing logic
1804*****************************************************************************/
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001805
1806/*
1807** Implementation of the sha3(X,SIZE) function.
1808**
1809** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default
1810** size is 256. If X is a BLOB, it is hashed as is.
1811** For all other non-NULL types of input, X is converted into a UTF-8 string
1812** and the string is hashed without the trailing 0x00 terminator. The hash
1813** of a NULL value is NULL.
1814*/
1815static void sha3Func(
1816 sqlite3_context *context,
1817 int argc,
1818 sqlite3_value **argv
1819){
1820 SHA3Context cx;
1821 int eType = sqlite3_value_type(argv[0]);
1822 int nByte = sqlite3_value_bytes(argv[0]);
1823 int iSize;
1824 if( argc==1 ){
1825 iSize = 256;
1826 }else{
1827 iSize = sqlite3_value_int(argv[1]);
1828 if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
1829 sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
1830 "384 512", -1);
1831 return;
1832 }
1833 }
1834 if( eType==SQLITE_NULL ) return;
1835 SHA3Init(&cx, iSize);
1836 if( eType==SQLITE_BLOB ){
1837 SHA3Update(&cx, sqlite3_value_blob(argv[0]), nByte);
1838 }else{
1839 SHA3Update(&cx, sqlite3_value_text(argv[0]), nByte);
1840 }
1841 sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
1842}
1843
1844/* Compute a string using sqlite3_vsnprintf() with a maximum length
1845** of 50 bytes and add it to the hash.
1846*/
1847static void hash_step_vformat(
1848 SHA3Context *p, /* Add content to this context */
1849 const char *zFormat,
1850 ...
1851){
1852 va_list ap;
1853 int n;
1854 char zBuf[50];
1855 va_start(ap, zFormat);
1856 sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
1857 va_end(ap);
1858 n = (int)strlen(zBuf);
1859 SHA3Update(p, (unsigned char*)zBuf, n);
1860}
1861
1862/*
1863** Implementation of the sha3_query(SQL,SIZE) function.
1864**
1865** This function compiles and runs the SQL statement(s) given in the
1866** argument. The results are hashed using a SIZE-bit SHA3. The default
1867** size is 256.
1868**
1869** The format of the byte stream that is hashed is summarized as follows:
1870**
1871** S<n>:<sql>
1872** R
1873** N
1874** I<int>
1875** F<ieee-float>
1876** B<size>:<bytes>
1877** T<size>:<text>
1878**
1879** <sql> is the original SQL text for each statement run and <n> is
1880** the size of that text. The SQL text is UTF-8. A single R character
1881** occurs before the start of each row. N means a NULL value.
1882** I mean an 8-byte little-endian integer <int>. F is a floating point
1883** number with an 8-byte little-endian IEEE floating point value <ieee-float>.
1884** B means blobs of <size> bytes. T means text rendered as <size>
1885** bytes of UTF-8. The <n> and <size> values are expressed as an ASCII
1886** text integers.
1887**
1888** For each SQL statement in the X input, there is one S segment. Each
1889** S segment is followed by zero or more R segments, one for each row in the
1890** result set. After each R, there are one or more N, I, F, B, or T segments,
1891** one for each column in the result set. Segments are concatentated directly
1892** with no delimiters of any kind.
1893*/
1894static void sha3QueryFunc(
1895 sqlite3_context *context,
1896 int argc,
1897 sqlite3_value **argv
1898){
1899 sqlite3 *db = sqlite3_context_db_handle(context);
1900 const char *zSql = (const char*)sqlite3_value_text(argv[0]);
1901 sqlite3_stmt *pStmt = 0;
1902 int nCol; /* Number of columns in the result set */
1903 int i; /* Loop counter */
1904 int rc;
1905 int n;
1906 const char *z;
1907 SHA3Context cx;
1908 int iSize;
1909
1910 if( argc==1 ){
1911 iSize = 256;
1912 }else{
1913 iSize = sqlite3_value_int(argv[1]);
1914 if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
1915 sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
1916 "384 512", -1);
1917 return;
1918 }
1919 }
1920 if( zSql==0 ) return;
1921 SHA3Init(&cx, iSize);
1922 while( zSql[0] ){
1923 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
1924 if( rc ){
1925 char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s",
1926 zSql, sqlite3_errmsg(db));
1927 sqlite3_finalize(pStmt);
1928 sqlite3_result_error(context, zMsg, -1);
1929 sqlite3_free(zMsg);
1930 return;
1931 }
1932 if( !sqlite3_stmt_readonly(pStmt) ){
1933 char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt));
1934 sqlite3_finalize(pStmt);
1935 sqlite3_result_error(context, zMsg, -1);
1936 sqlite3_free(zMsg);
1937 return;
1938 }
1939 nCol = sqlite3_column_count(pStmt);
1940 z = sqlite3_sql(pStmt);
Alex Naidisb86c0cf2017-03-31 14:12:35 +02001941 n = (int)strlen(z);
1942 hash_step_vformat(&cx,"S%d:",n);
1943 SHA3Update(&cx,(unsigned char*)z,n);
1944
1945 /* Compute a hash over the result of the query */
1946 while( SQLITE_ROW==sqlite3_step(pStmt) ){
1947 SHA3Update(&cx,(const unsigned char*)"R",1);
1948 for(i=0; i<nCol; i++){
1949 switch( sqlite3_column_type(pStmt,i) ){
1950 case SQLITE_NULL: {
1951 SHA3Update(&cx, (const unsigned char*)"N",1);
1952 break;
1953 }
1954 case SQLITE_INTEGER: {
1955 sqlite3_uint64 u;
1956 int j;
1957 unsigned char x[9];
1958 sqlite3_int64 v = sqlite3_column_int64(pStmt,i);
1959 memcpy(&u, &v, 8);
1960 for(j=8; j>=1; j--){
1961 x[j] = u & 0xff;
1962 u >>= 8;
1963 }
1964 x[0] = 'I';
1965 SHA3Update(&cx, x, 9);
1966 break;
1967 }
1968 case SQLITE_FLOAT: {
1969 sqlite3_uint64 u;
1970 int j;
1971 unsigned char x[9];
1972 double r = sqlite3_column_double(pStmt,i);
1973 memcpy(&u, &r, 8);
1974 for(j=8; j>=1; j--){
1975 x[j] = u & 0xff;
1976 u >>= 8;
1977 }
1978 x[0] = 'F';
1979 SHA3Update(&cx,x,9);
1980 break;
1981 }
1982 case SQLITE_TEXT: {
1983 int n2 = sqlite3_column_bytes(pStmt, i);
1984 const unsigned char *z2 = sqlite3_column_text(pStmt, i);
1985 hash_step_vformat(&cx,"T%d:",n2);
1986 SHA3Update(&cx, z2, n2);
1987 break;
1988 }
1989 case SQLITE_BLOB: {
1990 int n2 = sqlite3_column_bytes(pStmt, i);
1991 const unsigned char *z2 = sqlite3_column_blob(pStmt, i);
1992 hash_step_vformat(&cx,"B%d:",n2);
1993 SHA3Update(&cx, z2, n2);
1994 break;
1995 }
1996 }
1997 }
1998 }
1999 sqlite3_finalize(pStmt);
2000 }
2001 sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
2002}
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002003
2004
2005#ifdef _WIN32
2006
2007#endif
2008int sqlite3_shathree_init(
2009 sqlite3 *db,
2010 char **pzErrMsg,
2011 const sqlite3_api_routines *pApi
2012){
2013 int rc = SQLITE_OK;
2014 SQLITE_EXTENSION_INIT2(pApi);
2015 (void)pzErrMsg; /* Unused parameter */
2016 rc = sqlite3_create_function(db, "sha3", 1, SQLITE_UTF8, 0,
2017 sha3Func, 0, 0);
2018 if( rc==SQLITE_OK ){
2019 rc = sqlite3_create_function(db, "sha3", 2, SQLITE_UTF8, 0,
2020 sha3Func, 0, 0);
2021 }
2022 if( rc==SQLITE_OK ){
2023 rc = sqlite3_create_function(db, "sha3_query", 1, SQLITE_UTF8, 0,
2024 sha3QueryFunc, 0, 0);
2025 }
2026 if( rc==SQLITE_OK ){
2027 rc = sqlite3_create_function(db, "sha3_query", 2, SQLITE_UTF8, 0,
2028 sha3QueryFunc, 0, 0);
2029 }
2030 return rc;
2031}
2032
2033/************************* End ../ext/misc/shathree.c ********************/
2034/************************* Begin ../ext/misc/fileio.c ******************/
2035/*
2036** 2014-06-13
2037**
2038** The author disclaims copyright to this source code. In place of
2039** a legal notice, here is a blessing:
2040**
2041** May you do good and not evil.
2042** May you find forgiveness for yourself and forgive others.
2043** May you share freely, never taking more than you give.
2044**
2045******************************************************************************
2046**
2047** This SQLite extension implements SQL functions readfile() and
2048** writefile(), and eponymous virtual type "fsdir".
2049**
2050** WRITEFILE(FILE, DATA [, MODE [, MTIME]]):
2051**
2052** If neither of the optional arguments is present, then this UDF
2053** function writes blob DATA to file FILE. If successful, the number
2054** of bytes written is returned. If an error occurs, NULL is returned.
2055**
2056** If the first option argument - MODE - is present, then it must
2057** be passed an integer value that corresponds to a POSIX mode
2058** value (file type + permissions, as returned in the stat.st_mode
2059** field by the stat() system call). Three types of files may
2060** be written/created:
2061**
2062** regular files: (mode & 0170000)==0100000
2063** symbolic links: (mode & 0170000)==0120000
2064** directories: (mode & 0170000)==0040000
2065**
2066** For a directory, the DATA is ignored. For a symbolic link, it is
2067** interpreted as text and used as the target of the link. For a
2068** regular file, it is interpreted as a blob and written into the
2069** named file. Regardless of the type of file, its permissions are
2070** set to (mode & 0777) before returning.
2071**
2072** If the optional MTIME argument is present, then it is interpreted
2073** as an integer - the number of seconds since the unix epoch. The
2074** modification-time of the target file is set to this value before
2075** returning.
2076**
2077** If three or more arguments are passed to this function and an
2078** error is encountered, an exception is raised.
2079**
2080** READFILE(FILE):
2081**
2082** Read and return the contents of file FILE (type blob) from disk.
2083**
2084** FSDIR:
2085**
2086** Used as follows:
2087**
2088** SELECT * FROM fsdir($path [, $dir]);
2089**
2090** Parameter $path is an absolute or relative pathname. If the file that it
2091** refers to does not exist, it is an error. If the path refers to a regular
2092** file or symbolic link, it returns a single row. Or, if the path refers
2093** to a directory, it returns one row for the directory, and one row for each
2094** file within the hierarchy rooted at $path.
2095**
2096** Each row has the following columns:
2097**
2098** name: Path to file or directory (text value).
2099** mode: Value of stat.st_mode for directory entry (an integer).
2100** mtime: Value of stat.st_mtime for directory entry (an integer).
2101** data: For a regular file, a blob containing the file data. For a
2102** symlink, a text value containing the text of the link. For a
2103** directory, NULL.
2104**
2105** If a non-NULL value is specified for the optional $dir parameter and
2106** $path is a relative path, then $path is interpreted relative to $dir.
2107** And the paths returned in the "name" column of the table are also
2108** relative to directory $dir.
2109*/
mydongistiny63ee58c2019-09-21 18:04:30 -07002110/* #include "sqlite3ext.h" */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002111SQLITE_EXTENSION_INIT1
2112#include <stdio.h>
2113#include <string.h>
2114#include <assert.h>
2115
2116#include <sys/types.h>
2117#include <sys/stat.h>
2118#include <fcntl.h>
2119#if !defined(_WIN32) && !defined(WIN32)
2120# include <unistd.h>
2121# include <dirent.h>
2122# include <utime.h>
2123# include <sys/time.h>
2124#else
2125# include "windows.h"
2126# include <io.h>
2127# include <direct.h>
2128/* # include "test_windirent.h" */
2129# define dirent DIRENT
mydongistiny63ee58c2019-09-21 18:04:30 -07002130# ifndef chmod
2131# define chmod _chmod
2132# endif
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002133# ifndef stat
2134# define stat _stat
2135# endif
2136# define mkdir(path,mode) _mkdir(path)
2137# define lstat(path,buf) stat(path,buf)
2138#endif
2139#include <time.h>
2140#include <errno.h>
2141
2142
mydongistiny63ee58c2019-09-21 18:04:30 -07002143/*
2144** Structure of the fsdir() table-valued function
2145*/
2146 /* 0 1 2 3 4 5 */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002147#define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)"
mydongistiny63ee58c2019-09-21 18:04:30 -07002148#define FSDIR_COLUMN_NAME 0 /* Name of the file */
2149#define FSDIR_COLUMN_MODE 1 /* Access mode */
2150#define FSDIR_COLUMN_MTIME 2 /* Last modification time */
2151#define FSDIR_COLUMN_DATA 3 /* File content */
2152#define FSDIR_COLUMN_PATH 4 /* Path to top of search */
2153#define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */
2154
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002155
2156/*
2157** Set the result stored by context ctx to a blob containing the
mydongistiny63ee58c2019-09-21 18:04:30 -07002158** contents of file zName. Or, leave the result unchanged (NULL)
2159** if the file does not exist or is unreadable.
2160**
2161** If the file exceeds the SQLite blob size limit, through an
2162** SQLITE_TOOBIG error.
2163**
2164** Throw an SQLITE_IOERR if there are difficulties pulling the file
2165** off of disk.
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002166*/
2167static void readFileContents(sqlite3_context *ctx, const char *zName){
2168 FILE *in;
mydongistiny63ee58c2019-09-21 18:04:30 -07002169 sqlite3_int64 nIn;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002170 void *pBuf;
mydongistiny63ee58c2019-09-21 18:04:30 -07002171 sqlite3 *db;
2172 int mxBlob;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002173
2174 in = fopen(zName, "rb");
mydongistiny63ee58c2019-09-21 18:04:30 -07002175 if( in==0 ){
2176 /* File does not exist or is unreadable. Leave the result set to NULL. */
2177 return;
2178 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002179 fseek(in, 0, SEEK_END);
2180 nIn = ftell(in);
2181 rewind(in);
mydongistiny63ee58c2019-09-21 18:04:30 -07002182 db = sqlite3_context_db_handle(ctx);
2183 mxBlob = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1);
2184 if( nIn>mxBlob ){
2185 sqlite3_result_error_code(ctx, SQLITE_TOOBIG);
2186 fclose(in);
2187 return;
2188 }
2189 pBuf = sqlite3_malloc64( nIn ? nIn : 1 );
2190 if( pBuf==0 ){
2191 sqlite3_result_error_nomem(ctx);
2192 fclose(in);
2193 return;
2194 }
2195 if( nIn==(sqlite3_int64)fread(pBuf, 1, (size_t)nIn, in) ){
2196 sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002197 }else{
mydongistiny63ee58c2019-09-21 18:04:30 -07002198 sqlite3_result_error_code(ctx, SQLITE_IOERR);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002199 sqlite3_free(pBuf);
2200 }
2201 fclose(in);
2202}
2203
2204/*
2205** Implementation of the "readfile(X)" SQL function. The entire content
2206** of the file named X is read and returned as a BLOB. NULL is returned
2207** if the file does not exist or is unreadable.
2208*/
2209static void readfileFunc(
2210 sqlite3_context *context,
2211 int argc,
2212 sqlite3_value **argv
2213){
2214 const char *zName;
2215 (void)(argc); /* Unused parameter */
2216 zName = (const char*)sqlite3_value_text(argv[0]);
2217 if( zName==0 ) return;
2218 readFileContents(context, zName);
2219}
2220
2221/*
2222** Set the error message contained in context ctx to the results of
2223** vprintf(zFmt, ...).
2224*/
2225static void ctxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
2226 char *zMsg = 0;
2227 va_list ap;
2228 va_start(ap, zFmt);
2229 zMsg = sqlite3_vmprintf(zFmt, ap);
2230 sqlite3_result_error(ctx, zMsg, -1);
2231 sqlite3_free(zMsg);
2232 va_end(ap);
2233}
2234
mydongistiny63ee58c2019-09-21 18:04:30 -07002235#if defined(_WIN32)
2236/*
2237** This function is designed to convert a Win32 FILETIME structure into the
2238** number of seconds since the Unix Epoch (1970-01-01 00:00:00 UTC).
2239*/
2240static sqlite3_uint64 fileTimeToUnixTime(
2241 LPFILETIME pFileTime
2242){
2243 SYSTEMTIME epochSystemTime;
2244 ULARGE_INTEGER epochIntervals;
2245 FILETIME epochFileTime;
2246 ULARGE_INTEGER fileIntervals;
2247
2248 memset(&epochSystemTime, 0, sizeof(SYSTEMTIME));
2249 epochSystemTime.wYear = 1970;
2250 epochSystemTime.wMonth = 1;
2251 epochSystemTime.wDay = 1;
2252 SystemTimeToFileTime(&epochSystemTime, &epochFileTime);
2253 epochIntervals.LowPart = epochFileTime.dwLowDateTime;
2254 epochIntervals.HighPart = epochFileTime.dwHighDateTime;
2255
2256 fileIntervals.LowPart = pFileTime->dwLowDateTime;
2257 fileIntervals.HighPart = pFileTime->dwHighDateTime;
2258
2259 return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000;
2260}
2261
2262/*
2263** This function attempts to normalize the time values found in the stat()
2264** buffer to UTC. This is necessary on Win32, where the runtime library
2265** appears to return these values as local times.
2266*/
2267static void statTimesToUtc(
2268 const char *zPath,
2269 struct stat *pStatBuf
2270){
2271 HANDLE hFindFile;
2272 WIN32_FIND_DATAW fd;
2273 LPWSTR zUnicodeName;
2274 extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
2275 zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath);
2276 if( zUnicodeName ){
2277 memset(&fd, 0, sizeof(WIN32_FIND_DATAW));
2278 hFindFile = FindFirstFileW(zUnicodeName, &fd);
2279 if( hFindFile!=NULL ){
2280 pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime);
2281 pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime);
2282 pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime);
2283 FindClose(hFindFile);
2284 }
2285 sqlite3_free(zUnicodeName);
2286 }
2287}
2288#endif
2289
2290/*
2291** This function is used in place of stat(). On Windows, special handling
2292** is required in order for the included time to be returned as UTC. On all
2293** other systems, this function simply calls stat().
2294*/
2295static int fileStat(
2296 const char *zPath,
2297 struct stat *pStatBuf
2298){
2299#if defined(_WIN32)
2300 int rc = stat(zPath, pStatBuf);
2301 if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
2302 return rc;
2303#else
2304 return stat(zPath, pStatBuf);
2305#endif
2306}
2307
2308/*
2309** This function is used in place of lstat(). On Windows, special handling
2310** is required in order for the included time to be returned as UTC. On all
2311** other systems, this function simply calls lstat().
2312*/
2313static int fileLinkStat(
2314 const char *zPath,
2315 struct stat *pStatBuf
2316){
2317#if defined(_WIN32)
2318 int rc = lstat(zPath, pStatBuf);
2319 if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
2320 return rc;
2321#else
2322 return lstat(zPath, pStatBuf);
2323#endif
2324}
2325
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002326/*
2327** Argument zFile is the name of a file that will be created and/or written
2328** by SQL function writefile(). This function ensures that the directory
2329** zFile will be written to exists, creating it if required. The permissions
mydongistiny63ee58c2019-09-21 18:04:30 -07002330** for any path components created by this function are set in accordance
2331** with the current umask.
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002332**
2333** If an OOM condition is encountered, SQLITE_NOMEM is returned. Otherwise,
2334** SQLITE_OK is returned if the directory is successfully created, or
2335** SQLITE_ERROR otherwise.
2336*/
2337static int makeDirectory(
mydongistiny63ee58c2019-09-21 18:04:30 -07002338 const char *zFile
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002339){
2340 char *zCopy = sqlite3_mprintf("%s", zFile);
2341 int rc = SQLITE_OK;
2342
2343 if( zCopy==0 ){
2344 rc = SQLITE_NOMEM;
2345 }else{
2346 int nCopy = (int)strlen(zCopy);
2347 int i = 1;
2348
2349 while( rc==SQLITE_OK ){
2350 struct stat sStat;
2351 int rc2;
2352
2353 for(; zCopy[i]!='/' && i<nCopy; i++);
2354 if( i==nCopy ) break;
2355 zCopy[i] = '\0';
2356
mydongistiny63ee58c2019-09-21 18:04:30 -07002357 rc2 = fileStat(zCopy, &sStat);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002358 if( rc2!=0 ){
mydongistiny63ee58c2019-09-21 18:04:30 -07002359 if( mkdir(zCopy, 0777) ) rc = SQLITE_ERROR;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002360 }else{
2361 if( !S_ISDIR(sStat.st_mode) ) rc = SQLITE_ERROR;
2362 }
2363 zCopy[i] = '/';
2364 i++;
2365 }
2366
2367 sqlite3_free(zCopy);
2368 }
2369
2370 return rc;
2371}
2372
2373/*
2374** This function does the work for the writefile() UDF. Refer to
2375** header comments at the top of this file for details.
2376*/
2377static int writeFile(
2378 sqlite3_context *pCtx, /* Context to return bytes written in */
2379 const char *zFile, /* File to write */
2380 sqlite3_value *pData, /* Data to write */
2381 mode_t mode, /* MODE parameter passed to writefile() */
2382 sqlite3_int64 mtime /* MTIME parameter (or -1 to not set time) */
2383){
2384#if !defined(_WIN32) && !defined(WIN32)
2385 if( S_ISLNK(mode) ){
2386 const char *zTo = (const char*)sqlite3_value_text(pData);
2387 if( symlink(zTo, zFile)<0 ) return 1;
2388 }else
2389#endif
2390 {
2391 if( S_ISDIR(mode) ){
2392 if( mkdir(zFile, mode) ){
2393 /* The mkdir() call to create the directory failed. This might not
2394 ** be an error though - if there is already a directory at the same
2395 ** path and either the permissions already match or can be changed
2396 ** to do so using chmod(), it is not an error. */
2397 struct stat sStat;
2398 if( errno!=EEXIST
mydongistiny63ee58c2019-09-21 18:04:30 -07002399 || 0!=fileStat(zFile, &sStat)
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002400 || !S_ISDIR(sStat.st_mode)
2401 || ((sStat.st_mode&0777)!=(mode&0777) && 0!=chmod(zFile, mode&0777))
2402 ){
2403 return 1;
2404 }
2405 }
2406 }else{
2407 sqlite3_int64 nWrite = 0;
2408 const char *z;
2409 int rc = 0;
2410 FILE *out = fopen(zFile, "wb");
2411 if( out==0 ) return 1;
2412 z = (const char*)sqlite3_value_blob(pData);
2413 if( z ){
2414 sqlite3_int64 n = fwrite(z, 1, sqlite3_value_bytes(pData), out);
2415 nWrite = sqlite3_value_bytes(pData);
2416 if( nWrite!=n ){
2417 rc = 1;
2418 }
2419 }
2420 fclose(out);
2421 if( rc==0 && mode && chmod(zFile, mode & 0777) ){
2422 rc = 1;
2423 }
2424 if( rc ) return 2;
2425 sqlite3_result_int64(pCtx, nWrite);
2426 }
2427 }
2428
2429 if( mtime>=0 ){
2430#if defined(_WIN32)
2431 /* Windows */
2432 FILETIME lastAccess;
2433 FILETIME lastWrite;
2434 SYSTEMTIME currentTime;
2435 LONGLONG intervals;
2436 HANDLE hFile;
mydongistiny63ee58c2019-09-21 18:04:30 -07002437 LPWSTR zUnicodeName;
2438 extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
2439
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002440 GetSystemTime(&currentTime);
2441 SystemTimeToFileTime(&currentTime, &lastAccess);
2442 intervals = Int32x32To64(mtime, 10000000) + 116444736000000000;
2443 lastWrite.dwLowDateTime = (DWORD)intervals;
2444 lastWrite.dwHighDateTime = intervals >> 32;
mydongistiny63ee58c2019-09-21 18:04:30 -07002445 zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile);
2446 if( zUnicodeName==0 ){
2447 return 1;
2448 }
2449 hFile = CreateFileW(
2450 zUnicodeName, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002451 FILE_FLAG_BACKUP_SEMANTICS, NULL
2452 );
mydongistiny63ee58c2019-09-21 18:04:30 -07002453 sqlite3_free(zUnicodeName);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002454 if( hFile!=INVALID_HANDLE_VALUE ){
2455 BOOL bResult = SetFileTime(hFile, NULL, &lastAccess, &lastWrite);
2456 CloseHandle(hFile);
2457 return !bResult;
2458 }else{
2459 return 1;
2460 }
mydongistiny63ee58c2019-09-21 18:04:30 -07002461#elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002462 /* Recent unix */
2463 struct timespec times[2];
2464 times[0].tv_nsec = times[1].tv_nsec = 0;
2465 times[0].tv_sec = time(0);
2466 times[1].tv_sec = mtime;
2467 if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){
2468 return 1;
2469 }
2470#else
2471 /* Legacy unix */
2472 struct timeval times[2];
2473 times[0].tv_usec = times[1].tv_usec = 0;
2474 times[0].tv_sec = time(0);
2475 times[1].tv_sec = mtime;
2476 if( utimes(zFile, times) ){
2477 return 1;
2478 }
2479#endif
2480 }
2481
2482 return 0;
2483}
2484
2485/*
2486** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function.
2487** Refer to header comments at the top of this file for details.
2488*/
2489static void writefileFunc(
2490 sqlite3_context *context,
2491 int argc,
2492 sqlite3_value **argv
2493){
2494 const char *zFile;
2495 mode_t mode = 0;
2496 int res;
2497 sqlite3_int64 mtime = -1;
2498
2499 if( argc<2 || argc>4 ){
2500 sqlite3_result_error(context,
2501 "wrong number of arguments to function writefile()", -1
2502 );
2503 return;
2504 }
2505
2506 zFile = (const char*)sqlite3_value_text(argv[0]);
2507 if( zFile==0 ) return;
2508 if( argc>=3 ){
2509 mode = (mode_t)sqlite3_value_int(argv[2]);
2510 }
2511 if( argc==4 ){
2512 mtime = sqlite3_value_int64(argv[3]);
2513 }
2514
2515 res = writeFile(context, zFile, argv[1], mode, mtime);
2516 if( res==1 && errno==ENOENT ){
mydongistiny63ee58c2019-09-21 18:04:30 -07002517 if( makeDirectory(zFile)==SQLITE_OK ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002518 res = writeFile(context, zFile, argv[1], mode, mtime);
2519 }
2520 }
2521
2522 if( argc>2 && res!=0 ){
2523 if( S_ISLNK(mode) ){
2524 ctxErrorMsg(context, "failed to create symlink: %s", zFile);
2525 }else if( S_ISDIR(mode) ){
2526 ctxErrorMsg(context, "failed to create directory: %s", zFile);
2527 }else{
2528 ctxErrorMsg(context, "failed to write file: %s", zFile);
2529 }
2530 }
2531}
2532
2533/*
2534** SQL function: lsmode(MODE)
2535**
2536** Given a numberic st_mode from stat(), convert it into a human-readable
2537** text string in the style of "ls -l".
2538*/
2539static void lsModeFunc(
2540 sqlite3_context *context,
2541 int argc,
2542 sqlite3_value **argv
2543){
2544 int i;
2545 int iMode = sqlite3_value_int(argv[0]);
2546 char z[16];
2547 (void)argc;
2548 if( S_ISLNK(iMode) ){
2549 z[0] = 'l';
2550 }else if( S_ISREG(iMode) ){
2551 z[0] = '-';
2552 }else if( S_ISDIR(iMode) ){
2553 z[0] = 'd';
2554 }else{
2555 z[0] = '?';
2556 }
2557 for(i=0; i<3; i++){
2558 int m = (iMode >> ((2-i)*3));
2559 char *a = &z[1 + i*3];
2560 a[0] = (m & 0x4) ? 'r' : '-';
2561 a[1] = (m & 0x2) ? 'w' : '-';
2562 a[2] = (m & 0x1) ? 'x' : '-';
2563 }
2564 z[10] = '\0';
2565 sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
2566}
2567
2568#ifndef SQLITE_OMIT_VIRTUALTABLE
2569
2570/*
2571** Cursor type for recursively iterating through a directory structure.
2572*/
2573typedef struct fsdir_cursor fsdir_cursor;
2574typedef struct FsdirLevel FsdirLevel;
2575
2576struct FsdirLevel {
2577 DIR *pDir; /* From opendir() */
2578 char *zDir; /* Name of directory (nul-terminated) */
2579};
2580
2581struct fsdir_cursor {
2582 sqlite3_vtab_cursor base; /* Base class - must be first */
2583
2584 int nLvl; /* Number of entries in aLvl[] array */
2585 int iLvl; /* Index of current entry */
2586 FsdirLevel *aLvl; /* Hierarchy of directories being traversed */
2587
2588 const char *zBase;
2589 int nBase;
2590
2591 struct stat sStat; /* Current lstat() results */
2592 char *zPath; /* Path to current entry */
2593 sqlite3_int64 iRowid; /* Current rowid */
2594};
2595
2596typedef struct fsdir_tab fsdir_tab;
2597struct fsdir_tab {
2598 sqlite3_vtab base; /* Base class - must be first */
2599};
2600
2601/*
2602** Construct a new fsdir virtual table object.
2603*/
2604static int fsdirConnect(
2605 sqlite3 *db,
2606 void *pAux,
2607 int argc, const char *const*argv,
2608 sqlite3_vtab **ppVtab,
2609 char **pzErr
2610){
2611 fsdir_tab *pNew = 0;
2612 int rc;
2613 (void)pAux;
2614 (void)argc;
2615 (void)argv;
2616 (void)pzErr;
2617 rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA);
2618 if( rc==SQLITE_OK ){
2619 pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) );
2620 if( pNew==0 ) return SQLITE_NOMEM;
2621 memset(pNew, 0, sizeof(*pNew));
2622 }
2623 *ppVtab = (sqlite3_vtab*)pNew;
2624 return rc;
2625}
2626
2627/*
2628** This method is the destructor for fsdir vtab objects.
2629*/
2630static int fsdirDisconnect(sqlite3_vtab *pVtab){
2631 sqlite3_free(pVtab);
2632 return SQLITE_OK;
2633}
2634
2635/*
2636** Constructor for a new fsdir_cursor object.
2637*/
2638static int fsdirOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
2639 fsdir_cursor *pCur;
2640 (void)p;
2641 pCur = sqlite3_malloc( sizeof(*pCur) );
2642 if( pCur==0 ) return SQLITE_NOMEM;
2643 memset(pCur, 0, sizeof(*pCur));
2644 pCur->iLvl = -1;
2645 *ppCursor = &pCur->base;
2646 return SQLITE_OK;
2647}
2648
2649/*
2650** Reset a cursor back to the state it was in when first returned
2651** by fsdirOpen().
2652*/
2653static void fsdirResetCursor(fsdir_cursor *pCur){
2654 int i;
2655 for(i=0; i<=pCur->iLvl; i++){
2656 FsdirLevel *pLvl = &pCur->aLvl[i];
2657 if( pLvl->pDir ) closedir(pLvl->pDir);
2658 sqlite3_free(pLvl->zDir);
2659 }
2660 sqlite3_free(pCur->zPath);
mydongistiny63ee58c2019-09-21 18:04:30 -07002661 sqlite3_free(pCur->aLvl);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002662 pCur->aLvl = 0;
2663 pCur->zPath = 0;
2664 pCur->zBase = 0;
2665 pCur->nBase = 0;
mydongistiny63ee58c2019-09-21 18:04:30 -07002666 pCur->nLvl = 0;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002667 pCur->iLvl = -1;
2668 pCur->iRowid = 1;
2669}
2670
2671/*
2672** Destructor for an fsdir_cursor.
2673*/
2674static int fsdirClose(sqlite3_vtab_cursor *cur){
2675 fsdir_cursor *pCur = (fsdir_cursor*)cur;
2676
2677 fsdirResetCursor(pCur);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002678 sqlite3_free(pCur);
2679 return SQLITE_OK;
2680}
2681
2682/*
2683** Set the error message for the virtual table associated with cursor
2684** pCur to the results of vprintf(zFmt, ...).
2685*/
2686static void fsdirSetErrmsg(fsdir_cursor *pCur, const char *zFmt, ...){
2687 va_list ap;
2688 va_start(ap, zFmt);
2689 pCur->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
2690 va_end(ap);
2691}
2692
2693
2694/*
2695** Advance an fsdir_cursor to its next row of output.
2696*/
2697static int fsdirNext(sqlite3_vtab_cursor *cur){
2698 fsdir_cursor *pCur = (fsdir_cursor*)cur;
2699 mode_t m = pCur->sStat.st_mode;
2700
2701 pCur->iRowid++;
2702 if( S_ISDIR(m) ){
2703 /* Descend into this directory */
2704 int iNew = pCur->iLvl + 1;
2705 FsdirLevel *pLvl;
2706 if( iNew>=pCur->nLvl ){
2707 int nNew = iNew+1;
mydongistiny63ee58c2019-09-21 18:04:30 -07002708 sqlite3_int64 nByte = nNew*sizeof(FsdirLevel);
2709 FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc64(pCur->aLvl, nByte);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002710 if( aNew==0 ) return SQLITE_NOMEM;
2711 memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl));
2712 pCur->aLvl = aNew;
2713 pCur->nLvl = nNew;
2714 }
2715 pCur->iLvl = iNew;
2716 pLvl = &pCur->aLvl[iNew];
2717
2718 pLvl->zDir = pCur->zPath;
2719 pCur->zPath = 0;
2720 pLvl->pDir = opendir(pLvl->zDir);
2721 if( pLvl->pDir==0 ){
2722 fsdirSetErrmsg(pCur, "cannot read directory: %s", pCur->zPath);
2723 return SQLITE_ERROR;
2724 }
2725 }
2726
2727 while( pCur->iLvl>=0 ){
2728 FsdirLevel *pLvl = &pCur->aLvl[pCur->iLvl];
2729 struct dirent *pEntry = readdir(pLvl->pDir);
2730 if( pEntry ){
2731 if( pEntry->d_name[0]=='.' ){
2732 if( pEntry->d_name[1]=='.' && pEntry->d_name[2]=='\0' ) continue;
2733 if( pEntry->d_name[1]=='\0' ) continue;
2734 }
2735 sqlite3_free(pCur->zPath);
2736 pCur->zPath = sqlite3_mprintf("%s/%s", pLvl->zDir, pEntry->d_name);
2737 if( pCur->zPath==0 ) return SQLITE_NOMEM;
mydongistiny63ee58c2019-09-21 18:04:30 -07002738 if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002739 fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
2740 return SQLITE_ERROR;
2741 }
2742 return SQLITE_OK;
2743 }
2744 closedir(pLvl->pDir);
2745 sqlite3_free(pLvl->zDir);
2746 pLvl->pDir = 0;
2747 pLvl->zDir = 0;
2748 pCur->iLvl--;
2749 }
2750
2751 /* EOF */
2752 sqlite3_free(pCur->zPath);
2753 pCur->zPath = 0;
2754 return SQLITE_OK;
2755}
2756
2757/*
2758** Return values of columns for the row at which the series_cursor
2759** is currently pointing.
2760*/
2761static int fsdirColumn(
2762 sqlite3_vtab_cursor *cur, /* The cursor */
2763 sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
2764 int i /* Which column to return */
2765){
2766 fsdir_cursor *pCur = (fsdir_cursor*)cur;
2767 switch( i ){
mydongistiny63ee58c2019-09-21 18:04:30 -07002768 case FSDIR_COLUMN_NAME: {
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002769 sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT);
2770 break;
2771 }
2772
mydongistiny63ee58c2019-09-21 18:04:30 -07002773 case FSDIR_COLUMN_MODE:
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002774 sqlite3_result_int64(ctx, pCur->sStat.st_mode);
2775 break;
2776
mydongistiny63ee58c2019-09-21 18:04:30 -07002777 case FSDIR_COLUMN_MTIME:
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002778 sqlite3_result_int64(ctx, pCur->sStat.st_mtime);
2779 break;
2780
mydongistiny63ee58c2019-09-21 18:04:30 -07002781 case FSDIR_COLUMN_DATA: {
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002782 mode_t m = pCur->sStat.st_mode;
2783 if( S_ISDIR(m) ){
2784 sqlite3_result_null(ctx);
2785#if !defined(_WIN32) && !defined(WIN32)
2786 }else if( S_ISLNK(m) ){
2787 char aStatic[64];
2788 char *aBuf = aStatic;
mydongistiny63ee58c2019-09-21 18:04:30 -07002789 sqlite3_int64 nBuf = 64;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002790 int n;
2791
2792 while( 1 ){
2793 n = readlink(pCur->zPath, aBuf, nBuf);
2794 if( n<nBuf ) break;
2795 if( aBuf!=aStatic ) sqlite3_free(aBuf);
2796 nBuf = nBuf*2;
mydongistiny63ee58c2019-09-21 18:04:30 -07002797 aBuf = sqlite3_malloc64(nBuf);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002798 if( aBuf==0 ){
2799 sqlite3_result_error_nomem(ctx);
2800 return SQLITE_NOMEM;
2801 }
2802 }
2803
2804 sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT);
2805 if( aBuf!=aStatic ) sqlite3_free(aBuf);
2806#endif
2807 }else{
2808 readFileContents(ctx, pCur->zPath);
2809 }
2810 }
mydongistiny63ee58c2019-09-21 18:04:30 -07002811 case FSDIR_COLUMN_PATH:
2812 default: {
2813 /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters.
2814 ** always return their values as NULL */
2815 break;
2816 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002817 }
2818 return SQLITE_OK;
2819}
2820
2821/*
2822** Return the rowid for the current row. In this implementation, the
2823** first row returned is assigned rowid value 1, and each subsequent
2824** row a value 1 more than that of the previous.
2825*/
2826static int fsdirRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
2827 fsdir_cursor *pCur = (fsdir_cursor*)cur;
2828 *pRowid = pCur->iRowid;
2829 return SQLITE_OK;
2830}
2831
2832/*
2833** Return TRUE if the cursor has been moved off of the last
2834** row of output.
2835*/
2836static int fsdirEof(sqlite3_vtab_cursor *cur){
2837 fsdir_cursor *pCur = (fsdir_cursor*)cur;
2838 return (pCur->zPath==0);
2839}
2840
2841/*
2842** xFilter callback.
mydongistiny63ee58c2019-09-21 18:04:30 -07002843**
2844** idxNum==1 PATH parameter only
2845** idxNum==2 Both PATH and DIR supplied
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002846*/
2847static int fsdirFilter(
2848 sqlite3_vtab_cursor *cur,
2849 int idxNum, const char *idxStr,
2850 int argc, sqlite3_value **argv
2851){
2852 const char *zDir = 0;
2853 fsdir_cursor *pCur = (fsdir_cursor*)cur;
2854 (void)idxStr;
2855 fsdirResetCursor(pCur);
2856
2857 if( idxNum==0 ){
2858 fsdirSetErrmsg(pCur, "table function fsdir requires an argument");
2859 return SQLITE_ERROR;
2860 }
2861
2862 assert( argc==idxNum && (argc==1 || argc==2) );
2863 zDir = (const char*)sqlite3_value_text(argv[0]);
2864 if( zDir==0 ){
2865 fsdirSetErrmsg(pCur, "table function fsdir requires a non-NULL argument");
2866 return SQLITE_ERROR;
2867 }
2868 if( argc==2 ){
2869 pCur->zBase = (const char*)sqlite3_value_text(argv[1]);
2870 }
2871 if( pCur->zBase ){
2872 pCur->nBase = (int)strlen(pCur->zBase)+1;
2873 pCur->zPath = sqlite3_mprintf("%s/%s", pCur->zBase, zDir);
2874 }else{
2875 pCur->zPath = sqlite3_mprintf("%s", zDir);
2876 }
2877
2878 if( pCur->zPath==0 ){
2879 return SQLITE_NOMEM;
2880 }
mydongistiny63ee58c2019-09-21 18:04:30 -07002881 if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002882 fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
2883 return SQLITE_ERROR;
2884 }
2885
2886 return SQLITE_OK;
2887}
2888
2889/*
2890** SQLite will invoke this method one or more times while planning a query
2891** that uses the generate_series virtual table. This routine needs to create
2892** a query plan for each invocation and compute an estimated cost for that
2893** plan.
2894**
2895** In this implementation idxNum is used to represent the
2896** query plan. idxStr is unused.
2897**
mydongistiny63ee58c2019-09-21 18:04:30 -07002898** The query plan is represented by values of idxNum:
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002899**
mydongistiny63ee58c2019-09-21 18:04:30 -07002900** (1) The path value is supplied by argv[0]
2901** (2) Path is in argv[0] and dir is in argv[1]
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002902*/
2903static int fsdirBestIndex(
2904 sqlite3_vtab *tab,
2905 sqlite3_index_info *pIdxInfo
2906){
2907 int i; /* Loop over constraints */
mydongistiny63ee58c2019-09-21 18:04:30 -07002908 int idxPath = -1; /* Index in pIdxInfo->aConstraint of PATH= */
2909 int idxDir = -1; /* Index in pIdxInfo->aConstraint of DIR= */
2910 int seenPath = 0; /* True if an unusable PATH= constraint is seen */
2911 int seenDir = 0; /* True if an unusable DIR= constraint is seen */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002912 const struct sqlite3_index_constraint *pConstraint;
2913
2914 (void)tab;
2915 pConstraint = pIdxInfo->aConstraint;
2916 for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002917 if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
mydongistiny63ee58c2019-09-21 18:04:30 -07002918 switch( pConstraint->iColumn ){
2919 case FSDIR_COLUMN_PATH: {
2920 if( pConstraint->usable ){
2921 idxPath = i;
2922 seenPath = 0;
2923 }else if( idxPath<0 ){
2924 seenPath = 1;
2925 }
2926 break;
2927 }
2928 case FSDIR_COLUMN_DIR: {
2929 if( pConstraint->usable ){
2930 idxDir = i;
2931 seenDir = 0;
2932 }else if( idxDir<0 ){
2933 seenDir = 1;
2934 }
2935 break;
2936 }
2937 }
2938 }
2939 if( seenPath || seenDir ){
2940 /* If input parameters are unusable, disallow this plan */
2941 return SQLITE_CONSTRAINT;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002942 }
2943
mydongistiny63ee58c2019-09-21 18:04:30 -07002944 if( idxPath<0 ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002945 pIdxInfo->idxNum = 0;
mydongistiny63ee58c2019-09-21 18:04:30 -07002946 /* The pIdxInfo->estimatedCost should have been initialized to a huge
2947 ** number. Leave it unchanged. */
2948 pIdxInfo->estimatedRows = 0x7fffffff;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002949 }else{
mydongistiny63ee58c2019-09-21 18:04:30 -07002950 pIdxInfo->aConstraintUsage[idxPath].omit = 1;
2951 pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1;
2952 if( idxDir>=0 ){
2953 pIdxInfo->aConstraintUsage[idxDir].omit = 1;
2954 pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002955 pIdxInfo->idxNum = 2;
2956 pIdxInfo->estimatedCost = 10.0;
2957 }else{
2958 pIdxInfo->idxNum = 1;
2959 pIdxInfo->estimatedCost = 100.0;
2960 }
2961 }
2962
2963 return SQLITE_OK;
2964}
2965
2966/*
2967** Register the "fsdir" virtual table.
2968*/
2969static int fsdirRegister(sqlite3 *db){
2970 static sqlite3_module fsdirModule = {
2971 0, /* iVersion */
2972 0, /* xCreate */
2973 fsdirConnect, /* xConnect */
2974 fsdirBestIndex, /* xBestIndex */
2975 fsdirDisconnect, /* xDisconnect */
2976 0, /* xDestroy */
2977 fsdirOpen, /* xOpen - open a cursor */
2978 fsdirClose, /* xClose - close a cursor */
2979 fsdirFilter, /* xFilter - configure scan constraints */
2980 fsdirNext, /* xNext - advance a cursor */
2981 fsdirEof, /* xEof - check for end of scan */
2982 fsdirColumn, /* xColumn - read data */
2983 fsdirRowid, /* xRowid - read data */
2984 0, /* xUpdate */
2985 0, /* xBegin */
2986 0, /* xSync */
2987 0, /* xCommit */
2988 0, /* xRollback */
2989 0, /* xFindMethod */
2990 0, /* xRename */
2991 0, /* xSavepoint */
2992 0, /* xRelease */
mydongistiny63ee58c2019-09-21 18:04:30 -07002993 0, /* xRollbackTo */
2994 0, /* xShadowName */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08002995 };
2996
2997 int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
2998 return rc;
2999}
3000#else /* SQLITE_OMIT_VIRTUALTABLE */
3001# define fsdirRegister(x) SQLITE_OK
3002#endif
3003
3004#ifdef _WIN32
3005
3006#endif
3007int sqlite3_fileio_init(
3008 sqlite3 *db,
3009 char **pzErrMsg,
3010 const sqlite3_api_routines *pApi
3011){
3012 int rc = SQLITE_OK;
3013 SQLITE_EXTENSION_INIT2(pApi);
3014 (void)pzErrMsg; /* Unused parameter */
3015 rc = sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
3016 readfileFunc, 0, 0);
3017 if( rc==SQLITE_OK ){
3018 rc = sqlite3_create_function(db, "writefile", -1, SQLITE_UTF8, 0,
3019 writefileFunc, 0, 0);
3020 }
3021 if( rc==SQLITE_OK ){
3022 rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0,
3023 lsModeFunc, 0, 0);
3024 }
3025 if( rc==SQLITE_OK ){
3026 rc = fsdirRegister(db);
3027 }
3028 return rc;
3029}
3030
3031/************************* End ../ext/misc/fileio.c ********************/
3032/************************* Begin ../ext/misc/completion.c ******************/
3033/*
3034** 2017-07-10
3035**
3036** The author disclaims copyright to this source code. In place of
3037** a legal notice, here is a blessing:
3038**
3039** May you do good and not evil.
3040** May you find forgiveness for yourself and forgive others.
3041** May you share freely, never taking more than you give.
3042**
3043*************************************************************************
3044**
3045** This file implements an eponymous virtual table that returns suggested
3046** completions for a partial SQL input.
3047**
3048** Suggested usage:
3049**
3050** SELECT DISTINCT candidate COLLATE nocase
3051** FROM completion($prefix,$wholeline)
3052** ORDER BY 1;
3053**
3054** The two query parameters are optional. $prefix is the text of the
3055** current word being typed and that is to be completed. $wholeline is
3056** the complete input line, used for context.
3057**
3058** The raw completion() table might return the same candidate multiple
3059** times, for example if the same column name is used to two or more
3060** tables. And the candidates are returned in an arbitrary order. Hence,
3061** the DISTINCT and ORDER BY are recommended.
3062**
3063** This virtual table operates at the speed of human typing, and so there
3064** is no attempt to make it fast. Even a slow implementation will be much
3065** faster than any human can type.
3066**
3067*/
mydongistiny63ee58c2019-09-21 18:04:30 -07003068/* #include "sqlite3ext.h" */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08003069SQLITE_EXTENSION_INIT1
3070#include <assert.h>
3071#include <string.h>
3072#include <ctype.h>
3073
3074#ifndef SQLITE_OMIT_VIRTUALTABLE
3075
3076/* completion_vtab is a subclass of sqlite3_vtab which will
3077** serve as the underlying representation of a completion virtual table
3078*/
3079typedef struct completion_vtab completion_vtab;
3080struct completion_vtab {
3081 sqlite3_vtab base; /* Base class - must be first */
3082 sqlite3 *db; /* Database connection for this completion vtab */
3083};
3084
3085/* completion_cursor is a subclass of sqlite3_vtab_cursor which will
3086** serve as the underlying representation of a cursor that scans
3087** over rows of the result
3088*/
3089typedef struct completion_cursor completion_cursor;
3090struct completion_cursor {
3091 sqlite3_vtab_cursor base; /* Base class - must be first */
3092 sqlite3 *db; /* Database connection for this cursor */
3093 int nPrefix, nLine; /* Number of bytes in zPrefix and zLine */
3094 char *zPrefix; /* The prefix for the word we want to complete */
3095 char *zLine; /* The whole that we want to complete */
3096 const char *zCurrentRow; /* Current output row */
mydongistiny63ee58c2019-09-21 18:04:30 -07003097 int szRow; /* Length of the zCurrentRow string */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08003098 sqlite3_stmt *pStmt; /* Current statement */
3099 sqlite3_int64 iRowid; /* The rowid */
3100 int ePhase; /* Current phase */
3101 int j; /* inter-phase counter */
3102};
3103
3104/* Values for ePhase:
3105*/
3106#define COMPLETION_FIRST_PHASE 1
3107#define COMPLETION_KEYWORDS 1
3108#define COMPLETION_PRAGMAS 2
3109#define COMPLETION_FUNCTIONS 3
3110#define COMPLETION_COLLATIONS 4
3111#define COMPLETION_INDEXES 5
3112#define COMPLETION_TRIGGERS 6
3113#define COMPLETION_DATABASES 7
mydongistiny63ee58c2019-09-21 18:04:30 -07003114#define COMPLETION_TABLES 8 /* Also VIEWs and TRIGGERs */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08003115#define COMPLETION_COLUMNS 9
3116#define COMPLETION_MODULES 10
3117#define COMPLETION_EOF 11
3118
3119/*
3120** The completionConnect() method is invoked to create a new
3121** completion_vtab that describes the completion virtual table.
3122**
3123** Think of this routine as the constructor for completion_vtab objects.
3124**
3125** All this routine needs to do is:
3126**
3127** (1) Allocate the completion_vtab object and initialize all fields.
3128**
3129** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
3130** result set of queries against completion will look like.
3131*/
3132static int completionConnect(
3133 sqlite3 *db,
3134 void *pAux,
3135 int argc, const char *const*argv,
3136 sqlite3_vtab **ppVtab,
3137 char **pzErr
3138){
3139 completion_vtab *pNew;
3140 int rc;
3141
3142 (void)(pAux); /* Unused parameter */
3143 (void)(argc); /* Unused parameter */
3144 (void)(argv); /* Unused parameter */
3145 (void)(pzErr); /* Unused parameter */
3146
3147/* Column numbers */
3148#define COMPLETION_COLUMN_CANDIDATE 0 /* Suggested completion of the input */
3149#define COMPLETION_COLUMN_PREFIX 1 /* Prefix of the word to be completed */
3150#define COMPLETION_COLUMN_WHOLELINE 2 /* Entire line seen so far */
3151#define COMPLETION_COLUMN_PHASE 3 /* ePhase - used for debugging only */
3152
3153 rc = sqlite3_declare_vtab(db,
3154 "CREATE TABLE x("
3155 " candidate TEXT,"
3156 " prefix TEXT HIDDEN,"
3157 " wholeline TEXT HIDDEN,"
3158 " phase INT HIDDEN" /* Used for debugging only */
3159 ")");
3160 if( rc==SQLITE_OK ){
3161 pNew = sqlite3_malloc( sizeof(*pNew) );
3162 *ppVtab = (sqlite3_vtab*)pNew;
3163 if( pNew==0 ) return SQLITE_NOMEM;
3164 memset(pNew, 0, sizeof(*pNew));
3165 pNew->db = db;
3166 }
3167 return rc;
3168}
3169
3170/*
3171** This method is the destructor for completion_cursor objects.
3172*/
3173static int completionDisconnect(sqlite3_vtab *pVtab){
3174 sqlite3_free(pVtab);
3175 return SQLITE_OK;
3176}
3177
3178/*
3179** Constructor for a new completion_cursor object.
3180*/
3181static int completionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
3182 completion_cursor *pCur;
3183 pCur = sqlite3_malloc( sizeof(*pCur) );
3184 if( pCur==0 ) return SQLITE_NOMEM;
3185 memset(pCur, 0, sizeof(*pCur));
3186 pCur->db = ((completion_vtab*)p)->db;
3187 *ppCursor = &pCur->base;
3188 return SQLITE_OK;
3189}
3190
3191/*
3192** Reset the completion_cursor.
3193*/
3194static void completionCursorReset(completion_cursor *pCur){
3195 sqlite3_free(pCur->zPrefix); pCur->zPrefix = 0; pCur->nPrefix = 0;
3196 sqlite3_free(pCur->zLine); pCur->zLine = 0; pCur->nLine = 0;
3197 sqlite3_finalize(pCur->pStmt); pCur->pStmt = 0;
3198 pCur->j = 0;
3199}
3200
3201/*
3202** Destructor for a completion_cursor.
3203*/
3204static int completionClose(sqlite3_vtab_cursor *cur){
3205 completionCursorReset((completion_cursor*)cur);
3206 sqlite3_free(cur);
3207 return SQLITE_OK;
3208}
3209
3210/*
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08003211** Advance a completion_cursor to its next row of output.
3212**
3213** The ->ePhase, ->j, and ->pStmt fields of the completion_cursor object
3214** record the current state of the scan. This routine sets ->zCurrentRow
3215** to the current row of output and then returns. If no more rows remain,
3216** then ->ePhase is set to COMPLETION_EOF which will signal the virtual
3217** table that has reached the end of its scan.
3218**
3219** The current implementation just lists potential identifiers and
3220** keywords and filters them by zPrefix. Future enhancements should
3221** take zLine into account to try to restrict the set of identifiers and
3222** keywords based on what would be legal at the current point of input.
3223*/
3224static int completionNext(sqlite3_vtab_cursor *cur){
3225 completion_cursor *pCur = (completion_cursor*)cur;
3226 int eNextPhase = 0; /* Next phase to try if current phase reaches end */
3227 int iCol = -1; /* If >=0, step pCur->pStmt and use the i-th column */
3228 pCur->iRowid++;
3229 while( pCur->ePhase!=COMPLETION_EOF ){
3230 switch( pCur->ePhase ){
3231 case COMPLETION_KEYWORDS: {
mydongistiny63ee58c2019-09-21 18:04:30 -07003232 if( pCur->j >= sqlite3_keyword_count() ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08003233 pCur->zCurrentRow = 0;
3234 pCur->ePhase = COMPLETION_DATABASES;
3235 }else{
mydongistiny63ee58c2019-09-21 18:04:30 -07003236 sqlite3_keyword_name(pCur->j++, &pCur->zCurrentRow, &pCur->szRow);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08003237 }
3238 iCol = -1;
3239 break;
3240 }
3241 case COMPLETION_DATABASES: {
3242 if( pCur->pStmt==0 ){
3243 sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1,
3244 &pCur->pStmt, 0);
3245 }
3246 iCol = 1;
3247 eNextPhase = COMPLETION_TABLES;
3248 break;
3249 }
3250 case COMPLETION_TABLES: {
3251 if( pCur->pStmt==0 ){
3252 sqlite3_stmt *pS2;
3253 char *zSql = 0;
3254 const char *zSep = "";
3255 sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
3256 while( sqlite3_step(pS2)==SQLITE_ROW ){
3257 const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
3258 zSql = sqlite3_mprintf(
3259 "%z%s"
mydongistiny63ee58c2019-09-21 18:04:30 -07003260 "SELECT name FROM \"%w\".sqlite_master",
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08003261 zSql, zSep, zDb
3262 );
3263 if( zSql==0 ) return SQLITE_NOMEM;
3264 zSep = " UNION ";
3265 }
3266 sqlite3_finalize(pS2);
3267 sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
3268 sqlite3_free(zSql);
3269 }
3270 iCol = 0;
3271 eNextPhase = COMPLETION_COLUMNS;
3272 break;
3273 }
3274 case COMPLETION_COLUMNS: {
3275 if( pCur->pStmt==0 ){
3276 sqlite3_stmt *pS2;
3277 char *zSql = 0;
3278 const char *zSep = "";
3279 sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
3280 while( sqlite3_step(pS2)==SQLITE_ROW ){
3281 const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
3282 zSql = sqlite3_mprintf(
3283 "%z%s"
3284 "SELECT pti.name FROM \"%w\".sqlite_master AS sm"
3285 " JOIN pragma_table_info(sm.name,%Q) AS pti"
3286 " WHERE sm.type='table'",
3287 zSql, zSep, zDb, zDb
3288 );
3289 if( zSql==0 ) return SQLITE_NOMEM;
3290 zSep = " UNION ";
3291 }
3292 sqlite3_finalize(pS2);
3293 sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
3294 sqlite3_free(zSql);
3295 }
3296 iCol = 0;
3297 eNextPhase = COMPLETION_EOF;
3298 break;
3299 }
3300 }
3301 if( iCol<0 ){
3302 /* This case is when the phase presets zCurrentRow */
3303 if( pCur->zCurrentRow==0 ) continue;
3304 }else{
3305 if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){
3306 /* Extract the next row of content */
3307 pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol);
mydongistiny63ee58c2019-09-21 18:04:30 -07003308 pCur->szRow = sqlite3_column_bytes(pCur->pStmt, iCol);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08003309 }else{
3310 /* When all rows are finished, advance to the next phase */
3311 sqlite3_finalize(pCur->pStmt);
3312 pCur->pStmt = 0;
3313 pCur->ePhase = eNextPhase;
3314 continue;
3315 }
3316 }
3317 if( pCur->nPrefix==0 ) break;
mydongistiny63ee58c2019-09-21 18:04:30 -07003318 if( pCur->nPrefix<=pCur->szRow
3319 && sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0
3320 ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08003321 break;
3322 }
3323 }
3324
3325 return SQLITE_OK;
3326}
3327
3328/*
3329** Return values of columns for the row at which the completion_cursor
3330** is currently pointing.
3331*/
3332static int completionColumn(
3333 sqlite3_vtab_cursor *cur, /* The cursor */
3334 sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
3335 int i /* Which column to return */
3336){
3337 completion_cursor *pCur = (completion_cursor*)cur;
3338 switch( i ){
3339 case COMPLETION_COLUMN_CANDIDATE: {
mydongistiny63ee58c2019-09-21 18:04:30 -07003340 sqlite3_result_text(ctx, pCur->zCurrentRow, pCur->szRow,SQLITE_TRANSIENT);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08003341 break;
3342 }
3343 case COMPLETION_COLUMN_PREFIX: {
3344 sqlite3_result_text(ctx, pCur->zPrefix, -1, SQLITE_TRANSIENT);
3345 break;
3346 }
3347 case COMPLETION_COLUMN_WHOLELINE: {
3348 sqlite3_result_text(ctx, pCur->zLine, -1, SQLITE_TRANSIENT);
3349 break;
3350 }
3351 case COMPLETION_COLUMN_PHASE: {
3352 sqlite3_result_int(ctx, pCur->ePhase);
3353 break;
3354 }
3355 }
3356 return SQLITE_OK;
3357}
3358
3359/*
3360** Return the rowid for the current row. In this implementation, the
3361** rowid is the same as the output value.
3362*/
3363static int completionRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
3364 completion_cursor *pCur = (completion_cursor*)cur;
3365 *pRowid = pCur->iRowid;
3366 return SQLITE_OK;
3367}
3368
3369/*
3370** Return TRUE if the cursor has been moved off of the last
3371** row of output.
3372*/
3373static int completionEof(sqlite3_vtab_cursor *cur){
3374 completion_cursor *pCur = (completion_cursor*)cur;
3375 return pCur->ePhase >= COMPLETION_EOF;
3376}
3377
3378/*
3379** This method is called to "rewind" the completion_cursor object back
3380** to the first row of output. This method is always called at least
3381** once prior to any call to completionColumn() or completionRowid() or
3382** completionEof().
3383*/
3384static int completionFilter(
3385 sqlite3_vtab_cursor *pVtabCursor,
3386 int idxNum, const char *idxStr,
3387 int argc, sqlite3_value **argv
3388){
3389 completion_cursor *pCur = (completion_cursor *)pVtabCursor;
3390 int iArg = 0;
3391 (void)(idxStr); /* Unused parameter */
3392 (void)(argc); /* Unused parameter */
3393 completionCursorReset(pCur);
3394 if( idxNum & 1 ){
3395 pCur->nPrefix = sqlite3_value_bytes(argv[iArg]);
3396 if( pCur->nPrefix>0 ){
3397 pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
3398 if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
3399 }
mydongistiny63ee58c2019-09-21 18:04:30 -07003400 iArg = 1;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08003401 }
3402 if( idxNum & 2 ){
3403 pCur->nLine = sqlite3_value_bytes(argv[iArg]);
3404 if( pCur->nLine>0 ){
3405 pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
3406 if( pCur->zLine==0 ) return SQLITE_NOMEM;
3407 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08003408 }
3409 if( pCur->zLine!=0 && pCur->zPrefix==0 ){
3410 int i = pCur->nLine;
3411 while( i>0 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
3412 i--;
3413 }
3414 pCur->nPrefix = pCur->nLine - i;
3415 if( pCur->nPrefix>0 ){
3416 pCur->zPrefix = sqlite3_mprintf("%.*s", pCur->nPrefix, pCur->zLine + i);
3417 if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
3418 }
3419 }
3420 pCur->iRowid = 0;
3421 pCur->ePhase = COMPLETION_FIRST_PHASE;
3422 return completionNext(pVtabCursor);
3423}
3424
3425/*
3426** SQLite will invoke this method one or more times while planning a query
3427** that uses the completion virtual table. This routine needs to create
3428** a query plan for each invocation and compute an estimated cost for that
3429** plan.
3430**
3431** There are two hidden parameters that act as arguments to the table-valued
3432** function: "prefix" and "wholeline". Bit 0 of idxNum is set if "prefix"
3433** is available and bit 1 is set if "wholeline" is available.
3434*/
3435static int completionBestIndex(
3436 sqlite3_vtab *tab,
3437 sqlite3_index_info *pIdxInfo
3438){
3439 int i; /* Loop over constraints */
3440 int idxNum = 0; /* The query plan bitmask */
3441 int prefixIdx = -1; /* Index of the start= constraint, or -1 if none */
3442 int wholelineIdx = -1; /* Index of the stop= constraint, or -1 if none */
3443 int nArg = 0; /* Number of arguments that completeFilter() expects */
3444 const struct sqlite3_index_constraint *pConstraint;
3445
3446 (void)(tab); /* Unused parameter */
3447 pConstraint = pIdxInfo->aConstraint;
3448 for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
3449 if( pConstraint->usable==0 ) continue;
3450 if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
3451 switch( pConstraint->iColumn ){
3452 case COMPLETION_COLUMN_PREFIX:
3453 prefixIdx = i;
3454 idxNum |= 1;
3455 break;
3456 case COMPLETION_COLUMN_WHOLELINE:
3457 wholelineIdx = i;
3458 idxNum |= 2;
3459 break;
3460 }
3461 }
3462 if( prefixIdx>=0 ){
3463 pIdxInfo->aConstraintUsage[prefixIdx].argvIndex = ++nArg;
3464 pIdxInfo->aConstraintUsage[prefixIdx].omit = 1;
3465 }
3466 if( wholelineIdx>=0 ){
3467 pIdxInfo->aConstraintUsage[wholelineIdx].argvIndex = ++nArg;
3468 pIdxInfo->aConstraintUsage[wholelineIdx].omit = 1;
3469 }
3470 pIdxInfo->idxNum = idxNum;
3471 pIdxInfo->estimatedCost = (double)5000 - 1000*nArg;
3472 pIdxInfo->estimatedRows = 500 - 100*nArg;
3473 return SQLITE_OK;
3474}
3475
3476/*
3477** This following structure defines all the methods for the
3478** completion virtual table.
3479*/
3480static sqlite3_module completionModule = {
3481 0, /* iVersion */
3482 0, /* xCreate */
3483 completionConnect, /* xConnect */
3484 completionBestIndex, /* xBestIndex */
3485 completionDisconnect, /* xDisconnect */
3486 0, /* xDestroy */
3487 completionOpen, /* xOpen - open a cursor */
3488 completionClose, /* xClose - close a cursor */
3489 completionFilter, /* xFilter - configure scan constraints */
3490 completionNext, /* xNext - advance a cursor */
3491 completionEof, /* xEof - check for end of scan */
3492 completionColumn, /* xColumn - read data */
3493 completionRowid, /* xRowid - read data */
3494 0, /* xUpdate */
3495 0, /* xBegin */
3496 0, /* xSync */
3497 0, /* xCommit */
3498 0, /* xRollback */
3499 0, /* xFindMethod */
3500 0, /* xRename */
3501 0, /* xSavepoint */
3502 0, /* xRelease */
mydongistiny63ee58c2019-09-21 18:04:30 -07003503 0, /* xRollbackTo */
3504 0 /* xShadowName */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08003505};
3506
3507#endif /* SQLITE_OMIT_VIRTUALTABLE */
3508
3509int sqlite3CompletionVtabInit(sqlite3 *db){
3510 int rc = SQLITE_OK;
3511#ifndef SQLITE_OMIT_VIRTUALTABLE
3512 rc = sqlite3_create_module(db, "completion", &completionModule, 0);
3513#endif
3514 return rc;
3515}
3516
3517#ifdef _WIN32
3518
3519#endif
3520int sqlite3_completion_init(
3521 sqlite3 *db,
3522 char **pzErrMsg,
3523 const sqlite3_api_routines *pApi
3524){
3525 int rc = SQLITE_OK;
3526 SQLITE_EXTENSION_INIT2(pApi);
3527 (void)(pzErrMsg); /* Unused parameter */
3528#ifndef SQLITE_OMIT_VIRTUALTABLE
3529 rc = sqlite3CompletionVtabInit(db);
3530#endif
3531 return rc;
3532}
3533
3534/************************* End ../ext/misc/completion.c ********************/
3535/************************* Begin ../ext/misc/appendvfs.c ******************/
3536/*
3537** 2017-10-20
3538**
3539** The author disclaims copyright to this source code. In place of
3540** a legal notice, here is a blessing:
3541**
3542** May you do good and not evil.
3543** May you find forgiveness for yourself and forgive others.
3544** May you share freely, never taking more than you give.
3545**
3546******************************************************************************
3547**
3548** This file implements a VFS shim that allows an SQLite database to be
3549** appended onto the end of some other file, such as an executable.
3550**
3551** A special record must appear at the end of the file that identifies the
3552** file as an appended database and provides an offset to page 1. For
3553** best performance page 1 should be located at a disk page boundary, though
3554** that is not required.
3555**
3556** When opening a database using this VFS, the connection might treat
3557** the file as an ordinary SQLite database, or it might treat is as a
3558** database appended onto some other file. Here are the rules:
3559**
3560** (1) When opening a new empty file, that file is treated as an ordinary
3561** database.
3562**
3563** (2) When opening a file that begins with the standard SQLite prefix
3564** string "SQLite format 3", that file is treated as an ordinary
3565** database.
3566**
3567** (3) When opening a file that ends with the appendvfs trailer string
3568** "Start-Of-SQLite3-NNNNNNNN" that file is treated as an appended
3569** database.
3570**
3571** (4) If none of the above apply and the SQLITE_OPEN_CREATE flag is
3572** set, then a new database is appended to the already existing file.
3573**
3574** (5) Otherwise, SQLITE_CANTOPEN is returned.
3575**
3576** To avoid unnecessary complications with the PENDING_BYTE, the size of
3577** the file containing the database is limited to 1GB. This VFS will refuse
3578** to read or write past the 1GB mark. This restriction might be lifted in
3579** future versions. For now, if you need a large database, then keep the
3580** database in a separate file.
3581**
3582** If the file being opened is not an appended database, then this shim is
3583** a pass-through into the default underlying VFS.
3584**/
mydongistiny63ee58c2019-09-21 18:04:30 -07003585/* #include "sqlite3ext.h" */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08003586SQLITE_EXTENSION_INIT1
3587#include <string.h>
3588#include <assert.h>
3589
3590/* The append mark at the end of the database is:
3591**
3592** Start-Of-SQLite3-NNNNNNNN
3593** 123456789 123456789 12345
3594**
3595** The NNNNNNNN represents a 64-bit big-endian unsigned integer which is
3596** the offset to page 1.
3597*/
3598#define APND_MARK_PREFIX "Start-Of-SQLite3-"
3599#define APND_MARK_PREFIX_SZ 17
3600#define APND_MARK_SIZE 25
3601
3602/*
3603** Maximum size of the combined prefix + database + append-mark. This
3604** must be less than 0x40000000 to avoid locking issues on Windows.
3605*/
3606#define APND_MAX_SIZE (65536*15259)
3607
3608/*
3609** Forward declaration of objects used by this utility
3610*/
3611typedef struct sqlite3_vfs ApndVfs;
3612typedef struct ApndFile ApndFile;
3613
3614/* Access to a lower-level VFS that (might) implement dynamic loading,
3615** access to randomness, etc.
3616*/
3617#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
3618#define ORIGFILE(p) ((sqlite3_file*)(((ApndFile*)(p))+1))
3619
3620/* An open file */
3621struct ApndFile {
3622 sqlite3_file base; /* IO methods */
3623 sqlite3_int64 iPgOne; /* File offset to page 1 */
3624 sqlite3_int64 iMark; /* Start of the append-mark */
3625};
3626
3627/*
3628** Methods for ApndFile
3629*/
3630static int apndClose(sqlite3_file*);
3631static int apndRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
3632static int apndWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
3633static int apndTruncate(sqlite3_file*, sqlite3_int64 size);
3634static int apndSync(sqlite3_file*, int flags);
3635static int apndFileSize(sqlite3_file*, sqlite3_int64 *pSize);
3636static int apndLock(sqlite3_file*, int);
3637static int apndUnlock(sqlite3_file*, int);
3638static int apndCheckReservedLock(sqlite3_file*, int *pResOut);
3639static int apndFileControl(sqlite3_file*, int op, void *pArg);
3640static int apndSectorSize(sqlite3_file*);
3641static int apndDeviceCharacteristics(sqlite3_file*);
3642static int apndShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
3643static int apndShmLock(sqlite3_file*, int offset, int n, int flags);
3644static void apndShmBarrier(sqlite3_file*);
3645static int apndShmUnmap(sqlite3_file*, int deleteFlag);
3646static int apndFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
3647static int apndUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
3648
3649/*
3650** Methods for ApndVfs
3651*/
3652static int apndOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
3653static int apndDelete(sqlite3_vfs*, const char *zName, int syncDir);
3654static int apndAccess(sqlite3_vfs*, const char *zName, int flags, int *);
3655static int apndFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
3656static void *apndDlOpen(sqlite3_vfs*, const char *zFilename);
3657static void apndDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
3658static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
3659static void apndDlClose(sqlite3_vfs*, void*);
3660static int apndRandomness(sqlite3_vfs*, int nByte, char *zOut);
3661static int apndSleep(sqlite3_vfs*, int microseconds);
3662static int apndCurrentTime(sqlite3_vfs*, double*);
3663static int apndGetLastError(sqlite3_vfs*, int, char *);
3664static int apndCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
3665static int apndSetSystemCall(sqlite3_vfs*, const char*,sqlite3_syscall_ptr);
3666static sqlite3_syscall_ptr apndGetSystemCall(sqlite3_vfs*, const char *z);
3667static const char *apndNextSystemCall(sqlite3_vfs*, const char *zName);
3668
3669static sqlite3_vfs apnd_vfs = {
3670 3, /* iVersion (set when registered) */
3671 0, /* szOsFile (set when registered) */
3672 1024, /* mxPathname */
3673 0, /* pNext */
3674 "apndvfs", /* zName */
3675 0, /* pAppData (set when registered) */
3676 apndOpen, /* xOpen */
3677 apndDelete, /* xDelete */
3678 apndAccess, /* xAccess */
3679 apndFullPathname, /* xFullPathname */
3680 apndDlOpen, /* xDlOpen */
3681 apndDlError, /* xDlError */
3682 apndDlSym, /* xDlSym */
3683 apndDlClose, /* xDlClose */
3684 apndRandomness, /* xRandomness */
3685 apndSleep, /* xSleep */
3686 apndCurrentTime, /* xCurrentTime */
3687 apndGetLastError, /* xGetLastError */
3688 apndCurrentTimeInt64, /* xCurrentTimeInt64 */
3689 apndSetSystemCall, /* xSetSystemCall */
3690 apndGetSystemCall, /* xGetSystemCall */
3691 apndNextSystemCall /* xNextSystemCall */
3692};
3693
3694static const sqlite3_io_methods apnd_io_methods = {
3695 3, /* iVersion */
3696 apndClose, /* xClose */
3697 apndRead, /* xRead */
3698 apndWrite, /* xWrite */
3699 apndTruncate, /* xTruncate */
3700 apndSync, /* xSync */
3701 apndFileSize, /* xFileSize */
3702 apndLock, /* xLock */
3703 apndUnlock, /* xUnlock */
3704 apndCheckReservedLock, /* xCheckReservedLock */
3705 apndFileControl, /* xFileControl */
3706 apndSectorSize, /* xSectorSize */
3707 apndDeviceCharacteristics, /* xDeviceCharacteristics */
3708 apndShmMap, /* xShmMap */
3709 apndShmLock, /* xShmLock */
3710 apndShmBarrier, /* xShmBarrier */
3711 apndShmUnmap, /* xShmUnmap */
3712 apndFetch, /* xFetch */
3713 apndUnfetch /* xUnfetch */
3714};
3715
3716
3717
3718/*
3719** Close an apnd-file.
3720*/
3721static int apndClose(sqlite3_file *pFile){
3722 pFile = ORIGFILE(pFile);
3723 return pFile->pMethods->xClose(pFile);
3724}
3725
3726/*
3727** Read data from an apnd-file.
3728*/
3729static int apndRead(
3730 sqlite3_file *pFile,
3731 void *zBuf,
3732 int iAmt,
3733 sqlite_int64 iOfst
3734){
3735 ApndFile *p = (ApndFile *)pFile;
3736 pFile = ORIGFILE(pFile);
3737 return pFile->pMethods->xRead(pFile, zBuf, iAmt, iOfst+p->iPgOne);
3738}
3739
3740/*
3741** Add the append-mark onto the end of the file.
3742*/
3743static int apndWriteMark(ApndFile *p, sqlite3_file *pFile){
3744 int i;
3745 unsigned char a[APND_MARK_SIZE];
3746 memcpy(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ);
3747 for(i=0; i<8; i++){
3748 a[APND_MARK_PREFIX_SZ+i] = (p->iPgOne >> (56 - i*8)) & 0xff;
3749 }
3750 return pFile->pMethods->xWrite(pFile, a, APND_MARK_SIZE, p->iMark);
3751}
3752
3753/*
3754** Write data to an apnd-file.
3755*/
3756static int apndWrite(
3757 sqlite3_file *pFile,
3758 const void *zBuf,
3759 int iAmt,
3760 sqlite_int64 iOfst
3761){
3762 int rc;
3763 ApndFile *p = (ApndFile *)pFile;
3764 pFile = ORIGFILE(pFile);
3765 if( iOfst+iAmt>=APND_MAX_SIZE ) return SQLITE_FULL;
3766 rc = pFile->pMethods->xWrite(pFile, zBuf, iAmt, iOfst+p->iPgOne);
3767 if( rc==SQLITE_OK && iOfst + iAmt + p->iPgOne > p->iMark ){
3768 sqlite3_int64 sz = 0;
3769 rc = pFile->pMethods->xFileSize(pFile, &sz);
3770 if( rc==SQLITE_OK ){
3771 p->iMark = sz - APND_MARK_SIZE;
3772 if( iOfst + iAmt + p->iPgOne > p->iMark ){
3773 p->iMark = p->iPgOne + iOfst + iAmt;
3774 rc = apndWriteMark(p, pFile);
3775 }
3776 }
3777 }
3778 return rc;
3779}
3780
3781/*
3782** Truncate an apnd-file.
3783*/
3784static int apndTruncate(sqlite3_file *pFile, sqlite_int64 size){
3785 int rc;
3786 ApndFile *p = (ApndFile *)pFile;
3787 pFile = ORIGFILE(pFile);
3788 rc = pFile->pMethods->xTruncate(pFile, size+p->iPgOne+APND_MARK_SIZE);
3789 if( rc==SQLITE_OK ){
3790 p->iMark = p->iPgOne+size;
3791 rc = apndWriteMark(p, pFile);
3792 }
3793 return rc;
3794}
3795
3796/*
3797** Sync an apnd-file.
3798*/
3799static int apndSync(sqlite3_file *pFile, int flags){
3800 pFile = ORIGFILE(pFile);
3801 return pFile->pMethods->xSync(pFile, flags);
3802}
3803
3804/*
3805** Return the current file-size of an apnd-file.
3806*/
3807static int apndFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
3808 ApndFile *p = (ApndFile *)pFile;
3809 int rc;
3810 pFile = ORIGFILE(p);
3811 rc = pFile->pMethods->xFileSize(pFile, pSize);
3812 if( rc==SQLITE_OK && p->iPgOne ){
3813 *pSize -= p->iPgOne + APND_MARK_SIZE;
3814 }
3815 return rc;
3816}
3817
3818/*
3819** Lock an apnd-file.
3820*/
3821static int apndLock(sqlite3_file *pFile, int eLock){
3822 pFile = ORIGFILE(pFile);
3823 return pFile->pMethods->xLock(pFile, eLock);
3824}
3825
3826/*
3827** Unlock an apnd-file.
3828*/
3829static int apndUnlock(sqlite3_file *pFile, int eLock){
3830 pFile = ORIGFILE(pFile);
3831 return pFile->pMethods->xUnlock(pFile, eLock);
3832}
3833
3834/*
3835** Check if another file-handle holds a RESERVED lock on an apnd-file.
3836*/
3837static int apndCheckReservedLock(sqlite3_file *pFile, int *pResOut){
3838 pFile = ORIGFILE(pFile);
3839 return pFile->pMethods->xCheckReservedLock(pFile, pResOut);
3840}
3841
3842/*
3843** File control method. For custom operations on an apnd-file.
3844*/
3845static int apndFileControl(sqlite3_file *pFile, int op, void *pArg){
3846 ApndFile *p = (ApndFile *)pFile;
3847 int rc;
3848 pFile = ORIGFILE(pFile);
3849 rc = pFile->pMethods->xFileControl(pFile, op, pArg);
3850 if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
3851 *(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", p->iPgOne, *(char**)pArg);
3852 }
3853 return rc;
3854}
3855
3856/*
3857** Return the sector-size in bytes for an apnd-file.
3858*/
3859static int apndSectorSize(sqlite3_file *pFile){
3860 pFile = ORIGFILE(pFile);
3861 return pFile->pMethods->xSectorSize(pFile);
3862}
3863
3864/*
3865** Return the device characteristic flags supported by an apnd-file.
3866*/
3867static int apndDeviceCharacteristics(sqlite3_file *pFile){
3868 pFile = ORIGFILE(pFile);
3869 return pFile->pMethods->xDeviceCharacteristics(pFile);
3870}
3871
3872/* Create a shared memory file mapping */
3873static int apndShmMap(
3874 sqlite3_file *pFile,
3875 int iPg,
3876 int pgsz,
3877 int bExtend,
3878 void volatile **pp
3879){
3880 pFile = ORIGFILE(pFile);
3881 return pFile->pMethods->xShmMap(pFile,iPg,pgsz,bExtend,pp);
3882}
3883
3884/* Perform locking on a shared-memory segment */
3885static int apndShmLock(sqlite3_file *pFile, int offset, int n, int flags){
3886 pFile = ORIGFILE(pFile);
3887 return pFile->pMethods->xShmLock(pFile,offset,n,flags);
3888}
3889
3890/* Memory barrier operation on shared memory */
3891static void apndShmBarrier(sqlite3_file *pFile){
3892 pFile = ORIGFILE(pFile);
3893 pFile->pMethods->xShmBarrier(pFile);
3894}
3895
3896/* Unmap a shared memory segment */
3897static int apndShmUnmap(sqlite3_file *pFile, int deleteFlag){
3898 pFile = ORIGFILE(pFile);
3899 return pFile->pMethods->xShmUnmap(pFile,deleteFlag);
3900}
3901
3902/* Fetch a page of a memory-mapped file */
3903static int apndFetch(
3904 sqlite3_file *pFile,
3905 sqlite3_int64 iOfst,
3906 int iAmt,
3907 void **pp
3908){
3909 ApndFile *p = (ApndFile *)pFile;
3910 pFile = ORIGFILE(pFile);
3911 return pFile->pMethods->xFetch(pFile, iOfst+p->iPgOne, iAmt, pp);
3912}
3913
3914/* Release a memory-mapped page */
3915static int apndUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
3916 ApndFile *p = (ApndFile *)pFile;
3917 pFile = ORIGFILE(pFile);
3918 return pFile->pMethods->xUnfetch(pFile, iOfst+p->iPgOne, pPage);
3919}
3920
3921/*
3922** Check to see if the file is an ordinary SQLite database file.
3923*/
3924static int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){
3925 int rc;
3926 char zHdr[16];
3927 static const char aSqliteHdr[] = "SQLite format 3";
3928 if( sz<512 ) return 0;
3929 rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0);
3930 if( rc ) return 0;
3931 return memcmp(zHdr, aSqliteHdr, sizeof(zHdr))==0;
3932}
3933
3934/*
3935** Try to read the append-mark off the end of a file. Return the
3936** start of the appended database if the append-mark is present. If
3937** there is no append-mark, return -1;
3938*/
3939static sqlite3_int64 apndReadMark(sqlite3_int64 sz, sqlite3_file *pFile){
3940 int rc, i;
3941 sqlite3_int64 iMark;
3942 unsigned char a[APND_MARK_SIZE];
3943
3944 if( sz<=APND_MARK_SIZE ) return -1;
3945 rc = pFile->pMethods->xRead(pFile, a, APND_MARK_SIZE, sz-APND_MARK_SIZE);
3946 if( rc ) return -1;
3947 if( memcmp(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ)!=0 ) return -1;
3948 iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ]&0x7f))<<56;
3949 for(i=1; i<8; i++){
3950 iMark += (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]<<(56-8*i);
3951 }
3952 return iMark;
3953}
3954
3955/*
3956** Open an apnd file handle.
3957*/
3958static int apndOpen(
3959 sqlite3_vfs *pVfs,
3960 const char *zName,
3961 sqlite3_file *pFile,
3962 int flags,
3963 int *pOutFlags
3964){
3965 ApndFile *p;
3966 sqlite3_file *pSubFile;
3967 sqlite3_vfs *pSubVfs;
3968 int rc;
3969 sqlite3_int64 sz;
3970 pSubVfs = ORIGVFS(pVfs);
3971 if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
3972 return pSubVfs->xOpen(pSubVfs, zName, pFile, flags, pOutFlags);
3973 }
3974 p = (ApndFile*)pFile;
3975 memset(p, 0, sizeof(*p));
3976 pSubFile = ORIGFILE(pFile);
3977 p->base.pMethods = &apnd_io_methods;
3978 rc = pSubVfs->xOpen(pSubVfs, zName, pSubFile, flags, pOutFlags);
3979 if( rc ) goto apnd_open_done;
3980 rc = pSubFile->pMethods->xFileSize(pSubFile, &sz);
3981 if( rc ){
3982 pSubFile->pMethods->xClose(pSubFile);
3983 goto apnd_open_done;
3984 }
3985 if( apndIsOrdinaryDatabaseFile(sz, pSubFile) ){
3986 memmove(pFile, pSubFile, pSubVfs->szOsFile);
3987 return SQLITE_OK;
3988 }
3989 p->iMark = 0;
3990 p->iPgOne = apndReadMark(sz, pFile);
3991 if( p->iPgOne>0 ){
3992 return SQLITE_OK;
3993 }
3994 if( (flags & SQLITE_OPEN_CREATE)==0 ){
3995 pSubFile->pMethods->xClose(pSubFile);
3996 rc = SQLITE_CANTOPEN;
3997 }
3998 p->iPgOne = (sz+0xfff) & ~(sqlite3_int64)0xfff;
3999apnd_open_done:
4000 if( rc ) pFile->pMethods = 0;
4001 return rc;
4002}
4003
4004/*
4005** All other VFS methods are pass-thrus.
4006*/
4007static int apndDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
4008 return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync);
4009}
4010static int apndAccess(
4011 sqlite3_vfs *pVfs,
4012 const char *zPath,
4013 int flags,
4014 int *pResOut
4015){
4016 return ORIGVFS(pVfs)->xAccess(ORIGVFS(pVfs), zPath, flags, pResOut);
4017}
4018static int apndFullPathname(
4019 sqlite3_vfs *pVfs,
4020 const char *zPath,
4021 int nOut,
4022 char *zOut
4023){
4024 return ORIGVFS(pVfs)->xFullPathname(ORIGVFS(pVfs),zPath,nOut,zOut);
4025}
4026static void *apndDlOpen(sqlite3_vfs *pVfs, const char *zPath){
4027 return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
4028}
4029static void apndDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
4030 ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
4031}
4032static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
4033 return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
4034}
4035static void apndDlClose(sqlite3_vfs *pVfs, void *pHandle){
4036 ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
4037}
4038static int apndRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
4039 return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
4040}
4041static int apndSleep(sqlite3_vfs *pVfs, int nMicro){
4042 return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
4043}
4044static int apndCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
4045 return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
4046}
4047static int apndGetLastError(sqlite3_vfs *pVfs, int a, char *b){
4048 return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
4049}
4050static int apndCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
4051 return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
4052}
4053static int apndSetSystemCall(
4054 sqlite3_vfs *pVfs,
4055 const char *zName,
4056 sqlite3_syscall_ptr pCall
4057){
4058 return ORIGVFS(pVfs)->xSetSystemCall(ORIGVFS(pVfs),zName,pCall);
4059}
4060static sqlite3_syscall_ptr apndGetSystemCall(
4061 sqlite3_vfs *pVfs,
4062 const char *zName
4063){
4064 return ORIGVFS(pVfs)->xGetSystemCall(ORIGVFS(pVfs),zName);
4065}
4066static const char *apndNextSystemCall(sqlite3_vfs *pVfs, const char *zName){
4067 return ORIGVFS(pVfs)->xNextSystemCall(ORIGVFS(pVfs), zName);
4068}
4069
4070
4071#ifdef _WIN32
4072
4073#endif
4074/*
4075** This routine is called when the extension is loaded.
4076** Register the new VFS.
4077*/
4078int sqlite3_appendvfs_init(
4079 sqlite3 *db,
4080 char **pzErrMsg,
4081 const sqlite3_api_routines *pApi
4082){
4083 int rc = SQLITE_OK;
4084 sqlite3_vfs *pOrig;
4085 SQLITE_EXTENSION_INIT2(pApi);
4086 (void)pzErrMsg;
4087 (void)db;
4088 pOrig = sqlite3_vfs_find(0);
4089 apnd_vfs.iVersion = pOrig->iVersion;
4090 apnd_vfs.pAppData = pOrig;
4091 apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile);
4092 rc = sqlite3_vfs_register(&apnd_vfs, 0);
4093#ifdef APPENDVFS_TEST
4094 if( rc==SQLITE_OK ){
4095 rc = sqlite3_auto_extension((void(*)(void))apndvfsRegister);
4096 }
4097#endif
4098 if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
4099 return rc;
4100}
4101
4102/************************* End ../ext/misc/appendvfs.c ********************/
mydongistiny63ee58c2019-09-21 18:04:30 -07004103/************************* Begin ../ext/misc/memtrace.c ******************/
4104/*
4105** 2019-01-21
4106**
4107** The author disclaims copyright to this source code. In place of
4108** a legal notice, here is a blessing:
4109**
4110** May you do good and not evil.
4111** May you find forgiveness for yourself and forgive others.
4112** May you share freely, never taking more than you give.
4113**
4114*************************************************************************
4115**
4116** This file implements an extension that uses the SQLITE_CONFIG_MALLOC
4117** mechanism to add a tracing layer on top of SQLite. If this extension
4118** is registered prior to sqlite3_initialize(), it will cause all memory
4119** allocation activities to be logged on standard output, or to some other
4120** FILE specified by the initializer.
4121**
4122** This file needs to be compiled into the application that uses it.
4123**
4124** This extension is used to implement the --memtrace option of the
4125** command-line shell.
4126*/
4127#include <assert.h>
4128#include <string.h>
4129#include <stdio.h>
4130
4131/* The original memory allocation routines */
4132static sqlite3_mem_methods memtraceBase;
4133static FILE *memtraceOut;
4134
4135/* Methods that trace memory allocations */
4136static void *memtraceMalloc(int n){
4137 if( memtraceOut ){
4138 fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n",
4139 memtraceBase.xRoundup(n));
4140 }
4141 return memtraceBase.xMalloc(n);
4142}
4143static void memtraceFree(void *p){
4144 if( p==0 ) return;
4145 if( memtraceOut ){
4146 fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p));
4147 }
4148 memtraceBase.xFree(p);
4149}
4150static void *memtraceRealloc(void *p, int n){
4151 if( p==0 ) return memtraceMalloc(n);
4152 if( n==0 ){
4153 memtraceFree(p);
4154 return 0;
4155 }
4156 if( memtraceOut ){
4157 fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n",
4158 memtraceBase.xSize(p), memtraceBase.xRoundup(n));
4159 }
4160 return memtraceBase.xRealloc(p, n);
4161}
4162static int memtraceSize(void *p){
4163 return memtraceBase.xSize(p);
4164}
4165static int memtraceRoundup(int n){
4166 return memtraceBase.xRoundup(n);
4167}
4168static int memtraceInit(void *p){
4169 return memtraceBase.xInit(p);
4170}
4171static void memtraceShutdown(void *p){
4172 memtraceBase.xShutdown(p);
4173}
4174
4175/* The substitute memory allocator */
4176static sqlite3_mem_methods ersaztMethods = {
4177 memtraceMalloc,
4178 memtraceFree,
4179 memtraceRealloc,
4180 memtraceSize,
4181 memtraceRoundup,
4182 memtraceInit,
4183 memtraceShutdown,
4184 0
4185};
4186
4187/* Begin tracing memory allocations to out. */
4188int sqlite3MemTraceActivate(FILE *out){
4189 int rc = SQLITE_OK;
4190 if( memtraceBase.xMalloc==0 ){
4191 rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase);
4192 if( rc==SQLITE_OK ){
4193 rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods);
4194 }
4195 }
4196 memtraceOut = out;
4197 return rc;
4198}
4199
4200/* Deactivate memory tracing */
4201int sqlite3MemTraceDeactivate(void){
4202 int rc = SQLITE_OK;
4203 if( memtraceBase.xMalloc!=0 ){
4204 rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase);
4205 if( rc==SQLITE_OK ){
4206 memset(&memtraceBase, 0, sizeof(memtraceBase));
4207 }
4208 }
4209 memtraceOut = 0;
4210 return rc;
4211}
4212
4213/************************* End ../ext/misc/memtrace.c ********************/
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004214#ifdef SQLITE_HAVE_ZLIB
4215/************************* Begin ../ext/misc/zipfile.c ******************/
4216/*
4217** 2017-12-26
4218**
4219** The author disclaims copyright to this source code. In place of
4220** a legal notice, here is a blessing:
4221**
4222** May you do good and not evil.
4223** May you find forgiveness for yourself and forgive others.
4224** May you share freely, never taking more than you give.
4225**
4226******************************************************************************
4227**
4228** This file implements a virtual table for reading and writing ZIP archive
4229** files.
4230**
4231** Usage example:
4232**
4233** SELECT name, sz, datetime(mtime,'unixepoch') FROM zipfile($filename);
4234**
4235** Current limitations:
4236**
4237** * No support for encryption
4238** * No support for ZIP archives spanning multiple files
4239** * No support for zip64 extensions
4240** * Only the "inflate/deflate" (zlib) compression method is supported
4241*/
mydongistiny63ee58c2019-09-21 18:04:30 -07004242/* #include "sqlite3ext.h" */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004243SQLITE_EXTENSION_INIT1
4244#include <stdio.h>
4245#include <string.h>
4246#include <assert.h>
4247
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004248#include <zlib.h>
4249
4250#ifndef SQLITE_OMIT_VIRTUALTABLE
4251
4252#ifndef SQLITE_AMALGAMATION
mydongistiny63ee58c2019-09-21 18:04:30 -07004253
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004254/* typedef sqlite3_int64 i64; */
4255/* typedef unsigned char u8; */
4256typedef unsigned short u16;
4257typedef unsigned long u32;
4258#define MIN(a,b) ((a)<(b) ? (a) : (b))
mydongistiny63ee58c2019-09-21 18:04:30 -07004259
4260#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
4261# define ALWAYS(X) (1)
4262# define NEVER(X) (0)
4263#elif !defined(NDEBUG)
4264# define ALWAYS(X) ((X)?1:(assert(0),0))
4265# define NEVER(X) ((X)?(assert(0),1):0)
4266#else
4267# define ALWAYS(X) (X)
4268# define NEVER(X) (X)
4269#endif
4270
4271#endif /* SQLITE_AMALGAMATION */
4272
4273/*
4274** Definitions for mode bitmasks S_IFDIR, S_IFREG and S_IFLNK.
4275**
4276** In some ways it would be better to obtain these values from system
4277** header files. But, the dependency is undesirable and (a) these
4278** have been stable for decades, (b) the values are part of POSIX and
4279** are also made explicit in [man stat], and (c) are part of the
4280** file format for zip archives.
4281*/
4282#ifndef S_IFDIR
4283# define S_IFDIR 0040000
4284#endif
4285#ifndef S_IFREG
4286# define S_IFREG 0100000
4287#endif
4288#ifndef S_IFLNK
4289# define S_IFLNK 0120000
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004290#endif
4291
4292static const char ZIPFILE_SCHEMA[] =
4293 "CREATE TABLE y("
4294 "name PRIMARY KEY," /* 0: Name of file in zip archive */
4295 "mode," /* 1: POSIX mode for file */
4296 "mtime," /* 2: Last modification time (secs since 1970)*/
4297 "sz," /* 3: Size of object */
4298 "rawdata," /* 4: Raw data */
4299 "data," /* 5: Uncompressed data */
4300 "method," /* 6: Compression method (integer) */
4301 "z HIDDEN" /* 7: Name of zip file */
4302 ") WITHOUT ROWID;";
4303
4304#define ZIPFILE_F_COLUMN_IDX 7 /* Index of column "file" in the above */
4305#define ZIPFILE_BUFFER_SIZE (64*1024)
4306
4307
4308/*
4309** Magic numbers used to read and write zip files.
4310**
4311** ZIPFILE_NEWENTRY_MADEBY:
4312** Use this value for the "version-made-by" field in new zip file
4313** entries. The upper byte indicates "unix", and the lower byte
4314** indicates that the zip file matches pkzip specification 3.0.
4315** This is what info-zip seems to do.
4316**
4317** ZIPFILE_NEWENTRY_REQUIRED:
4318** Value for "version-required-to-extract" field of new entries.
4319** Version 2.0 is required to support folders and deflate compression.
4320**
4321** ZIPFILE_NEWENTRY_FLAGS:
4322** Value for "general-purpose-bit-flags" field of new entries. Bit
4323** 11 means "utf-8 filename and comment".
4324**
4325** ZIPFILE_SIGNATURE_CDS:
4326** First 4 bytes of a valid CDS record.
4327**
4328** ZIPFILE_SIGNATURE_LFH:
4329** First 4 bytes of a valid LFH record.
mydongistiny63ee58c2019-09-21 18:04:30 -07004330**
4331** ZIPFILE_SIGNATURE_EOCD
4332** First 4 bytes of a valid EOCD record.
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004333*/
4334#define ZIPFILE_EXTRA_TIMESTAMP 0x5455
4335#define ZIPFILE_NEWENTRY_MADEBY ((3<<8) + 30)
4336#define ZIPFILE_NEWENTRY_REQUIRED 20
4337#define ZIPFILE_NEWENTRY_FLAGS 0x800
4338#define ZIPFILE_SIGNATURE_CDS 0x02014b50
4339#define ZIPFILE_SIGNATURE_LFH 0x04034b50
4340#define ZIPFILE_SIGNATURE_EOCD 0x06054b50
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004341
4342/*
mydongistiny63ee58c2019-09-21 18:04:30 -07004343** The sizes of the fixed-size part of each of the three main data
4344** structures in a zip archive.
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004345*/
mydongistiny63ee58c2019-09-21 18:04:30 -07004346#define ZIPFILE_LFH_FIXED_SZ 30
4347#define ZIPFILE_EOCD_FIXED_SZ 22
4348#define ZIPFILE_CDS_FIXED_SZ 46
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004349
4350/*
4351*** 4.3.16 End of central directory record:
4352***
4353*** end of central dir signature 4 bytes (0x06054b50)
4354*** number of this disk 2 bytes
4355*** number of the disk with the
4356*** start of the central directory 2 bytes
4357*** total number of entries in the
4358*** central directory on this disk 2 bytes
4359*** total number of entries in
4360*** the central directory 2 bytes
4361*** size of the central directory 4 bytes
4362*** offset of start of central
4363*** directory with respect to
4364*** the starting disk number 4 bytes
4365*** .ZIP file comment length 2 bytes
4366*** .ZIP file comment (variable size)
4367*/
4368typedef struct ZipfileEOCD ZipfileEOCD;
4369struct ZipfileEOCD {
4370 u16 iDisk;
4371 u16 iFirstDisk;
4372 u16 nEntry;
4373 u16 nEntryTotal;
4374 u32 nSize;
4375 u32 iOffset;
4376};
4377
4378/*
4379*** 4.3.12 Central directory structure:
4380***
4381*** ...
4382***
4383*** central file header signature 4 bytes (0x02014b50)
4384*** version made by 2 bytes
4385*** version needed to extract 2 bytes
4386*** general purpose bit flag 2 bytes
4387*** compression method 2 bytes
4388*** last mod file time 2 bytes
4389*** last mod file date 2 bytes
4390*** crc-32 4 bytes
4391*** compressed size 4 bytes
4392*** uncompressed size 4 bytes
4393*** file name length 2 bytes
4394*** extra field length 2 bytes
4395*** file comment length 2 bytes
4396*** disk number start 2 bytes
4397*** internal file attributes 2 bytes
4398*** external file attributes 4 bytes
4399*** relative offset of local header 4 bytes
4400*/
4401typedef struct ZipfileCDS ZipfileCDS;
4402struct ZipfileCDS {
4403 u16 iVersionMadeBy;
4404 u16 iVersionExtract;
4405 u16 flags;
4406 u16 iCompression;
4407 u16 mTime;
4408 u16 mDate;
4409 u32 crc32;
4410 u32 szCompressed;
4411 u32 szUncompressed;
4412 u16 nFile;
4413 u16 nExtra;
4414 u16 nComment;
4415 u16 iDiskStart;
4416 u16 iInternalAttr;
4417 u32 iExternalAttr;
4418 u32 iOffset;
4419 char *zFile; /* Filename (sqlite3_malloc()) */
4420};
4421
4422/*
4423*** 4.3.7 Local file header:
4424***
4425*** local file header signature 4 bytes (0x04034b50)
4426*** version needed to extract 2 bytes
4427*** general purpose bit flag 2 bytes
4428*** compression method 2 bytes
4429*** last mod file time 2 bytes
4430*** last mod file date 2 bytes
4431*** crc-32 4 bytes
4432*** compressed size 4 bytes
4433*** uncompressed size 4 bytes
4434*** file name length 2 bytes
4435*** extra field length 2 bytes
4436***
4437*/
4438typedef struct ZipfileLFH ZipfileLFH;
4439struct ZipfileLFH {
4440 u16 iVersionExtract;
4441 u16 flags;
4442 u16 iCompression;
4443 u16 mTime;
4444 u16 mDate;
4445 u32 crc32;
4446 u32 szCompressed;
4447 u32 szUncompressed;
4448 u16 nFile;
4449 u16 nExtra;
4450};
4451
4452typedef struct ZipfileEntry ZipfileEntry;
4453struct ZipfileEntry {
mydongistiny63ee58c2019-09-21 18:04:30 -07004454 ZipfileCDS cds; /* Parsed CDS record */
4455 u32 mUnixTime; /* Modification time, in UNIX format */
4456 u8 *aExtra; /* cds.nExtra+cds.nComment bytes of extra data */
4457 i64 iDataOff; /* Offset to data in file (if aData==0) */
4458 u8 *aData; /* cds.szCompressed bytes of compressed data */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004459 ZipfileEntry *pNext; /* Next element in in-memory CDS */
4460};
4461
4462/*
mydongistiny63ee58c2019-09-21 18:04:30 -07004463** Cursor type for zipfile tables.
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004464*/
4465typedef struct ZipfileCsr ZipfileCsr;
4466struct ZipfileCsr {
4467 sqlite3_vtab_cursor base; /* Base class - must be first */
4468 i64 iId; /* Cursor ID */
mydongistiny63ee58c2019-09-21 18:04:30 -07004469 u8 bEof; /* True when at EOF */
4470 u8 bNoop; /* If next xNext() call is no-op */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004471
4472 /* Used outside of write transactions */
4473 FILE *pFile; /* Zip file */
4474 i64 iNextOff; /* Offset of next record in central directory */
4475 ZipfileEOCD eocd; /* Parse of central directory record */
4476
mydongistiny63ee58c2019-09-21 18:04:30 -07004477 ZipfileEntry *pFreeEntry; /* Free this list when cursor is closed or reset */
4478 ZipfileEntry *pCurrent; /* Current entry */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004479 ZipfileCsr *pCsrNext; /* Next cursor on same virtual table */
4480};
4481
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004482typedef struct ZipfileTab ZipfileTab;
4483struct ZipfileTab {
4484 sqlite3_vtab base; /* Base class - must be first */
4485 char *zFile; /* Zip file this table accesses (may be NULL) */
mydongistiny63ee58c2019-09-21 18:04:30 -07004486 sqlite3 *db; /* Host database connection */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004487 u8 *aBuffer; /* Temporary buffer used for various tasks */
4488
4489 ZipfileCsr *pCsrList; /* List of cursors */
4490 i64 iNextCsrid;
4491
4492 /* The following are used by write transactions only */
4493 ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */
4494 ZipfileEntry *pLastEntry; /* Last element in pFirstEntry list */
4495 FILE *pWriteFd; /* File handle open on zip archive */
4496 i64 szCurrent; /* Current size of zip archive */
4497 i64 szOrig; /* Size of archive at start of transaction */
4498};
4499
mydongistiny63ee58c2019-09-21 18:04:30 -07004500/*
4501** Set the error message contained in context ctx to the results of
4502** vprintf(zFmt, ...).
4503*/
4504static void zipfileCtxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
4505 char *zMsg = 0;
4506 va_list ap;
4507 va_start(ap, zFmt);
4508 zMsg = sqlite3_vmprintf(zFmt, ap);
4509 sqlite3_result_error(ctx, zMsg, -1);
4510 sqlite3_free(zMsg);
4511 va_end(ap);
4512}
4513
4514/*
4515** If string zIn is quoted, dequote it in place. Otherwise, if the string
4516** is not quoted, do nothing.
4517*/
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004518static void zipfileDequote(char *zIn){
4519 char q = zIn[0];
4520 if( q=='"' || q=='\'' || q=='`' || q=='[' ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004521 int iIn = 1;
4522 int iOut = 0;
4523 if( q=='[' ) q = ']';
mydongistiny63ee58c2019-09-21 18:04:30 -07004524 while( ALWAYS(zIn[iIn]) ){
4525 char c = zIn[iIn++];
4526 if( c==q && zIn[iIn++]!=q ) break;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004527 zIn[iOut++] = c;
4528 }
4529 zIn[iOut] = '\0';
4530 }
4531}
4532
4533/*
4534** Construct a new ZipfileTab virtual table object.
4535**
4536** argv[0] -> module name ("zipfile")
4537** argv[1] -> database name
4538** argv[2] -> table name
4539** argv[...] -> "column name" and other module argument fields.
4540*/
4541static int zipfileConnect(
4542 sqlite3 *db,
4543 void *pAux,
4544 int argc, const char *const*argv,
4545 sqlite3_vtab **ppVtab,
4546 char **pzErr
4547){
4548 int nByte = sizeof(ZipfileTab) + ZIPFILE_BUFFER_SIZE;
4549 int nFile = 0;
4550 const char *zFile = 0;
4551 ZipfileTab *pNew = 0;
4552 int rc;
4553
mydongistiny63ee58c2019-09-21 18:04:30 -07004554 /* If the table name is not "zipfile", require that the argument be
4555 ** specified. This stops zipfile tables from being created as:
4556 **
4557 ** CREATE VIRTUAL TABLE zzz USING zipfile();
4558 **
4559 ** It does not prevent:
4560 **
4561 ** CREATE VIRTUAL TABLE zipfile USING zipfile();
4562 */
4563 assert( 0==sqlite3_stricmp(argv[0], "zipfile") );
4564 if( (0!=sqlite3_stricmp(argv[2], "zipfile") && argc<4) || argc>4 ){
4565 *pzErr = sqlite3_mprintf("zipfile constructor requires one argument");
4566 return SQLITE_ERROR;
4567 }
4568
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004569 if( argc>3 ){
4570 zFile = argv[3];
4571 nFile = (int)strlen(zFile)+1;
4572 }
4573
4574 rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
4575 if( rc==SQLITE_OK ){
mydongistiny63ee58c2019-09-21 18:04:30 -07004576 pNew = (ZipfileTab*)sqlite3_malloc64((sqlite3_int64)nByte+nFile);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004577 if( pNew==0 ) return SQLITE_NOMEM;
4578 memset(pNew, 0, nByte+nFile);
mydongistiny63ee58c2019-09-21 18:04:30 -07004579 pNew->db = db;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004580 pNew->aBuffer = (u8*)&pNew[1];
4581 if( zFile ){
4582 pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE];
4583 memcpy(pNew->zFile, zFile, nFile);
4584 zipfileDequote(pNew->zFile);
4585 }
4586 }
4587 *ppVtab = (sqlite3_vtab*)pNew;
4588 return rc;
4589}
4590
4591/*
mydongistiny63ee58c2019-09-21 18:04:30 -07004592** Free the ZipfileEntry structure indicated by the only argument.
4593*/
4594static void zipfileEntryFree(ZipfileEntry *p){
4595 if( p ){
4596 sqlite3_free(p->cds.zFile);
4597 sqlite3_free(p);
4598 }
4599}
4600
4601/*
4602** Release resources that should be freed at the end of a write
4603** transaction.
4604*/
4605static void zipfileCleanupTransaction(ZipfileTab *pTab){
4606 ZipfileEntry *pEntry;
4607 ZipfileEntry *pNext;
4608
4609 if( pTab->pWriteFd ){
4610 fclose(pTab->pWriteFd);
4611 pTab->pWriteFd = 0;
4612 }
4613 for(pEntry=pTab->pFirstEntry; pEntry; pEntry=pNext){
4614 pNext = pEntry->pNext;
4615 zipfileEntryFree(pEntry);
4616 }
4617 pTab->pFirstEntry = 0;
4618 pTab->pLastEntry = 0;
4619 pTab->szCurrent = 0;
4620 pTab->szOrig = 0;
4621}
4622
4623/*
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004624** This method is the destructor for zipfile vtab objects.
4625*/
4626static int zipfileDisconnect(sqlite3_vtab *pVtab){
mydongistiny63ee58c2019-09-21 18:04:30 -07004627 zipfileCleanupTransaction((ZipfileTab*)pVtab);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004628 sqlite3_free(pVtab);
4629 return SQLITE_OK;
4630}
4631
4632/*
4633** Constructor for a new ZipfileCsr object.
4634*/
4635static int zipfileOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){
4636 ZipfileTab *pTab = (ZipfileTab*)p;
4637 ZipfileCsr *pCsr;
4638 pCsr = sqlite3_malloc(sizeof(*pCsr));
4639 *ppCsr = (sqlite3_vtab_cursor*)pCsr;
4640 if( pCsr==0 ){
4641 return SQLITE_NOMEM;
4642 }
4643 memset(pCsr, 0, sizeof(*pCsr));
4644 pCsr->iId = ++pTab->iNextCsrid;
4645 pCsr->pCsrNext = pTab->pCsrList;
4646 pTab->pCsrList = pCsr;
4647 return SQLITE_OK;
4648}
4649
4650/*
4651** Reset a cursor back to the state it was in when first returned
4652** by zipfileOpen().
4653*/
4654static void zipfileResetCursor(ZipfileCsr *pCsr){
mydongistiny63ee58c2019-09-21 18:04:30 -07004655 ZipfileEntry *p;
4656 ZipfileEntry *pNext;
4657
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004658 pCsr->bEof = 0;
4659 if( pCsr->pFile ){
4660 fclose(pCsr->pFile);
4661 pCsr->pFile = 0;
mydongistiny63ee58c2019-09-21 18:04:30 -07004662 zipfileEntryFree(pCsr->pCurrent);
4663 pCsr->pCurrent = 0;
4664 }
4665
4666 for(p=pCsr->pFreeEntry; p; p=pNext){
4667 pNext = p->pNext;
4668 zipfileEntryFree(p);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004669 }
4670}
4671
4672/*
4673** Destructor for an ZipfileCsr.
4674*/
4675static int zipfileClose(sqlite3_vtab_cursor *cur){
4676 ZipfileCsr *pCsr = (ZipfileCsr*)cur;
4677 ZipfileTab *pTab = (ZipfileTab*)(pCsr->base.pVtab);
4678 ZipfileCsr **pp;
4679 zipfileResetCursor(pCsr);
4680
4681 /* Remove this cursor from the ZipfileTab.pCsrList list. */
mydongistiny63ee58c2019-09-21 18:04:30 -07004682 for(pp=&pTab->pCsrList; *pp!=pCsr; pp=&((*pp)->pCsrNext));
4683 *pp = pCsr->pCsrNext;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004684
4685 sqlite3_free(pCsr);
4686 return SQLITE_OK;
4687}
4688
4689/*
4690** Set the error message for the virtual table associated with cursor
4691** pCsr to the results of vprintf(zFmt, ...).
4692*/
mydongistiny63ee58c2019-09-21 18:04:30 -07004693static void zipfileTableErr(ZipfileTab *pTab, const char *zFmt, ...){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004694 va_list ap;
4695 va_start(ap, zFmt);
mydongistiny63ee58c2019-09-21 18:04:30 -07004696 sqlite3_free(pTab->base.zErrMsg);
4697 pTab->base.zErrMsg = sqlite3_vmprintf(zFmt, ap);
4698 va_end(ap);
4699}
4700static void zipfileCursorErr(ZipfileCsr *pCsr, const char *zFmt, ...){
4701 va_list ap;
4702 va_start(ap, zFmt);
4703 sqlite3_free(pCsr->base.pVtab->zErrMsg);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004704 pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
4705 va_end(ap);
4706}
4707
mydongistiny63ee58c2019-09-21 18:04:30 -07004708/*
4709** Read nRead bytes of data from offset iOff of file pFile into buffer
4710** aRead[]. Return SQLITE_OK if successful, or an SQLite error code
4711** otherwise.
4712**
4713** If an error does occur, output variable (*pzErrmsg) may be set to point
4714** to an English language error message. It is the responsibility of the
4715** caller to eventually free this buffer using
4716** sqlite3_free().
4717*/
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004718static int zipfileReadData(
4719 FILE *pFile, /* Read from this file */
4720 u8 *aRead, /* Read into this buffer */
4721 int nRead, /* Number of bytes to read */
4722 i64 iOff, /* Offset to read from */
4723 char **pzErrmsg /* OUT: Error message (from sqlite3_malloc) */
4724){
4725 size_t n;
4726 fseek(pFile, (long)iOff, SEEK_SET);
4727 n = fread(aRead, 1, nRead, pFile);
4728 if( (int)n!=nRead ){
4729 *pzErrmsg = sqlite3_mprintf("error in fread()");
4730 return SQLITE_ERROR;
4731 }
4732 return SQLITE_OK;
4733}
4734
4735static int zipfileAppendData(
4736 ZipfileTab *pTab,
4737 const u8 *aWrite,
4738 int nWrite
4739){
4740 size_t n;
4741 fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
4742 n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
4743 if( (int)n!=nWrite ){
4744 pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
4745 return SQLITE_ERROR;
4746 }
4747 pTab->szCurrent += nWrite;
4748 return SQLITE_OK;
4749}
4750
mydongistiny63ee58c2019-09-21 18:04:30 -07004751/*
4752** Read and return a 16-bit little-endian unsigned integer from buffer aBuf.
4753*/
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004754static u16 zipfileGetU16(const u8 *aBuf){
4755 return (aBuf[1] << 8) + aBuf[0];
4756}
mydongistiny63ee58c2019-09-21 18:04:30 -07004757
4758/*
4759** Read and return a 32-bit little-endian unsigned integer from buffer aBuf.
4760*/
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004761static u32 zipfileGetU32(const u8 *aBuf){
4762 return ((u32)(aBuf[3]) << 24)
4763 + ((u32)(aBuf[2]) << 16)
4764 + ((u32)(aBuf[1]) << 8)
4765 + ((u32)(aBuf[0]) << 0);
4766}
4767
mydongistiny63ee58c2019-09-21 18:04:30 -07004768/*
4769** Write a 16-bit little endiate integer into buffer aBuf.
4770*/
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004771static void zipfilePutU16(u8 *aBuf, u16 val){
4772 aBuf[0] = val & 0xFF;
4773 aBuf[1] = (val>>8) & 0xFF;
4774}
mydongistiny63ee58c2019-09-21 18:04:30 -07004775
4776/*
4777** Write a 32-bit little endiate integer into buffer aBuf.
4778*/
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004779static void zipfilePutU32(u8 *aBuf, u32 val){
4780 aBuf[0] = val & 0xFF;
4781 aBuf[1] = (val>>8) & 0xFF;
4782 aBuf[2] = (val>>16) & 0xFF;
4783 aBuf[3] = (val>>24) & 0xFF;
4784}
4785
4786#define zipfileRead32(aBuf) ( aBuf+=4, zipfileGetU32(aBuf-4) )
4787#define zipfileRead16(aBuf) ( aBuf+=2, zipfileGetU16(aBuf-2) )
4788
4789#define zipfileWrite32(aBuf,val) { zipfilePutU32(aBuf,val); aBuf+=4; }
4790#define zipfileWrite16(aBuf,val) { zipfilePutU16(aBuf,val); aBuf+=2; }
4791
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004792/*
4793** Magic numbers used to read CDS records.
4794*/
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004795#define ZIPFILE_CDS_NFILE_OFF 28
mydongistiny63ee58c2019-09-21 18:04:30 -07004796#define ZIPFILE_CDS_SZCOMPRESSED_OFF 20
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004797
4798/*
4799** Decode the CDS record in buffer aBuf into (*pCDS). Return SQLITE_ERROR
4800** if the record is not well-formed, or SQLITE_OK otherwise.
4801*/
4802static int zipfileReadCDS(u8 *aBuf, ZipfileCDS *pCDS){
4803 u8 *aRead = aBuf;
4804 u32 sig = zipfileRead32(aRead);
4805 int rc = SQLITE_OK;
4806 if( sig!=ZIPFILE_SIGNATURE_CDS ){
4807 rc = SQLITE_ERROR;
4808 }else{
4809 pCDS->iVersionMadeBy = zipfileRead16(aRead);
4810 pCDS->iVersionExtract = zipfileRead16(aRead);
4811 pCDS->flags = zipfileRead16(aRead);
4812 pCDS->iCompression = zipfileRead16(aRead);
4813 pCDS->mTime = zipfileRead16(aRead);
4814 pCDS->mDate = zipfileRead16(aRead);
4815 pCDS->crc32 = zipfileRead32(aRead);
4816 pCDS->szCompressed = zipfileRead32(aRead);
4817 pCDS->szUncompressed = zipfileRead32(aRead);
4818 assert( aRead==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
4819 pCDS->nFile = zipfileRead16(aRead);
4820 pCDS->nExtra = zipfileRead16(aRead);
4821 pCDS->nComment = zipfileRead16(aRead);
4822 pCDS->iDiskStart = zipfileRead16(aRead);
4823 pCDS->iInternalAttr = zipfileRead16(aRead);
4824 pCDS->iExternalAttr = zipfileRead32(aRead);
4825 pCDS->iOffset = zipfileRead32(aRead);
4826 assert( aRead==&aBuf[ZIPFILE_CDS_FIXED_SZ] );
4827 }
4828
4829 return rc;
4830}
4831
4832/*
mydongistiny63ee58c2019-09-21 18:04:30 -07004833** Decode the LFH record in buffer aBuf into (*pLFH). Return SQLITE_ERROR
4834** if the record is not well-formed, or SQLITE_OK otherwise.
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004835*/
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004836static int zipfileReadLFH(
mydongistiny63ee58c2019-09-21 18:04:30 -07004837 u8 *aBuffer,
4838 ZipfileLFH *pLFH
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004839){
mydongistiny63ee58c2019-09-21 18:04:30 -07004840 u8 *aRead = aBuffer;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004841 int rc = SQLITE_OK;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004842
mydongistiny63ee58c2019-09-21 18:04:30 -07004843 u32 sig = zipfileRead32(aRead);
4844 if( sig!=ZIPFILE_SIGNATURE_LFH ){
4845 rc = SQLITE_ERROR;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004846 }else{
mydongistiny63ee58c2019-09-21 18:04:30 -07004847 pLFH->iVersionExtract = zipfileRead16(aRead);
4848 pLFH->flags = zipfileRead16(aRead);
4849 pLFH->iCompression = zipfileRead16(aRead);
4850 pLFH->mTime = zipfileRead16(aRead);
4851 pLFH->mDate = zipfileRead16(aRead);
4852 pLFH->crc32 = zipfileRead32(aRead);
4853 pLFH->szCompressed = zipfileRead32(aRead);
4854 pLFH->szUncompressed = zipfileRead32(aRead);
4855 pLFH->nFile = zipfileRead16(aRead);
4856 pLFH->nExtra = zipfileRead16(aRead);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004857 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004858 return rc;
4859}
4860
mydongistiny63ee58c2019-09-21 18:04:30 -07004861
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004862/*
mydongistiny63ee58c2019-09-21 18:04:30 -07004863** Buffer aExtra (size nExtra bytes) contains zip archive "extra" fields.
4864** Scan through this buffer to find an "extra-timestamp" field. If one
4865** exists, extract the 32-bit modification-timestamp from it and store
4866** the value in output parameter *pmTime.
4867**
4868** Zero is returned if no extra-timestamp record could be found (and so
4869** *pmTime is left unchanged), or non-zero otherwise.
4870**
4871** The general format of an extra field is:
4872**
4873** Header ID 2 bytes
4874** Data Size 2 bytes
4875** Data N bytes
4876*/
4877static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){
4878 int ret = 0;
4879 u8 *p = aExtra;
4880 u8 *pEnd = &aExtra[nExtra];
4881
4882 while( p<pEnd ){
4883 u16 id = zipfileRead16(p);
4884 u16 nByte = zipfileRead16(p);
4885
4886 switch( id ){
4887 case ZIPFILE_EXTRA_TIMESTAMP: {
4888 u8 b = p[0];
4889 if( b & 0x01 ){ /* 0x01 -> modtime is present */
4890 *pmTime = zipfileGetU32(&p[1]);
4891 ret = 1;
4892 }
4893 break;
4894 }
4895 }
4896
4897 p += nByte;
4898 }
4899 return ret;
4900}
4901
4902/*
4903** Convert the standard MS-DOS timestamp stored in the mTime and mDate
4904** fields of the CDS structure passed as the only argument to a 32-bit
4905** UNIX seconds-since-the-epoch timestamp. Return the result.
4906**
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004907** "Standard" MS-DOS time format:
4908**
4909** File modification time:
4910** Bits 00-04: seconds divided by 2
4911** Bits 05-10: minute
4912** Bits 11-15: hour
4913** File modification date:
4914** Bits 00-04: day
4915** Bits 05-08: month (1-12)
4916** Bits 09-15: years from 1980
mydongistiny63ee58c2019-09-21 18:04:30 -07004917**
4918** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004919*/
mydongistiny63ee58c2019-09-21 18:04:30 -07004920static u32 zipfileMtime(ZipfileCDS *pCDS){
4921 int Y = (1980 + ((pCDS->mDate >> 9) & 0x7F));
4922 int M = ((pCDS->mDate >> 5) & 0x0F);
4923 int D = (pCDS->mDate & 0x1F);
4924 int B = -13;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004925
mydongistiny63ee58c2019-09-21 18:04:30 -07004926 int sec = (pCDS->mTime & 0x1F)*2;
4927 int min = (pCDS->mTime >> 5) & 0x3F;
4928 int hr = (pCDS->mTime >> 11) & 0x1F;
4929 i64 JD;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004930
mydongistiny63ee58c2019-09-21 18:04:30 -07004931 /* JD = INT(365.25 * (Y+4716)) + INT(30.6001 * (M+1)) + D + B - 1524.5 */
4932
4933 /* Calculate the JD in seconds for noon on the day in question */
4934 if( M<3 ){
4935 Y = Y-1;
4936 M = M+12;
4937 }
4938 JD = (i64)(24*60*60) * (
4939 (int)(365.25 * (Y + 4716))
4940 + (int)(30.6001 * (M + 1))
4941 + D + B - 1524
4942 );
4943
4944 /* Correct the JD for the time within the day */
4945 JD += (hr-12) * 3600 + min * 60 + sec;
4946
4947 /* Convert JD to unix timestamp (the JD epoch is 2440587.5) */
4948 return (u32)(JD - (i64)(24405875) * 24*60*6);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004949}
4950
mydongistiny63ee58c2019-09-21 18:04:30 -07004951/*
4952** The opposite of zipfileMtime(). This function populates the mTime and
4953** mDate fields of the CDS structure passed as the first argument according
4954** to the UNIX timestamp value passed as the second.
4955*/
4956static void zipfileMtimeToDos(ZipfileCDS *pCds, u32 mUnixTime){
4957 /* Convert unix timestamp to JD (2440588 is noon on 1/1/1970) */
4958 i64 JD = (i64)2440588 + mUnixTime / (24*60*60);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004959
mydongistiny63ee58c2019-09-21 18:04:30 -07004960 int A, B, C, D, E;
4961 int yr, mon, day;
4962 int hr, min, sec;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004963
mydongistiny63ee58c2019-09-21 18:04:30 -07004964 A = (int)((JD - 1867216.25)/36524.25);
4965 A = (int)(JD + 1 + A - (A/4));
4966 B = A + 1524;
4967 C = (int)((B - 122.1)/365.25);
4968 D = (36525*(C&32767))/100;
4969 E = (int)((B-D)/30.6001);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004970
mydongistiny63ee58c2019-09-21 18:04:30 -07004971 day = B - D - (int)(30.6001*E);
4972 mon = (E<14 ? E-1 : E-13);
4973 yr = mon>2 ? C-4716 : C-4715;
4974
4975 hr = (mUnixTime % (24*60*60)) / (60*60);
4976 min = (mUnixTime % (60*60)) / 60;
4977 sec = (mUnixTime % 60);
4978
4979 if( yr>=1980 ){
4980 pCds->mDate = (u16)(day + (mon << 5) + ((yr-1980) << 9));
4981 pCds->mTime = (u16)(sec/2 + (min<<5) + (hr<<11));
4982 }else{
4983 pCds->mDate = pCds->mTime = 0;
4984 }
4985
4986 assert( mUnixTime<315507600
4987 || mUnixTime==zipfileMtime(pCds)
4988 || ((mUnixTime % 2) && mUnixTime-1==zipfileMtime(pCds))
4989 /* || (mUnixTime % 2) */
4990 );
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08004991}
4992
mydongistiny63ee58c2019-09-21 18:04:30 -07004993/*
4994** If aBlob is not NULL, then it is a pointer to a buffer (nBlob bytes in
4995** size) containing an entire zip archive image. Or, if aBlob is NULL,
4996** then pFile is a file-handle open on a zip file. In either case, this
4997** function creates a ZipfileEntry object based on the zip archive entry
4998** for which the CDS record is at offset iOff.
4999**
5000** If successful, SQLITE_OK is returned and (*ppEntry) set to point to
5001** the new object. Otherwise, an SQLite error code is returned and the
5002** final value of (*ppEntry) undefined.
5003*/
5004static int zipfileGetEntry(
5005 ZipfileTab *pTab, /* Store any error message here */
5006 const u8 *aBlob, /* Pointer to in-memory file image */
5007 int nBlob, /* Size of aBlob[] in bytes */
5008 FILE *pFile, /* If aBlob==0, read from this file */
5009 i64 iOff, /* Offset of CDS record */
5010 ZipfileEntry **ppEntry /* OUT: Pointer to new object */
5011){
5012 u8 *aRead;
5013 char **pzErr = &pTab->base.zErrMsg;
5014 int rc = SQLITE_OK;
5015
5016 if( aBlob==0 ){
5017 aRead = pTab->aBuffer;
5018 rc = zipfileReadData(pFile, aRead, ZIPFILE_CDS_FIXED_SZ, iOff, pzErr);
5019 }else{
5020 aRead = (u8*)&aBlob[iOff];
5021 }
5022
5023 if( rc==SQLITE_OK ){
5024 sqlite3_int64 nAlloc;
5025 ZipfileEntry *pNew;
5026
5027 int nFile = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF]);
5028 int nExtra = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+2]);
5029 nExtra += zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+4]);
5030
5031 nAlloc = sizeof(ZipfileEntry) + nExtra;
5032 if( aBlob ){
5033 nAlloc += zipfileGetU32(&aRead[ZIPFILE_CDS_SZCOMPRESSED_OFF]);
5034 }
5035
5036 pNew = (ZipfileEntry*)sqlite3_malloc64(nAlloc);
5037 if( pNew==0 ){
5038 rc = SQLITE_NOMEM;
5039 }else{
5040 memset(pNew, 0, sizeof(ZipfileEntry));
5041 rc = zipfileReadCDS(aRead, &pNew->cds);
5042 if( rc!=SQLITE_OK ){
5043 *pzErr = sqlite3_mprintf("failed to read CDS at offset %lld", iOff);
5044 }else if( aBlob==0 ){
5045 rc = zipfileReadData(
5046 pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr
5047 );
5048 }else{
5049 aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ];
5050 }
5051 }
5052
5053 if( rc==SQLITE_OK ){
5054 u32 *pt = &pNew->mUnixTime;
5055 pNew->cds.zFile = sqlite3_mprintf("%.*s", nFile, aRead);
5056 pNew->aExtra = (u8*)&pNew[1];
5057 memcpy(pNew->aExtra, &aRead[nFile], nExtra);
5058 if( pNew->cds.zFile==0 ){
5059 rc = SQLITE_NOMEM;
5060 }else if( 0==zipfileScanExtra(&aRead[nFile], pNew->cds.nExtra, pt) ){
5061 pNew->mUnixTime = zipfileMtime(&pNew->cds);
5062 }
5063 }
5064
5065 if( rc==SQLITE_OK ){
5066 static const int szFix = ZIPFILE_LFH_FIXED_SZ;
5067 ZipfileLFH lfh;
5068 if( pFile ){
5069 rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr);
5070 }else{
5071 aRead = (u8*)&aBlob[pNew->cds.iOffset];
5072 }
5073
5074 rc = zipfileReadLFH(aRead, &lfh);
5075 if( rc==SQLITE_OK ){
5076 pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
5077 pNew->iDataOff += lfh.nFile + lfh.nExtra;
5078 if( aBlob && pNew->cds.szCompressed ){
5079 pNew->aData = &pNew->aExtra[nExtra];
5080 memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed);
5081 }
5082 }else{
5083 *pzErr = sqlite3_mprintf("failed to read LFH at offset %d",
5084 (int)pNew->cds.iOffset
5085 );
5086 }
5087 }
5088
5089 if( rc!=SQLITE_OK ){
5090 zipfileEntryFree(pNew);
5091 }else{
5092 *ppEntry = pNew;
5093 }
5094 }
5095
5096 return rc;
5097}
5098
5099/*
5100** Advance an ZipfileCsr to its next row of output.
5101*/
5102static int zipfileNext(sqlite3_vtab_cursor *cur){
5103 ZipfileCsr *pCsr = (ZipfileCsr*)cur;
5104 int rc = SQLITE_OK;
5105
5106 if( pCsr->pFile ){
5107 i64 iEof = pCsr->eocd.iOffset + pCsr->eocd.nSize;
5108 zipfileEntryFree(pCsr->pCurrent);
5109 pCsr->pCurrent = 0;
5110 if( pCsr->iNextOff>=iEof ){
5111 pCsr->bEof = 1;
5112 }else{
5113 ZipfileEntry *p = 0;
5114 ZipfileTab *pTab = (ZipfileTab*)(cur->pVtab);
5115 rc = zipfileGetEntry(pTab, 0, 0, pCsr->pFile, pCsr->iNextOff, &p);
5116 if( rc==SQLITE_OK ){
5117 pCsr->iNextOff += ZIPFILE_CDS_FIXED_SZ;
5118 pCsr->iNextOff += (int)p->cds.nExtra + p->cds.nFile + p->cds.nComment;
5119 }
5120 pCsr->pCurrent = p;
5121 }
5122 }else{
5123 if( !pCsr->bNoop ){
5124 pCsr->pCurrent = pCsr->pCurrent->pNext;
5125 }
5126 if( pCsr->pCurrent==0 ){
5127 pCsr->bEof = 1;
5128 }
5129 }
5130
5131 pCsr->bNoop = 0;
5132 return rc;
5133}
5134
5135static void zipfileFree(void *p) {
5136 sqlite3_free(p);
5137}
5138
5139/*
5140** Buffer aIn (size nIn bytes) contains compressed data. Uncompressed, the
5141** size is nOut bytes. This function uncompresses the data and sets the
5142** return value in context pCtx to the result (a blob).
5143**
5144** If an error occurs, an error code is left in pCtx instead.
5145*/
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005146static void zipfileInflate(
mydongistiny63ee58c2019-09-21 18:04:30 -07005147 sqlite3_context *pCtx, /* Store result here */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005148 const u8 *aIn, /* Compressed data */
5149 int nIn, /* Size of buffer aIn[] in bytes */
5150 int nOut /* Expected output size */
5151){
5152 u8 *aRes = sqlite3_malloc(nOut);
5153 if( aRes==0 ){
5154 sqlite3_result_error_nomem(pCtx);
5155 }else{
5156 int err;
5157 z_stream str;
5158 memset(&str, 0, sizeof(str));
5159
5160 str.next_in = (Byte*)aIn;
5161 str.avail_in = nIn;
5162 str.next_out = (Byte*)aRes;
5163 str.avail_out = nOut;
5164
5165 err = inflateInit2(&str, -15);
5166 if( err!=Z_OK ){
5167 zipfileCtxErrorMsg(pCtx, "inflateInit2() failed (%d)", err);
5168 }else{
5169 err = inflate(&str, Z_NO_FLUSH);
5170 if( err!=Z_STREAM_END ){
5171 zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err);
5172 }else{
mydongistiny63ee58c2019-09-21 18:04:30 -07005173 sqlite3_result_blob(pCtx, aRes, nOut, zipfileFree);
5174 aRes = 0;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005175 }
5176 }
5177 sqlite3_free(aRes);
5178 inflateEnd(&str);
5179 }
5180}
5181
mydongistiny63ee58c2019-09-21 18:04:30 -07005182/*
5183** Buffer aIn (size nIn bytes) contains uncompressed data. This function
5184** compresses it and sets (*ppOut) to point to a buffer containing the
5185** compressed data. The caller is responsible for eventually calling
5186** sqlite3_free() to release buffer (*ppOut). Before returning, (*pnOut)
5187** is set to the size of buffer (*ppOut) in bytes.
5188**
5189** If no error occurs, SQLITE_OK is returned. Otherwise, an SQLite error
5190** code is returned and an error message left in virtual-table handle
5191** pTab. The values of (*ppOut) and (*pnOut) are left unchanged in this
5192** case.
5193*/
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005194static int zipfileDeflate(
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005195 const u8 *aIn, int nIn, /* Input */
mydongistiny63ee58c2019-09-21 18:04:30 -07005196 u8 **ppOut, int *pnOut, /* Output */
5197 char **pzErr /* OUT: Error message */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005198){
mydongistiny63ee58c2019-09-21 18:04:30 -07005199 sqlite3_int64 nAlloc = compressBound(nIn);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005200 u8 *aOut;
5201 int rc = SQLITE_OK;
5202
mydongistiny63ee58c2019-09-21 18:04:30 -07005203 aOut = (u8*)sqlite3_malloc64(nAlloc);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005204 if( aOut==0 ){
5205 rc = SQLITE_NOMEM;
5206 }else{
5207 int res;
5208 z_stream str;
5209 memset(&str, 0, sizeof(str));
5210 str.next_in = (Bytef*)aIn;
5211 str.avail_in = nIn;
5212 str.next_out = aOut;
5213 str.avail_out = nAlloc;
5214
5215 deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
5216 res = deflate(&str, Z_FINISH);
5217
5218 if( res==Z_STREAM_END ){
5219 *ppOut = aOut;
5220 *pnOut = (int)str.total_out;
5221 }else{
5222 sqlite3_free(aOut);
mydongistiny63ee58c2019-09-21 18:04:30 -07005223 *pzErr = sqlite3_mprintf("zipfile: deflate() error");
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005224 rc = SQLITE_ERROR;
5225 }
5226 deflateEnd(&str);
5227 }
5228
5229 return rc;
5230}
5231
5232
5233/*
5234** Return values of columns for the row at which the series_cursor
5235** is currently pointing.
5236*/
5237static int zipfileColumn(
5238 sqlite3_vtab_cursor *cur, /* The cursor */
5239 sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
5240 int i /* Which column to return */
5241){
5242 ZipfileCsr *pCsr = (ZipfileCsr*)cur;
mydongistiny63ee58c2019-09-21 18:04:30 -07005243 ZipfileCDS *pCDS = &pCsr->pCurrent->cds;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005244 int rc = SQLITE_OK;
5245 switch( i ){
5246 case 0: /* name */
mydongistiny63ee58c2019-09-21 18:04:30 -07005247 sqlite3_result_text(ctx, pCDS->zFile, -1, SQLITE_TRANSIENT);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005248 break;
5249 case 1: /* mode */
5250 /* TODO: Whether or not the following is correct surely depends on
5251 ** the platform on which the archive was created. */
mydongistiny63ee58c2019-09-21 18:04:30 -07005252 sqlite3_result_int(ctx, pCDS->iExternalAttr >> 16);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005253 break;
5254 case 2: { /* mtime */
mydongistiny63ee58c2019-09-21 18:04:30 -07005255 sqlite3_result_int64(ctx, pCsr->pCurrent->mUnixTime);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005256 break;
5257 }
5258 case 3: { /* sz */
5259 if( sqlite3_vtab_nochange(ctx)==0 ){
mydongistiny63ee58c2019-09-21 18:04:30 -07005260 sqlite3_result_int64(ctx, pCDS->szUncompressed);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005261 }
5262 break;
5263 }
5264 case 4: /* rawdata */
5265 if( sqlite3_vtab_nochange(ctx) ) break;
5266 case 5: { /* data */
mydongistiny63ee58c2019-09-21 18:04:30 -07005267 if( i==4 || pCDS->iCompression==0 || pCDS->iCompression==8 ){
5268 int sz = pCDS->szCompressed;
5269 int szFinal = pCDS->szUncompressed;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005270 if( szFinal>0 ){
mydongistiny63ee58c2019-09-21 18:04:30 -07005271 u8 *aBuf;
5272 u8 *aFree = 0;
5273 if( pCsr->pCurrent->aData ){
5274 aBuf = pCsr->pCurrent->aData;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005275 }else{
mydongistiny63ee58c2019-09-21 18:04:30 -07005276 aBuf = aFree = sqlite3_malloc64(sz);
5277 if( aBuf==0 ){
5278 rc = SQLITE_NOMEM;
5279 }else{
5280 FILE *pFile = pCsr->pFile;
5281 if( pFile==0 ){
5282 pFile = ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd;
5283 }
5284 rc = zipfileReadData(pFile, aBuf, sz, pCsr->pCurrent->iDataOff,
5285 &pCsr->base.pVtab->zErrMsg
5286 );
5287 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005288 }
5289 if( rc==SQLITE_OK ){
mydongistiny63ee58c2019-09-21 18:04:30 -07005290 if( i==5 && pCDS->iCompression ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005291 zipfileInflate(ctx, aBuf, sz, szFinal);
5292 }else{
5293 sqlite3_result_blob(ctx, aBuf, sz, SQLITE_TRANSIENT);
5294 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005295 }
mydongistiny63ee58c2019-09-21 18:04:30 -07005296 sqlite3_free(aFree);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005297 }else{
5298 /* Figure out if this is a directory or a zero-sized file. Consider
5299 ** it to be a directory either if the mode suggests so, or if
5300 ** the final character in the name is '/'. */
mydongistiny63ee58c2019-09-21 18:04:30 -07005301 u32 mode = pCDS->iExternalAttr >> 16;
5302 if( !(mode & S_IFDIR) && pCDS->zFile[pCDS->nFile-1]!='/' ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005303 sqlite3_result_blob(ctx, "", 0, SQLITE_STATIC);
5304 }
5305 }
5306 }
5307 break;
5308 }
5309 case 6: /* method */
mydongistiny63ee58c2019-09-21 18:04:30 -07005310 sqlite3_result_int(ctx, pCDS->iCompression);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005311 break;
mydongistiny63ee58c2019-09-21 18:04:30 -07005312 default: /* z */
5313 assert( i==7 );
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005314 sqlite3_result_int64(ctx, pCsr->iId);
5315 break;
5316 }
5317
5318 return rc;
5319}
5320
5321/*
mydongistiny63ee58c2019-09-21 18:04:30 -07005322** Return TRUE if the cursor is at EOF.
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005323*/
5324static int zipfileEof(sqlite3_vtab_cursor *cur){
5325 ZipfileCsr *pCsr = (ZipfileCsr*)cur;
5326 return pCsr->bEof;
5327}
5328
5329/*
mydongistiny63ee58c2019-09-21 18:04:30 -07005330** If aBlob is not NULL, then it points to a buffer nBlob bytes in size
5331** containing an entire zip archive image. Or, if aBlob is NULL, then pFile
5332** is guaranteed to be a file-handle open on a zip file.
5333**
5334** This function attempts to locate the EOCD record within the zip archive
5335** and populate *pEOCD with the results of decoding it. SQLITE_OK is
5336** returned if successful. Otherwise, an SQLite error code is returned and
5337** an English language error message may be left in virtual-table pTab.
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005338*/
5339static int zipfileReadEOCD(
5340 ZipfileTab *pTab, /* Return errors here */
mydongistiny63ee58c2019-09-21 18:04:30 -07005341 const u8 *aBlob, /* Pointer to in-memory file image */
5342 int nBlob, /* Size of aBlob[] in bytes */
5343 FILE *pFile, /* Read from this file if aBlob==0 */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005344 ZipfileEOCD *pEOCD /* Object to populate */
5345){
5346 u8 *aRead = pTab->aBuffer; /* Temporary buffer */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005347 int nRead; /* Bytes to read from file */
mydongistiny63ee58c2019-09-21 18:04:30 -07005348 int rc = SQLITE_OK;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005349
mydongistiny63ee58c2019-09-21 18:04:30 -07005350 if( aBlob==0 ){
5351 i64 iOff; /* Offset to read from */
5352 i64 szFile; /* Total size of file in bytes */
5353 fseek(pFile, 0, SEEK_END);
5354 szFile = (i64)ftell(pFile);
5355 if( szFile==0 ){
5356 memset(pEOCD, 0, sizeof(ZipfileEOCD));
5357 return SQLITE_OK;
5358 }
5359 nRead = (int)(MIN(szFile, ZIPFILE_BUFFER_SIZE));
5360 iOff = szFile - nRead;
5361 rc = zipfileReadData(pFile, aRead, nRead, iOff, &pTab->base.zErrMsg);
5362 }else{
5363 nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE));
5364 aRead = (u8*)&aBlob[nBlob-nRead];
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005365 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005366
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005367 if( rc==SQLITE_OK ){
5368 int i;
5369
5370 /* Scan backwards looking for the signature bytes */
5371 for(i=nRead-20; i>=0; i--){
5372 if( aRead[i]==0x50 && aRead[i+1]==0x4b
5373 && aRead[i+2]==0x05 && aRead[i+3]==0x06
5374 ){
5375 break;
5376 }
5377 }
5378 if( i<0 ){
5379 pTab->base.zErrMsg = sqlite3_mprintf(
5380 "cannot find end of central directory record"
5381 );
5382 return SQLITE_ERROR;
5383 }
5384
5385 aRead += i+4;
5386 pEOCD->iDisk = zipfileRead16(aRead);
5387 pEOCD->iFirstDisk = zipfileRead16(aRead);
5388 pEOCD->nEntry = zipfileRead16(aRead);
5389 pEOCD->nEntryTotal = zipfileRead16(aRead);
5390 pEOCD->nSize = zipfileRead32(aRead);
5391 pEOCD->iOffset = zipfileRead32(aRead);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005392 }
5393
5394 return rc;
5395}
5396
5397/*
mydongistiny63ee58c2019-09-21 18:04:30 -07005398** Add object pNew to the linked list that begins at ZipfileTab.pFirstEntry
5399** and ends with pLastEntry. If argument pBefore is NULL, then pNew is added
5400** to the end of the list. Otherwise, it is added to the list immediately
5401** before pBefore (which is guaranteed to be a part of said list).
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005402*/
5403static void zipfileAddEntry(
5404 ZipfileTab *pTab,
5405 ZipfileEntry *pBefore,
5406 ZipfileEntry *pNew
5407){
5408 assert( (pTab->pFirstEntry==0)==(pTab->pLastEntry==0) );
5409 assert( pNew->pNext==0 );
5410 if( pBefore==0 ){
5411 if( pTab->pFirstEntry==0 ){
5412 pTab->pFirstEntry = pTab->pLastEntry = pNew;
5413 }else{
5414 assert( pTab->pLastEntry->pNext==0 );
5415 pTab->pLastEntry->pNext = pNew;
5416 pTab->pLastEntry = pNew;
5417 }
5418 }else{
5419 ZipfileEntry **pp;
5420 for(pp=&pTab->pFirstEntry; *pp!=pBefore; pp=&((*pp)->pNext));
5421 pNew->pNext = pBefore;
5422 *pp = pNew;
5423 }
5424}
5425
mydongistiny63ee58c2019-09-21 18:04:30 -07005426static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, int nBlob){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005427 ZipfileEOCD eocd;
5428 int rc;
mydongistiny63ee58c2019-09-21 18:04:30 -07005429 int i;
5430 i64 iOff;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005431
mydongistiny63ee58c2019-09-21 18:04:30 -07005432 rc = zipfileReadEOCD(pTab, aBlob, nBlob, pTab->pWriteFd, &eocd);
5433 iOff = eocd.iOffset;
5434 for(i=0; rc==SQLITE_OK && i<eocd.nEntry; i++){
5435 ZipfileEntry *pNew = 0;
5436 rc = zipfileGetEntry(pTab, aBlob, nBlob, pTab->pWriteFd, iOff, &pNew);
5437
5438 if( rc==SQLITE_OK ){
5439 zipfileAddEntry(pTab, 0, pNew);
5440 iOff += ZIPFILE_CDS_FIXED_SZ;
5441 iOff += (int)pNew->cds.nExtra + pNew->cds.nFile + pNew->cds.nComment;
5442 }
5443 }
5444 return rc;
5445}
5446
5447/*
5448** xFilter callback.
5449*/
5450static int zipfileFilter(
5451 sqlite3_vtab_cursor *cur,
5452 int idxNum, const char *idxStr,
5453 int argc, sqlite3_value **argv
5454){
5455 ZipfileTab *pTab = (ZipfileTab*)cur->pVtab;
5456 ZipfileCsr *pCsr = (ZipfileCsr*)cur;
5457 const char *zFile = 0; /* Zip file to scan */
5458 int rc = SQLITE_OK; /* Return Code */
5459 int bInMemory = 0; /* True for an in-memory zipfile */
5460
5461 zipfileResetCursor(pCsr);
5462
5463 if( pTab->zFile ){
5464 zFile = pTab->zFile;
5465 }else if( idxNum==0 ){
5466 zipfileCursorErr(pCsr, "zipfile() function requires an argument");
5467 return SQLITE_ERROR;
5468 }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
5469 const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
5470 int nBlob = sqlite3_value_bytes(argv[0]);
5471 assert( pTab->pFirstEntry==0 );
5472 rc = zipfileLoadDirectory(pTab, aBlob, nBlob);
5473 pCsr->pFreeEntry = pTab->pFirstEntry;
5474 pTab->pFirstEntry = pTab->pLastEntry = 0;
5475 if( rc!=SQLITE_OK ) return rc;
5476 bInMemory = 1;
5477 }else{
5478 zFile = (const char*)sqlite3_value_text(argv[0]);
5479 }
5480
5481 if( 0==pTab->pWriteFd && 0==bInMemory ){
5482 pCsr->pFile = fopen(zFile, "rb");
5483 if( pCsr->pFile==0 ){
5484 zipfileCursorErr(pCsr, "cannot open file: %s", zFile);
5485 rc = SQLITE_ERROR;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005486 }else{
mydongistiny63ee58c2019-09-21 18:04:30 -07005487 rc = zipfileReadEOCD(pTab, 0, 0, pCsr->pFile, &pCsr->eocd);
5488 if( rc==SQLITE_OK ){
5489 if( pCsr->eocd.nEntry==0 ){
5490 pCsr->bEof = 1;
5491 }else{
5492 pCsr->iNextOff = pCsr->eocd.iOffset;
5493 rc = zipfileNext(cur);
5494 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005495 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005496 }
mydongistiny63ee58c2019-09-21 18:04:30 -07005497 }else{
5498 pCsr->bNoop = 1;
5499 pCsr->pCurrent = pCsr->pFreeEntry ? pCsr->pFreeEntry : pTab->pFirstEntry;
5500 rc = zipfileNext(cur);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005501 }
5502
5503 return rc;
5504}
5505
mydongistiny63ee58c2019-09-21 18:04:30 -07005506/*
5507** xBestIndex callback.
5508*/
5509static int zipfileBestIndex(
5510 sqlite3_vtab *tab,
5511 sqlite3_index_info *pIdxInfo
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005512){
mydongistiny63ee58c2019-09-21 18:04:30 -07005513 int i;
5514 int idx = -1;
5515 int unusable = 0;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005516
mydongistiny63ee58c2019-09-21 18:04:30 -07005517 for(i=0; i<pIdxInfo->nConstraint; i++){
5518 const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
5519 if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue;
5520 if( pCons->usable==0 ){
5521 unusable = 1;
5522 }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
5523 idx = i;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005524 }
5525 }
mydongistiny63ee58c2019-09-21 18:04:30 -07005526 if( idx>=0 ){
5527 pIdxInfo->aConstraintUsage[idx].argvIndex = 1;
5528 pIdxInfo->aConstraintUsage[idx].omit = 1;
5529 pIdxInfo->estimatedCost = 1000.0;
5530 pIdxInfo->idxNum = 1;
5531 }else if( unusable ){
5532 return SQLITE_CONSTRAINT;
5533 }
5534 return SQLITE_OK;
5535}
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005536
mydongistiny63ee58c2019-09-21 18:04:30 -07005537static ZipfileEntry *zipfileNewEntry(const char *zPath){
5538 ZipfileEntry *pNew;
5539 pNew = sqlite3_malloc(sizeof(ZipfileEntry));
5540 if( pNew ){
5541 memset(pNew, 0, sizeof(ZipfileEntry));
5542 pNew->cds.zFile = sqlite3_mprintf("%s", zPath);
5543 if( pNew->cds.zFile==0 ){
5544 sqlite3_free(pNew);
5545 pNew = 0;
5546 }
5547 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005548 return pNew;
5549}
5550
mydongistiny63ee58c2019-09-21 18:04:30 -07005551static int zipfileSerializeLFH(ZipfileEntry *pEntry, u8 *aBuf){
5552 ZipfileCDS *pCds = &pEntry->cds;
5553 u8 *a = aBuf;
5554
5555 pCds->nExtra = 9;
5556
5557 /* Write the LFH itself */
5558 zipfileWrite32(a, ZIPFILE_SIGNATURE_LFH);
5559 zipfileWrite16(a, pCds->iVersionExtract);
5560 zipfileWrite16(a, pCds->flags);
5561 zipfileWrite16(a, pCds->iCompression);
5562 zipfileWrite16(a, pCds->mTime);
5563 zipfileWrite16(a, pCds->mDate);
5564 zipfileWrite32(a, pCds->crc32);
5565 zipfileWrite32(a, pCds->szCompressed);
5566 zipfileWrite32(a, pCds->szUncompressed);
5567 zipfileWrite16(a, (u16)pCds->nFile);
5568 zipfileWrite16(a, pCds->nExtra);
5569 assert( a==&aBuf[ZIPFILE_LFH_FIXED_SZ] );
5570
5571 /* Add the file name */
5572 memcpy(a, pCds->zFile, (int)pCds->nFile);
5573 a += (int)pCds->nFile;
5574
5575 /* The "extra" data */
5576 zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP);
5577 zipfileWrite16(a, 5);
5578 *a++ = 0x01;
5579 zipfileWrite32(a, pEntry->mUnixTime);
5580
5581 return a-aBuf;
5582}
5583
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005584static int zipfileAppendEntry(
5585 ZipfileTab *pTab,
mydongistiny63ee58c2019-09-21 18:04:30 -07005586 ZipfileEntry *pEntry,
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005587 const u8 *pData,
mydongistiny63ee58c2019-09-21 18:04:30 -07005588 int nData
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005589){
5590 u8 *aBuf = pTab->aBuffer;
mydongistiny63ee58c2019-09-21 18:04:30 -07005591 int nBuf;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005592 int rc;
5593
mydongistiny63ee58c2019-09-21 18:04:30 -07005594 nBuf = zipfileSerializeLFH(pEntry, aBuf);
5595 rc = zipfileAppendData(pTab, aBuf, nBuf);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005596 if( rc==SQLITE_OK ){
mydongistiny63ee58c2019-09-21 18:04:30 -07005597 pEntry->iDataOff = pTab->szCurrent;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005598 rc = zipfileAppendData(pTab, pData, nData);
5599 }
5600
5601 return rc;
5602}
5603
5604static int zipfileGetMode(
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005605 sqlite3_value *pVal,
mydongistiny63ee58c2019-09-21 18:04:30 -07005606 int bIsDir, /* If true, default to directory */
5607 u32 *pMode, /* OUT: Mode value */
5608 char **pzErr /* OUT: Error message */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005609){
5610 const char *z = (const char*)sqlite3_value_text(pVal);
5611 u32 mode = 0;
5612 if( z==0 ){
mydongistiny63ee58c2019-09-21 18:04:30 -07005613 mode = (bIsDir ? (S_IFDIR + 0755) : (S_IFREG + 0644));
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005614 }else if( z[0]>='0' && z[0]<='9' ){
5615 mode = (unsigned int)sqlite3_value_int(pVal);
5616 }else{
5617 const char zTemplate[11] = "-rwxrwxrwx";
5618 int i;
5619 if( strlen(z)!=10 ) goto parse_error;
5620 switch( z[0] ){
5621 case '-': mode |= S_IFREG; break;
5622 case 'd': mode |= S_IFDIR; break;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005623 case 'l': mode |= S_IFLNK; break;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005624 default: goto parse_error;
5625 }
5626 for(i=1; i<10; i++){
5627 if( z[i]==zTemplate[i] ) mode |= 1 << (9-i);
5628 else if( z[i]!='-' ) goto parse_error;
5629 }
5630 }
mydongistiny63ee58c2019-09-21 18:04:30 -07005631 if( ((mode & S_IFDIR)==0)==bIsDir ){
5632 /* The "mode" attribute is a directory, but data has been specified.
5633 ** Or vice-versa - no data but "mode" is a file or symlink. */
5634 *pzErr = sqlite3_mprintf("zipfile: mode does not match data");
5635 return SQLITE_CONSTRAINT;
5636 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005637 *pMode = mode;
5638 return SQLITE_OK;
5639
5640 parse_error:
mydongistiny63ee58c2019-09-21 18:04:30 -07005641 *pzErr = sqlite3_mprintf("zipfile: parse error in mode: %s", z);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005642 return SQLITE_ERROR;
5643}
5644
5645/*
5646** Both (const char*) arguments point to nul-terminated strings. Argument
5647** nB is the value of strlen(zB). This function returns 0 if the strings are
5648** identical, ignoring any trailing '/' character in either path. */
5649static int zipfileComparePath(const char *zA, const char *zB, int nB){
5650 int nA = (int)strlen(zA);
5651 if( zA[nA-1]=='/' ) nA--;
5652 if( zB[nB-1]=='/' ) nB--;
5653 if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
5654 return 1;
5655}
5656
mydongistiny63ee58c2019-09-21 18:04:30 -07005657static int zipfileBegin(sqlite3_vtab *pVtab){
5658 ZipfileTab *pTab = (ZipfileTab*)pVtab;
5659 int rc = SQLITE_OK;
5660
5661 assert( pTab->pWriteFd==0 );
5662
5663 /* Open a write fd on the file. Also load the entire central directory
5664 ** structure into memory. During the transaction any new file data is
5665 ** appended to the archive file, but the central directory is accumulated
5666 ** in main-memory until the transaction is committed. */
5667 pTab->pWriteFd = fopen(pTab->zFile, "ab+");
5668 if( pTab->pWriteFd==0 ){
5669 pTab->base.zErrMsg = sqlite3_mprintf(
5670 "zipfile: failed to open file %s for writing", pTab->zFile
5671 );
5672 rc = SQLITE_ERROR;
5673 }else{
5674 fseek(pTab->pWriteFd, 0, SEEK_END);
5675 pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd);
5676 rc = zipfileLoadDirectory(pTab, 0, 0);
5677 }
5678
5679 if( rc!=SQLITE_OK ){
5680 zipfileCleanupTransaction(pTab);
5681 }
5682
5683 return rc;
5684}
5685
5686/*
5687** Return the current time as a 32-bit timestamp in UNIX epoch format (like
5688** time(2)).
5689*/
5690static u32 zipfileTime(void){
5691 sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
5692 u32 ret;
5693 if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
5694 i64 ms;
5695 pVfs->xCurrentTimeInt64(pVfs, &ms);
5696 ret = (u32)((ms/1000) - ((i64)24405875 * 8640));
5697 }else{
5698 double day;
5699 pVfs->xCurrentTime(pVfs, &day);
5700 ret = (u32)((day - 2440587.5) * 86400);
5701 }
5702 return ret;
5703}
5704
5705/*
5706** Return a 32-bit timestamp in UNIX epoch format.
5707**
5708** If the value passed as the only argument is either NULL or an SQL NULL,
5709** return the current time. Otherwise, return the value stored in (*pVal)
5710** cast to a 32-bit unsigned integer.
5711*/
5712static u32 zipfileGetTime(sqlite3_value *pVal){
5713 if( pVal==0 || sqlite3_value_type(pVal)==SQLITE_NULL ){
5714 return zipfileTime();
5715 }
5716 return (u32)sqlite3_value_int64(pVal);
5717}
5718
5719/*
5720** Unless it is NULL, entry pOld is currently part of the pTab->pFirstEntry
5721** linked list. Remove it from the list and free the object.
5722*/
5723static void zipfileRemoveEntryFromList(ZipfileTab *pTab, ZipfileEntry *pOld){
5724 if( pOld ){
5725 ZipfileEntry **pp;
5726 for(pp=&pTab->pFirstEntry; (*pp)!=pOld; pp=&((*pp)->pNext));
5727 *pp = (*pp)->pNext;
5728 zipfileEntryFree(pOld);
5729 }
5730}
5731
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005732/*
5733** xUpdate method.
5734*/
5735static int zipfileUpdate(
5736 sqlite3_vtab *pVtab,
5737 int nVal,
5738 sqlite3_value **apVal,
5739 sqlite_int64 *pRowid
5740){
5741 ZipfileTab *pTab = (ZipfileTab*)pVtab;
5742 int rc = SQLITE_OK; /* Return Code */
5743 ZipfileEntry *pNew = 0; /* New in-memory CDS entry */
5744
5745 u32 mode = 0; /* Mode for new entry */
mydongistiny63ee58c2019-09-21 18:04:30 -07005746 u32 mTime = 0; /* Modification time for new entry */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005747 i64 sz = 0; /* Uncompressed size */
5748 const char *zPath = 0; /* Path for new entry */
5749 int nPath = 0; /* strlen(zPath) */
5750 const u8 *pData = 0; /* Pointer to buffer containing content */
5751 int nData = 0; /* Size of pData buffer in bytes */
5752 int iMethod = 0; /* Compression method for new entry */
5753 u8 *pFree = 0; /* Free this */
5754 char *zFree = 0; /* Also free this */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005755 ZipfileEntry *pOld = 0;
mydongistiny63ee58c2019-09-21 18:04:30 -07005756 ZipfileEntry *pOld2 = 0;
5757 int bUpdate = 0; /* True for an update that modifies "name" */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005758 int bIsDir = 0;
5759 u32 iCrc32 = 0;
5760
mydongistiny63ee58c2019-09-21 18:04:30 -07005761 if( pTab->pWriteFd==0 ){
5762 rc = zipfileBegin(pVtab);
5763 if( rc!=SQLITE_OK ) return rc;
5764 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005765
mydongistiny63ee58c2019-09-21 18:04:30 -07005766 /* If this is a DELETE or UPDATE, find the archive entry to delete. */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005767 if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
5768 const char *zDelete = (const char*)sqlite3_value_text(apVal[0]);
5769 int nDelete = (int)strlen(zDelete);
mydongistiny63ee58c2019-09-21 18:04:30 -07005770 if( nVal>1 ){
5771 const char *zUpdate = (const char*)sqlite3_value_text(apVal[1]);
5772 if( zUpdate && zipfileComparePath(zUpdate, zDelete, nDelete)!=0 ){
5773 bUpdate = 1;
5774 }
5775 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005776 for(pOld=pTab->pFirstEntry; 1; pOld=pOld->pNext){
mydongistiny63ee58c2019-09-21 18:04:30 -07005777 if( zipfileComparePath(pOld->cds.zFile, zDelete, nDelete)==0 ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005778 break;
5779 }
5780 assert( pOld->pNext );
5781 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005782 }
5783
mydongistiny63ee58c2019-09-21 18:04:30 -07005784 if( nVal>1 ){
5785 /* Check that "sz" and "rawdata" are both NULL: */
5786 if( sqlite3_value_type(apVal[5])!=SQLITE_NULL ){
5787 zipfileTableErr(pTab, "sz must be NULL");
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005788 rc = SQLITE_CONSTRAINT;
5789 }
mydongistiny63ee58c2019-09-21 18:04:30 -07005790 if( sqlite3_value_type(apVal[6])!=SQLITE_NULL ){
5791 zipfileTableErr(pTab, "rawdata must be NULL");
5792 rc = SQLITE_CONSTRAINT;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005793 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005794
mydongistiny63ee58c2019-09-21 18:04:30 -07005795 if( rc==SQLITE_OK ){
5796 if( sqlite3_value_type(apVal[7])==SQLITE_NULL ){
5797 /* data=NULL. A directory */
5798 bIsDir = 1;
5799 }else{
5800 /* Value specified for "data", and possibly "method". This must be
5801 ** a regular file or a symlink. */
5802 const u8 *aIn = sqlite3_value_blob(apVal[7]);
5803 int nIn = sqlite3_value_bytes(apVal[7]);
5804 int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL;
5805
5806 iMethod = sqlite3_value_int(apVal[8]);
5807 sz = nIn;
5808 pData = aIn;
5809 nData = nIn;
5810 if( iMethod!=0 && iMethod!=8 ){
5811 zipfileTableErr(pTab, "unknown compression method: %d", iMethod);
5812 rc = SQLITE_CONSTRAINT;
5813 }else{
5814 if( bAuto || iMethod ){
5815 int nCmp;
5816 rc = zipfileDeflate(aIn, nIn, &pFree, &nCmp, &pTab->base.zErrMsg);
5817 if( rc==SQLITE_OK ){
5818 if( iMethod || nCmp<nIn ){
5819 iMethod = 8;
5820 pData = pFree;
5821 nData = nCmp;
5822 }
5823 }
5824 }
5825 iCrc32 = crc32(0, aIn, nIn);
5826 }
5827 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005828 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005829
mydongistiny63ee58c2019-09-21 18:04:30 -07005830 if( rc==SQLITE_OK ){
5831 rc = zipfileGetMode(apVal[3], bIsDir, &mode, &pTab->base.zErrMsg);
5832 }
5833
5834 if( rc==SQLITE_OK ){
5835 zPath = (const char*)sqlite3_value_text(apVal[2]);
5836 nPath = (int)strlen(zPath);
5837 mTime = zipfileGetTime(apVal[4]);
5838 }
5839
5840 if( rc==SQLITE_OK && bIsDir ){
5841 /* For a directory, check that the last character in the path is a
5842 ** '/'. This appears to be required for compatibility with info-zip
5843 ** (the unzip command on unix). It does not create directories
5844 ** otherwise. */
5845 if( zPath[nPath-1]!='/' ){
5846 zFree = sqlite3_mprintf("%s/", zPath);
5847 if( zFree==0 ){ rc = SQLITE_NOMEM; }
5848 zPath = (const char*)zFree;
5849 nPath++;
5850 }
5851 }
5852
5853 /* Check that we're not inserting a duplicate entry -OR- updating an
5854 ** entry with a path, thereby making it into a duplicate. */
5855 if( (pOld==0 || bUpdate) && rc==SQLITE_OK ){
5856 ZipfileEntry *p;
5857 for(p=pTab->pFirstEntry; p; p=p->pNext){
5858 if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){
5859 switch( sqlite3_vtab_on_conflict(pTab->db) ){
5860 case SQLITE_IGNORE: {
5861 goto zipfile_update_done;
5862 }
5863 case SQLITE_REPLACE: {
5864 pOld2 = p;
5865 break;
5866 }
5867 default: {
5868 zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath);
5869 rc = SQLITE_CONSTRAINT;
5870 break;
5871 }
5872 }
5873 break;
5874 }
5875 }
5876 }
5877
5878 if( rc==SQLITE_OK ){
5879 /* Create the new CDS record. */
5880 pNew = zipfileNewEntry(zPath);
5881 if( pNew==0 ){
5882 rc = SQLITE_NOMEM;
5883 }else{
5884 pNew->cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
5885 pNew->cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
5886 pNew->cds.flags = ZIPFILE_NEWENTRY_FLAGS;
5887 pNew->cds.iCompression = (u16)iMethod;
5888 zipfileMtimeToDos(&pNew->cds, mTime);
5889 pNew->cds.crc32 = iCrc32;
5890 pNew->cds.szCompressed = nData;
5891 pNew->cds.szUncompressed = (u32)sz;
5892 pNew->cds.iExternalAttr = (mode<<16);
5893 pNew->cds.iOffset = (u32)pTab->szCurrent;
5894 pNew->cds.nFile = (u16)nPath;
5895 pNew->mUnixTime = (u32)mTime;
5896 rc = zipfileAppendEntry(pTab, pNew, pData, nData);
5897 zipfileAddEntry(pTab, pOld, pNew);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005898 }
5899 }
5900 }
5901
mydongistiny63ee58c2019-09-21 18:04:30 -07005902 if( rc==SQLITE_OK && (pOld || pOld2) ){
5903 ZipfileCsr *pCsr;
5904 for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
5905 if( pCsr->pCurrent && (pCsr->pCurrent==pOld || pCsr->pCurrent==pOld2) ){
5906 pCsr->pCurrent = pCsr->pCurrent->pNext;
5907 pCsr->bNoop = 1;
5908 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005909 }
mydongistiny63ee58c2019-09-21 18:04:30 -07005910
5911 zipfileRemoveEntryFromList(pTab, pOld);
5912 zipfileRemoveEntryFromList(pTab, pOld2);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005913 }
5914
mydongistiny63ee58c2019-09-21 18:04:30 -07005915zipfile_update_done:
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005916 sqlite3_free(pFree);
5917 sqlite3_free(zFree);
5918 return rc;
5919}
5920
mydongistiny63ee58c2019-09-21 18:04:30 -07005921static int zipfileSerializeEOCD(ZipfileEOCD *p, u8 *aBuf){
5922 u8 *a = aBuf;
5923 zipfileWrite32(a, ZIPFILE_SIGNATURE_EOCD);
5924 zipfileWrite16(a, p->iDisk);
5925 zipfileWrite16(a, p->iFirstDisk);
5926 zipfileWrite16(a, p->nEntry);
5927 zipfileWrite16(a, p->nEntryTotal);
5928 zipfileWrite32(a, p->nSize);
5929 zipfileWrite32(a, p->iOffset);
5930 zipfileWrite16(a, 0); /* Size of trailing comment in bytes*/
5931
5932 return a-aBuf;
5933}
5934
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005935static int zipfileAppendEOCD(ZipfileTab *pTab, ZipfileEOCD *p){
mydongistiny63ee58c2019-09-21 18:04:30 -07005936 int nBuf = zipfileSerializeEOCD(p, pTab->aBuffer);
5937 assert( nBuf==ZIPFILE_EOCD_FIXED_SZ );
5938 return zipfileAppendData(pTab, pTab->aBuffer, nBuf);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005939}
5940
mydongistiny63ee58c2019-09-21 18:04:30 -07005941/*
5942** Serialize the CDS structure into buffer aBuf[]. Return the number
5943** of bytes written.
5944*/
5945static int zipfileSerializeCDS(ZipfileEntry *pEntry, u8 *aBuf){
5946 u8 *a = aBuf;
5947 ZipfileCDS *pCDS = &pEntry->cds;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005948
mydongistiny63ee58c2019-09-21 18:04:30 -07005949 if( pEntry->aExtra==0 ){
5950 pCDS->nExtra = 9;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005951 }
5952
mydongistiny63ee58c2019-09-21 18:04:30 -07005953 zipfileWrite32(a, ZIPFILE_SIGNATURE_CDS);
5954 zipfileWrite16(a, pCDS->iVersionMadeBy);
5955 zipfileWrite16(a, pCDS->iVersionExtract);
5956 zipfileWrite16(a, pCDS->flags);
5957 zipfileWrite16(a, pCDS->iCompression);
5958 zipfileWrite16(a, pCDS->mTime);
5959 zipfileWrite16(a, pCDS->mDate);
5960 zipfileWrite32(a, pCDS->crc32);
5961 zipfileWrite32(a, pCDS->szCompressed);
5962 zipfileWrite32(a, pCDS->szUncompressed);
5963 assert( a==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
5964 zipfileWrite16(a, pCDS->nFile);
5965 zipfileWrite16(a, pCDS->nExtra);
5966 zipfileWrite16(a, pCDS->nComment);
5967 zipfileWrite16(a, pCDS->iDiskStart);
5968 zipfileWrite16(a, pCDS->iInternalAttr);
5969 zipfileWrite32(a, pCDS->iExternalAttr);
5970 zipfileWrite32(a, pCDS->iOffset);
5971
5972 memcpy(a, pCDS->zFile, pCDS->nFile);
5973 a += pCDS->nFile;
5974
5975 if( pEntry->aExtra ){
5976 int n = (int)pCDS->nExtra + (int)pCDS->nComment;
5977 memcpy(a, pEntry->aExtra, n);
5978 a += n;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005979 }else{
mydongistiny63ee58c2019-09-21 18:04:30 -07005980 assert( pCDS->nExtra==9 );
5981 zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP);
5982 zipfileWrite16(a, 5);
5983 *a++ = 0x01;
5984 zipfileWrite32(a, pEntry->mUnixTime);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005985 }
5986
mydongistiny63ee58c2019-09-21 18:04:30 -07005987 return a-aBuf;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08005988}
5989
5990static int zipfileCommit(sqlite3_vtab *pVtab){
5991 ZipfileTab *pTab = (ZipfileTab*)pVtab;
5992 int rc = SQLITE_OK;
5993 if( pTab->pWriteFd ){
5994 i64 iOffset = pTab->szCurrent;
5995 ZipfileEntry *p;
5996 ZipfileEOCD eocd;
5997 int nEntry = 0;
5998
mydongistiny63ee58c2019-09-21 18:04:30 -07005999 /* Write out all entries */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08006000 for(p=pTab->pFirstEntry; rc==SQLITE_OK && p; p=p->pNext){
mydongistiny63ee58c2019-09-21 18:04:30 -07006001 int n = zipfileSerializeCDS(p, pTab->aBuffer);
6002 rc = zipfileAppendData(pTab, pTab->aBuffer, n);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08006003 nEntry++;
6004 }
6005
6006 /* Write out the EOCD record */
6007 eocd.iDisk = 0;
6008 eocd.iFirstDisk = 0;
6009 eocd.nEntry = (u16)nEntry;
6010 eocd.nEntryTotal = (u16)nEntry;
6011 eocd.nSize = (u32)(pTab->szCurrent - iOffset);
6012 eocd.iOffset = (u32)iOffset;
6013 rc = zipfileAppendEOCD(pTab, &eocd);
6014
6015 zipfileCleanupTransaction(pTab);
6016 }
6017 return rc;
6018}
6019
6020static int zipfileRollback(sqlite3_vtab *pVtab){
6021 return zipfileCommit(pVtab);
6022}
6023
6024static ZipfileCsr *zipfileFindCursor(ZipfileTab *pTab, i64 iId){
6025 ZipfileCsr *pCsr;
6026 for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
6027 if( iId==pCsr->iId ) break;
6028 }
6029 return pCsr;
6030}
6031
6032static void zipfileFunctionCds(
6033 sqlite3_context *context,
6034 int argc,
6035 sqlite3_value **argv
6036){
6037 ZipfileCsr *pCsr;
6038 ZipfileTab *pTab = (ZipfileTab*)sqlite3_user_data(context);
6039 assert( argc>0 );
6040
6041 pCsr = zipfileFindCursor(pTab, sqlite3_value_int64(argv[0]));
6042 if( pCsr ){
mydongistiny63ee58c2019-09-21 18:04:30 -07006043 ZipfileCDS *p = &pCsr->pCurrent->cds;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08006044 char *zRes = sqlite3_mprintf("{"
6045 "\"version-made-by\" : %u, "
6046 "\"version-to-extract\" : %u, "
6047 "\"flags\" : %u, "
6048 "\"compression\" : %u, "
6049 "\"time\" : %u, "
6050 "\"date\" : %u, "
6051 "\"crc32\" : %u, "
6052 "\"compressed-size\" : %u, "
6053 "\"uncompressed-size\" : %u, "
6054 "\"file-name-length\" : %u, "
6055 "\"extra-field-length\" : %u, "
6056 "\"file-comment-length\" : %u, "
6057 "\"disk-number-start\" : %u, "
6058 "\"internal-attr\" : %u, "
6059 "\"external-attr\" : %u, "
6060 "\"offset\" : %u }",
6061 (u32)p->iVersionMadeBy, (u32)p->iVersionExtract,
6062 (u32)p->flags, (u32)p->iCompression,
6063 (u32)p->mTime, (u32)p->mDate,
6064 (u32)p->crc32, (u32)p->szCompressed,
6065 (u32)p->szUncompressed, (u32)p->nFile,
6066 (u32)p->nExtra, (u32)p->nComment,
6067 (u32)p->iDiskStart, (u32)p->iInternalAttr,
6068 (u32)p->iExternalAttr, (u32)p->iOffset
6069 );
6070
6071 if( zRes==0 ){
6072 sqlite3_result_error_nomem(context);
6073 }else{
6074 sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
6075 sqlite3_free(zRes);
6076 }
6077 }
6078}
6079
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08006080/*
6081** xFindFunction method.
6082*/
6083static int zipfileFindFunction(
6084 sqlite3_vtab *pVtab, /* Virtual table handle */
6085 int nArg, /* Number of SQL function arguments */
6086 const char *zName, /* Name of SQL function */
6087 void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
6088 void **ppArg /* OUT: User data for *pxFunc */
6089){
mydongistiny63ee58c2019-09-21 18:04:30 -07006090 if( sqlite3_stricmp("zipfile_cds", zName)==0 ){
6091 *pxFunc = zipfileFunctionCds;
6092 *ppArg = (void*)pVtab;
6093 return 1;
6094 }
6095 return 0;
6096}
6097
6098typedef struct ZipfileBuffer ZipfileBuffer;
6099struct ZipfileBuffer {
6100 u8 *a; /* Pointer to buffer */
6101 int n; /* Size of buffer in bytes */
6102 int nAlloc; /* Byte allocated at a[] */
6103};
6104
6105typedef struct ZipfileCtx ZipfileCtx;
6106struct ZipfileCtx {
6107 int nEntry;
6108 ZipfileBuffer body;
6109 ZipfileBuffer cds;
6110};
6111
6112static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){
6113 if( pBuf->n+nByte>pBuf->nAlloc ){
6114 u8 *aNew;
6115 sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512;
6116 int nReq = pBuf->n + nByte;
6117
6118 while( nNew<nReq ) nNew = nNew*2;
6119 aNew = sqlite3_realloc64(pBuf->a, nNew);
6120 if( aNew==0 ) return SQLITE_NOMEM;
6121 pBuf->a = aNew;
6122 pBuf->nAlloc = (int)nNew;
6123 }
6124 return SQLITE_OK;
6125}
6126
6127/*
6128** xStep() callback for the zipfile() aggregate. This can be called in
6129** any of the following ways:
6130**
6131** SELECT zipfile(name,data) ...
6132** SELECT zipfile(name,mode,mtime,data) ...
6133** SELECT zipfile(name,mode,mtime,data,method) ...
6134*/
6135void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
6136 ZipfileCtx *p; /* Aggregate function context */
6137 ZipfileEntry e; /* New entry to add to zip archive */
6138
6139 sqlite3_value *pName = 0;
6140 sqlite3_value *pMode = 0;
6141 sqlite3_value *pMtime = 0;
6142 sqlite3_value *pData = 0;
6143 sqlite3_value *pMethod = 0;
6144
6145 int bIsDir = 0;
6146 u32 mode;
6147 int rc = SQLITE_OK;
6148 char *zErr = 0;
6149
6150 int iMethod = -1; /* Compression method to use (0 or 8) */
6151
6152 const u8 *aData = 0; /* Possibly compressed data for new entry */
6153 int nData = 0; /* Size of aData[] in bytes */
6154 int szUncompressed = 0; /* Size of data before compression */
6155 u8 *aFree = 0; /* Free this before returning */
6156 u32 iCrc32 = 0; /* crc32 of uncompressed data */
6157
6158 char *zName = 0; /* Path (name) of new entry */
6159 int nName = 0; /* Size of zName in bytes */
6160 char *zFree = 0; /* Free this before returning */
6161 int nByte;
6162
6163 memset(&e, 0, sizeof(e));
6164 p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
6165 if( p==0 ) return;
6166
6167 /* Martial the arguments into stack variables */
6168 if( nVal!=2 && nVal!=4 && nVal!=5 ){
6169 zErr = sqlite3_mprintf("wrong number of arguments to function zipfile()");
6170 rc = SQLITE_ERROR;
6171 goto zipfile_step_out;
6172 }
6173 pName = apVal[0];
6174 if( nVal==2 ){
6175 pData = apVal[1];
6176 }else{
6177 pMode = apVal[1];
6178 pMtime = apVal[2];
6179 pData = apVal[3];
6180 if( nVal==5 ){
6181 pMethod = apVal[4];
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08006182 }
6183 }
6184
mydongistiny63ee58c2019-09-21 18:04:30 -07006185 /* Check that the 'name' parameter looks ok. */
6186 zName = (char*)sqlite3_value_text(pName);
6187 nName = sqlite3_value_bytes(pName);
6188 if( zName==0 ){
6189 zErr = sqlite3_mprintf("first argument to zipfile() must be non-NULL");
6190 rc = SQLITE_ERROR;
6191 goto zipfile_step_out;
6192 }
6193
6194 /* Inspect the 'method' parameter. This must be either 0 (store), 8 (use
6195 ** deflate compression) or NULL (choose automatically). */
6196 if( pMethod && SQLITE_NULL!=sqlite3_value_type(pMethod) ){
6197 iMethod = (int)sqlite3_value_int64(pMethod);
6198 if( iMethod!=0 && iMethod!=8 ){
6199 zErr = sqlite3_mprintf("illegal method value: %d", iMethod);
6200 rc = SQLITE_ERROR;
6201 goto zipfile_step_out;
6202 }
6203 }
6204
6205 /* Now inspect the data. If this is NULL, then the new entry must be a
6206 ** directory. Otherwise, figure out whether or not the data should
6207 ** be deflated or simply stored in the zip archive. */
6208 if( sqlite3_value_type(pData)==SQLITE_NULL ){
6209 bIsDir = 1;
6210 iMethod = 0;
6211 }else{
6212 aData = sqlite3_value_blob(pData);
6213 szUncompressed = nData = sqlite3_value_bytes(pData);
6214 iCrc32 = crc32(0, aData, nData);
6215 if( iMethod<0 || iMethod==8 ){
6216 int nOut = 0;
6217 rc = zipfileDeflate(aData, nData, &aFree, &nOut, &zErr);
6218 if( rc!=SQLITE_OK ){
6219 goto zipfile_step_out;
6220 }
6221 if( iMethod==8 || nOut<nData ){
6222 aData = aFree;
6223 nData = nOut;
6224 iMethod = 8;
6225 }else{
6226 iMethod = 0;
6227 }
6228 }
6229 }
6230
6231 /* Decode the "mode" argument. */
6232 rc = zipfileGetMode(pMode, bIsDir, &mode, &zErr);
6233 if( rc ) goto zipfile_step_out;
6234
6235 /* Decode the "mtime" argument. */
6236 e.mUnixTime = zipfileGetTime(pMtime);
6237
6238 /* If this is a directory entry, ensure that there is exactly one '/'
6239 ** at the end of the path. Or, if this is not a directory and the path
6240 ** ends in '/' it is an error. */
6241 if( bIsDir==0 ){
6242 if( zName[nName-1]=='/' ){
6243 zErr = sqlite3_mprintf("non-directory name must not end with /");
6244 rc = SQLITE_ERROR;
6245 goto zipfile_step_out;
6246 }
6247 }else{
6248 if( zName[nName-1]!='/' ){
6249 zName = zFree = sqlite3_mprintf("%s/", zName);
6250 nName++;
6251 if( zName==0 ){
6252 rc = SQLITE_NOMEM;
6253 goto zipfile_step_out;
6254 }
6255 }else{
6256 while( nName>1 && zName[nName-2]=='/' ) nName--;
6257 }
6258 }
6259
6260 /* Assemble the ZipfileEntry object for the new zip archive entry */
6261 e.cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
6262 e.cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
6263 e.cds.flags = ZIPFILE_NEWENTRY_FLAGS;
6264 e.cds.iCompression = (u16)iMethod;
6265 zipfileMtimeToDos(&e.cds, (u32)e.mUnixTime);
6266 e.cds.crc32 = iCrc32;
6267 e.cds.szCompressed = nData;
6268 e.cds.szUncompressed = szUncompressed;
6269 e.cds.iExternalAttr = (mode<<16);
6270 e.cds.iOffset = p->body.n;
6271 e.cds.nFile = (u16)nName;
6272 e.cds.zFile = zName;
6273
6274 /* Append the LFH to the body of the new archive */
6275 nByte = ZIPFILE_LFH_FIXED_SZ + e.cds.nFile + 9;
6276 if( (rc = zipfileBufferGrow(&p->body, nByte)) ) goto zipfile_step_out;
6277 p->body.n += zipfileSerializeLFH(&e, &p->body.a[p->body.n]);
6278
6279 /* Append the data to the body of the new archive */
6280 if( nData>0 ){
6281 if( (rc = zipfileBufferGrow(&p->body, nData)) ) goto zipfile_step_out;
6282 memcpy(&p->body.a[p->body.n], aData, nData);
6283 p->body.n += nData;
6284 }
6285
6286 /* Append the CDS record to the directory of the new archive */
6287 nByte = ZIPFILE_CDS_FIXED_SZ + e.cds.nFile + 9;
6288 if( (rc = zipfileBufferGrow(&p->cds, nByte)) ) goto zipfile_step_out;
6289 p->cds.n += zipfileSerializeCDS(&e, &p->cds.a[p->cds.n]);
6290
6291 /* Increment the count of entries in the archive */
6292 p->nEntry++;
6293
6294 zipfile_step_out:
6295 sqlite3_free(aFree);
6296 sqlite3_free(zFree);
6297 if( rc ){
6298 if( zErr ){
6299 sqlite3_result_error(pCtx, zErr, -1);
6300 }else{
6301 sqlite3_result_error_code(pCtx, rc);
6302 }
6303 }
6304 sqlite3_free(zErr);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08006305}
6306
6307/*
mydongistiny63ee58c2019-09-21 18:04:30 -07006308** xFinalize() callback for zipfile aggregate function.
6309*/
6310void zipfileFinal(sqlite3_context *pCtx){
6311 ZipfileCtx *p;
6312 ZipfileEOCD eocd;
6313 sqlite3_int64 nZip;
6314 u8 *aZip;
6315
6316 p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
6317 if( p==0 ) return;
6318 if( p->nEntry>0 ){
6319 memset(&eocd, 0, sizeof(eocd));
6320 eocd.nEntry = (u16)p->nEntry;
6321 eocd.nEntryTotal = (u16)p->nEntry;
6322 eocd.nSize = p->cds.n;
6323 eocd.iOffset = p->body.n;
6324
6325 nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ;
6326 aZip = (u8*)sqlite3_malloc64(nZip);
6327 if( aZip==0 ){
6328 sqlite3_result_error_nomem(pCtx);
6329 }else{
6330 memcpy(aZip, p->body.a, p->body.n);
6331 memcpy(&aZip[p->body.n], p->cds.a, p->cds.n);
6332 zipfileSerializeEOCD(&eocd, &aZip[p->body.n + p->cds.n]);
6333 sqlite3_result_blob(pCtx, aZip, (int)nZip, zipfileFree);
6334 }
6335 }
6336
6337 sqlite3_free(p->body.a);
6338 sqlite3_free(p->cds.a);
6339}
6340
6341
6342/*
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08006343** Register the "zipfile" virtual table.
6344*/
6345static int zipfileRegister(sqlite3 *db){
6346 static sqlite3_module zipfileModule = {
6347 1, /* iVersion */
6348 zipfileConnect, /* xCreate */
6349 zipfileConnect, /* xConnect */
6350 zipfileBestIndex, /* xBestIndex */
6351 zipfileDisconnect, /* xDisconnect */
6352 zipfileDisconnect, /* xDestroy */
6353 zipfileOpen, /* xOpen - open a cursor */
6354 zipfileClose, /* xClose - close a cursor */
6355 zipfileFilter, /* xFilter - configure scan constraints */
6356 zipfileNext, /* xNext - advance a cursor */
6357 zipfileEof, /* xEof - check for end of scan */
6358 zipfileColumn, /* xColumn - read data */
mydongistiny63ee58c2019-09-21 18:04:30 -07006359 0, /* xRowid - read data */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08006360 zipfileUpdate, /* xUpdate */
6361 zipfileBegin, /* xBegin */
6362 0, /* xSync */
6363 zipfileCommit, /* xCommit */
6364 zipfileRollback, /* xRollback */
6365 zipfileFindFunction, /* xFindMethod */
6366 0, /* xRename */
6367 };
6368
6369 int rc = sqlite3_create_module(db, "zipfile" , &zipfileModule, 0);
mydongistiny63ee58c2019-09-21 18:04:30 -07006370 if( rc==SQLITE_OK ) rc = sqlite3_overload_function(db, "zipfile_cds", -1);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08006371 if( rc==SQLITE_OK ){
mydongistiny63ee58c2019-09-21 18:04:30 -07006372 rc = sqlite3_create_function(db, "zipfile", -1, SQLITE_UTF8, 0, 0,
6373 zipfileStep, zipfileFinal
6374 );
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08006375 }
6376 return rc;
6377}
6378#else /* SQLITE_OMIT_VIRTUALTABLE */
6379# define zipfileRegister(x) SQLITE_OK
6380#endif
6381
6382#ifdef _WIN32
6383
6384#endif
6385int sqlite3_zipfile_init(
6386 sqlite3 *db,
6387 char **pzErrMsg,
6388 const sqlite3_api_routines *pApi
6389){
6390 SQLITE_EXTENSION_INIT2(pApi);
6391 (void)pzErrMsg; /* Unused parameter */
6392 return zipfileRegister(db);
6393}
6394
6395/************************* End ../ext/misc/zipfile.c ********************/
6396/************************* Begin ../ext/misc/sqlar.c ******************/
6397/*
6398** 2017-12-17
6399**
6400** The author disclaims copyright to this source code. In place of
6401** a legal notice, here is a blessing:
6402**
6403** May you do good and not evil.
6404** May you find forgiveness for yourself and forgive others.
6405** May you share freely, never taking more than you give.
6406**
6407******************************************************************************
6408**
6409** Utility functions sqlar_compress() and sqlar_uncompress(). Useful
6410** for working with sqlar archives and used by the shell tool's built-in
6411** sqlar support.
6412*/
mydongistiny63ee58c2019-09-21 18:04:30 -07006413/* #include "sqlite3ext.h" */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08006414SQLITE_EXTENSION_INIT1
6415#include <zlib.h>
6416
6417/*
6418** Implementation of the "sqlar_compress(X)" SQL function.
6419**
6420** If the type of X is SQLITE_BLOB, and compressing that blob using
6421** zlib utility function compress() yields a smaller blob, return the
6422** compressed blob. Otherwise, return a copy of X.
6423**
6424** SQLar uses the "zlib format" for compressed content. The zlib format
6425** contains a two-byte identification header and a four-byte checksum at
6426** the end. This is different from ZIP which uses the raw deflate format.
6427**
6428** Future enhancements to SQLar might add support for new compression formats.
6429** If so, those new formats will be identified by alternative headers in the
6430** compressed data.
6431*/
6432static void sqlarCompressFunc(
6433 sqlite3_context *context,
6434 int argc,
6435 sqlite3_value **argv
6436){
6437 assert( argc==1 );
6438 if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
6439 const Bytef *pData = sqlite3_value_blob(argv[0]);
6440 uLong nData = sqlite3_value_bytes(argv[0]);
6441 uLongf nOut = compressBound(nData);
6442 Bytef *pOut;
6443
6444 pOut = (Bytef*)sqlite3_malloc(nOut);
6445 if( pOut==0 ){
6446 sqlite3_result_error_nomem(context);
6447 return;
6448 }else{
6449 if( Z_OK!=compress(pOut, &nOut, pData, nData) ){
6450 sqlite3_result_error(context, "error in compress()", -1);
6451 }else if( nOut<nData ){
6452 sqlite3_result_blob(context, pOut, nOut, SQLITE_TRANSIENT);
6453 }else{
6454 sqlite3_result_value(context, argv[0]);
6455 }
6456 sqlite3_free(pOut);
6457 }
6458 }else{
6459 sqlite3_result_value(context, argv[0]);
6460 }
6461}
6462
6463/*
6464** Implementation of the "sqlar_uncompress(X,SZ)" SQL function
6465**
6466** Parameter SZ is interpreted as an integer. If it is less than or
6467** equal to zero, then this function returns a copy of X. Or, if
6468** SZ is equal to the size of X when interpreted as a blob, also
6469** return a copy of X. Otherwise, decompress blob X using zlib
6470** utility function uncompress() and return the results (another
6471** blob).
6472*/
6473static void sqlarUncompressFunc(
6474 sqlite3_context *context,
6475 int argc,
6476 sqlite3_value **argv
6477){
6478 uLong nData;
6479 uLongf sz;
6480
6481 assert( argc==2 );
6482 sz = sqlite3_value_int(argv[1]);
6483
6484 if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){
6485 sqlite3_result_value(context, argv[0]);
6486 }else{
6487 const Bytef *pData= sqlite3_value_blob(argv[0]);
6488 Bytef *pOut = sqlite3_malloc(sz);
6489 if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){
6490 sqlite3_result_error(context, "error in uncompress()", -1);
6491 }else{
6492 sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT);
6493 }
6494 sqlite3_free(pOut);
6495 }
6496}
6497
6498
6499#ifdef _WIN32
6500
6501#endif
6502int sqlite3_sqlar_init(
6503 sqlite3 *db,
6504 char **pzErrMsg,
6505 const sqlite3_api_routines *pApi
6506){
6507 int rc = SQLITE_OK;
6508 SQLITE_EXTENSION_INIT2(pApi);
6509 (void)pzErrMsg; /* Unused parameter */
6510 rc = sqlite3_create_function(db, "sqlar_compress", 1, SQLITE_UTF8, 0,
6511 sqlarCompressFunc, 0, 0);
6512 if( rc==SQLITE_OK ){
6513 rc = sqlite3_create_function(db, "sqlar_uncompress", 2, SQLITE_UTF8, 0,
6514 sqlarUncompressFunc, 0, 0);
6515 }
6516 return rc;
6517}
6518
6519/************************* End ../ext/misc/sqlar.c ********************/
6520#endif
6521/************************* Begin ../ext/expert/sqlite3expert.h ******************/
6522/*
6523** 2017 April 07
6524**
6525** The author disclaims copyright to this source code. In place of
6526** a legal notice, here is a blessing:
6527**
6528** May you do good and not evil.
6529** May you find forgiveness for yourself and forgive others.
6530** May you share freely, never taking more than you give.
6531**
6532*************************************************************************
6533*/
6534
6535
mydongistiny63ee58c2019-09-21 18:04:30 -07006536/* #include "sqlite3.h" */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08006537
6538typedef struct sqlite3expert sqlite3expert;
6539
6540/*
6541** Create a new sqlite3expert object.
6542**
6543** If successful, a pointer to the new object is returned and (*pzErr) set
6544** to NULL. Or, if an error occurs, NULL is returned and (*pzErr) set to
6545** an English-language error message. In this case it is the responsibility
6546** of the caller to eventually free the error message buffer using
6547** sqlite3_free().
6548*/
6549sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErr);
6550
6551/*
6552** Configure an sqlite3expert object.
6553**
6554** EXPERT_CONFIG_SAMPLE:
6555** By default, sqlite3_expert_analyze() generates sqlite_stat1 data for
6556** each candidate index. This involves scanning and sorting the entire
6557** contents of each user database table once for each candidate index
6558** associated with the table. For large databases, this can be
6559** prohibitively slow. This option allows the sqlite3expert object to
6560** be configured so that sqlite_stat1 data is instead generated based on a
6561** subset of each table, or so that no sqlite_stat1 data is used at all.
6562**
6563** A single integer argument is passed to this option. If the value is less
6564** than or equal to zero, then no sqlite_stat1 data is generated or used by
6565** the analysis - indexes are recommended based on the database schema only.
6566** Or, if the value is 100 or greater, complete sqlite_stat1 data is
6567** generated for each candidate index (this is the default). Finally, if the
6568** value falls between 0 and 100, then it represents the percentage of user
6569** table rows that should be considered when generating sqlite_stat1 data.
6570**
6571** Examples:
6572**
6573** // Do not generate any sqlite_stat1 data
6574** sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 0);
6575**
6576** // Generate sqlite_stat1 data based on 10% of the rows in each table.
6577** sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 10);
6578*/
6579int sqlite3_expert_config(sqlite3expert *p, int op, ...);
6580
6581#define EXPERT_CONFIG_SAMPLE 1 /* int */
6582
6583/*
6584** Specify zero or more SQL statements to be included in the analysis.
6585**
6586** Buffer zSql must contain zero or more complete SQL statements. This
6587** function parses all statements contained in the buffer and adds them
6588** to the internal list of statements to analyze. If successful, SQLITE_OK
6589** is returned and (*pzErr) set to NULL. Or, if an error occurs - for example
6590** due to a error in the SQL - an SQLite error code is returned and (*pzErr)
6591** may be set to point to an English language error message. In this case
6592** the caller is responsible for eventually freeing the error message buffer
6593** using sqlite3_free().
6594**
6595** If an error does occur while processing one of the statements in the
6596** buffer passed as the second argument, none of the statements in the
6597** buffer are added to the analysis.
6598**
6599** This function must be called before sqlite3_expert_analyze(). If a call
6600** to this function is made on an sqlite3expert object that has already
6601** been passed to sqlite3_expert_analyze() SQLITE_MISUSE is returned
6602** immediately and no statements are added to the analysis.
6603*/
6604int sqlite3_expert_sql(
6605 sqlite3expert *p, /* From a successful sqlite3_expert_new() */
6606 const char *zSql, /* SQL statement(s) to add */
6607 char **pzErr /* OUT: Error message (if any) */
6608);
6609
6610
6611/*
6612** This function is called after the sqlite3expert object has been configured
6613** with all SQL statements using sqlite3_expert_sql() to actually perform
6614** the analysis. Once this function has been called, it is not possible to
6615** add further SQL statements to the analysis.
6616**
6617** If successful, SQLITE_OK is returned and (*pzErr) is set to NULL. Or, if
6618** an error occurs, an SQLite error code is returned and (*pzErr) set to
6619** point to a buffer containing an English language error message. In this
6620** case it is the responsibility of the caller to eventually free the buffer
6621** using sqlite3_free().
6622**
6623** If an error does occur within this function, the sqlite3expert object
6624** is no longer useful for any purpose. At that point it is no longer
6625** possible to add further SQL statements to the object or to re-attempt
6626** the analysis. The sqlite3expert object must still be freed using a call
6627** sqlite3_expert_destroy().
6628*/
6629int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr);
6630
6631/*
6632** Return the total number of statements loaded using sqlite3_expert_sql().
6633** The total number of SQL statements may be different from the total number
6634** to calls to sqlite3_expert_sql().
6635*/
6636int sqlite3_expert_count(sqlite3expert*);
6637
6638/*
6639** Return a component of the report.
6640**
6641** This function is called after sqlite3_expert_analyze() to extract the
6642** results of the analysis. Each call to this function returns either a
6643** NULL pointer or a pointer to a buffer containing a nul-terminated string.
6644** The value passed as the third argument must be one of the EXPERT_REPORT_*
6645** #define constants defined below.
6646**
6647** For some EXPERT_REPORT_* parameters, the buffer returned contains
6648** information relating to a specific SQL statement. In these cases that
6649** SQL statement is identified by the value passed as the second argument.
6650** SQL statements are numbered from 0 in the order in which they are parsed.
6651** If an out-of-range value (less than zero or equal to or greater than the
6652** value returned by sqlite3_expert_count()) is passed as the second argument
6653** along with such an EXPERT_REPORT_* parameter, NULL is always returned.
6654**
6655** EXPERT_REPORT_SQL:
6656** Return the text of SQL statement iStmt.
6657**
6658** EXPERT_REPORT_INDEXES:
6659** Return a buffer containing the CREATE INDEX statements for all recommended
6660** indexes for statement iStmt. If there are no new recommeded indexes, NULL
6661** is returned.
6662**
6663** EXPERT_REPORT_PLAN:
6664** Return a buffer containing the EXPLAIN QUERY PLAN output for SQL query
6665** iStmt after the proposed indexes have been added to the database schema.
6666**
6667** EXPERT_REPORT_CANDIDATES:
6668** Return a pointer to a buffer containing the CREATE INDEX statements
6669** for all indexes that were tested (for all SQL statements). The iStmt
6670** parameter is ignored for EXPERT_REPORT_CANDIDATES calls.
6671*/
6672const char *sqlite3_expert_report(sqlite3expert*, int iStmt, int eReport);
6673
6674/*
6675** Values for the third argument passed to sqlite3_expert_report().
6676*/
6677#define EXPERT_REPORT_SQL 1
6678#define EXPERT_REPORT_INDEXES 2
6679#define EXPERT_REPORT_PLAN 3
6680#define EXPERT_REPORT_CANDIDATES 4
6681
6682/*
6683** Free an (sqlite3expert*) handle and all associated resources. There
6684** should be one call to this function for each successful call to
6685** sqlite3-expert_new().
6686*/
6687void sqlite3_expert_destroy(sqlite3expert*);
6688
6689
6690
6691/************************* End ../ext/expert/sqlite3expert.h ********************/
6692/************************* Begin ../ext/expert/sqlite3expert.c ******************/
6693/*
6694** 2017 April 09
6695**
6696** The author disclaims copyright to this source code. In place of
6697** a legal notice, here is a blessing:
6698**
6699** May you do good and not evil.
6700** May you find forgiveness for yourself and forgive others.
6701** May you share freely, never taking more than you give.
6702**
6703*************************************************************************
6704*/
mydongistiny63ee58c2019-09-21 18:04:30 -07006705/* #include "sqlite3expert.h" */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08006706#include <assert.h>
6707#include <string.h>
6708#include <stdio.h>
6709
6710#ifndef SQLITE_OMIT_VIRTUALTABLE
6711
6712/* typedef sqlite3_int64 i64; */
6713/* typedef sqlite3_uint64 u64; */
6714
6715typedef struct IdxColumn IdxColumn;
6716typedef struct IdxConstraint IdxConstraint;
6717typedef struct IdxScan IdxScan;
6718typedef struct IdxStatement IdxStatement;
6719typedef struct IdxTable IdxTable;
6720typedef struct IdxWrite IdxWrite;
6721
6722#define STRLEN (int)strlen
6723
6724/*
6725** A temp table name that we assume no user database will actually use.
6726** If this assumption proves incorrect triggers on the table with the
6727** conflicting name will be ignored.
6728*/
6729#define UNIQUE_TABLE_NAME "t592690916721053953805701627921227776"
6730
6731/*
6732** A single constraint. Equivalent to either "col = ?" or "col < ?" (or
6733** any other type of single-ended range constraint on a column).
6734**
6735** pLink:
6736** Used to temporarily link IdxConstraint objects into lists while
6737** creating candidate indexes.
6738*/
6739struct IdxConstraint {
6740 char *zColl; /* Collation sequence */
6741 int bRange; /* True for range, false for eq */
6742 int iCol; /* Constrained table column */
6743 int bFlag; /* Used by idxFindCompatible() */
6744 int bDesc; /* True if ORDER BY <expr> DESC */
6745 IdxConstraint *pNext; /* Next constraint in pEq or pRange list */
6746 IdxConstraint *pLink; /* See above */
6747};
6748
6749/*
6750** A single scan of a single table.
6751*/
6752struct IdxScan {
6753 IdxTable *pTab; /* Associated table object */
6754 int iDb; /* Database containing table zTable */
6755 i64 covering; /* Mask of columns required for cov. index */
6756 IdxConstraint *pOrder; /* ORDER BY columns */
6757 IdxConstraint *pEq; /* List of == constraints */
6758 IdxConstraint *pRange; /* List of < constraints */
6759 IdxScan *pNextScan; /* Next IdxScan object for same analysis */
6760};
6761
6762/*
6763** Information regarding a single database table. Extracted from
6764** "PRAGMA table_info" by function idxGetTableInfo().
6765*/
6766struct IdxColumn {
6767 char *zName;
6768 char *zColl;
6769 int iPk;
6770};
6771struct IdxTable {
6772 int nCol;
6773 char *zName; /* Table name */
6774 IdxColumn *aCol;
6775 IdxTable *pNext; /* Next table in linked list of all tables */
6776};
6777
6778/*
6779** An object of the following type is created for each unique table/write-op
6780** seen. The objects are stored in a singly-linked list beginning at
6781** sqlite3expert.pWrite.
6782*/
6783struct IdxWrite {
6784 IdxTable *pTab;
6785 int eOp; /* SQLITE_UPDATE, DELETE or INSERT */
6786 IdxWrite *pNext;
6787};
6788
6789/*
6790** Each statement being analyzed is represented by an instance of this
6791** structure.
6792*/
6793struct IdxStatement {
6794 int iId; /* Statement number */
6795 char *zSql; /* SQL statement */
6796 char *zIdx; /* Indexes */
6797 char *zEQP; /* Plan */
6798 IdxStatement *pNext;
6799};
6800
6801
6802/*
6803** A hash table for storing strings. With space for a payload string
6804** with each entry. Methods are:
6805**
6806** idxHashInit()
6807** idxHashClear()
6808** idxHashAdd()
6809** idxHashSearch()
6810*/
6811#define IDX_HASH_SIZE 1023
6812typedef struct IdxHashEntry IdxHashEntry;
6813typedef struct IdxHash IdxHash;
6814struct IdxHashEntry {
6815 char *zKey; /* nul-terminated key */
6816 char *zVal; /* nul-terminated value string */
6817 char *zVal2; /* nul-terminated value string 2 */
6818 IdxHashEntry *pHashNext; /* Next entry in same hash bucket */
6819 IdxHashEntry *pNext; /* Next entry in hash */
6820};
6821struct IdxHash {
6822 IdxHashEntry *pFirst;
6823 IdxHashEntry *aHash[IDX_HASH_SIZE];
6824};
6825
6826/*
6827** sqlite3expert object.
6828*/
6829struct sqlite3expert {
6830 int iSample; /* Percentage of tables to sample for stat1 */
6831 sqlite3 *db; /* User database */
6832 sqlite3 *dbm; /* In-memory db for this analysis */
6833 sqlite3 *dbv; /* Vtab schema for this analysis */
6834 IdxTable *pTable; /* List of all IdxTable objects */
6835 IdxScan *pScan; /* List of scan objects */
6836 IdxWrite *pWrite; /* List of write objects */
6837 IdxStatement *pStatement; /* List of IdxStatement objects */
6838 int bRun; /* True once analysis has run */
6839 char **pzErrmsg;
6840 int rc; /* Error code from whereinfo hook */
6841 IdxHash hIdx; /* Hash containing all candidate indexes */
6842 char *zCandidates; /* For EXPERT_REPORT_CANDIDATES */
6843};
6844
6845
6846/*
6847** Allocate and return nByte bytes of zeroed memory using sqlite3_malloc().
6848** If the allocation fails, set *pRc to SQLITE_NOMEM and return NULL.
6849*/
6850static void *idxMalloc(int *pRc, int nByte){
6851 void *pRet;
6852 assert( *pRc==SQLITE_OK );
6853 assert( nByte>0 );
6854 pRet = sqlite3_malloc(nByte);
6855 if( pRet ){
6856 memset(pRet, 0, nByte);
6857 }else{
6858 *pRc = SQLITE_NOMEM;
6859 }
6860 return pRet;
6861}
6862
6863/*
6864** Initialize an IdxHash hash table.
6865*/
6866static void idxHashInit(IdxHash *pHash){
6867 memset(pHash, 0, sizeof(IdxHash));
6868}
6869
6870/*
6871** Reset an IdxHash hash table.
6872*/
6873static void idxHashClear(IdxHash *pHash){
6874 int i;
6875 for(i=0; i<IDX_HASH_SIZE; i++){
6876 IdxHashEntry *pEntry;
6877 IdxHashEntry *pNext;
6878 for(pEntry=pHash->aHash[i]; pEntry; pEntry=pNext){
6879 pNext = pEntry->pHashNext;
6880 sqlite3_free(pEntry->zVal2);
6881 sqlite3_free(pEntry);
6882 }
6883 }
6884 memset(pHash, 0, sizeof(IdxHash));
6885}
6886
6887/*
6888** Return the index of the hash bucket that the string specified by the
6889** arguments to this function belongs.
6890*/
6891static int idxHashString(const char *z, int n){
6892 unsigned int ret = 0;
6893 int i;
6894 for(i=0; i<n; i++){
6895 ret += (ret<<3) + (unsigned char)(z[i]);
6896 }
6897 return (int)(ret % IDX_HASH_SIZE);
6898}
6899
6900/*
6901** If zKey is already present in the hash table, return non-zero and do
6902** nothing. Otherwise, add an entry with key zKey and payload string zVal to
6903** the hash table passed as the second argument.
6904*/
6905static int idxHashAdd(
6906 int *pRc,
6907 IdxHash *pHash,
6908 const char *zKey,
6909 const char *zVal
6910){
6911 int nKey = STRLEN(zKey);
6912 int iHash = idxHashString(zKey, nKey);
6913 int nVal = (zVal ? STRLEN(zVal) : 0);
6914 IdxHashEntry *pEntry;
6915 assert( iHash>=0 );
6916 for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){
6917 if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){
6918 return 1;
6919 }
6920 }
6921 pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + nKey+1 + nVal+1);
6922 if( pEntry ){
6923 pEntry->zKey = (char*)&pEntry[1];
6924 memcpy(pEntry->zKey, zKey, nKey);
6925 if( zVal ){
6926 pEntry->zVal = &pEntry->zKey[nKey+1];
6927 memcpy(pEntry->zVal, zVal, nVal);
6928 }
6929 pEntry->pHashNext = pHash->aHash[iHash];
6930 pHash->aHash[iHash] = pEntry;
6931
6932 pEntry->pNext = pHash->pFirst;
6933 pHash->pFirst = pEntry;
6934 }
6935 return 0;
6936}
6937
6938/*
6939** If zKey/nKey is present in the hash table, return a pointer to the
6940** hash-entry object.
6941*/
6942static IdxHashEntry *idxHashFind(IdxHash *pHash, const char *zKey, int nKey){
6943 int iHash;
6944 IdxHashEntry *pEntry;
6945 if( nKey<0 ) nKey = STRLEN(zKey);
6946 iHash = idxHashString(zKey, nKey);
6947 assert( iHash>=0 );
6948 for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){
6949 if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){
6950 return pEntry;
6951 }
6952 }
6953 return 0;
6954}
6955
6956/*
6957** If the hash table contains an entry with a key equal to the string
6958** passed as the final two arguments to this function, return a pointer
6959** to the payload string. Otherwise, if zKey/nKey is not present in the
6960** hash table, return NULL.
6961*/
6962static const char *idxHashSearch(IdxHash *pHash, const char *zKey, int nKey){
6963 IdxHashEntry *pEntry = idxHashFind(pHash, zKey, nKey);
6964 if( pEntry ) return pEntry->zVal;
6965 return 0;
6966}
6967
6968/*
6969** Allocate and return a new IdxConstraint object. Set the IdxConstraint.zColl
6970** variable to point to a copy of nul-terminated string zColl.
6971*/
6972static IdxConstraint *idxNewConstraint(int *pRc, const char *zColl){
6973 IdxConstraint *pNew;
6974 int nColl = STRLEN(zColl);
6975
6976 assert( *pRc==SQLITE_OK );
6977 pNew = (IdxConstraint*)idxMalloc(pRc, sizeof(IdxConstraint) * nColl + 1);
6978 if( pNew ){
6979 pNew->zColl = (char*)&pNew[1];
6980 memcpy(pNew->zColl, zColl, nColl+1);
6981 }
6982 return pNew;
6983}
6984
6985/*
6986** An error associated with database handle db has just occurred. Pass
6987** the error message to callback function xOut.
6988*/
6989static void idxDatabaseError(
6990 sqlite3 *db, /* Database handle */
6991 char **pzErrmsg /* Write error here */
6992){
6993 *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db));
6994}
6995
6996/*
6997** Prepare an SQL statement.
6998*/
6999static int idxPrepareStmt(
7000 sqlite3 *db, /* Database handle to compile against */
7001 sqlite3_stmt **ppStmt, /* OUT: Compiled SQL statement */
7002 char **pzErrmsg, /* OUT: sqlite3_malloc()ed error message */
7003 const char *zSql /* SQL statement to compile */
7004){
7005 int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
7006 if( rc!=SQLITE_OK ){
7007 *ppStmt = 0;
7008 idxDatabaseError(db, pzErrmsg);
7009 }
7010 return rc;
7011}
7012
7013/*
7014** Prepare an SQL statement using the results of a printf() formatting.
7015*/
7016static int idxPrintfPrepareStmt(
7017 sqlite3 *db, /* Database handle to compile against */
7018 sqlite3_stmt **ppStmt, /* OUT: Compiled SQL statement */
7019 char **pzErrmsg, /* OUT: sqlite3_malloc()ed error message */
7020 const char *zFmt, /* printf() format of SQL statement */
7021 ... /* Trailing printf() arguments */
7022){
7023 va_list ap;
7024 int rc;
7025 char *zSql;
7026 va_start(ap, zFmt);
7027 zSql = sqlite3_vmprintf(zFmt, ap);
7028 if( zSql==0 ){
7029 rc = SQLITE_NOMEM;
7030 }else{
7031 rc = idxPrepareStmt(db, ppStmt, pzErrmsg, zSql);
7032 sqlite3_free(zSql);
7033 }
7034 va_end(ap);
7035 return rc;
7036}
7037
7038
7039/*************************************************************************
7040** Beginning of virtual table implementation.
7041*/
7042typedef struct ExpertVtab ExpertVtab;
7043struct ExpertVtab {
7044 sqlite3_vtab base;
7045 IdxTable *pTab;
7046 sqlite3expert *pExpert;
7047};
7048
7049typedef struct ExpertCsr ExpertCsr;
7050struct ExpertCsr {
7051 sqlite3_vtab_cursor base;
7052 sqlite3_stmt *pData;
7053};
7054
7055static char *expertDequote(const char *zIn){
7056 int n = STRLEN(zIn);
7057 char *zRet = sqlite3_malloc(n);
7058
7059 assert( zIn[0]=='\'' );
7060 assert( zIn[n-1]=='\'' );
7061
7062 if( zRet ){
7063 int iOut = 0;
7064 int iIn = 0;
7065 for(iIn=1; iIn<(n-1); iIn++){
7066 if( zIn[iIn]=='\'' ){
7067 assert( zIn[iIn+1]=='\'' );
7068 iIn++;
7069 }
7070 zRet[iOut++] = zIn[iIn];
7071 }
7072 zRet[iOut] = '\0';
7073 }
7074
7075 return zRet;
7076}
7077
7078/*
7079** This function is the implementation of both the xConnect and xCreate
7080** methods of the r-tree virtual table.
7081**
7082** argv[0] -> module name
7083** argv[1] -> database name
7084** argv[2] -> table name
7085** argv[...] -> column names...
7086*/
7087static int expertConnect(
7088 sqlite3 *db,
7089 void *pAux,
7090 int argc, const char *const*argv,
7091 sqlite3_vtab **ppVtab,
7092 char **pzErr
7093){
7094 sqlite3expert *pExpert = (sqlite3expert*)pAux;
7095 ExpertVtab *p = 0;
7096 int rc;
7097
7098 if( argc!=4 ){
7099 *pzErr = sqlite3_mprintf("internal error!");
7100 rc = SQLITE_ERROR;
7101 }else{
7102 char *zCreateTable = expertDequote(argv[3]);
7103 if( zCreateTable ){
7104 rc = sqlite3_declare_vtab(db, zCreateTable);
7105 if( rc==SQLITE_OK ){
7106 p = idxMalloc(&rc, sizeof(ExpertVtab));
7107 }
7108 if( rc==SQLITE_OK ){
7109 p->pExpert = pExpert;
7110 p->pTab = pExpert->pTable;
7111 assert( sqlite3_stricmp(p->pTab->zName, argv[2])==0 );
7112 }
7113 sqlite3_free(zCreateTable);
7114 }else{
7115 rc = SQLITE_NOMEM;
7116 }
7117 }
7118
7119 *ppVtab = (sqlite3_vtab*)p;
7120 return rc;
7121}
7122
7123static int expertDisconnect(sqlite3_vtab *pVtab){
7124 ExpertVtab *p = (ExpertVtab*)pVtab;
7125 sqlite3_free(p);
7126 return SQLITE_OK;
7127}
7128
7129static int expertBestIndex(sqlite3_vtab *pVtab, sqlite3_index_info *pIdxInfo){
7130 ExpertVtab *p = (ExpertVtab*)pVtab;
7131 int rc = SQLITE_OK;
7132 int n = 0;
7133 IdxScan *pScan;
7134 const int opmask =
7135 SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_GT |
7136 SQLITE_INDEX_CONSTRAINT_LT | SQLITE_INDEX_CONSTRAINT_GE |
7137 SQLITE_INDEX_CONSTRAINT_LE;
7138
7139 pScan = idxMalloc(&rc, sizeof(IdxScan));
7140 if( pScan ){
7141 int i;
7142
7143 /* Link the new scan object into the list */
7144 pScan->pTab = p->pTab;
7145 pScan->pNextScan = p->pExpert->pScan;
7146 p->pExpert->pScan = pScan;
7147
7148 /* Add the constraints to the IdxScan object */
7149 for(i=0; i<pIdxInfo->nConstraint; i++){
7150 struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
7151 if( pCons->usable
7152 && pCons->iColumn>=0
7153 && p->pTab->aCol[pCons->iColumn].iPk==0
7154 && (pCons->op & opmask)
7155 ){
7156 IdxConstraint *pNew;
7157 const char *zColl = sqlite3_vtab_collation(pIdxInfo, i);
7158 pNew = idxNewConstraint(&rc, zColl);
7159 if( pNew ){
7160 pNew->iCol = pCons->iColumn;
7161 if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
7162 pNew->pNext = pScan->pEq;
7163 pScan->pEq = pNew;
7164 }else{
7165 pNew->bRange = 1;
7166 pNew->pNext = pScan->pRange;
7167 pScan->pRange = pNew;
7168 }
7169 }
7170 n++;
7171 pIdxInfo->aConstraintUsage[i].argvIndex = n;
7172 }
7173 }
7174
7175 /* Add the ORDER BY to the IdxScan object */
7176 for(i=pIdxInfo->nOrderBy-1; i>=0; i--){
7177 int iCol = pIdxInfo->aOrderBy[i].iColumn;
7178 if( iCol>=0 ){
7179 IdxConstraint *pNew = idxNewConstraint(&rc, p->pTab->aCol[iCol].zColl);
7180 if( pNew ){
7181 pNew->iCol = iCol;
7182 pNew->bDesc = pIdxInfo->aOrderBy[i].desc;
7183 pNew->pNext = pScan->pOrder;
7184 pNew->pLink = pScan->pOrder;
7185 pScan->pOrder = pNew;
7186 n++;
7187 }
7188 }
7189 }
7190 }
7191
7192 pIdxInfo->estimatedCost = 1000000.0 / (n+1);
7193 return rc;
7194}
7195
7196static int expertUpdate(
7197 sqlite3_vtab *pVtab,
7198 int nData,
7199 sqlite3_value **azData,
7200 sqlite_int64 *pRowid
7201){
7202 (void)pVtab;
7203 (void)nData;
7204 (void)azData;
7205 (void)pRowid;
7206 return SQLITE_OK;
7207}
7208
7209/*
7210** Virtual table module xOpen method.
7211*/
7212static int expertOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
7213 int rc = SQLITE_OK;
7214 ExpertCsr *pCsr;
7215 (void)pVTab;
7216 pCsr = idxMalloc(&rc, sizeof(ExpertCsr));
7217 *ppCursor = (sqlite3_vtab_cursor*)pCsr;
7218 return rc;
7219}
7220
7221/*
7222** Virtual table module xClose method.
7223*/
7224static int expertClose(sqlite3_vtab_cursor *cur){
7225 ExpertCsr *pCsr = (ExpertCsr*)cur;
7226 sqlite3_finalize(pCsr->pData);
7227 sqlite3_free(pCsr);
7228 return SQLITE_OK;
7229}
7230
7231/*
7232** Virtual table module xEof method.
7233**
7234** Return non-zero if the cursor does not currently point to a valid
7235** record (i.e if the scan has finished), or zero otherwise.
7236*/
7237static int expertEof(sqlite3_vtab_cursor *cur){
7238 ExpertCsr *pCsr = (ExpertCsr*)cur;
7239 return pCsr->pData==0;
7240}
7241
7242/*
7243** Virtual table module xNext method.
7244*/
7245static int expertNext(sqlite3_vtab_cursor *cur){
7246 ExpertCsr *pCsr = (ExpertCsr*)cur;
7247 int rc = SQLITE_OK;
7248
7249 assert( pCsr->pData );
7250 rc = sqlite3_step(pCsr->pData);
7251 if( rc!=SQLITE_ROW ){
7252 rc = sqlite3_finalize(pCsr->pData);
7253 pCsr->pData = 0;
7254 }else{
7255 rc = SQLITE_OK;
7256 }
7257
7258 return rc;
7259}
7260
7261/*
7262** Virtual table module xRowid method.
7263*/
7264static int expertRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
7265 (void)cur;
7266 *pRowid = 0;
7267 return SQLITE_OK;
7268}
7269
7270/*
7271** Virtual table module xColumn method.
7272*/
7273static int expertColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
7274 ExpertCsr *pCsr = (ExpertCsr*)cur;
7275 sqlite3_value *pVal;
7276 pVal = sqlite3_column_value(pCsr->pData, i);
7277 if( pVal ){
7278 sqlite3_result_value(ctx, pVal);
7279 }
7280 return SQLITE_OK;
7281}
7282
7283/*
7284** Virtual table module xFilter method.
7285*/
7286static int expertFilter(
7287 sqlite3_vtab_cursor *cur,
7288 int idxNum, const char *idxStr,
7289 int argc, sqlite3_value **argv
7290){
7291 ExpertCsr *pCsr = (ExpertCsr*)cur;
7292 ExpertVtab *pVtab = (ExpertVtab*)(cur->pVtab);
7293 sqlite3expert *pExpert = pVtab->pExpert;
7294 int rc;
7295
7296 (void)idxNum;
7297 (void)idxStr;
7298 (void)argc;
7299 (void)argv;
7300 rc = sqlite3_finalize(pCsr->pData);
7301 pCsr->pData = 0;
7302 if( rc==SQLITE_OK ){
7303 rc = idxPrintfPrepareStmt(pExpert->db, &pCsr->pData, &pVtab->base.zErrMsg,
7304 "SELECT * FROM main.%Q WHERE sample()", pVtab->pTab->zName
7305 );
7306 }
7307
7308 if( rc==SQLITE_OK ){
7309 rc = expertNext(cur);
7310 }
7311 return rc;
7312}
7313
7314static int idxRegisterVtab(sqlite3expert *p){
7315 static sqlite3_module expertModule = {
7316 2, /* iVersion */
7317 expertConnect, /* xCreate - create a table */
7318 expertConnect, /* xConnect - connect to an existing table */
7319 expertBestIndex, /* xBestIndex - Determine search strategy */
7320 expertDisconnect, /* xDisconnect - Disconnect from a table */
7321 expertDisconnect, /* xDestroy - Drop a table */
7322 expertOpen, /* xOpen - open a cursor */
7323 expertClose, /* xClose - close a cursor */
7324 expertFilter, /* xFilter - configure scan constraints */
7325 expertNext, /* xNext - advance a cursor */
7326 expertEof, /* xEof */
7327 expertColumn, /* xColumn - read data */
7328 expertRowid, /* xRowid - read data */
7329 expertUpdate, /* xUpdate - write data */
7330 0, /* xBegin - begin transaction */
7331 0, /* xSync - sync transaction */
7332 0, /* xCommit - commit transaction */
7333 0, /* xRollback - rollback transaction */
7334 0, /* xFindFunction - function overloading */
7335 0, /* xRename - rename the table */
7336 0, /* xSavepoint */
7337 0, /* xRelease */
7338 0, /* xRollbackTo */
mydongistiny63ee58c2019-09-21 18:04:30 -07007339 0, /* xShadowName */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08007340 };
7341
7342 return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p);
7343}
7344/*
7345** End of virtual table implementation.
7346*************************************************************************/
7347/*
7348** Finalize SQL statement pStmt. If (*pRc) is SQLITE_OK when this function
7349** is called, set it to the return value of sqlite3_finalize() before
7350** returning. Otherwise, discard the sqlite3_finalize() return value.
7351*/
7352static void idxFinalize(int *pRc, sqlite3_stmt *pStmt){
7353 int rc = sqlite3_finalize(pStmt);
7354 if( *pRc==SQLITE_OK ) *pRc = rc;
7355}
7356
7357/*
7358** Attempt to allocate an IdxTable structure corresponding to table zTab
7359** in the main database of connection db. If successful, set (*ppOut) to
7360** point to the new object and return SQLITE_OK. Otherwise, return an
7361** SQLite error code and set (*ppOut) to NULL. In this case *pzErrmsg may be
7362** set to point to an error string.
7363**
7364** It is the responsibility of the caller to eventually free either the
7365** IdxTable object or error message using sqlite3_free().
7366*/
7367static int idxGetTableInfo(
7368 sqlite3 *db, /* Database connection to read details from */
7369 const char *zTab, /* Table name */
7370 IdxTable **ppOut, /* OUT: New object (if successful) */
7371 char **pzErrmsg /* OUT: Error message (if not) */
7372){
7373 sqlite3_stmt *p1 = 0;
7374 int nCol = 0;
7375 int nTab = STRLEN(zTab);
7376 int nByte = sizeof(IdxTable) + nTab + 1;
7377 IdxTable *pNew = 0;
7378 int rc, rc2;
7379 char *pCsr = 0;
7380
7381 rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_info=%Q", zTab);
7382 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
7383 const char *zCol = (const char*)sqlite3_column_text(p1, 1);
7384 nByte += 1 + STRLEN(zCol);
7385 rc = sqlite3_table_column_metadata(
7386 db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
7387 );
7388 nByte += 1 + STRLEN(zCol);
7389 nCol++;
7390 }
7391 rc2 = sqlite3_reset(p1);
7392 if( rc==SQLITE_OK ) rc = rc2;
7393
7394 nByte += sizeof(IdxColumn) * nCol;
7395 if( rc==SQLITE_OK ){
7396 pNew = idxMalloc(&rc, nByte);
7397 }
7398 if( rc==SQLITE_OK ){
7399 pNew->aCol = (IdxColumn*)&pNew[1];
7400 pNew->nCol = nCol;
7401 pCsr = (char*)&pNew->aCol[nCol];
7402 }
7403
7404 nCol = 0;
7405 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
7406 const char *zCol = (const char*)sqlite3_column_text(p1, 1);
7407 int nCopy = STRLEN(zCol) + 1;
7408 pNew->aCol[nCol].zName = pCsr;
7409 pNew->aCol[nCol].iPk = sqlite3_column_int(p1, 5);
7410 memcpy(pCsr, zCol, nCopy);
7411 pCsr += nCopy;
7412
7413 rc = sqlite3_table_column_metadata(
7414 db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
7415 );
7416 if( rc==SQLITE_OK ){
7417 nCopy = STRLEN(zCol) + 1;
7418 pNew->aCol[nCol].zColl = pCsr;
7419 memcpy(pCsr, zCol, nCopy);
7420 pCsr += nCopy;
7421 }
7422
7423 nCol++;
7424 }
7425 idxFinalize(&rc, p1);
7426
7427 if( rc!=SQLITE_OK ){
7428 sqlite3_free(pNew);
7429 pNew = 0;
7430 }else{
7431 pNew->zName = pCsr;
7432 memcpy(pNew->zName, zTab, nTab+1);
7433 }
7434
7435 *ppOut = pNew;
7436 return rc;
7437}
7438
7439/*
7440** This function is a no-op if *pRc is set to anything other than
7441** SQLITE_OK when it is called.
7442**
7443** If *pRc is initially set to SQLITE_OK, then the text specified by
7444** the printf() style arguments is appended to zIn and the result returned
7445** in a buffer allocated by sqlite3_malloc(). sqlite3_free() is called on
7446** zIn before returning.
7447*/
7448static char *idxAppendText(int *pRc, char *zIn, const char *zFmt, ...){
7449 va_list ap;
7450 char *zAppend = 0;
7451 char *zRet = 0;
7452 int nIn = zIn ? STRLEN(zIn) : 0;
7453 int nAppend = 0;
7454 va_start(ap, zFmt);
7455 if( *pRc==SQLITE_OK ){
7456 zAppend = sqlite3_vmprintf(zFmt, ap);
7457 if( zAppend ){
7458 nAppend = STRLEN(zAppend);
7459 zRet = (char*)sqlite3_malloc(nIn + nAppend + 1);
7460 }
7461 if( zAppend && zRet ){
7462 if( nIn ) memcpy(zRet, zIn, nIn);
7463 memcpy(&zRet[nIn], zAppend, nAppend+1);
7464 }else{
7465 sqlite3_free(zRet);
7466 zRet = 0;
7467 *pRc = SQLITE_NOMEM;
7468 }
7469 sqlite3_free(zAppend);
7470 sqlite3_free(zIn);
7471 }
7472 va_end(ap);
7473 return zRet;
7474}
7475
7476/*
7477** Return true if zId must be quoted in order to use it as an SQL
7478** identifier, or false otherwise.
7479*/
7480static int idxIdentifierRequiresQuotes(const char *zId){
7481 int i;
7482 for(i=0; zId[i]; i++){
7483 if( !(zId[i]=='_')
7484 && !(zId[i]>='0' && zId[i]<='9')
7485 && !(zId[i]>='a' && zId[i]<='z')
7486 && !(zId[i]>='A' && zId[i]<='Z')
7487 ){
7488 return 1;
7489 }
7490 }
7491 return 0;
7492}
7493
7494/*
7495** This function appends an index column definition suitable for constraint
7496** pCons to the string passed as zIn and returns the result.
7497*/
7498static char *idxAppendColDefn(
7499 int *pRc, /* IN/OUT: Error code */
7500 char *zIn, /* Column defn accumulated so far */
7501 IdxTable *pTab, /* Table index will be created on */
7502 IdxConstraint *pCons
7503){
7504 char *zRet = zIn;
7505 IdxColumn *p = &pTab->aCol[pCons->iCol];
7506 if( zRet ) zRet = idxAppendText(pRc, zRet, ", ");
7507
7508 if( idxIdentifierRequiresQuotes(p->zName) ){
7509 zRet = idxAppendText(pRc, zRet, "%Q", p->zName);
7510 }else{
7511 zRet = idxAppendText(pRc, zRet, "%s", p->zName);
7512 }
7513
7514 if( sqlite3_stricmp(p->zColl, pCons->zColl) ){
7515 if( idxIdentifierRequiresQuotes(pCons->zColl) ){
7516 zRet = idxAppendText(pRc, zRet, " COLLATE %Q", pCons->zColl);
7517 }else{
7518 zRet = idxAppendText(pRc, zRet, " COLLATE %s", pCons->zColl);
7519 }
7520 }
7521
7522 if( pCons->bDesc ){
7523 zRet = idxAppendText(pRc, zRet, " DESC");
7524 }
7525 return zRet;
7526}
7527
7528/*
7529** Search database dbm for an index compatible with the one idxCreateFromCons()
7530** would create from arguments pScan, pEq and pTail. If no error occurs and
7531** such an index is found, return non-zero. Or, if no such index is found,
7532** return zero.
7533**
7534** If an error occurs, set *pRc to an SQLite error code and return zero.
7535*/
7536static int idxFindCompatible(
7537 int *pRc, /* OUT: Error code */
7538 sqlite3* dbm, /* Database to search */
7539 IdxScan *pScan, /* Scan for table to search for index on */
7540 IdxConstraint *pEq, /* List of == constraints */
7541 IdxConstraint *pTail /* List of range constraints */
7542){
7543 const char *zTbl = pScan->pTab->zName;
7544 sqlite3_stmt *pIdxList = 0;
7545 IdxConstraint *pIter;
7546 int nEq = 0; /* Number of elements in pEq */
7547 int rc;
7548
7549 /* Count the elements in list pEq */
7550 for(pIter=pEq; pIter; pIter=pIter->pLink) nEq++;
7551
7552 rc = idxPrintfPrepareStmt(dbm, &pIdxList, 0, "PRAGMA index_list=%Q", zTbl);
7553 while( rc==SQLITE_OK && sqlite3_step(pIdxList)==SQLITE_ROW ){
7554 int bMatch = 1;
7555 IdxConstraint *pT = pTail;
7556 sqlite3_stmt *pInfo = 0;
7557 const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1);
7558
7559 /* Zero the IdxConstraint.bFlag values in the pEq list */
7560 for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0;
7561
7562 rc = idxPrintfPrepareStmt(dbm, &pInfo, 0, "PRAGMA index_xInfo=%Q", zIdx);
7563 while( rc==SQLITE_OK && sqlite3_step(pInfo)==SQLITE_ROW ){
7564 int iIdx = sqlite3_column_int(pInfo, 0);
7565 int iCol = sqlite3_column_int(pInfo, 1);
7566 const char *zColl = (const char*)sqlite3_column_text(pInfo, 4);
7567
7568 if( iIdx<nEq ){
7569 for(pIter=pEq; pIter; pIter=pIter->pLink){
7570 if( pIter->bFlag ) continue;
7571 if( pIter->iCol!=iCol ) continue;
7572 if( sqlite3_stricmp(pIter->zColl, zColl) ) continue;
7573 pIter->bFlag = 1;
7574 break;
7575 }
7576 if( pIter==0 ){
7577 bMatch = 0;
7578 break;
7579 }
7580 }else{
7581 if( pT ){
7582 if( pT->iCol!=iCol || sqlite3_stricmp(pT->zColl, zColl) ){
7583 bMatch = 0;
7584 break;
7585 }
7586 pT = pT->pLink;
7587 }
7588 }
7589 }
7590 idxFinalize(&rc, pInfo);
7591
7592 if( rc==SQLITE_OK && bMatch ){
7593 sqlite3_finalize(pIdxList);
7594 return 1;
7595 }
7596 }
7597 idxFinalize(&rc, pIdxList);
7598
7599 *pRc = rc;
7600 return 0;
7601}
7602
7603static int idxCreateFromCons(
7604 sqlite3expert *p,
7605 IdxScan *pScan,
7606 IdxConstraint *pEq,
7607 IdxConstraint *pTail
7608){
7609 sqlite3 *dbm = p->dbm;
7610 int rc = SQLITE_OK;
7611 if( (pEq || pTail) && 0==idxFindCompatible(&rc, dbm, pScan, pEq, pTail) ){
7612 IdxTable *pTab = pScan->pTab;
7613 char *zCols = 0;
7614 char *zIdx = 0;
7615 IdxConstraint *pCons;
7616 unsigned int h = 0;
7617 const char *zFmt;
7618
7619 for(pCons=pEq; pCons; pCons=pCons->pLink){
7620 zCols = idxAppendColDefn(&rc, zCols, pTab, pCons);
7621 }
7622 for(pCons=pTail; pCons; pCons=pCons->pLink){
7623 zCols = idxAppendColDefn(&rc, zCols, pTab, pCons);
7624 }
7625
7626 if( rc==SQLITE_OK ){
7627 /* Hash the list of columns to come up with a name for the index */
7628 const char *zTable = pScan->pTab->zName;
7629 char *zName; /* Index name */
7630 int i;
7631 for(i=0; zCols[i]; i++){
7632 h += ((h<<3) + zCols[i]);
7633 }
7634 zName = sqlite3_mprintf("%s_idx_%08x", zTable, h);
7635 if( zName==0 ){
7636 rc = SQLITE_NOMEM;
7637 }else{
7638 if( idxIdentifierRequiresQuotes(zTable) ){
7639 zFmt = "CREATE INDEX '%q' ON %Q(%s)";
7640 }else{
7641 zFmt = "CREATE INDEX %s ON %s(%s)";
7642 }
7643 zIdx = sqlite3_mprintf(zFmt, zName, zTable, zCols);
7644 if( !zIdx ){
7645 rc = SQLITE_NOMEM;
7646 }else{
7647 rc = sqlite3_exec(dbm, zIdx, 0, 0, p->pzErrmsg);
7648 idxHashAdd(&rc, &p->hIdx, zName, zIdx);
7649 }
7650 sqlite3_free(zName);
7651 sqlite3_free(zIdx);
7652 }
7653 }
7654
7655 sqlite3_free(zCols);
7656 }
7657 return rc;
7658}
7659
7660/*
7661** Return true if list pList (linked by IdxConstraint.pLink) contains
7662** a constraint compatible with *p. Otherwise return false.
7663*/
7664static int idxFindConstraint(IdxConstraint *pList, IdxConstraint *p){
7665 IdxConstraint *pCmp;
7666 for(pCmp=pList; pCmp; pCmp=pCmp->pLink){
7667 if( p->iCol==pCmp->iCol ) return 1;
7668 }
7669 return 0;
7670}
7671
7672static int idxCreateFromWhere(
7673 sqlite3expert *p,
7674 IdxScan *pScan, /* Create indexes for this scan */
7675 IdxConstraint *pTail /* range/ORDER BY constraints for inclusion */
7676){
7677 IdxConstraint *p1 = 0;
7678 IdxConstraint *pCon;
7679 int rc;
7680
7681 /* Gather up all the == constraints. */
7682 for(pCon=pScan->pEq; pCon; pCon=pCon->pNext){
7683 if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
7684 pCon->pLink = p1;
7685 p1 = pCon;
7686 }
7687 }
7688
7689 /* Create an index using the == constraints collected above. And the
7690 ** range constraint/ORDER BY terms passed in by the caller, if any. */
7691 rc = idxCreateFromCons(p, pScan, p1, pTail);
7692
7693 /* If no range/ORDER BY passed by the caller, create a version of the
7694 ** index for each range constraint. */
7695 if( pTail==0 ){
7696 for(pCon=pScan->pRange; rc==SQLITE_OK && pCon; pCon=pCon->pNext){
7697 assert( pCon->pLink==0 );
7698 if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
7699 rc = idxCreateFromCons(p, pScan, p1, pCon);
7700 }
7701 }
7702 }
7703
7704 return rc;
7705}
7706
7707/*
7708** Create candidate indexes in database [dbm] based on the data in
7709** linked-list pScan.
7710*/
7711static int idxCreateCandidates(sqlite3expert *p){
7712 int rc = SQLITE_OK;
7713 IdxScan *pIter;
7714
7715 for(pIter=p->pScan; pIter && rc==SQLITE_OK; pIter=pIter->pNextScan){
7716 rc = idxCreateFromWhere(p, pIter, 0);
7717 if( rc==SQLITE_OK && pIter->pOrder ){
7718 rc = idxCreateFromWhere(p, pIter, pIter->pOrder);
7719 }
7720 }
7721
7722 return rc;
7723}
7724
7725/*
7726** Free all elements of the linked list starting at pConstraint.
7727*/
7728static void idxConstraintFree(IdxConstraint *pConstraint){
7729 IdxConstraint *pNext;
7730 IdxConstraint *p;
7731
7732 for(p=pConstraint; p; p=pNext){
7733 pNext = p->pNext;
7734 sqlite3_free(p);
7735 }
7736}
7737
7738/*
7739** Free all elements of the linked list starting from pScan up until pLast
7740** (pLast is not freed).
7741*/
7742static void idxScanFree(IdxScan *pScan, IdxScan *pLast){
7743 IdxScan *p;
7744 IdxScan *pNext;
7745 for(p=pScan; p!=pLast; p=pNext){
7746 pNext = p->pNextScan;
7747 idxConstraintFree(p->pOrder);
7748 idxConstraintFree(p->pEq);
7749 idxConstraintFree(p->pRange);
7750 sqlite3_free(p);
7751 }
7752}
7753
7754/*
7755** Free all elements of the linked list starting from pStatement up
7756** until pLast (pLast is not freed).
7757*/
7758static void idxStatementFree(IdxStatement *pStatement, IdxStatement *pLast){
7759 IdxStatement *p;
7760 IdxStatement *pNext;
7761 for(p=pStatement; p!=pLast; p=pNext){
7762 pNext = p->pNext;
7763 sqlite3_free(p->zEQP);
7764 sqlite3_free(p->zIdx);
7765 sqlite3_free(p);
7766 }
7767}
7768
7769/*
7770** Free the linked list of IdxTable objects starting at pTab.
7771*/
7772static void idxTableFree(IdxTable *pTab){
7773 IdxTable *pIter;
7774 IdxTable *pNext;
7775 for(pIter=pTab; pIter; pIter=pNext){
7776 pNext = pIter->pNext;
7777 sqlite3_free(pIter);
7778 }
7779}
7780
7781/*
7782** Free the linked list of IdxWrite objects starting at pTab.
7783*/
7784static void idxWriteFree(IdxWrite *pTab){
7785 IdxWrite *pIter;
7786 IdxWrite *pNext;
7787 for(pIter=pTab; pIter; pIter=pNext){
7788 pNext = pIter->pNext;
7789 sqlite3_free(pIter);
7790 }
7791}
7792
7793
7794
7795/*
7796** This function is called after candidate indexes have been created. It
7797** runs all the queries to see which indexes they prefer, and populates
7798** IdxStatement.zIdx and IdxStatement.zEQP with the results.
7799*/
7800int idxFindIndexes(
7801 sqlite3expert *p,
7802 char **pzErr /* OUT: Error message (sqlite3_malloc) */
7803){
7804 IdxStatement *pStmt;
7805 sqlite3 *dbm = p->dbm;
7806 int rc = SQLITE_OK;
7807
7808 IdxHash hIdx;
7809 idxHashInit(&hIdx);
7810
7811 for(pStmt=p->pStatement; rc==SQLITE_OK && pStmt; pStmt=pStmt->pNext){
7812 IdxHashEntry *pEntry;
7813 sqlite3_stmt *pExplain = 0;
7814 idxHashClear(&hIdx);
7815 rc = idxPrintfPrepareStmt(dbm, &pExplain, pzErr,
7816 "EXPLAIN QUERY PLAN %s", pStmt->zSql
7817 );
7818 while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){
mydongistiny63ee58c2019-09-21 18:04:30 -07007819 /* int iId = sqlite3_column_int(pExplain, 0); */
7820 /* int iParent = sqlite3_column_int(pExplain, 1); */
7821 /* int iNotUsed = sqlite3_column_int(pExplain, 2); */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08007822 const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
7823 int nDetail = STRLEN(zDetail);
7824 int i;
7825
7826 for(i=0; i<nDetail; i++){
7827 const char *zIdx = 0;
7828 if( memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
7829 zIdx = &zDetail[i+13];
7830 }else if( memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0 ){
7831 zIdx = &zDetail[i+22];
7832 }
7833 if( zIdx ){
7834 const char *zSql;
7835 int nIdx = 0;
7836 while( zIdx[nIdx]!='\0' && (zIdx[nIdx]!=' ' || zIdx[nIdx+1]!='(') ){
7837 nIdx++;
7838 }
7839 zSql = idxHashSearch(&p->hIdx, zIdx, nIdx);
7840 if( zSql ){
7841 idxHashAdd(&rc, &hIdx, zSql, 0);
7842 if( rc ) goto find_indexes_out;
7843 }
7844 break;
7845 }
7846 }
7847
mydongistiny63ee58c2019-09-21 18:04:30 -07007848 if( zDetail[0]!='-' ){
7849 pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%s\n", zDetail);
7850 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08007851 }
7852
7853 for(pEntry=hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
7854 pStmt->zIdx = idxAppendText(&rc, pStmt->zIdx, "%s;\n", pEntry->zKey);
7855 }
7856
7857 idxFinalize(&rc, pExplain);
7858 }
7859
7860 find_indexes_out:
7861 idxHashClear(&hIdx);
7862 return rc;
7863}
7864
7865static int idxAuthCallback(
7866 void *pCtx,
7867 int eOp,
7868 const char *z3,
7869 const char *z4,
7870 const char *zDb,
7871 const char *zTrigger
7872){
7873 int rc = SQLITE_OK;
7874 (void)z4;
7875 (void)zTrigger;
7876 if( eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE || eOp==SQLITE_DELETE ){
7877 if( sqlite3_stricmp(zDb, "main")==0 ){
7878 sqlite3expert *p = (sqlite3expert*)pCtx;
7879 IdxTable *pTab;
7880 for(pTab=p->pTable; pTab; pTab=pTab->pNext){
7881 if( 0==sqlite3_stricmp(z3, pTab->zName) ) break;
7882 }
7883 if( pTab ){
7884 IdxWrite *pWrite;
7885 for(pWrite=p->pWrite; pWrite; pWrite=pWrite->pNext){
7886 if( pWrite->pTab==pTab && pWrite->eOp==eOp ) break;
7887 }
7888 if( pWrite==0 ){
7889 pWrite = idxMalloc(&rc, sizeof(IdxWrite));
7890 if( rc==SQLITE_OK ){
7891 pWrite->pTab = pTab;
7892 pWrite->eOp = eOp;
7893 pWrite->pNext = p->pWrite;
7894 p->pWrite = pWrite;
7895 }
7896 }
7897 }
7898 }
7899 }
7900 return rc;
7901}
7902
7903static int idxProcessOneTrigger(
7904 sqlite3expert *p,
7905 IdxWrite *pWrite,
7906 char **pzErr
7907){
7908 static const char *zInt = UNIQUE_TABLE_NAME;
7909 static const char *zDrop = "DROP TABLE " UNIQUE_TABLE_NAME;
7910 IdxTable *pTab = pWrite->pTab;
7911 const char *zTab = pTab->zName;
7912 const char *zSql =
7913 "SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_master "
7914 "WHERE tbl_name = %Q AND type IN ('table', 'trigger') "
7915 "ORDER BY type;";
7916 sqlite3_stmt *pSelect = 0;
7917 int rc = SQLITE_OK;
7918 char *zWrite = 0;
7919
7920 /* Create the table and its triggers in the temp schema */
7921 rc = idxPrintfPrepareStmt(p->db, &pSelect, pzErr, zSql, zTab, zTab);
7922 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSelect) ){
7923 const char *zCreate = (const char*)sqlite3_column_text(pSelect, 0);
7924 rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr);
7925 }
7926 idxFinalize(&rc, pSelect);
7927
7928 /* Rename the table in the temp schema to zInt */
7929 if( rc==SQLITE_OK ){
7930 char *z = sqlite3_mprintf("ALTER TABLE temp.%Q RENAME TO %Q", zTab, zInt);
7931 if( z==0 ){
7932 rc = SQLITE_NOMEM;
7933 }else{
7934 rc = sqlite3_exec(p->dbv, z, 0, 0, pzErr);
7935 sqlite3_free(z);
7936 }
7937 }
7938
7939 switch( pWrite->eOp ){
7940 case SQLITE_INSERT: {
7941 int i;
7942 zWrite = idxAppendText(&rc, zWrite, "INSERT INTO %Q VALUES(", zInt);
7943 for(i=0; i<pTab->nCol; i++){
7944 zWrite = idxAppendText(&rc, zWrite, "%s?", i==0 ? "" : ", ");
7945 }
7946 zWrite = idxAppendText(&rc, zWrite, ")");
7947 break;
7948 }
7949 case SQLITE_UPDATE: {
7950 int i;
7951 zWrite = idxAppendText(&rc, zWrite, "UPDATE %Q SET ", zInt);
7952 for(i=0; i<pTab->nCol; i++){
7953 zWrite = idxAppendText(&rc, zWrite, "%s%Q=?", i==0 ? "" : ", ",
7954 pTab->aCol[i].zName
7955 );
7956 }
7957 break;
7958 }
7959 default: {
7960 assert( pWrite->eOp==SQLITE_DELETE );
7961 if( rc==SQLITE_OK ){
7962 zWrite = sqlite3_mprintf("DELETE FROM %Q", zInt);
7963 if( zWrite==0 ) rc = SQLITE_NOMEM;
7964 }
7965 }
7966 }
7967
7968 if( rc==SQLITE_OK ){
7969 sqlite3_stmt *pX = 0;
7970 rc = sqlite3_prepare_v2(p->dbv, zWrite, -1, &pX, 0);
7971 idxFinalize(&rc, pX);
7972 if( rc!=SQLITE_OK ){
7973 idxDatabaseError(p->dbv, pzErr);
7974 }
7975 }
7976 sqlite3_free(zWrite);
7977
7978 if( rc==SQLITE_OK ){
7979 rc = sqlite3_exec(p->dbv, zDrop, 0, 0, pzErr);
7980 }
7981
7982 return rc;
7983}
7984
7985static int idxProcessTriggers(sqlite3expert *p, char **pzErr){
7986 int rc = SQLITE_OK;
7987 IdxWrite *pEnd = 0;
7988 IdxWrite *pFirst = p->pWrite;
7989
7990 while( rc==SQLITE_OK && pFirst!=pEnd ){
7991 IdxWrite *pIter;
7992 for(pIter=pFirst; rc==SQLITE_OK && pIter!=pEnd; pIter=pIter->pNext){
7993 rc = idxProcessOneTrigger(p, pIter, pzErr);
7994 }
7995 pEnd = pFirst;
7996 pFirst = p->pWrite;
7997 }
7998
7999 return rc;
8000}
8001
8002
8003static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
8004 int rc = idxRegisterVtab(p);
8005 sqlite3_stmt *pSchema = 0;
8006
8007 /* For each table in the main db schema:
8008 **
8009 ** 1) Add an entry to the p->pTable list, and
8010 ** 2) Create the equivalent virtual table in dbv.
8011 */
8012 rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg,
8013 "SELECT type, name, sql, 1 FROM sqlite_master "
8014 "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' "
8015 " UNION ALL "
8016 "SELECT type, name, sql, 2 FROM sqlite_master "
8017 "WHERE type = 'trigger'"
8018 " AND tbl_name IN(SELECT name FROM sqlite_master WHERE type = 'view') "
8019 "ORDER BY 4, 1"
8020 );
8021 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){
8022 const char *zType = (const char*)sqlite3_column_text(pSchema, 0);
8023 const char *zName = (const char*)sqlite3_column_text(pSchema, 1);
8024 const char *zSql = (const char*)sqlite3_column_text(pSchema, 2);
8025
8026 if( zType[0]=='v' || zType[1]=='r' ){
8027 rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
8028 }else{
8029 IdxTable *pTab;
8030 rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
8031 if( rc==SQLITE_OK ){
8032 int i;
8033 char *zInner = 0;
8034 char *zOuter = 0;
8035 pTab->pNext = p->pTable;
8036 p->pTable = pTab;
8037
8038 /* The statement the vtab will pass to sqlite3_declare_vtab() */
8039 zInner = idxAppendText(&rc, 0, "CREATE TABLE x(");
8040 for(i=0; i<pTab->nCol; i++){
8041 zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %s",
8042 (i==0 ? "" : ", "), pTab->aCol[i].zName, pTab->aCol[i].zColl
8043 );
8044 }
8045 zInner = idxAppendText(&rc, zInner, ")");
8046
8047 /* The CVT statement to create the vtab */
8048 zOuter = idxAppendText(&rc, 0,
8049 "CREATE VIRTUAL TABLE %Q USING expert(%Q)", zName, zInner
8050 );
8051 if( rc==SQLITE_OK ){
8052 rc = sqlite3_exec(p->dbv, zOuter, 0, 0, pzErrmsg);
8053 }
8054 sqlite3_free(zInner);
8055 sqlite3_free(zOuter);
8056 }
8057 }
8058 }
8059 idxFinalize(&rc, pSchema);
8060 return rc;
8061}
8062
8063struct IdxSampleCtx {
8064 int iTarget;
8065 double target; /* Target nRet/nRow value */
8066 double nRow; /* Number of rows seen */
8067 double nRet; /* Number of rows returned */
8068};
8069
8070static void idxSampleFunc(
8071 sqlite3_context *pCtx,
8072 int argc,
8073 sqlite3_value **argv
8074){
8075 struct IdxSampleCtx *p = (struct IdxSampleCtx*)sqlite3_user_data(pCtx);
8076 int bRet;
8077
8078 (void)argv;
8079 assert( argc==0 );
8080 if( p->nRow==0.0 ){
8081 bRet = 1;
8082 }else{
8083 bRet = (p->nRet / p->nRow) <= p->target;
8084 if( bRet==0 ){
8085 unsigned short rnd;
8086 sqlite3_randomness(2, (void*)&rnd);
8087 bRet = ((int)rnd % 100) <= p->iTarget;
8088 }
8089 }
8090
8091 sqlite3_result_int(pCtx, bRet);
8092 p->nRow += 1.0;
8093 p->nRet += (double)bRet;
8094}
8095
8096struct IdxRemCtx {
8097 int nSlot;
8098 struct IdxRemSlot {
8099 int eType; /* SQLITE_NULL, INTEGER, REAL, TEXT, BLOB */
8100 i64 iVal; /* SQLITE_INTEGER value */
8101 double rVal; /* SQLITE_FLOAT value */
8102 int nByte; /* Bytes of space allocated at z */
8103 int n; /* Size of buffer z */
8104 char *z; /* SQLITE_TEXT/BLOB value */
8105 } aSlot[1];
8106};
8107
8108/*
8109** Implementation of scalar function rem().
8110*/
8111static void idxRemFunc(
8112 sqlite3_context *pCtx,
8113 int argc,
8114 sqlite3_value **argv
8115){
8116 struct IdxRemCtx *p = (struct IdxRemCtx*)sqlite3_user_data(pCtx);
8117 struct IdxRemSlot *pSlot;
8118 int iSlot;
8119 assert( argc==2 );
8120
8121 iSlot = sqlite3_value_int(argv[0]);
8122 assert( iSlot<=p->nSlot );
8123 pSlot = &p->aSlot[iSlot];
8124
8125 switch( pSlot->eType ){
8126 case SQLITE_NULL:
8127 /* no-op */
8128 break;
8129
8130 case SQLITE_INTEGER:
8131 sqlite3_result_int64(pCtx, pSlot->iVal);
8132 break;
8133
8134 case SQLITE_FLOAT:
8135 sqlite3_result_double(pCtx, pSlot->rVal);
8136 break;
8137
8138 case SQLITE_BLOB:
8139 sqlite3_result_blob(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT);
8140 break;
8141
8142 case SQLITE_TEXT:
8143 sqlite3_result_text(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT);
8144 break;
8145 }
8146
8147 pSlot->eType = sqlite3_value_type(argv[1]);
8148 switch( pSlot->eType ){
8149 case SQLITE_NULL:
8150 /* no-op */
8151 break;
8152
8153 case SQLITE_INTEGER:
8154 pSlot->iVal = sqlite3_value_int64(argv[1]);
8155 break;
8156
8157 case SQLITE_FLOAT:
8158 pSlot->rVal = sqlite3_value_double(argv[1]);
8159 break;
8160
8161 case SQLITE_BLOB:
8162 case SQLITE_TEXT: {
8163 int nByte = sqlite3_value_bytes(argv[1]);
8164 if( nByte>pSlot->nByte ){
8165 char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2);
8166 if( zNew==0 ){
8167 sqlite3_result_error_nomem(pCtx);
8168 return;
8169 }
8170 pSlot->nByte = nByte*2;
8171 pSlot->z = zNew;
8172 }
8173 pSlot->n = nByte;
8174 if( pSlot->eType==SQLITE_BLOB ){
8175 memcpy(pSlot->z, sqlite3_value_blob(argv[1]), nByte);
8176 }else{
8177 memcpy(pSlot->z, sqlite3_value_text(argv[1]), nByte);
8178 }
8179 break;
8180 }
8181 }
8182}
8183
8184static int idxLargestIndex(sqlite3 *db, int *pnMax, char **pzErr){
8185 int rc = SQLITE_OK;
8186 const char *zMax =
8187 "SELECT max(i.seqno) FROM "
8188 " sqlite_master AS s, "
8189 " pragma_index_list(s.name) AS l, "
8190 " pragma_index_info(l.name) AS i "
8191 "WHERE s.type = 'table'";
8192 sqlite3_stmt *pMax = 0;
8193
8194 *pnMax = 0;
8195 rc = idxPrepareStmt(db, &pMax, pzErr, zMax);
8196 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){
8197 *pnMax = sqlite3_column_int(pMax, 0) + 1;
8198 }
8199 idxFinalize(&rc, pMax);
8200
8201 return rc;
8202}
8203
8204static int idxPopulateOneStat1(
8205 sqlite3expert *p,
8206 sqlite3_stmt *pIndexXInfo,
8207 sqlite3_stmt *pWriteStat,
8208 const char *zTab,
8209 const char *zIdx,
8210 char **pzErr
8211){
8212 char *zCols = 0;
8213 char *zOrder = 0;
8214 char *zQuery = 0;
8215 int nCol = 0;
8216 int i;
8217 sqlite3_stmt *pQuery = 0;
8218 int *aStat = 0;
8219 int rc = SQLITE_OK;
8220
8221 assert( p->iSample>0 );
8222
8223 /* Formulate the query text */
8224 sqlite3_bind_text(pIndexXInfo, 1, zIdx, -1, SQLITE_STATIC);
8225 while( SQLITE_OK==rc && SQLITE_ROW==sqlite3_step(pIndexXInfo) ){
8226 const char *zComma = zCols==0 ? "" : ", ";
8227 const char *zName = (const char*)sqlite3_column_text(pIndexXInfo, 0);
8228 const char *zColl = (const char*)sqlite3_column_text(pIndexXInfo, 1);
8229 zCols = idxAppendText(&rc, zCols,
8230 "%sx.%Q IS rem(%d, x.%Q) COLLATE %s", zComma, zName, nCol, zName, zColl
8231 );
8232 zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol);
8233 }
8234 sqlite3_reset(pIndexXInfo);
8235 if( rc==SQLITE_OK ){
8236 if( p->iSample==100 ){
8237 zQuery = sqlite3_mprintf(
8238 "SELECT %s FROM %Q x ORDER BY %s", zCols, zTab, zOrder
8239 );
8240 }else{
8241 zQuery = sqlite3_mprintf(
8242 "SELECT %s FROM temp."UNIQUE_TABLE_NAME" x ORDER BY %s", zCols, zOrder
8243 );
8244 }
8245 }
8246 sqlite3_free(zCols);
8247 sqlite3_free(zOrder);
8248
8249 /* Formulate the query text */
8250 if( rc==SQLITE_OK ){
8251 sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv);
8252 rc = idxPrepareStmt(dbrem, &pQuery, pzErr, zQuery);
8253 }
8254 sqlite3_free(zQuery);
8255
8256 if( rc==SQLITE_OK ){
8257 aStat = (int*)idxMalloc(&rc, sizeof(int)*(nCol+1));
8258 }
8259 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){
8260 IdxHashEntry *pEntry;
8261 char *zStat = 0;
8262 for(i=0; i<=nCol; i++) aStat[i] = 1;
8263 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){
8264 aStat[0]++;
8265 for(i=0; i<nCol; i++){
8266 if( sqlite3_column_int(pQuery, i)==0 ) break;
8267 }
8268 for(/*no-op*/; i<nCol; i++){
8269 aStat[i+1]++;
8270 }
8271 }
8272
8273 if( rc==SQLITE_OK ){
8274 int s0 = aStat[0];
8275 zStat = sqlite3_mprintf("%d", s0);
8276 if( zStat==0 ) rc = SQLITE_NOMEM;
8277 for(i=1; rc==SQLITE_OK && i<=nCol; i++){
8278 zStat = idxAppendText(&rc, zStat, " %d", (s0+aStat[i]/2) / aStat[i]);
8279 }
8280 }
8281
8282 if( rc==SQLITE_OK ){
8283 sqlite3_bind_text(pWriteStat, 1, zTab, -1, SQLITE_STATIC);
8284 sqlite3_bind_text(pWriteStat, 2, zIdx, -1, SQLITE_STATIC);
8285 sqlite3_bind_text(pWriteStat, 3, zStat, -1, SQLITE_STATIC);
8286 sqlite3_step(pWriteStat);
8287 rc = sqlite3_reset(pWriteStat);
8288 }
8289
8290 pEntry = idxHashFind(&p->hIdx, zIdx, STRLEN(zIdx));
8291 if( pEntry ){
8292 assert( pEntry->zVal2==0 );
8293 pEntry->zVal2 = zStat;
8294 }else{
8295 sqlite3_free(zStat);
8296 }
8297 }
8298 sqlite3_free(aStat);
8299 idxFinalize(&rc, pQuery);
8300
8301 return rc;
8302}
8303
8304static int idxBuildSampleTable(sqlite3expert *p, const char *zTab){
8305 int rc;
8306 char *zSql;
8307
8308 rc = sqlite3_exec(p->dbv,"DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
8309 if( rc!=SQLITE_OK ) return rc;
8310
8311 zSql = sqlite3_mprintf(
8312 "CREATE TABLE temp." UNIQUE_TABLE_NAME " AS SELECT * FROM %Q", zTab
8313 );
8314 if( zSql==0 ) return SQLITE_NOMEM;
8315 rc = sqlite3_exec(p->dbv, zSql, 0, 0, 0);
8316 sqlite3_free(zSql);
8317
8318 return rc;
8319}
8320
8321/*
8322** This function is called as part of sqlite3_expert_analyze(). Candidate
8323** indexes have already been created in database sqlite3expert.dbm, this
8324** function populates sqlite_stat1 table in the same database.
8325**
8326** The stat1 data is generated by querying the
8327*/
8328static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
8329 int rc = SQLITE_OK;
8330 int nMax =0;
8331 struct IdxRemCtx *pCtx = 0;
8332 struct IdxSampleCtx samplectx;
8333 int i;
8334 i64 iPrev = -100000;
8335 sqlite3_stmt *pAllIndex = 0;
8336 sqlite3_stmt *pIndexXInfo = 0;
8337 sqlite3_stmt *pWrite = 0;
8338
8339 const char *zAllIndex =
8340 "SELECT s.rowid, s.name, l.name FROM "
8341 " sqlite_master AS s, "
8342 " pragma_index_list(s.name) AS l "
8343 "WHERE s.type = 'table'";
8344 const char *zIndexXInfo =
8345 "SELECT name, coll FROM pragma_index_xinfo(?) WHERE key";
8346 const char *zWrite = "INSERT INTO sqlite_stat1 VALUES(?, ?, ?)";
8347
8348 /* If iSample==0, no sqlite_stat1 data is required. */
8349 if( p->iSample==0 ) return SQLITE_OK;
8350
8351 rc = idxLargestIndex(p->dbm, &nMax, pzErr);
8352 if( nMax<=0 || rc!=SQLITE_OK ) return rc;
8353
8354 rc = sqlite3_exec(p->dbm, "ANALYZE; PRAGMA writable_schema=1", 0, 0, 0);
8355
8356 if( rc==SQLITE_OK ){
8357 int nByte = sizeof(struct IdxRemCtx) + (sizeof(struct IdxRemSlot) * nMax);
8358 pCtx = (struct IdxRemCtx*)idxMalloc(&rc, nByte);
8359 }
8360
8361 if( rc==SQLITE_OK ){
8362 sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv);
8363 rc = sqlite3_create_function(
8364 dbrem, "rem", 2, SQLITE_UTF8, (void*)pCtx, idxRemFunc, 0, 0
8365 );
8366 }
8367 if( rc==SQLITE_OK ){
8368 rc = sqlite3_create_function(
8369 p->db, "sample", 0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0
8370 );
8371 }
8372
8373 if( rc==SQLITE_OK ){
8374 pCtx->nSlot = nMax+1;
8375 rc = idxPrepareStmt(p->dbm, &pAllIndex, pzErr, zAllIndex);
8376 }
8377 if( rc==SQLITE_OK ){
8378 rc = idxPrepareStmt(p->dbm, &pIndexXInfo, pzErr, zIndexXInfo);
8379 }
8380 if( rc==SQLITE_OK ){
8381 rc = idxPrepareStmt(p->dbm, &pWrite, pzErr, zWrite);
8382 }
8383
8384 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pAllIndex) ){
8385 i64 iRowid = sqlite3_column_int64(pAllIndex, 0);
8386 const char *zTab = (const char*)sqlite3_column_text(pAllIndex, 1);
8387 const char *zIdx = (const char*)sqlite3_column_text(pAllIndex, 2);
8388 if( p->iSample<100 && iPrev!=iRowid ){
8389 samplectx.target = (double)p->iSample / 100.0;
8390 samplectx.iTarget = p->iSample;
8391 samplectx.nRow = 0.0;
8392 samplectx.nRet = 0.0;
8393 rc = idxBuildSampleTable(p, zTab);
8394 if( rc!=SQLITE_OK ) break;
8395 }
8396 rc = idxPopulateOneStat1(p, pIndexXInfo, pWrite, zTab, zIdx, pzErr);
8397 iPrev = iRowid;
8398 }
8399 if( rc==SQLITE_OK && p->iSample<100 ){
8400 rc = sqlite3_exec(p->dbv,
8401 "DROP TABLE IF EXISTS temp." UNIQUE_TABLE_NAME, 0,0,0
8402 );
8403 }
8404
8405 idxFinalize(&rc, pAllIndex);
8406 idxFinalize(&rc, pIndexXInfo);
8407 idxFinalize(&rc, pWrite);
8408
8409 for(i=0; i<pCtx->nSlot; i++){
8410 sqlite3_free(pCtx->aSlot[i].z);
8411 }
8412 sqlite3_free(pCtx);
8413
8414 if( rc==SQLITE_OK ){
8415 rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_master", 0, 0, 0);
8416 }
8417
8418 sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
8419 return rc;
8420}
8421
8422/*
8423** Allocate a new sqlite3expert object.
8424*/
8425sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
8426 int rc = SQLITE_OK;
8427 sqlite3expert *pNew;
8428
8429 pNew = (sqlite3expert*)idxMalloc(&rc, sizeof(sqlite3expert));
8430
8431 /* Open two in-memory databases to work with. The "vtab database" (dbv)
8432 ** will contain a virtual table corresponding to each real table in
8433 ** the user database schema, and a copy of each view. It is used to
8434 ** collect information regarding the WHERE, ORDER BY and other clauses
8435 ** of the user's query.
8436 */
8437 if( rc==SQLITE_OK ){
8438 pNew->db = db;
8439 pNew->iSample = 100;
8440 rc = sqlite3_open(":memory:", &pNew->dbv);
8441 }
8442 if( rc==SQLITE_OK ){
8443 rc = sqlite3_open(":memory:", &pNew->dbm);
8444 if( rc==SQLITE_OK ){
8445 sqlite3_db_config(pNew->dbm, SQLITE_DBCONFIG_TRIGGER_EQP, 1, (int*)0);
8446 }
8447 }
8448
8449
8450 /* Copy the entire schema of database [db] into [dbm]. */
8451 if( rc==SQLITE_OK ){
8452 sqlite3_stmt *pSql;
8453 rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg,
8454 "SELECT sql FROM sqlite_master WHERE name NOT LIKE 'sqlite_%%'"
8455 " AND sql NOT LIKE 'CREATE VIRTUAL %%'"
8456 );
8457 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
8458 const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
8459 rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
8460 }
8461 idxFinalize(&rc, pSql);
8462 }
8463
8464 /* Create the vtab schema */
8465 if( rc==SQLITE_OK ){
8466 rc = idxCreateVtabSchema(pNew, pzErrmsg);
8467 }
8468
8469 /* Register the auth callback with dbv */
8470 if( rc==SQLITE_OK ){
8471 sqlite3_set_authorizer(pNew->dbv, idxAuthCallback, (void*)pNew);
8472 }
8473
8474 /* If an error has occurred, free the new object and reutrn NULL. Otherwise,
8475 ** return the new sqlite3expert handle. */
8476 if( rc!=SQLITE_OK ){
8477 sqlite3_expert_destroy(pNew);
8478 pNew = 0;
8479 }
8480 return pNew;
8481}
8482
8483/*
8484** Configure an sqlite3expert object.
8485*/
8486int sqlite3_expert_config(sqlite3expert *p, int op, ...){
8487 int rc = SQLITE_OK;
8488 va_list ap;
8489 va_start(ap, op);
8490 switch( op ){
8491 case EXPERT_CONFIG_SAMPLE: {
8492 int iVal = va_arg(ap, int);
8493 if( iVal<0 ) iVal = 0;
8494 if( iVal>100 ) iVal = 100;
8495 p->iSample = iVal;
8496 break;
8497 }
8498 default:
8499 rc = SQLITE_NOTFOUND;
8500 break;
8501 }
8502
8503 va_end(ap);
8504 return rc;
8505}
8506
8507/*
8508** Add an SQL statement to the analysis.
8509*/
8510int sqlite3_expert_sql(
8511 sqlite3expert *p, /* From sqlite3_expert_new() */
8512 const char *zSql, /* SQL statement to add */
8513 char **pzErr /* OUT: Error message (if any) */
8514){
8515 IdxScan *pScanOrig = p->pScan;
8516 IdxStatement *pStmtOrig = p->pStatement;
8517 int rc = SQLITE_OK;
8518 const char *zStmt = zSql;
8519
8520 if( p->bRun ) return SQLITE_MISUSE;
8521
8522 while( rc==SQLITE_OK && zStmt && zStmt[0] ){
8523 sqlite3_stmt *pStmt = 0;
8524 rc = sqlite3_prepare_v2(p->dbv, zStmt, -1, &pStmt, &zStmt);
8525 if( rc==SQLITE_OK ){
8526 if( pStmt ){
8527 IdxStatement *pNew;
8528 const char *z = sqlite3_sql(pStmt);
8529 int n = STRLEN(z);
8530 pNew = (IdxStatement*)idxMalloc(&rc, sizeof(IdxStatement) + n+1);
8531 if( rc==SQLITE_OK ){
8532 pNew->zSql = (char*)&pNew[1];
8533 memcpy(pNew->zSql, z, n+1);
8534 pNew->pNext = p->pStatement;
8535 if( p->pStatement ) pNew->iId = p->pStatement->iId+1;
8536 p->pStatement = pNew;
8537 }
8538 sqlite3_finalize(pStmt);
8539 }
8540 }else{
8541 idxDatabaseError(p->dbv, pzErr);
8542 }
8543 }
8544
8545 if( rc!=SQLITE_OK ){
8546 idxScanFree(p->pScan, pScanOrig);
8547 idxStatementFree(p->pStatement, pStmtOrig);
8548 p->pScan = pScanOrig;
8549 p->pStatement = pStmtOrig;
8550 }
8551
8552 return rc;
8553}
8554
8555int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr){
8556 int rc;
8557 IdxHashEntry *pEntry;
8558
8559 /* Do trigger processing to collect any extra IdxScan structures */
8560 rc = idxProcessTriggers(p, pzErr);
8561
8562 /* Create candidate indexes within the in-memory database file */
8563 if( rc==SQLITE_OK ){
8564 rc = idxCreateCandidates(p);
8565 }
8566
8567 /* Generate the stat1 data */
8568 if( rc==SQLITE_OK ){
8569 rc = idxPopulateStat1(p, pzErr);
8570 }
8571
8572 /* Formulate the EXPERT_REPORT_CANDIDATES text */
8573 for(pEntry=p->hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
8574 p->zCandidates = idxAppendText(&rc, p->zCandidates,
8575 "%s;%s%s\n", pEntry->zVal,
8576 pEntry->zVal2 ? " -- stat1: " : "", pEntry->zVal2
8577 );
8578 }
8579
8580 /* Figure out which of the candidate indexes are preferred by the query
8581 ** planner and report the results to the user. */
8582 if( rc==SQLITE_OK ){
8583 rc = idxFindIndexes(p, pzErr);
8584 }
8585
8586 if( rc==SQLITE_OK ){
8587 p->bRun = 1;
8588 }
8589 return rc;
8590}
8591
8592/*
8593** Return the total number of statements that have been added to this
8594** sqlite3expert using sqlite3_expert_sql().
8595*/
8596int sqlite3_expert_count(sqlite3expert *p){
8597 int nRet = 0;
8598 if( p->pStatement ) nRet = p->pStatement->iId+1;
8599 return nRet;
8600}
8601
8602/*
8603** Return a component of the report.
8604*/
8605const char *sqlite3_expert_report(sqlite3expert *p, int iStmt, int eReport){
8606 const char *zRet = 0;
8607 IdxStatement *pStmt;
8608
8609 if( p->bRun==0 ) return 0;
8610 for(pStmt=p->pStatement; pStmt && pStmt->iId!=iStmt; pStmt=pStmt->pNext);
8611 switch( eReport ){
8612 case EXPERT_REPORT_SQL:
8613 if( pStmt ) zRet = pStmt->zSql;
8614 break;
8615 case EXPERT_REPORT_INDEXES:
8616 if( pStmt ) zRet = pStmt->zIdx;
8617 break;
8618 case EXPERT_REPORT_PLAN:
8619 if( pStmt ) zRet = pStmt->zEQP;
8620 break;
8621 case EXPERT_REPORT_CANDIDATES:
8622 zRet = p->zCandidates;
8623 break;
8624 }
8625 return zRet;
8626}
8627
8628/*
8629** Free an sqlite3expert object.
8630*/
8631void sqlite3_expert_destroy(sqlite3expert *p){
8632 if( p ){
8633 sqlite3_close(p->dbm);
8634 sqlite3_close(p->dbv);
8635 idxScanFree(p->pScan, 0);
8636 idxStatementFree(p->pStatement, 0);
8637 idxTableFree(p->pTable);
8638 idxWriteFree(p->pWrite);
8639 idxHashClear(&p->hIdx);
8640 sqlite3_free(p->zCandidates);
8641 sqlite3_free(p);
8642 }
8643}
8644
8645#endif /* ifndef SQLITE_OMIT_VIRTUAL_TABLE */
8646
8647/************************* End ../ext/expert/sqlite3expert.c ********************/
The Android Open Source Project7790ef52009-03-03 19:30:40 -08008648
mydongistiny63ee58c2019-09-21 18:04:30 -07008649#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
8650/************************* Begin ../ext/misc/dbdata.c ******************/
8651/*
8652** 2019-04-17
8653**
8654** The author disclaims copyright to this source code. In place of
8655** a legal notice, here is a blessing:
8656**
8657** May you do good and not evil.
8658** May you find forgiveness for yourself and forgive others.
8659** May you share freely, never taking more than you give.
8660**
8661******************************************************************************
8662**
8663** This file contains an implementation of two eponymous virtual tables,
8664** "sqlite_dbdata" and "sqlite_dbptr". Both modules require that the
8665** "sqlite_dbpage" eponymous virtual table be available.
8666**
8667** SQLITE_DBDATA:
8668** sqlite_dbdata is used to extract data directly from a database b-tree
8669** page and its associated overflow pages, bypassing the b-tree layer.
8670** The table schema is equivalent to:
8671**
8672** CREATE TABLE sqlite_dbdata(
8673** pgno INTEGER,
8674** cell INTEGER,
8675** field INTEGER,
8676** value ANY,
8677** schema TEXT HIDDEN
8678** );
8679**
8680** IMPORTANT: THE VIRTUAL TABLE SCHEMA ABOVE IS SUBJECT TO CHANGE. IN THE
8681** FUTURE NEW NON-HIDDEN COLUMNS MAY BE ADDED BETWEEN "value" AND
8682** "schema".
8683**
8684** Each page of the database is inspected. If it cannot be interpreted as
8685** a b-tree page, or if it is a b-tree page containing 0 entries, the
8686** sqlite_dbdata table contains no rows for that page. Otherwise, the
8687** table contains one row for each field in the record associated with
8688** each cell on the page. For intkey b-trees, the key value is stored in
8689** field -1.
8690**
8691** For example, for the database:
8692**
8693** CREATE TABLE t1(a, b); -- root page is page 2
8694** INSERT INTO t1(rowid, a, b) VALUES(5, 'v', 'five');
8695** INSERT INTO t1(rowid, a, b) VALUES(10, 'x', 'ten');
8696**
8697** the sqlite_dbdata table contains, as well as from entries related to
8698** page 1, content equivalent to:
8699**
8700** INSERT INTO sqlite_dbdata(pgno, cell, field, value) VALUES
8701** (2, 0, -1, 5 ),
8702** (2, 0, 0, 'v' ),
8703** (2, 0, 1, 'five'),
8704** (2, 1, -1, 10 ),
8705** (2, 1, 0, 'x' ),
8706** (2, 1, 1, 'ten' );
8707**
8708** If database corruption is encountered, this module does not report an
8709** error. Instead, it attempts to extract as much data as possible and
8710** ignores the corruption.
8711**
8712** SQLITE_DBPTR:
8713** The sqlite_dbptr table has the following schema:
8714**
8715** CREATE TABLE sqlite_dbptr(
8716** pgno INTEGER,
8717** child INTEGER,
8718** schema TEXT HIDDEN
8719** );
8720**
8721** It contains one entry for each b-tree pointer between a parent and
8722** child page in the database.
8723*/
8724#if !defined(SQLITEINT_H)
8725/* #include "sqlite3ext.h" */
8726
8727/* typedef unsigned char u8; */
8728
8729#endif
8730SQLITE_EXTENSION_INIT1
8731#include <string.h>
8732#include <assert.h>
8733
8734#define DBDATA_PADDING_BYTES 100
8735
8736typedef struct DbdataTable DbdataTable;
8737typedef struct DbdataCursor DbdataCursor;
8738
8739/* Cursor object */
8740struct DbdataCursor {
8741 sqlite3_vtab_cursor base; /* Base class. Must be first */
8742 sqlite3_stmt *pStmt; /* For fetching database pages */
8743
8744 int iPgno; /* Current page number */
8745 u8 *aPage; /* Buffer containing page */
8746 int nPage; /* Size of aPage[] in bytes */
8747 int nCell; /* Number of cells on aPage[] */
8748 int iCell; /* Current cell number */
8749 int bOnePage; /* True to stop after one page */
8750 int szDb;
8751 sqlite3_int64 iRowid;
8752
8753 /* Only for the sqlite_dbdata table */
8754 u8 *pRec; /* Buffer containing current record */
8755 int nRec; /* Size of pRec[] in bytes */
8756 int nHdr; /* Size of header in bytes */
8757 int iField; /* Current field number */
8758 u8 *pHdrPtr;
8759 u8 *pPtr;
8760
8761 sqlite3_int64 iIntkey; /* Integer key value */
8762};
8763
8764/* Table object */
8765struct DbdataTable {
8766 sqlite3_vtab base; /* Base class. Must be first */
8767 sqlite3 *db; /* The database connection */
8768 sqlite3_stmt *pStmt; /* For fetching database pages */
8769 int bPtr; /* True for sqlite3_dbptr table */
8770};
8771
8772/* Column and schema definitions for sqlite_dbdata */
8773#define DBDATA_COLUMN_PGNO 0
8774#define DBDATA_COLUMN_CELL 1
8775#define DBDATA_COLUMN_FIELD 2
8776#define DBDATA_COLUMN_VALUE 3
8777#define DBDATA_COLUMN_SCHEMA 4
8778#define DBDATA_SCHEMA \
8779 "CREATE TABLE x(" \
8780 " pgno INTEGER," \
8781 " cell INTEGER," \
8782 " field INTEGER," \
8783 " value ANY," \
8784 " schema TEXT HIDDEN" \
8785 ")"
8786
8787/* Column and schema definitions for sqlite_dbptr */
8788#define DBPTR_COLUMN_PGNO 0
8789#define DBPTR_COLUMN_CHILD 1
8790#define DBPTR_COLUMN_SCHEMA 2
8791#define DBPTR_SCHEMA \
8792 "CREATE TABLE x(" \
8793 " pgno INTEGER," \
8794 " child INTEGER," \
8795 " schema TEXT HIDDEN" \
8796 ")"
8797
8798/*
8799** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual
8800** table.
8801*/
8802static int dbdataConnect(
8803 sqlite3 *db,
8804 void *pAux,
8805 int argc, const char *const*argv,
8806 sqlite3_vtab **ppVtab,
8807 char **pzErr
8808){
8809 DbdataTable *pTab = 0;
8810 int rc = sqlite3_declare_vtab(db, pAux ? DBPTR_SCHEMA : DBDATA_SCHEMA);
8811
8812 if( rc==SQLITE_OK ){
8813 pTab = (DbdataTable*)sqlite3_malloc64(sizeof(DbdataTable));
8814 if( pTab==0 ){
8815 rc = SQLITE_NOMEM;
8816 }else{
8817 memset(pTab, 0, sizeof(DbdataTable));
8818 pTab->db = db;
8819 pTab->bPtr = (pAux!=0);
8820 }
8821 }
8822
8823 *ppVtab = (sqlite3_vtab*)pTab;
8824 return rc;
8825}
8826
8827/*
8828** Disconnect from or destroy a sqlite_dbdata or sqlite_dbptr virtual table.
8829*/
8830static int dbdataDisconnect(sqlite3_vtab *pVtab){
8831 DbdataTable *pTab = (DbdataTable*)pVtab;
8832 if( pTab ){
8833 sqlite3_finalize(pTab->pStmt);
8834 sqlite3_free(pVtab);
8835 }
8836 return SQLITE_OK;
8837}
8838
8839/*
8840** This function interprets two types of constraints:
8841**
8842** schema=?
8843** pgno=?
8844**
8845** If neither are present, idxNum is set to 0. If schema=? is present,
8846** the 0x01 bit in idxNum is set. If pgno=? is present, the 0x02 bit
8847** in idxNum is set.
8848**
8849** If both parameters are present, schema is in position 0 and pgno in
8850** position 1.
8851*/
8852static int dbdataBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdx){
8853 DbdataTable *pTab = (DbdataTable*)tab;
8854 int i;
8855 int iSchema = -1;
8856 int iPgno = -1;
8857 int colSchema = (pTab->bPtr ? DBPTR_COLUMN_SCHEMA : DBDATA_COLUMN_SCHEMA);
8858
8859 for(i=0; i<pIdx->nConstraint; i++){
8860 struct sqlite3_index_constraint *p = &pIdx->aConstraint[i];
8861 if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
8862 if( p->iColumn==colSchema ){
8863 if( p->usable==0 ) return SQLITE_CONSTRAINT;
8864 iSchema = i;
8865 }
8866 if( p->iColumn==DBDATA_COLUMN_PGNO && p->usable ){
8867 iPgno = i;
8868 }
8869 }
8870 }
8871
8872 if( iSchema>=0 ){
8873 pIdx->aConstraintUsage[iSchema].argvIndex = 1;
8874 pIdx->aConstraintUsage[iSchema].omit = 1;
8875 }
8876 if( iPgno>=0 ){
8877 pIdx->aConstraintUsage[iPgno].argvIndex = 1 + (iSchema>=0);
8878 pIdx->aConstraintUsage[iPgno].omit = 1;
8879 pIdx->estimatedCost = 100;
8880 pIdx->estimatedRows = 50;
8881
8882 if( pTab->bPtr==0 && pIdx->nOrderBy && pIdx->aOrderBy[0].desc==0 ){
8883 int iCol = pIdx->aOrderBy[0].iColumn;
8884 if( pIdx->nOrderBy==1 ){
8885 pIdx->orderByConsumed = (iCol==0 || iCol==1);
8886 }else if( pIdx->nOrderBy==2 && pIdx->aOrderBy[1].desc==0 && iCol==0 ){
8887 pIdx->orderByConsumed = (pIdx->aOrderBy[1].iColumn==1);
8888 }
8889 }
8890
8891 }else{
8892 pIdx->estimatedCost = 100000000;
8893 pIdx->estimatedRows = 1000000000;
8894 }
8895 pIdx->idxNum = (iSchema>=0 ? 0x01 : 0x00) | (iPgno>=0 ? 0x02 : 0x00);
8896 return SQLITE_OK;
8897}
8898
8899/*
8900** Open a new sqlite_dbdata or sqlite_dbptr cursor.
8901*/
8902static int dbdataOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
8903 DbdataCursor *pCsr;
8904
8905 pCsr = (DbdataCursor*)sqlite3_malloc64(sizeof(DbdataCursor));
8906 if( pCsr==0 ){
8907 return SQLITE_NOMEM;
8908 }else{
8909 memset(pCsr, 0, sizeof(DbdataCursor));
8910 pCsr->base.pVtab = pVTab;
8911 }
8912
8913 *ppCursor = (sqlite3_vtab_cursor *)pCsr;
8914 return SQLITE_OK;
8915}
8916
8917/*
8918** Restore a cursor object to the state it was in when first allocated
8919** by dbdataOpen().
8920*/
8921static void dbdataResetCursor(DbdataCursor *pCsr){
8922 DbdataTable *pTab = (DbdataTable*)(pCsr->base.pVtab);
8923 if( pTab->pStmt==0 ){
8924 pTab->pStmt = pCsr->pStmt;
8925 }else{
8926 sqlite3_finalize(pCsr->pStmt);
8927 }
8928 pCsr->pStmt = 0;
8929 pCsr->iPgno = 1;
8930 pCsr->iCell = 0;
8931 pCsr->iField = 0;
8932 pCsr->bOnePage = 0;
8933 sqlite3_free(pCsr->aPage);
8934 sqlite3_free(pCsr->pRec);
8935 pCsr->pRec = 0;
8936 pCsr->aPage = 0;
8937}
8938
8939/*
8940** Close an sqlite_dbdata or sqlite_dbptr cursor.
8941*/
8942static int dbdataClose(sqlite3_vtab_cursor *pCursor){
8943 DbdataCursor *pCsr = (DbdataCursor*)pCursor;
8944 dbdataResetCursor(pCsr);
8945 sqlite3_free(pCsr);
8946 return SQLITE_OK;
8947}
8948
8949/*
8950** Utility methods to decode 16 and 32-bit big-endian unsigned integers.
8951*/
8952static unsigned int get_uint16(unsigned char *a){
8953 return (a[0]<<8)|a[1];
8954}
8955static unsigned int get_uint32(unsigned char *a){
8956 return ((unsigned int)a[0]<<24)
8957 | ((unsigned int)a[1]<<16)
8958 | ((unsigned int)a[2]<<8)
8959 | ((unsigned int)a[3]);
8960}
8961
8962/*
8963** Load page pgno from the database via the sqlite_dbpage virtual table.
8964** If successful, set (*ppPage) to point to a buffer containing the page
8965** data, (*pnPage) to the size of that buffer in bytes and return
8966** SQLITE_OK. In this case it is the responsibility of the caller to
8967** eventually free the buffer using sqlite3_free().
8968**
8969** Or, if an error occurs, set both (*ppPage) and (*pnPage) to 0 and
8970** return an SQLite error code.
8971*/
8972static int dbdataLoadPage(
8973 DbdataCursor *pCsr, /* Cursor object */
8974 unsigned int pgno, /* Page number of page to load */
8975 u8 **ppPage, /* OUT: pointer to page buffer */
8976 int *pnPage /* OUT: Size of (*ppPage) in bytes */
8977){
8978 int rc2;
8979 int rc = SQLITE_OK;
8980 sqlite3_stmt *pStmt = pCsr->pStmt;
8981
8982 *ppPage = 0;
8983 *pnPage = 0;
8984 sqlite3_bind_int64(pStmt, 2, pgno);
8985 if( SQLITE_ROW==sqlite3_step(pStmt) ){
8986 int nCopy = sqlite3_column_bytes(pStmt, 0);
8987 if( nCopy>0 ){
8988 u8 *pPage;
8989 pPage = (u8*)sqlite3_malloc64(nCopy + DBDATA_PADDING_BYTES);
8990 if( pPage==0 ){
8991 rc = SQLITE_NOMEM;
8992 }else{
8993 const u8 *pCopy = sqlite3_column_blob(pStmt, 0);
8994 memcpy(pPage, pCopy, nCopy);
8995 memset(&pPage[nCopy], 0, DBDATA_PADDING_BYTES);
8996 }
8997 *ppPage = pPage;
8998 *pnPage = nCopy;
8999 }
9000 }
9001 rc2 = sqlite3_reset(pStmt);
9002 if( rc==SQLITE_OK ) rc = rc2;
9003
9004 return rc;
9005}
9006
9007/*
9008** Read a varint. Put the value in *pVal and return the number of bytes.
9009*/
9010static int dbdataGetVarint(const u8 *z, sqlite3_int64 *pVal){
9011 sqlite3_int64 v = 0;
9012 int i;
9013 for(i=0; i<8; i++){
9014 v = (v<<7) + (z[i]&0x7f);
9015 if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
9016 }
9017 v = (v<<8) + (z[i]&0xff);
9018 *pVal = v;
9019 return 9;
9020}
9021
9022/*
9023** Return the number of bytes of space used by an SQLite value of type
9024** eType.
9025*/
9026static int dbdataValueBytes(int eType){
9027 switch( eType ){
9028 case 0: case 8: case 9:
9029 case 10: case 11:
9030 return 0;
9031 case 1:
9032 return 1;
9033 case 2:
9034 return 2;
9035 case 3:
9036 return 3;
9037 case 4:
9038 return 4;
9039 case 5:
9040 return 6;
9041 case 6:
9042 case 7:
9043 return 8;
9044 default:
9045 if( eType>0 ){
9046 return ((eType-12) / 2);
9047 }
9048 return 0;
9049 }
9050}
9051
9052/*
9053** Load a value of type eType from buffer pData and use it to set the
9054** result of context object pCtx.
9055*/
9056static void dbdataValue(
9057 sqlite3_context *pCtx,
9058 int eType,
9059 u8 *pData,
9060 int nData
9061){
9062 if( eType>=0 && dbdataValueBytes(eType)<=nData ){
9063 switch( eType ){
9064 case 0:
9065 case 10:
9066 case 11:
9067 sqlite3_result_null(pCtx);
9068 break;
9069
9070 case 8:
9071 sqlite3_result_int(pCtx, 0);
9072 break;
9073 case 9:
9074 sqlite3_result_int(pCtx, 1);
9075 break;
9076
9077 case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
9078 sqlite3_uint64 v = (signed char)pData[0];
9079 pData++;
9080 switch( eType ){
9081 case 7:
9082 case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
9083 case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2;
9084 case 4: v = (v<<8) + pData[0]; pData++;
9085 case 3: v = (v<<8) + pData[0]; pData++;
9086 case 2: v = (v<<8) + pData[0]; pData++;
9087 }
9088
9089 if( eType==7 ){
9090 double r;
9091 memcpy(&r, &v, sizeof(r));
9092 sqlite3_result_double(pCtx, r);
9093 }else{
9094 sqlite3_result_int64(pCtx, (sqlite3_int64)v);
9095 }
9096 break;
9097 }
9098
9099 default: {
9100 int n = ((eType-12) / 2);
9101 if( eType % 2 ){
9102 sqlite3_result_text(pCtx, (const char*)pData, n, SQLITE_TRANSIENT);
9103 }else{
9104 sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
9105 }
9106 }
9107 }
9108 }
9109}
9110
9111/*
9112** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry.
9113*/
9114static int dbdataNext(sqlite3_vtab_cursor *pCursor){
9115 DbdataCursor *pCsr = (DbdataCursor*)pCursor;
9116 DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
9117
9118 pCsr->iRowid++;
9119 while( 1 ){
9120 int rc;
9121 int iOff = (pCsr->iPgno==1 ? 100 : 0);
9122 int bNextPage = 0;
9123
9124 if( pCsr->aPage==0 ){
9125 while( 1 ){
9126 if( pCsr->bOnePage==0 && pCsr->iPgno>pCsr->szDb ) return SQLITE_OK;
9127 rc = dbdataLoadPage(pCsr, pCsr->iPgno, &pCsr->aPage, &pCsr->nPage);
9128 if( rc!=SQLITE_OK ) return rc;
9129 if( pCsr->aPage ) break;
9130 pCsr->iPgno++;
9131 }
9132 pCsr->iCell = pTab->bPtr ? -2 : 0;
9133 pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]);
9134 }
9135
9136 if( pTab->bPtr ){
9137 if( pCsr->aPage[iOff]!=0x02 && pCsr->aPage[iOff]!=0x05 ){
9138 pCsr->iCell = pCsr->nCell;
9139 }
9140 pCsr->iCell++;
9141 if( pCsr->iCell>=pCsr->nCell ){
9142 sqlite3_free(pCsr->aPage);
9143 pCsr->aPage = 0;
9144 if( pCsr->bOnePage ) return SQLITE_OK;
9145 pCsr->iPgno++;
9146 }else{
9147 return SQLITE_OK;
9148 }
9149 }else{
9150 /* If there is no record loaded, load it now. */
9151 if( pCsr->pRec==0 ){
9152 int bHasRowid = 0;
9153 int nPointer = 0;
9154 sqlite3_int64 nPayload = 0;
9155 sqlite3_int64 nHdr = 0;
9156 int iHdr;
9157 int U, X;
9158 int nLocal;
9159
9160 switch( pCsr->aPage[iOff] ){
9161 case 0x02:
9162 nPointer = 4;
9163 break;
9164 case 0x0a:
9165 break;
9166 case 0x0d:
9167 bHasRowid = 1;
9168 break;
9169 default:
9170 /* This is not a b-tree page with records on it. Continue. */
9171 pCsr->iCell = pCsr->nCell;
9172 break;
9173 }
9174
9175 if( pCsr->iCell>=pCsr->nCell ){
9176 bNextPage = 1;
9177 }else{
9178
9179 iOff += 8 + nPointer + pCsr->iCell*2;
9180 if( iOff>pCsr->nPage ){
9181 bNextPage = 1;
9182 }else{
9183 iOff = get_uint16(&pCsr->aPage[iOff]);
9184 }
9185
9186 /* For an interior node cell, skip past the child-page number */
9187 iOff += nPointer;
9188
9189 /* Load the "byte of payload including overflow" field */
9190 if( bNextPage || iOff>pCsr->nPage ){
9191 bNextPage = 1;
9192 }else{
9193 iOff += dbdataGetVarint(&pCsr->aPage[iOff], &nPayload);
9194 }
9195
9196 /* If this is a leaf intkey cell, load the rowid */
9197 if( bHasRowid && !bNextPage && iOff<pCsr->nPage ){
9198 iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey);
9199 }
9200
9201 /* Figure out how much data to read from the local page */
9202 U = pCsr->nPage;
9203 if( bHasRowid ){
9204 X = U-35;
9205 }else{
9206 X = ((U-12)*64/255)-23;
9207 }
9208 if( nPayload<=X ){
9209 nLocal = nPayload;
9210 }else{
9211 int M, K;
9212 M = ((U-12)*32/255)-23;
9213 K = M+((nPayload-M)%(U-4));
9214 if( K<=X ){
9215 nLocal = K;
9216 }else{
9217 nLocal = M;
9218 }
9219 }
9220
9221 if( bNextPage || nLocal+iOff>pCsr->nPage ){
9222 bNextPage = 1;
9223 }else{
9224
9225 /* Allocate space for payload. And a bit more to catch small buffer
9226 ** overruns caused by attempting to read a varint or similar from
9227 ** near the end of a corrupt record. */
9228 pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES);
9229 if( pCsr->pRec==0 ) return SQLITE_NOMEM;
9230 memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES);
9231 pCsr->nRec = nPayload;
9232
9233 /* Load the nLocal bytes of payload */
9234 memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal);
9235 iOff += nLocal;
9236
9237 /* Load content from overflow pages */
9238 if( nPayload>nLocal ){
9239 sqlite3_int64 nRem = nPayload - nLocal;
9240 unsigned int pgnoOvfl = get_uint32(&pCsr->aPage[iOff]);
9241 while( nRem>0 ){
9242 u8 *aOvfl = 0;
9243 int nOvfl = 0;
9244 int nCopy;
9245 rc = dbdataLoadPage(pCsr, pgnoOvfl, &aOvfl, &nOvfl);
9246 assert( rc!=SQLITE_OK || aOvfl==0 || nOvfl==pCsr->nPage );
9247 if( rc!=SQLITE_OK ) return rc;
9248 if( aOvfl==0 ) break;
9249
9250 nCopy = U-4;
9251 if( nCopy>nRem ) nCopy = nRem;
9252 memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy);
9253 nRem -= nCopy;
9254
9255 pgnoOvfl = get_uint32(aOvfl);
9256 sqlite3_free(aOvfl);
9257 }
9258 }
9259
9260 iHdr = dbdataGetVarint(pCsr->pRec, &nHdr);
9261 pCsr->nHdr = nHdr;
9262 pCsr->pHdrPtr = &pCsr->pRec[iHdr];
9263 pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
9264 pCsr->iField = (bHasRowid ? -1 : 0);
9265 }
9266 }
9267 }else{
9268 pCsr->iField++;
9269 if( pCsr->iField>0 ){
9270 sqlite3_int64 iType;
9271 if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){
9272 bNextPage = 1;
9273 }else{
9274 pCsr->pHdrPtr += dbdataGetVarint(pCsr->pHdrPtr, &iType);
9275 pCsr->pPtr += dbdataValueBytes(iType);
9276 }
9277 }
9278 }
9279
9280 if( bNextPage ){
9281 sqlite3_free(pCsr->aPage);
9282 sqlite3_free(pCsr->pRec);
9283 pCsr->aPage = 0;
9284 pCsr->pRec = 0;
9285 if( pCsr->bOnePage ) return SQLITE_OK;
9286 pCsr->iPgno++;
9287 }else{
9288 if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){
9289 return SQLITE_OK;
9290 }
9291
9292 /* Advance to the next cell. The next iteration of the loop will load
9293 ** the record and so on. */
9294 sqlite3_free(pCsr->pRec);
9295 pCsr->pRec = 0;
9296 pCsr->iCell++;
9297 }
9298 }
9299 }
9300
9301 assert( !"can't get here" );
9302 return SQLITE_OK;
9303}
9304
9305/*
9306** Return true if the cursor is at EOF.
9307*/
9308static int dbdataEof(sqlite3_vtab_cursor *pCursor){
9309 DbdataCursor *pCsr = (DbdataCursor*)pCursor;
9310 return pCsr->aPage==0;
9311}
9312
9313/*
9314** Determine the size in pages of database zSchema (where zSchema is
9315** "main", "temp" or the name of an attached database) and set
9316** pCsr->szDb accordingly. If successful, return SQLITE_OK. Otherwise,
9317** an SQLite error code.
9318*/
9319static int dbdataDbsize(DbdataCursor *pCsr, const char *zSchema){
9320 DbdataTable *pTab = (DbdataTable*)pCsr->base.pVtab;
9321 char *zSql = 0;
9322 int rc, rc2;
9323 sqlite3_stmt *pStmt = 0;
9324
9325 zSql = sqlite3_mprintf("PRAGMA %Q.page_count", zSchema);
9326 if( zSql==0 ) return SQLITE_NOMEM;
9327 rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pStmt, 0);
9328 sqlite3_free(zSql);
9329 if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
9330 pCsr->szDb = sqlite3_column_int(pStmt, 0);
9331 }
9332 rc2 = sqlite3_finalize(pStmt);
9333 if( rc==SQLITE_OK ) rc = rc2;
9334 return rc;
9335}
9336
9337/*
9338** xFilter method for sqlite_dbdata and sqlite_dbptr.
9339*/
9340static int dbdataFilter(
9341 sqlite3_vtab_cursor *pCursor,
9342 int idxNum, const char *idxStr,
9343 int argc, sqlite3_value **argv
9344){
9345 DbdataCursor *pCsr = (DbdataCursor*)pCursor;
9346 DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
9347 int rc = SQLITE_OK;
9348 const char *zSchema = "main";
9349
9350 dbdataResetCursor(pCsr);
9351 assert( pCsr->iPgno==1 );
9352 if( idxNum & 0x01 ){
9353 zSchema = (const char*)sqlite3_value_text(argv[0]);
9354 }
9355 if( idxNum & 0x02 ){
9356 pCsr->iPgno = sqlite3_value_int(argv[(idxNum & 0x01)]);
9357 pCsr->bOnePage = 1;
9358 }else{
9359 pCsr->nPage = dbdataDbsize(pCsr, zSchema);
9360 rc = dbdataDbsize(pCsr, zSchema);
9361 }
9362
9363 if( rc==SQLITE_OK ){
9364 if( pTab->pStmt ){
9365 pCsr->pStmt = pTab->pStmt;
9366 pTab->pStmt = 0;
9367 }else{
9368 rc = sqlite3_prepare_v2(pTab->db,
9369 "SELECT data FROM sqlite_dbpage(?) WHERE pgno=?", -1,
9370 &pCsr->pStmt, 0
9371 );
9372 }
9373 }
9374 if( rc==SQLITE_OK ){
9375 rc = sqlite3_bind_text(pCsr->pStmt, 1, zSchema, -1, SQLITE_TRANSIENT);
9376 }else{
9377 pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
9378 }
9379 if( rc==SQLITE_OK ){
9380 rc = dbdataNext(pCursor);
9381 }
9382 return rc;
9383}
9384
9385/*
9386** Return a column for the sqlite_dbdata or sqlite_dbptr table.
9387*/
9388static int dbdataColumn(
9389 sqlite3_vtab_cursor *pCursor,
9390 sqlite3_context *ctx,
9391 int i
9392){
9393 DbdataCursor *pCsr = (DbdataCursor*)pCursor;
9394 DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
9395 if( pTab->bPtr ){
9396 switch( i ){
9397 case DBPTR_COLUMN_PGNO:
9398 sqlite3_result_int64(ctx, pCsr->iPgno);
9399 break;
9400 case DBPTR_COLUMN_CHILD: {
9401 int iOff = pCsr->iPgno==1 ? 100 : 0;
9402 if( pCsr->iCell<0 ){
9403 iOff += 8;
9404 }else{
9405 iOff += 12 + pCsr->iCell*2;
9406 if( iOff>pCsr->nPage ) return SQLITE_OK;
9407 iOff = get_uint16(&pCsr->aPage[iOff]);
9408 }
9409 if( iOff<=pCsr->nPage ){
9410 sqlite3_result_int64(ctx, get_uint32(&pCsr->aPage[iOff]));
9411 }
9412 break;
9413 }
9414 }
9415 }else{
9416 switch( i ){
9417 case DBDATA_COLUMN_PGNO:
9418 sqlite3_result_int64(ctx, pCsr->iPgno);
9419 break;
9420 case DBDATA_COLUMN_CELL:
9421 sqlite3_result_int(ctx, pCsr->iCell);
9422 break;
9423 case DBDATA_COLUMN_FIELD:
9424 sqlite3_result_int(ctx, pCsr->iField);
9425 break;
9426 case DBDATA_COLUMN_VALUE: {
9427 if( pCsr->iField<0 ){
9428 sqlite3_result_int64(ctx, pCsr->iIntkey);
9429 }else{
9430 sqlite3_int64 iType;
9431 dbdataGetVarint(pCsr->pHdrPtr, &iType);
9432 dbdataValue(
9433 ctx, iType, pCsr->pPtr, &pCsr->pRec[pCsr->nRec] - pCsr->pPtr
9434 );
9435 }
9436 break;
9437 }
9438 }
9439 }
9440 return SQLITE_OK;
9441}
9442
9443/*
9444** Return the rowid for an sqlite_dbdata or sqlite_dptr table.
9445*/
9446static int dbdataRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
9447 DbdataCursor *pCsr = (DbdataCursor*)pCursor;
9448 *pRowid = pCsr->iRowid;
9449 return SQLITE_OK;
9450}
9451
9452
9453/*
9454** Invoke this routine to register the "sqlite_dbdata" virtual table module
9455*/
9456static int sqlite3DbdataRegister(sqlite3 *db){
9457 static sqlite3_module dbdata_module = {
9458 0, /* iVersion */
9459 0, /* xCreate */
9460 dbdataConnect, /* xConnect */
9461 dbdataBestIndex, /* xBestIndex */
9462 dbdataDisconnect, /* xDisconnect */
9463 0, /* xDestroy */
9464 dbdataOpen, /* xOpen - open a cursor */
9465 dbdataClose, /* xClose - close a cursor */
9466 dbdataFilter, /* xFilter - configure scan constraints */
9467 dbdataNext, /* xNext - advance a cursor */
9468 dbdataEof, /* xEof - check for end of scan */
9469 dbdataColumn, /* xColumn - read data */
9470 dbdataRowid, /* xRowid - read data */
9471 0, /* xUpdate */
9472 0, /* xBegin */
9473 0, /* xSync */
9474 0, /* xCommit */
9475 0, /* xRollback */
9476 0, /* xFindMethod */
9477 0, /* xRename */
9478 0, /* xSavepoint */
9479 0, /* xRelease */
9480 0, /* xRollbackTo */
9481 0 /* xShadowName */
9482 };
9483
9484 int rc = sqlite3_create_module(db, "sqlite_dbdata", &dbdata_module, 0);
9485 if( rc==SQLITE_OK ){
9486 rc = sqlite3_create_module(db, "sqlite_dbptr", &dbdata_module, (void*)1);
9487 }
9488 return rc;
9489}
9490
9491#ifdef _WIN32
9492
9493#endif
9494int sqlite3_dbdata_init(
9495 sqlite3 *db,
9496 char **pzErrMsg,
9497 const sqlite3_api_routines *pApi
9498){
9499 SQLITE_EXTENSION_INIT2(pApi);
9500 return sqlite3DbdataRegister(db);
9501}
9502
9503/************************* End ../ext/misc/dbdata.c ********************/
9504#endif
9505
Alex Naidis60fa6fd2016-07-10 14:13:38 +02009506#if defined(SQLITE_ENABLE_SESSION)
Nick Kralevich3fcd43a2015-04-08 13:13:26 -07009507/*
Alex Naidis60fa6fd2016-07-10 14:13:38 +02009508** State information for a single open session
9509*/
9510typedef struct OpenSession OpenSession;
9511struct OpenSession {
9512 char *zName; /* Symbolic name for this session */
9513 int nFilter; /* Number of xFilter rejection GLOB patterns */
9514 char **azFilter; /* Array of xFilter rejection GLOB patterns */
9515 sqlite3_session *p; /* The open session */
9516};
9517#endif
9518
9519/*
9520** Shell output mode information from before ".explain on",
Nick Kralevich3fcd43a2015-04-08 13:13:26 -07009521** saved so that it can be restored by ".explain off"
9522*/
9523typedef struct SavedModeInfo SavedModeInfo;
9524struct SavedModeInfo {
9525 int valid; /* Is there legit data in here? */
9526 int mode; /* Mode prior to ".explain on" */
9527 int showHeader; /* The ".header" setting prior to ".explain on" */
9528 int colWidth[100]; /* Column widths prior to ".explain on" */
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009529};
9530
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009531typedef struct ExpertInfo ExpertInfo;
9532struct ExpertInfo {
9533 sqlite3expert *pExpert;
9534 int bVerbose;
9535};
9536
mydongistiny63ee58c2019-09-21 18:04:30 -07009537/* A single line in the EQP output */
9538typedef struct EQPGraphRow EQPGraphRow;
9539struct EQPGraphRow {
9540 int iEqpId; /* ID for this row */
9541 int iParentId; /* ID of the parent row */
9542 EQPGraphRow *pNext; /* Next row in sequence */
9543 char zText[1]; /* Text to display for this row */
9544};
9545
9546/* All EQP output is collected into an instance of the following */
9547typedef struct EQPGraph EQPGraph;
9548struct EQPGraph {
9549 EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */
9550 EQPGraphRow *pLast; /* Last element of the pRow list */
9551 char zPrefix[100]; /* Graph prefix */
9552};
9553
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009554/*
Nick Kralevich3fcd43a2015-04-08 13:13:26 -07009555** State information about the database connection is contained in an
9556** instance of the following structure.
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009557*/
Nick Kralevich3fcd43a2015-04-08 13:13:26 -07009558typedef struct ShellState ShellState;
9559struct ShellState {
Vasu Noria4356a02010-01-20 15:10:57 -08009560 sqlite3 *db; /* The database */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009561 u8 autoExplain; /* Automatically turn on .explain mode */
9562 u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
mydongistiny63ee58c2019-09-21 18:04:30 -07009563 u8 autoEQPtest; /* autoEQP is in test mode */
9564 u8 autoEQPtrace; /* autoEQP is in trace mode */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009565 u8 statsOn; /* True to display memory stats before each finalize */
9566 u8 scanstatsOn; /* True to display scan stats before each finalize */
9567 u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
9568 u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
mydongistiny63ee58c2019-09-21 18:04:30 -07009569 u8 nEqpLevel; /* Depth of the EQP output graph */
9570 u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
9571 unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */
Nick Kralevich1c7cea32014-06-06 19:53:11 -07009572 int outCount; /* Revert to stdout when reaching zero */
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009573 int cnt; /* Number of records displayed so far */
mydongistiny63ee58c2019-09-21 18:04:30 -07009574 int lineno; /* Line number of last line read from in */
9575 FILE *in; /* Read commands from this stream */
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009576 FILE *out; /* Write results here */
Nick Kralevich8fecf562014-05-29 16:56:33 -07009577 FILE *traceOut; /* Output for sqlite3_trace() */
Jeff Brown90ed05d2012-01-19 16:35:19 -08009578 int nErr; /* Number of errors seen */
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009579 int mode; /* An output mode setting */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009580 int modePrior; /* Saved mode */
Alex Naidis60fa6fd2016-07-10 14:13:38 +02009581 int cMode; /* temporary output mode for the current query */
9582 int normalMode; /* Output mode before ".explain on" */
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009583 int writableSchema; /* True if PRAGMA writable_schema=ON */
9584 int showHeader; /* True to show column names in List or Column mode */
Alex Naidis08f78cb2016-10-14 15:52:08 +02009585 int nCheck; /* Number of ".check" commands run */
mydongistiny63ee58c2019-09-21 18:04:30 -07009586 unsigned nProgress; /* Number of progress callbacks encountered */
9587 unsigned mxProgress; /* Maximum progress callbacks before failing */
9588 unsigned flgProgress; /* Flags for the progress callback */
Nick Kralevich3fcd43a2015-04-08 13:13:26 -07009589 unsigned shellFlgs; /* Various flags */
mydongistiny63ee58c2019-09-21 18:04:30 -07009590 sqlite3_int64 szMax; /* --maxsize argument to .open */
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009591 char *zDestTable; /* Name of destination table when MODE_Insert */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009592 char *zTempFile; /* Temporary file that might need deleting */
Alex Naidis08f78cb2016-10-14 15:52:08 +02009593 char zTestcase[30]; /* Name of current test case */
Nick Kralevich3fcd43a2015-04-08 13:13:26 -07009594 char colSeparator[20]; /* Column separator character for several modes */
9595 char rowSeparator[20]; /* Row separator character for MODE_Ascii */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009596 char colSepPrior[20]; /* Saved column separator */
9597 char rowSepPrior[20]; /* Saved row separator */
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009598 int colWidth[100]; /* Requested width of each column when in column mode*/
9599 int actualWidth[100]; /* Actual width of each column */
Nick Kralevich3fcd43a2015-04-08 13:13:26 -07009600 char nullValue[20]; /* The text to print when a NULL comes back from
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009601 ** the database */
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009602 char outfile[FILENAME_MAX]; /* Filename for *out */
9603 const char *zDbFilename; /* name of the database file */
Nick Kralevich8fecf562014-05-29 16:56:33 -07009604 char *zFreeOnClose; /* Filename to free when closing */
Jeff Brown90ed05d2012-01-19 16:35:19 -08009605 const char *zVfs; /* Name of VFS to use */
Vasu Noria4356a02010-01-20 15:10:57 -08009606 sqlite3_stmt *pStmt; /* Current statement if any. */
Vasu Noriaae12b82010-03-02 13:00:31 -08009607 FILE *pLog; /* Write log output here */
Nick Kralevich8fecf562014-05-29 16:56:33 -07009608 int *aiIndent; /* Array of indents used in MODE_Explain */
9609 int nIndent; /* Size of array aiIndent[] */
9610 int iIndent; /* Index of current op in aiIndent[] */
mydongistiny63ee58c2019-09-21 18:04:30 -07009611 EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */
Alex Naidis60fa6fd2016-07-10 14:13:38 +02009612#if defined(SQLITE_ENABLE_SESSION)
9613 int nSession; /* Number of active sessions */
9614 OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */
9615#endif
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009616 ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009617};
9618
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009619
9620/* Allowed values for ShellState.autoEQP
9621*/
mydongistiny63ee58c2019-09-21 18:04:30 -07009622#define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */
9623#define AUTOEQP_on 1 /* Automatic EQP is on */
9624#define AUTOEQP_trigger 2 /* On and also show plans for triggers */
9625#define AUTOEQP_full 3 /* Show full EXPLAIN */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009626
9627/* Allowed values for ShellState.openMode
9628*/
mydongistiny63ee58c2019-09-21 18:04:30 -07009629#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
9630#define SHELL_OPEN_NORMAL 1 /* Normal database file */
9631#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
9632#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
9633#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
9634#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
9635#define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */
9636
9637/* Allowed values for ShellState.eTraceType
9638*/
9639#define SHELL_TRACE_PLAIN 0 /* Show input SQL text */
9640#define SHELL_TRACE_EXPANDED 1 /* Show expanded SQL text */
9641#define SHELL_TRACE_NORMALIZED 2 /* Show normalized SQL text */
9642
9643/* Bits in the ShellState.flgProgress variable */
9644#define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */
9645#define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progres
9646 ** callback limit is reached, and for each
9647 ** top-level SQL statement */
9648#define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009649
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009650/*
Nick Kralevich3fcd43a2015-04-08 13:13:26 -07009651** These are the allowed shellFlgs values
9652*/
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009653#define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */
9654#define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */
9655#define SHFLG_Backslash 0x00000004 /* The --backslash option is used */
9656#define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */
9657#define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
Alex Naidisb86c0cf2017-03-31 14:12:35 +02009658#define SHFLG_CountChanges 0x00000020 /* .changes setting */
9659#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
9660
9661/*
9662** Macros for testing and setting shellFlgs
9663*/
9664#define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0)
9665#define ShellSetFlag(P,X) ((P)->shellFlgs|=(X))
9666#define ShellClearFlag(P,X) ((P)->shellFlgs&=(~(X)))
Nick Kralevich3fcd43a2015-04-08 13:13:26 -07009667
9668/*
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009669** These are the allowed modes.
9670*/
9671#define MODE_Line 0 /* One column per line. Blank line between records */
9672#define MODE_Column 1 /* One record per line in neat columns */
9673#define MODE_List 2 /* One record per line with a separator */
9674#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
9675#define MODE_Html 4 /* Generate an XHTML table */
9676#define MODE_Insert 5 /* Generate SQL "insert" statements */
Luca Stefanie7f3e802017-01-02 15:44:22 +01009677#define MODE_Quote 6 /* Quote values as for SQL */
9678#define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */
9679#define MODE_Csv 8 /* Quote strings, numbers are plain */
9680#define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */
9681#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
9682#define MODE_Pretty 11 /* Pretty-print schemas */
mydongistiny63ee58c2019-09-21 18:04:30 -07009683#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009684
9685static const char *modeDescr[] = {
9686 "line",
9687 "column",
9688 "list",
9689 "semi",
9690 "html",
9691 "insert",
Luca Stefanie7f3e802017-01-02 15:44:22 +01009692 "quote",
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009693 "tcl",
9694 "csv",
9695 "explain",
Nick Kralevich3fcd43a2015-04-08 13:13:26 -07009696 "ascii",
Alex Naidis60fa6fd2016-07-10 14:13:38 +02009697 "prettyprint",
mydongistiny63ee58c2019-09-21 18:04:30 -07009698 "eqp"
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009699};
9700
9701/*
Nick Kralevich3fcd43a2015-04-08 13:13:26 -07009702** These are the column/row/line separators used by the various
9703** import/export modes.
9704*/
9705#define SEP_Column "|"
9706#define SEP_Row "\n"
9707#define SEP_Tab "\t"
9708#define SEP_Space " "
9709#define SEP_Comma ","
9710#define SEP_CrLf "\r\n"
9711#define SEP_Unit "\x1F"
9712#define SEP_Record "\x1E"
9713
9714/*
Vasu Noriaae12b82010-03-02 13:00:31 -08009715** A callback for the sqlite3_log() interface.
9716*/
9717static void shellLog(void *pArg, int iErrCode, const char *zMsg){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -07009718 ShellState *p = (ShellState*)pArg;
Vasu Noriaae12b82010-03-02 13:00:31 -08009719 if( p->pLog==0 ) return;
Alex Naidis60fa6fd2016-07-10 14:13:38 +02009720 utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
Vasu Noriaae12b82010-03-02 13:00:31 -08009721 fflush(p->pLog);
9722}
9723
9724/*
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009725** SQL function: shell_putsnl(X)
9726**
9727** Write the text X to the screen (or whatever output is being directed)
9728** adding a newline at the end, and then return X.
9729*/
9730static void shellPutsFunc(
9731 sqlite3_context *pCtx,
9732 int nVal,
9733 sqlite3_value **apVal
9734){
9735 ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
9736 (void)nVal;
9737 utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
9738 sqlite3_result_value(pCtx, apVal[0]);
9739}
9740
9741/*
9742** SQL function: edit(VALUE)
9743** edit(VALUE,EDITOR)
9744**
9745** These steps:
9746**
9747** (1) Write VALUE into a temporary file.
9748** (2) Run program EDITOR on that temporary file.
9749** (3) Read the temporary file back and return its content as the result.
9750** (4) Delete the temporary file
9751**
9752** If the EDITOR argument is omitted, use the value in the VISUAL
9753** environment variable. If still there is no EDITOR, through an error.
9754**
9755** Also throw an error if the EDITOR program returns a non-zero exit code.
9756*/
mydongistiny63ee58c2019-09-21 18:04:30 -07009757#ifndef SQLITE_NOHAVE_SYSTEM
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009758static void editFunc(
9759 sqlite3_context *context,
9760 int argc,
9761 sqlite3_value **argv
9762){
9763 const char *zEditor;
9764 char *zTempFile = 0;
9765 sqlite3 *db;
9766 char *zCmd = 0;
9767 int bBin;
9768 int rc;
mydongistiny63ee58c2019-09-21 18:04:30 -07009769 int hasCRNL = 0;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009770 FILE *f = 0;
9771 sqlite3_int64 sz;
9772 sqlite3_int64 x;
9773 unsigned char *p = 0;
9774
9775 if( argc==2 ){
9776 zEditor = (const char*)sqlite3_value_text(argv[1]);
9777 }else{
9778 zEditor = getenv("VISUAL");
9779 }
9780 if( zEditor==0 ){
9781 sqlite3_result_error(context, "no editor for edit()", -1);
9782 return;
9783 }
9784 if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
9785 sqlite3_result_error(context, "NULL input to edit()", -1);
9786 return;
9787 }
9788 db = sqlite3_context_db_handle(context);
9789 zTempFile = 0;
9790 sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile);
9791 if( zTempFile==0 ){
9792 sqlite3_uint64 r = 0;
9793 sqlite3_randomness(sizeof(r), &r);
9794 zTempFile = sqlite3_mprintf("temp%llx", r);
9795 if( zTempFile==0 ){
9796 sqlite3_result_error_nomem(context);
9797 return;
9798 }
9799 }
9800 bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB;
mydongistiny63ee58c2019-09-21 18:04:30 -07009801 /* When writing the file to be edited, do \n to \r\n conversions on systems
9802 ** that want \r\n line endings */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009803 f = fopen(zTempFile, bBin ? "wb" : "w");
9804 if( f==0 ){
9805 sqlite3_result_error(context, "edit() cannot open temp file", -1);
9806 goto edit_func_end;
9807 }
9808 sz = sqlite3_value_bytes(argv[0]);
9809 if( bBin ){
mydongistiny8320bdc2019-10-06 12:50:35 -07009810 x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009811 }else{
mydongistiny63ee58c2019-09-21 18:04:30 -07009812 const char *z = (const char*)sqlite3_value_text(argv[0]);
9813 /* Remember whether or not the value originally contained \r\n */
9814 if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
mydongistiny8320bdc2019-10-06 12:50:35 -07009815 x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009816 }
9817 fclose(f);
9818 f = 0;
9819 if( x!=sz ){
9820 sqlite3_result_error(context, "edit() could not write the whole file", -1);
9821 goto edit_func_end;
9822 }
9823 zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile);
9824 if( zCmd==0 ){
9825 sqlite3_result_error_nomem(context);
9826 goto edit_func_end;
9827 }
9828 rc = system(zCmd);
9829 sqlite3_free(zCmd);
9830 if( rc ){
9831 sqlite3_result_error(context, "EDITOR returned non-zero", -1);
9832 goto edit_func_end;
9833 }
mydongistiny63ee58c2019-09-21 18:04:30 -07009834 f = fopen(zTempFile, "rb");
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009835 if( f==0 ){
9836 sqlite3_result_error(context,
9837 "edit() cannot reopen temp file after edit", -1);
9838 goto edit_func_end;
9839 }
9840 fseek(f, 0, SEEK_END);
9841 sz = ftell(f);
9842 rewind(f);
mydongistiny8320bdc2019-10-06 12:50:35 -07009843 p = sqlite3_malloc64( sz+1 );
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009844 if( p==0 ){
9845 sqlite3_result_error_nomem(context);
9846 goto edit_func_end;
9847 }
mydongistiny8320bdc2019-10-06 12:50:35 -07009848 x = fread(p, 1, (size_t)sz, f);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009849 fclose(f);
9850 f = 0;
9851 if( x!=sz ){
9852 sqlite3_result_error(context, "could not read back the whole file", -1);
9853 goto edit_func_end;
9854 }
9855 if( bBin ){
mydongistiny63ee58c2019-09-21 18:04:30 -07009856 sqlite3_result_blob64(context, p, sz, sqlite3_free);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009857 }else{
mydongistiny63ee58c2019-09-21 18:04:30 -07009858 sqlite3_int64 i, j;
9859 if( hasCRNL ){
9860 /* If the original contains \r\n then do no conversions back to \n */
9861 j = sz;
9862 }else{
9863 /* If the file did not originally contain \r\n then convert any new
9864 ** \r\n back into \n */
9865 for(i=j=0; i<sz; i++){
9866 if( p[i]=='\r' && p[i+1]=='\n' ) i++;
9867 p[j++] = p[i];
9868 }
9869 sz = j;
9870 p[sz] = 0;
9871 }
9872 sqlite3_result_text64(context, (const char*)p, sz,
9873 sqlite3_free, SQLITE_UTF8);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009874 }
9875 p = 0;
9876
9877edit_func_end:
9878 if( f ) fclose(f);
9879 unlink(zTempFile);
9880 sqlite3_free(zTempFile);
9881 sqlite3_free(p);
9882}
mydongistiny63ee58c2019-09-21 18:04:30 -07009883#endif /* SQLITE_NOHAVE_SYSTEM */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -08009884
9885/*
9886** Save or restore the current output mode
9887*/
9888static void outputModePush(ShellState *p){
9889 p->modePrior = p->mode;
9890 memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));
9891 memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));
9892}
9893static void outputModePop(ShellState *p){
9894 p->mode = p->modePrior;
9895 memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
9896 memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
9897}
9898
9899/*
Vasu Noria4356a02010-01-20 15:10:57 -08009900** Output the given string as a hex-encoded blob (eg. X'1234' )
9901*/
9902static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
9903 int i;
9904 char *zBlob = (char *)pBlob;
Alex Naidis60fa6fd2016-07-10 14:13:38 +02009905 raw_printf(out,"X'");
9906 for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); }
9907 raw_printf(out,"'");
Vasu Noria4356a02010-01-20 15:10:57 -08009908}
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009909
9910/*
Alex Naidisb94ea7b2017-05-24 19:25:14 +02009911** Find a string that is not found anywhere in z[]. Return a pointer
9912** to that string.
9913**
9914** Try to use zA and zB first. If both of those are already found in z[]
9915** then make up some string and store it in the buffer zBuf.
9916*/
9917static const char *unused_string(
9918 const char *z, /* Result must not appear anywhere in z */
9919 const char *zA, const char *zB, /* Try these first */
9920 char *zBuf /* Space to store a generated string */
9921){
9922 unsigned i = 0;
9923 if( strstr(z, zA)==0 ) return zA;
9924 if( strstr(z, zB)==0 ) return zB;
9925 do{
9926 sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
9927 }while( strstr(z,zBuf)!=0 );
9928 return zBuf;
9929}
9930
9931/*
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009932** Output the given string as a quoted string using SQL quoting conventions.
Alex Naidisb86c0cf2017-03-31 14:12:35 +02009933**
Alex Naidisb94ea7b2017-05-24 19:25:14 +02009934** See also: output_quoted_escaped_string()
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009935*/
9936static void output_quoted_string(FILE *out, const char *z){
9937 int i;
Alex Naidisb86c0cf2017-03-31 14:12:35 +02009938 char c;
Alex Naidis60fa6fd2016-07-10 14:13:38 +02009939 setBinaryMode(out, 1);
Alex Naidisb94ea7b2017-05-24 19:25:14 +02009940 for(i=0; (c = z[i])!=0 && c!='\''; i++){}
9941 if( c==0 ){
9942 utf8_printf(out,"'%s'",z);
9943 }else{
9944 raw_printf(out, "'");
9945 while( *z ){
9946 for(i=0; (c = z[i])!=0 && c!='\''; i++){}
9947 if( c=='\'' ) i++;
9948 if( i ){
9949 utf8_printf(out, "%.*s", i, z);
9950 z += i;
9951 }
9952 if( c=='\'' ){
9953 raw_printf(out, "'");
9954 continue;
9955 }
9956 if( c==0 ){
9957 break;
9958 }
9959 z++;
9960 }
9961 raw_printf(out, "'");
9962 }
9963 setTextMode(out, 1);
9964}
9965
9966/*
9967** Output the given string as a quoted string using SQL quoting conventions.
9968** Additionallly , escape the "\n" and "\r" characters so that they do not
9969** get corrupted by end-of-line translation facilities in some operating
9970** systems.
9971**
9972** This is like output_quoted_string() but with the addition of the \r\n
9973** escape mechanism.
9974*/
9975static void output_quoted_escaped_string(FILE *out, const char *z){
9976 int i;
9977 char c;
9978 setBinaryMode(out, 1);
Alex Naidisb86c0cf2017-03-31 14:12:35 +02009979 for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
9980 if( c==0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +02009981 utf8_printf(out,"'%s'",z);
The Android Open Source Project7790ef52009-03-03 19:30:40 -08009982 }else{
Alex Naidisb94ea7b2017-05-24 19:25:14 +02009983 const char *zNL = 0;
9984 const char *zCR = 0;
9985 int nNL = 0;
9986 int nCR = 0;
9987 char zBuf1[20], zBuf2[20];
9988 for(i=0; z[i]; i++){
9989 if( z[i]=='\n' ) nNL++;
9990 if( z[i]=='\r' ) nCR++;
9991 }
9992 if( nNL ){
9993 raw_printf(out, "replace(");
9994 zNL = unused_string(z, "\\n", "\\012", zBuf1);
9995 }
9996 if( nCR ){
9997 raw_printf(out, "replace(");
9998 zCR = unused_string(z, "\\r", "\\015", zBuf2);
9999 }
10000 raw_printf(out, "'");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010001 while( *z ){
Alex Naidisb86c0cf2017-03-31 14:12:35 +020010002 for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
10003 if( c=='\'' ) i++;
10004 if( i ){
Alex Naidisb86c0cf2017-03-31 14:12:35 +020010005 utf8_printf(out, "%.*s", i, z);
10006 z += i;
Alex Naidisb86c0cf2017-03-31 14:12:35 +020010007 }
10008 if( c=='\'' ){
10009 raw_printf(out, "'");
10010 continue;
10011 }
Alex Naidisb86c0cf2017-03-31 14:12:35 +020010012 if( c==0 ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010013 break;
10014 }
Alex Naidisb94ea7b2017-05-24 19:25:14 +020010015 z++;
10016 if( c=='\n' ){
10017 raw_printf(out, "%s", zNL);
10018 continue;
Alex Naidisb86c0cf2017-03-31 14:12:35 +020010019 }
Alex Naidisb94ea7b2017-05-24 19:25:14 +020010020 raw_printf(out, "%s", zCR);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010021 }
Alex Naidisb94ea7b2017-05-24 19:25:14 +020010022 raw_printf(out, "'");
10023 if( nCR ){
10024 raw_printf(out, ",'%s',char(13))", zCR);
10025 }
10026 if( nNL ){
10027 raw_printf(out, ",'%s',char(10))", zNL);
10028 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010029 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010030 setTextMode(out, 1);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010031}
10032
10033/*
10034** Output the given string as a quoted according to C or TCL quoting rules.
10035*/
10036static void output_c_string(FILE *out, const char *z){
10037 unsigned int c;
10038 fputc('"', out);
10039 while( (c = *(z++))!=0 ){
10040 if( c=='\\' ){
10041 fputc(c, out);
10042 fputc(c, out);
Nick Kralevich8fecf562014-05-29 16:56:33 -070010043 }else if( c=='"' ){
10044 fputc('\\', out);
10045 fputc('"', out);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010046 }else if( c=='\t' ){
10047 fputc('\\', out);
10048 fputc('t', out);
10049 }else if( c=='\n' ){
10050 fputc('\\', out);
10051 fputc('n', out);
10052 }else if( c=='\r' ){
10053 fputc('\\', out);
10054 fputc('r', out);
Nick Kralevich8fecf562014-05-29 16:56:33 -070010055 }else if( !isprint(c&0xff) ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010056 raw_printf(out, "\\%03o", c&0xff);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010057 }else{
10058 fputc(c, out);
10059 }
10060 }
10061 fputc('"', out);
10062}
10063
10064/*
10065** Output the given string with characters that are special to
10066** HTML escaped.
10067*/
10068static void output_html_string(FILE *out, const char *z){
10069 int i;
Nick Kralevich8fecf562014-05-29 16:56:33 -070010070 if( z==0 ) z = "";
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010071 while( *z ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010072 for(i=0; z[i]
10073 && z[i]!='<'
10074 && z[i]!='&'
10075 && z[i]!='>'
10076 && z[i]!='\"'
Vasu Noria4356a02010-01-20 15:10:57 -080010077 && z[i]!='\'';
10078 i++){}
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010079 if( i>0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010080 utf8_printf(out,"%.*s",i,z);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010081 }
10082 if( z[i]=='<' ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010083 raw_printf(out,"&lt;");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010084 }else if( z[i]=='&' ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010085 raw_printf(out,"&amp;");
Vasu Noria4356a02010-01-20 15:10:57 -080010086 }else if( z[i]=='>' ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010087 raw_printf(out,"&gt;");
Vasu Noria4356a02010-01-20 15:10:57 -080010088 }else if( z[i]=='\"' ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010089 raw_printf(out,"&quot;");
Vasu Noria4356a02010-01-20 15:10:57 -080010090 }else if( z[i]=='\'' ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010091 raw_printf(out,"&#39;");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010092 }else{
10093 break;
10094 }
10095 z += i + 1;
10096 }
10097}
10098
10099/*
10100** If a field contains any character identified by a 1 in the following
10101** array, then the string must be quoted for CSV.
10102*/
10103static const char needCsvQuote[] = {
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010104 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
10105 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
10106 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
10107 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10108 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10111 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
10112 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
10113 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
10114 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
10115 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
10116 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
10117 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
10118 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
10119 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010120};
10121
10122/*
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010123** Output a single term of CSV. Actually, p->colSeparator is used for
10124** the separator, which may or may not be a comma. p->nullValue is
Jeff Brown9bee60b2014-08-20 16:41:25 -070010125** the null value. Strings are quoted if necessary. The separator
10126** is only issued if bSep is true.
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010127*/
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010128static void output_csv(ShellState *p, const char *z, int bSep){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010129 FILE *out = p->out;
10130 if( z==0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010131 utf8_printf(out,"%s",p->nullValue);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010132 }else{
10133 int i;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010134 int nSep = strlen30(p->colSeparator);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010135 for(i=0; z[i]; i++){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010136 if( needCsvQuote[((unsigned char*)z)[i]]
10137 || (z[i]==p->colSeparator[0] &&
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010138 (nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010139 i = 0;
10140 break;
10141 }
10142 }
10143 if( i==0 ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080010144 char *zQuoted = sqlite3_mprintf("\"%w\"", z);
10145 utf8_printf(out, "%s", zQuoted);
10146 sqlite3_free(zQuoted);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010147 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010148 utf8_printf(out, "%s", z);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010149 }
10150 }
10151 if( bSep ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010152 utf8_printf(p->out, "%s", p->colSeparator);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010153 }
10154}
10155
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010156/*
10157** This routine runs when the user presses Ctrl-C
10158*/
10159static void interrupt_handler(int NotUsed){
Vasu Noria4356a02010-01-20 15:10:57 -080010160 UNUSED_PARAMETER(NotUsed);
Nick Kralevich1c7cea32014-06-06 19:53:11 -070010161 seenInterrupt++;
10162 if( seenInterrupt>2 ) exit(1);
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070010163 if( globalDb ) sqlite3_interrupt(globalDb);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010164}
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080010165
10166#if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
10167/*
10168** This routine runs for console events (e.g. Ctrl-C) on Win32
10169*/
10170static BOOL WINAPI ConsoleCtrlHandler(
10171 DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */
10172){
10173 if( dwCtrlType==CTRL_C_EVENT ){
10174 interrupt_handler(0);
10175 return TRUE;
10176 }
10177 return FALSE;
10178}
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010179#endif
10180
Alex Naidis08f78cb2016-10-14 15:52:08 +020010181#ifndef SQLITE_OMIT_AUTHORIZATION
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010182/*
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010183** When the ".auth ON" is set, the following authorizer callback is
10184** invoked. It always returns SQLITE_OK.
10185*/
10186static int shellAuth(
10187 void *pClientData,
10188 int op,
10189 const char *zA1,
10190 const char *zA2,
10191 const char *zA3,
10192 const char *zA4
10193){
10194 ShellState *p = (ShellState*)pClientData;
10195 static const char *azAction[] = { 0,
10196 "CREATE_INDEX", "CREATE_TABLE", "CREATE_TEMP_INDEX",
10197 "CREATE_TEMP_TABLE", "CREATE_TEMP_TRIGGER", "CREATE_TEMP_VIEW",
10198 "CREATE_TRIGGER", "CREATE_VIEW", "DELETE",
10199 "DROP_INDEX", "DROP_TABLE", "DROP_TEMP_INDEX",
10200 "DROP_TEMP_TABLE", "DROP_TEMP_TRIGGER", "DROP_TEMP_VIEW",
10201 "DROP_TRIGGER", "DROP_VIEW", "INSERT",
10202 "PRAGMA", "READ", "SELECT",
10203 "TRANSACTION", "UPDATE", "ATTACH",
10204 "DETACH", "ALTER_TABLE", "REINDEX",
10205 "ANALYZE", "CREATE_VTABLE", "DROP_VTABLE",
10206 "FUNCTION", "SAVEPOINT", "RECURSIVE"
10207 };
10208 int i;
10209 const char *az[4];
10210 az[0] = zA1;
10211 az[1] = zA2;
10212 az[2] = zA3;
10213 az[3] = zA4;
Alex Naidis08f78cb2016-10-14 15:52:08 +020010214 utf8_printf(p->out, "authorizer: %s", azAction[op]);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010215 for(i=0; i<4; i++){
10216 raw_printf(p->out, " ");
10217 if( az[i] ){
10218 output_c_string(p->out, az[i]);
10219 }else{
10220 raw_printf(p->out, "NULL");
10221 }
10222 }
10223 raw_printf(p->out, "\n");
10224 return SQLITE_OK;
10225}
Alex Naidis08f78cb2016-10-14 15:52:08 +020010226#endif
10227
Luca Stefanie7f3e802017-01-02 15:44:22 +010010228/*
10229** Print a schema statement. Part of MODE_Semi and MODE_Pretty output.
10230**
10231** This routine converts some CREATE TABLE statements for shadow tables
10232** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
10233*/
10234static void printSchemaLine(FILE *out, const char *z, const char *zTail){
mydongistiny63ee58c2019-09-21 18:04:30 -070010235 if( z==0 ) return;
10236 if( zTail==0 ) return;
Luca Stefanie7f3e802017-01-02 15:44:22 +010010237 if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
10238 utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
10239 }else{
10240 utf8_printf(out, "%s%s", z, zTail);
10241 }
10242}
10243static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
10244 char c = z[n];
10245 z[n] = 0;
10246 printSchemaLine(out, z, zTail);
10247 z[n] = c;
10248}
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010249
10250/*
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080010251** Return true if string z[] has nothing but whitespace and comments to the
10252** end of the first line.
10253*/
10254static int wsToEol(const char *z){
10255 int i;
10256 for(i=0; z[i]; i++){
10257 if( z[i]=='\n' ) return 1;
10258 if( IsSpace(z[i]) ) continue;
10259 if( z[i]=='-' && z[i+1]=='-' ) return 1;
10260 return 0;
10261 }
10262 return 1;
10263}
mydongistiny63ee58c2019-09-21 18:04:30 -070010264
10265/*
10266** Add a new entry to the EXPLAIN QUERY PLAN data
10267*/
10268static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
10269 EQPGraphRow *pNew;
10270 int nText = strlen30(zText);
10271 if( p->autoEQPtest ){
10272 utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
10273 }
10274 pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
10275 if( pNew==0 ) shell_out_of_memory();
10276 pNew->iEqpId = iEqpId;
10277 pNew->iParentId = p2;
10278 memcpy(pNew->zText, zText, nText+1);
10279 pNew->pNext = 0;
10280 if( p->sGraph.pLast ){
10281 p->sGraph.pLast->pNext = pNew;
10282 }else{
10283 p->sGraph.pRow = pNew;
10284 }
10285 p->sGraph.pLast = pNew;
10286}
10287
10288/*
10289** Free and reset the EXPLAIN QUERY PLAN data that has been collected
10290** in p->sGraph.
10291*/
10292static void eqp_reset(ShellState *p){
10293 EQPGraphRow *pRow, *pNext;
10294 for(pRow = p->sGraph.pRow; pRow; pRow = pNext){
10295 pNext = pRow->pNext;
10296 sqlite3_free(pRow);
10297 }
10298 memset(&p->sGraph, 0, sizeof(p->sGraph));
10299}
10300
10301/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after
10302** pOld, or return the first such line if pOld is NULL
10303*/
10304static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){
10305 EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow;
10306 while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext;
10307 return pRow;
10308}
10309
10310/* Render a single level of the graph that has iEqpId as its parent. Called
10311** recursively to render sublevels.
10312*/
10313static void eqp_render_level(ShellState *p, int iEqpId){
10314 EQPGraphRow *pRow, *pNext;
10315 int n = strlen30(p->sGraph.zPrefix);
10316 char *z;
10317 for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
10318 pNext = eqp_next_row(p, iEqpId, pRow);
10319 z = pRow->zText;
mydongistiny8320bdc2019-10-06 12:50:35 -070010320 utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
10321 pNext ? "|--" : "`--", z);
mydongistiny63ee58c2019-09-21 18:04:30 -070010322 if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){
10323 memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4);
10324 eqp_render_level(p, pRow->iEqpId);
10325 p->sGraph.zPrefix[n] = 0;
10326 }
10327 }
10328}
10329
10330/*
10331** Display and reset the EXPLAIN QUERY PLAN data
10332*/
10333static void eqp_render(ShellState *p){
10334 EQPGraphRow *pRow = p->sGraph.pRow;
10335 if( pRow ){
10336 if( pRow->zText[0]=='-' ){
10337 if( pRow->pNext==0 ){
10338 eqp_reset(p);
10339 return;
10340 }
10341 utf8_printf(p->out, "%s\n", pRow->zText+3);
10342 p->sGraph.pRow = pRow->pNext;
10343 sqlite3_free(pRow);
10344 }else{
10345 utf8_printf(p->out, "QUERY PLAN\n");
10346 }
10347 p->sGraph.zPrefix[0] = 0;
10348 eqp_render_level(p, 0);
10349 eqp_reset(p);
10350 }
10351}
10352
10353#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
10354/*
10355** Progress handler callback.
10356*/
10357static int progress_handler(void *pClientData) {
10358 ShellState *p = (ShellState*)pClientData;
10359 p->nProgress++;
10360 if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
10361 raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
10362 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
10363 if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
10364 return 1;
10365 }
10366 if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
10367 raw_printf(p->out, "Progress %u\n", p->nProgress);
10368 }
10369 return 0;
10370}
10371#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080010372
10373/*
Vasu Noria4356a02010-01-20 15:10:57 -080010374** This is the callback routine that the shell
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010375** invokes for each row of a query result.
10376*/
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010377static int shell_callback(
10378 void *pArg,
10379 int nArg, /* Number of result columns */
10380 char **azArg, /* Text of each result column */
10381 char **azCol, /* Column names */
10382 int *aiType /* Column types */
10383){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010384 int i;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010385 ShellState *p = (ShellState*)pArg;
Vasu Noria4356a02010-01-20 15:10:57 -080010386
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080010387 if( azArg==0 ) return 0;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010388 switch( p->cMode ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010389 case MODE_Line: {
10390 int w = 5;
10391 if( azArg==0 ) break;
10392 for(i=0; i<nArg; i++){
Vasu Noria4356a02010-01-20 15:10:57 -080010393 int len = strlen30(azCol[i] ? azCol[i] : "");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010394 if( len>w ) w = len;
10395 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010396 if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010397 for(i=0; i<nArg; i++){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010398 utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010399 azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010400 }
10401 break;
10402 }
10403 case MODE_Explain:
10404 case MODE_Column: {
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010405 static const int aExplainWidths[] = {4, 13, 4, 4, 4, 13, 2, 13};
10406 const int *colWidth;
10407 int showHdr;
10408 char *rowSep;
10409 if( p->cMode==MODE_Column ){
10410 colWidth = p->colWidth;
10411 showHdr = p->showHeader;
10412 rowSep = p->rowSeparator;
10413 }else{
10414 colWidth = aExplainWidths;
10415 showHdr = 1;
10416 rowSep = SEP_Row;
10417 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010418 if( p->cnt++==0 ){
10419 for(i=0; i<nArg; i++){
10420 int w, n;
10421 if( i<ArraySize(p->colWidth) ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010422 w = colWidth[i];
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010423 }else{
10424 w = 0;
10425 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070010426 if( w==0 ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080010427 w = strlenChar(azCol[i] ? azCol[i] : "");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010428 if( w<10 ) w = 10;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080010429 n = strlenChar(azArg && azArg[i] ? azArg[i] : p->nullValue);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010430 if( w<n ) w = n;
10431 }
10432 if( i<ArraySize(p->actualWidth) ){
10433 p->actualWidth[i] = w;
10434 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010435 if( showHdr ){
Alex Naidisb94ea7b2017-05-24 19:25:14 +020010436 utf8_width_print(p->out, w, azCol[i]);
10437 utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " ");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010438 }
10439 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010440 if( showHdr ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010441 for(i=0; i<nArg; i++){
10442 int w;
10443 if( i<ArraySize(p->actualWidth) ){
10444 w = p->actualWidth[i];
Nick Kralevich8fecf562014-05-29 16:56:33 -070010445 if( w<0 ) w = -w;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010446 }else{
10447 w = 10;
10448 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010449 utf8_printf(p->out,"%-*.*s%s",w,w,
10450 "----------------------------------------------------------"
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010451 "----------------------------------------------------------",
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010452 i==nArg-1 ? rowSep : " ");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010453 }
10454 }
10455 }
10456 if( azArg==0 ) break;
10457 for(i=0; i<nArg; i++){
10458 int w;
10459 if( i<ArraySize(p->actualWidth) ){
10460 w = p->actualWidth[i];
10461 }else{
10462 w = 10;
10463 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080010464 if( p->cMode==MODE_Explain && azArg[i] && strlenChar(azArg[i])>w ){
10465 w = strlenChar(azArg[i]);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010466 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070010467 if( i==1 && p->aiIndent && p->pStmt ){
10468 if( p->iIndent<p->nIndent ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010469 utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
Nick Kralevich8fecf562014-05-29 16:56:33 -070010470 }
10471 p->iIndent++;
10472 }
Alex Naidisb94ea7b2017-05-24 19:25:14 +020010473 utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
10474 utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " ");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010475 }
10476 break;
10477 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010478 case MODE_Semi: { /* .schema and .fullschema output */
Luca Stefanie7f3e802017-01-02 15:44:22 +010010479 printSchemaLine(p->out, azArg[0], ";\n");
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010480 break;
10481 }
10482 case MODE_Pretty: { /* .schema and .fullschema with --indent */
10483 char *z;
10484 int j;
10485 int nParen = 0;
10486 char cEnd = 0;
10487 char c;
10488 int nLine = 0;
10489 assert( nArg==1 );
10490 if( azArg[0]==0 ) break;
10491 if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
10492 || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
10493 ){
10494 utf8_printf(p->out, "%s;\n", azArg[0]);
10495 break;
10496 }
10497 z = sqlite3_mprintf("%s", azArg[0]);
10498 j = 0;
10499 for(i=0; IsSpace(z[i]); i++){}
10500 for(; (c = z[i])!=0; i++){
10501 if( IsSpace(c) ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080010502 if( z[j-1]=='\r' ) z[j-1] = '\n';
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010503 if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
10504 }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
10505 j--;
10506 }
10507 z[j++] = c;
10508 }
10509 while( j>0 && IsSpace(z[j-1]) ){ j--; }
10510 z[j] = 0;
10511 if( strlen30(z)>=79 ){
mydongistiny8320bdc2019-10-06 12:50:35 -070010512 for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010513 if( c==cEnd ){
10514 cEnd = 0;
10515 }else if( c=='"' || c=='\'' || c=='`' ){
10516 cEnd = c;
10517 }else if( c=='[' ){
10518 cEnd = ']';
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080010519 }else if( c=='-' && z[i+1]=='-' ){
10520 cEnd = '\n';
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010521 }else if( c=='(' ){
10522 nParen++;
10523 }else if( c==')' ){
10524 nParen--;
10525 if( nLine>0 && nParen==0 && j>0 ){
Luca Stefanie7f3e802017-01-02 15:44:22 +010010526 printSchemaLineN(p->out, z, j, "\n");
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010527 j = 0;
10528 }
10529 }
10530 z[j++] = c;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080010531 if( nParen==1 && cEnd==0
10532 && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
10533 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010534 if( c=='\n' ) j--;
Luca Stefanie7f3e802017-01-02 15:44:22 +010010535 printSchemaLineN(p->out, z, j, "\n ");
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010536 j = 0;
10537 nLine++;
10538 while( IsSpace(z[i+1]) ){ i++; }
10539 }
10540 }
10541 z[j] = 0;
10542 }
Luca Stefanie7f3e802017-01-02 15:44:22 +010010543 printSchemaLine(p->out, z, ";\n");
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010544 sqlite3_free(z);
10545 break;
10546 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010547 case MODE_List: {
10548 if( p->cnt++==0 && p->showHeader ){
10549 for(i=0; i<nArg; i++){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010550 utf8_printf(p->out,"%s%s",azCol[i],
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010551 i==nArg-1 ? p->rowSeparator : p->colSeparator);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010552 }
10553 }
10554 if( azArg==0 ) break;
10555 for(i=0; i<nArg; i++){
10556 char *z = azArg[i];
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010557 if( z==0 ) z = p->nullValue;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010558 utf8_printf(p->out, "%s", z);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010559 if( i<nArg-1 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010560 utf8_printf(p->out, "%s", p->colSeparator);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010561 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010562 utf8_printf(p->out, "%s", p->rowSeparator);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010563 }
10564 }
10565 break;
10566 }
10567 case MODE_Html: {
10568 if( p->cnt++==0 && p->showHeader ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010569 raw_printf(p->out,"<TR>");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010570 for(i=0; i<nArg; i++){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010571 raw_printf(p->out,"<TH>");
Vasu Noria4356a02010-01-20 15:10:57 -080010572 output_html_string(p->out, azCol[i]);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010573 raw_printf(p->out,"</TH>\n");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010574 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010575 raw_printf(p->out,"</TR>\n");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010576 }
10577 if( azArg==0 ) break;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010578 raw_printf(p->out,"<TR>");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010579 for(i=0; i<nArg; i++){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010580 raw_printf(p->out,"<TD>");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010581 output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010582 raw_printf(p->out,"</TD>\n");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010583 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010584 raw_printf(p->out,"</TR>\n");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010585 break;
10586 }
10587 case MODE_Tcl: {
10588 if( p->cnt++==0 && p->showHeader ){
10589 for(i=0; i<nArg; i++){
10590 output_c_string(p->out,azCol[i] ? azCol[i] : "");
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010591 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010592 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010593 utf8_printf(p->out, "%s", p->rowSeparator);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010594 }
10595 if( azArg==0 ) break;
10596 for(i=0; i<nArg; i++){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010597 output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010598 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010599 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010600 utf8_printf(p->out, "%s", p->rowSeparator);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010601 break;
10602 }
10603 case MODE_Csv: {
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010604 setBinaryMode(p->out, 1);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010605 if( p->cnt++==0 && p->showHeader ){
10606 for(i=0; i<nArg; i++){
10607 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
10608 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010609 utf8_printf(p->out, "%s", p->rowSeparator);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010610 }
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010611 if( nArg>0 ){
Jeff Brown9bee60b2014-08-20 16:41:25 -070010612 for(i=0; i<nArg; i++){
10613 output_csv(p, azArg[i], i<nArg-1);
10614 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010615 utf8_printf(p->out, "%s", p->rowSeparator);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010616 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010617 setTextMode(p->out, 1);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010618 break;
10619 }
10620 case MODE_Insert: {
10621 if( azArg==0 ) break;
Alex Naidisb94ea7b2017-05-24 19:25:14 +020010622 utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
10623 if( p->showHeader ){
10624 raw_printf(p->out,"(");
10625 for(i=0; i<nArg; i++){
10626 if( i>0 ) raw_printf(p->out, ",");
10627 if( quoteChar(azCol[i]) ){
10628 char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
10629 utf8_printf(p->out, "%s", z);
10630 sqlite3_free(z);
10631 }else{
10632 raw_printf(p->out, "%s", azCol[i]);
Luca Stefanie7f3e802017-01-02 15:44:22 +010010633 }
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070010634 }
Alex Naidisb94ea7b2017-05-24 19:25:14 +020010635 raw_printf(p->out,")");
10636 }
10637 p->cnt++;
10638 for(i=0; i<nArg; i++){
10639 raw_printf(p->out, i>0 ? "," : " VALUES(");
10640 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
10641 utf8_printf(p->out,"NULL");
10642 }else if( aiType && aiType[i]==SQLITE_TEXT ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080010643 if( ShellHasFlag(p, SHFLG_Newlines) ){
10644 output_quoted_string(p->out, azArg[i]);
10645 }else{
10646 output_quoted_escaped_string(p->out, azArg[i]);
10647 }
Alex Naidisb94ea7b2017-05-24 19:25:14 +020010648 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
10649 utf8_printf(p->out,"%s", azArg[i]);
10650 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
10651 char z[50];
10652 double r = sqlite3_column_double(p->pStmt, i);
mydongistiny63ee58c2019-09-21 18:04:30 -070010653 sqlite3_uint64 ur;
10654 memcpy(&ur,&r,sizeof(r));
10655 if( ur==0x7ff0000000000000LL ){
10656 raw_printf(p->out, "1e999");
10657 }else if( ur==0xfff0000000000000LL ){
10658 raw_printf(p->out, "-1e999");
10659 }else{
10660 sqlite3_snprintf(50,z,"%!.20g", r);
10661 raw_printf(p->out, "%s", z);
10662 }
Alex Naidisb94ea7b2017-05-24 19:25:14 +020010663 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
10664 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
10665 int nBlob = sqlite3_column_bytes(p->pStmt, i);
10666 output_hex_blob(p->out, pBlob, nBlob);
10667 }else if( isNumber(azArg[i], 0) ){
10668 utf8_printf(p->out,"%s", azArg[i]);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080010669 }else if( ShellHasFlag(p, SHFLG_Newlines) ){
10670 output_quoted_string(p->out, azArg[i]);
Alex Naidisb94ea7b2017-05-24 19:25:14 +020010671 }else{
10672 output_quoted_escaped_string(p->out, azArg[i]);
10673 }
10674 }
10675 raw_printf(p->out,");\n");
10676 break;
10677 }
10678 case MODE_Quote: {
10679 if( azArg==0 ) break;
10680 if( p->cnt==0 && p->showHeader ){
Luca Stefanie7f3e802017-01-02 15:44:22 +010010681 for(i=0; i<nArg; i++){
10682 if( i>0 ) raw_printf(p->out, ",");
10683 output_quoted_string(p->out, azCol[i]);
10684 }
10685 raw_printf(p->out,"\n");
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070010686 }
Luca Stefanie7f3e802017-01-02 15:44:22 +010010687 p->cnt++;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010688 for(i=0; i<nArg; i++){
Alex Naidisb94ea7b2017-05-24 19:25:14 +020010689 if( i>0 ) raw_printf(p->out, ",");
Vasu Noria4356a02010-01-20 15:10:57 -080010690 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
Alex Naidisb94ea7b2017-05-24 19:25:14 +020010691 utf8_printf(p->out,"NULL");
Vasu Noria4356a02010-01-20 15:10:57 -080010692 }else if( aiType && aiType[i]==SQLITE_TEXT ){
Vasu Noria4356a02010-01-20 15:10:57 -080010693 output_quoted_string(p->out, azArg[i]);
Alex Naidisb86c0cf2017-03-31 14:12:35 +020010694 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
Alex Naidisb94ea7b2017-05-24 19:25:14 +020010695 utf8_printf(p->out,"%s", azArg[i]);
Alex Naidisb86c0cf2017-03-31 14:12:35 +020010696 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
10697 char z[50];
10698 double r = sqlite3_column_double(p->pStmt, i);
10699 sqlite3_snprintf(50,z,"%!.20g", r);
Alex Naidisb94ea7b2017-05-24 19:25:14 +020010700 raw_printf(p->out, "%s", z);
Vasu Noria4356a02010-01-20 15:10:57 -080010701 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
10702 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
10703 int nBlob = sqlite3_column_bytes(p->pStmt, i);
Vasu Noria4356a02010-01-20 15:10:57 -080010704 output_hex_blob(p->out, pBlob, nBlob);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010705 }else if( isNumber(azArg[i], 0) ){
Alex Naidisb94ea7b2017-05-24 19:25:14 +020010706 utf8_printf(p->out,"%s", azArg[i]);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010707 }else{
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010708 output_quoted_string(p->out, azArg[i]);
10709 }
10710 }
Alex Naidisb94ea7b2017-05-24 19:25:14 +020010711 raw_printf(p->out,"\n");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010712 break;
10713 }
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010714 case MODE_Ascii: {
10715 if( p->cnt++==0 && p->showHeader ){
10716 for(i=0; i<nArg; i++){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010717 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
10718 utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010719 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010720 utf8_printf(p->out, "%s", p->rowSeparator);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010721 }
10722 if( azArg==0 ) break;
10723 for(i=0; i<nArg; i++){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010724 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
10725 utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010726 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010727 utf8_printf(p->out, "%s", p->rowSeparator);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010728 break;
10729 }
mydongistiny63ee58c2019-09-21 18:04:30 -070010730 case MODE_EQP: {
10731 eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]);
10732 break;
10733 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010734 }
10735 return 0;
10736}
10737
10738/*
Vasu Noria4356a02010-01-20 15:10:57 -080010739** This is the callback routine that the SQLite library
10740** invokes for each row of a query result.
10741*/
10742static int callback(void *pArg, int nArg, char **azArg, char **azCol){
10743 /* since we don't have type info, call the shell_callback with a NULL value */
10744 return shell_callback(pArg, nArg, azArg, azCol, NULL);
10745}
10746
10747/*
Alex Naidisb86c0cf2017-03-31 14:12:35 +020010748** This is the callback routine from sqlite3_exec() that appends all
10749** output onto the end of a ShellText object.
10750*/
10751static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
10752 ShellText *p = (ShellText*)pArg;
10753 int i;
10754 UNUSED_PARAMETER(az);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080010755 if( azArg==0 ) return 0;
Alex Naidisb86c0cf2017-03-31 14:12:35 +020010756 if( p->n ) appendText(p, "|", 0);
10757 for(i=0; i<nArg; i++){
10758 if( i ) appendText(p, ",", 0);
10759 if( azArg[i] ) appendText(p, azArg[i], 0);
10760 }
10761 return 0;
10762}
10763
10764/*
10765** Generate an appropriate SELFTEST table in the main database.
10766*/
10767static void createSelftestTable(ShellState *p){
10768 char *zErrMsg = 0;
10769 sqlite3_exec(p->db,
10770 "SAVEPOINT selftest_init;\n"
10771 "CREATE TABLE IF NOT EXISTS selftest(\n"
10772 " tno INTEGER PRIMARY KEY,\n" /* Test number */
10773 " op TEXT,\n" /* Operator: memo run */
10774 " cmd TEXT,\n" /* Command text */
10775 " ans TEXT\n" /* Desired answer */
10776 ");"
10777 "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n"
10778 "INSERT INTO [_shell$self](rowid,op,cmd)\n"
10779 " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n"
10780 " 'memo','Tests generated by --init');\n"
10781 "INSERT INTO [_shell$self]\n"
10782 " SELECT 'run',\n"
10783 " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql "
10784 "FROM sqlite_master ORDER BY 2'',224))',\n"
10785 " hex(sha3_query('SELECT type,name,tbl_name,sql "
10786 "FROM sqlite_master ORDER BY 2',224));\n"
10787 "INSERT INTO [_shell$self]\n"
10788 " SELECT 'run',"
10789 " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||"
10790 " printf('%w',name) || '\" NOT INDEXED'',224))',\n"
10791 " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"
10792 " FROM (\n"
10793 " SELECT name FROM sqlite_master\n"
10794 " WHERE type='table'\n"
10795 " AND name<>'selftest'\n"
10796 " AND coalesce(rootpage,0)>0\n"
10797 " )\n"
10798 " ORDER BY name;\n"
10799 "INSERT INTO [_shell$self]\n"
10800 " VALUES('run','PRAGMA integrity_check','ok');\n"
10801 "INSERT INTO selftest(tno,op,cmd,ans)"
10802 " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n"
10803 "DROP TABLE [_shell$self];"
10804 ,0,0,&zErrMsg);
10805 if( zErrMsg ){
10806 utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
10807 sqlite3_free(zErrMsg);
10808 }
10809 sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
10810}
10811
10812
10813/*
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010814** Set the destination table field of the ShellState structure to
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010815** the name of the table given. Escape any quote characters in the
10816** table name.
10817*/
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010818static void set_table_name(ShellState *p, const char *zName){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010819 int i, n;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080010820 char cQuote;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010821 char *z;
10822
10823 if( p->zDestTable ){
10824 free(p->zDestTable);
10825 p->zDestTable = 0;
10826 }
10827 if( zName==0 ) return;
Alex Naidisb86c0cf2017-03-31 14:12:35 +020010828 cQuote = quoteChar(zName);
10829 n = strlen30(zName);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080010830 if( cQuote ) n += n+2;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010831 z = p->zDestTable = malloc( n+1 );
mydongistiny63ee58c2019-09-21 18:04:30 -070010832 if( z==0 ) shell_out_of_memory();
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010833 n = 0;
Alex Naidisb86c0cf2017-03-31 14:12:35 +020010834 if( cQuote ) z[n++] = cQuote;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010835 for(i=0; zName[i]; i++){
10836 z[n++] = zName[i];
Alex Naidisb86c0cf2017-03-31 14:12:35 +020010837 if( zName[i]==cQuote ) z[n++] = cQuote;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010838 }
Alex Naidisb86c0cf2017-03-31 14:12:35 +020010839 if( cQuote ) z[n++] = cQuote;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010840 z[n] = 0;
10841}
10842
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010843
10844/*
Jeff Brownc82acac2012-04-19 19:31:30 -070010845** Execute a query statement that will generate SQL output. Print
10846** the result columns, comma-separated, on a line and then add a
10847** semicolon terminator to the end of that line.
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010848**
Jeff Brownc82acac2012-04-19 19:31:30 -070010849** If the number of columns is 1 and that column contains text "--"
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010850** then write the semicolon on a separate line. That way, if a
Jeff Brownc82acac2012-04-19 19:31:30 -070010851** "--" comment occurs at the end of the statement, the comment
10852** won't consume the semicolon terminator.
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010853*/
Vasu Noria4356a02010-01-20 15:10:57 -080010854static int run_table_dump_query(
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010855 ShellState *p, /* Query context */
Jeff Brown90ed05d2012-01-19 16:35:19 -080010856 const char *zSelect, /* SELECT statement to extract content */
10857 const char *zFirstRow /* Print before first row, if not NULL */
Vasu Noria4356a02010-01-20 15:10:57 -080010858){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010859 sqlite3_stmt *pSelect;
10860 int rc;
Jeff Brownc82acac2012-04-19 19:31:30 -070010861 int nResult;
10862 int i;
10863 const char *z;
Nick Kralevich8fecf562014-05-29 16:56:33 -070010864 rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010865 if( rc!=SQLITE_OK || !pSelect ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010866 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
10867 sqlite3_errmsg(p->db));
Nick Kralevich8fecf562014-05-29 16:56:33 -070010868 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010869 return rc;
10870 }
10871 rc = sqlite3_step(pSelect);
Jeff Brownc82acac2012-04-19 19:31:30 -070010872 nResult = sqlite3_column_count(pSelect);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010873 while( rc==SQLITE_ROW ){
Vasu Noria4356a02010-01-20 15:10:57 -080010874 if( zFirstRow ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010875 utf8_printf(p->out, "%s", zFirstRow);
Vasu Noria4356a02010-01-20 15:10:57 -080010876 zFirstRow = 0;
10877 }
Jeff Brownc82acac2012-04-19 19:31:30 -070010878 z = (const char*)sqlite3_column_text(pSelect, 0);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010879 utf8_printf(p->out, "%s", z);
10880 for(i=1; i<nResult; i++){
10881 utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
Jeff Brownc82acac2012-04-19 19:31:30 -070010882 }
10883 if( z==0 ) z = "";
10884 while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
10885 if( z[0] ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010886 raw_printf(p->out, "\n;\n");
Jeff Brownc82acac2012-04-19 19:31:30 -070010887 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010888 raw_printf(p->out, ";\n");
10889 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010890 rc = sqlite3_step(pSelect);
10891 }
Jeff Brown90ed05d2012-01-19 16:35:19 -080010892 rc = sqlite3_finalize(pSelect);
10893 if( rc!=SQLITE_OK ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010894 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
10895 sqlite3_errmsg(p->db));
Nick Kralevich8fecf562014-05-29 16:56:33 -070010896 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
Jeff Brown90ed05d2012-01-19 16:35:19 -080010897 }
10898 return rc;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080010899}
10900
Vasu Noria4356a02010-01-20 15:10:57 -080010901/*
10902** Allocate space and save off current error string.
10903*/
10904static char *save_err_msg(
10905 sqlite3 *db /* Database to query */
10906){
10907 int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070010908 char *zErrMsg = sqlite3_malloc64(nErrMsg);
Vasu Noria4356a02010-01-20 15:10:57 -080010909 if( zErrMsg ){
10910 memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
10911 }
10912 return zErrMsg;
10913}
10914
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010915#ifdef __linux__
10916/*
10917** Attempt to display I/O stats on Linux using /proc/PID/io
10918*/
10919static void displayLinuxIoStats(FILE *out){
10920 FILE *in;
10921 char z[200];
10922 sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
10923 in = fopen(z, "rb");
10924 if( in==0 ) return;
10925 while( fgets(z, sizeof(z), in)!=0 ){
10926 static const struct {
10927 const char *zPattern;
10928 const char *zDesc;
10929 } aTrans[] = {
10930 { "rchar: ", "Bytes received by read():" },
10931 { "wchar: ", "Bytes sent to write():" },
10932 { "syscr: ", "Read() system calls:" },
10933 { "syscw: ", "Write() system calls:" },
10934 { "read_bytes: ", "Bytes read from storage:" },
10935 { "write_bytes: ", "Bytes written to storage:" },
10936 { "cancelled_write_bytes: ", "Cancelled write bytes:" },
10937 };
10938 int i;
10939 for(i=0; i<ArraySize(aTrans); i++){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080010940 int n = strlen30(aTrans[i].zPattern);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010941 if( strncmp(aTrans[i].zPattern, z, n)==0 ){
Alex Naidis08f78cb2016-10-14 15:52:08 +020010942 utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010943 break;
10944 }
10945 }
10946 }
10947 fclose(in);
10948}
10949#endif
10950
Alex Naidisb86c0cf2017-03-31 14:12:35 +020010951/*
10952** Display a single line of status using 64-bit values.
10953*/
10954static void displayStatLine(
10955 ShellState *p, /* The shell context */
10956 char *zLabel, /* Label for this one line */
10957 char *zFormat, /* Format for the result */
10958 int iStatusCtrl, /* Which status to display */
10959 int bReset /* True to reset the stats */
10960){
10961 sqlite3_int64 iCur = -1;
10962 sqlite3_int64 iHiwtr = -1;
10963 int i, nPercent;
10964 char zLine[200];
10965 sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset);
10966 for(i=0, nPercent=0; zFormat[i]; i++){
10967 if( zFormat[i]=='%' ) nPercent++;
10968 }
10969 if( nPercent>1 ){
10970 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr);
10971 }else{
10972 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
10973 }
10974 raw_printf(p->out, "%-36s %s\n", zLabel, zLine);
10975}
Alex Naidis60fa6fd2016-07-10 14:13:38 +020010976
Vasu Noria4356a02010-01-20 15:10:57 -080010977/*
Vasu Noride2b3242010-09-29 15:33:53 -070010978** Display memory stats.
10979*/
10980static int display_stats(
10981 sqlite3 *db, /* Database to query */
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070010982 ShellState *pArg, /* Pointer to ShellState */
Vasu Noride2b3242010-09-29 15:33:53 -070010983 int bReset /* True to reset the stats */
10984){
10985 int iCur;
10986 int iHiwtr;
mydongistiny63ee58c2019-09-21 18:04:30 -070010987 FILE *out;
10988 if( pArg==0 || pArg->out==0 ) return 0;
10989 out = pArg->out;
Vasu Noride2b3242010-09-29 15:33:53 -070010990
mydongistiny63ee58c2019-09-21 18:04:30 -070010991 if( pArg->pStmt && (pArg->statsOn & 2) ){
10992 int nCol, i, x;
10993 sqlite3_stmt *pStmt = pArg->pStmt;
10994 char z[100];
10995 nCol = sqlite3_column_count(pStmt);
10996 raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
10997 for(i=0; i<nCol; i++){
10998 sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
10999 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
11000#ifndef SQLITE_OMIT_DECLTYPE
11001 sqlite3_snprintf(30, z+x, "declared type:");
11002 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
Vasu Noride2b3242010-09-29 15:33:53 -070011003#endif
mydongistiny63ee58c2019-09-21 18:04:30 -070011004#ifdef SQLITE_ENABLE_COLUMN_METADATA
11005 sqlite3_snprintf(30, z+x, "database name:");
11006 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
11007 sqlite3_snprintf(30, z+x, "table name:");
11008 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
11009 sqlite3_snprintf(30, z+x, "origin name:");
11010 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
11011#endif
11012 }
Vasu Noride2b3242010-09-29 15:33:53 -070011013 }
11014
mydongistiny63ee58c2019-09-21 18:04:30 -070011015 displayStatLine(pArg, "Memory Used:",
11016 "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
11017 displayStatLine(pArg, "Number of Outstanding Allocations:",
11018 "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
11019 if( pArg->shellFlgs & SHFLG_Pagecache ){
11020 displayStatLine(pArg, "Number of Pcache Pages Used:",
11021 "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
11022 }
11023 displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
11024 "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
11025 displayStatLine(pArg, "Largest Allocation:",
11026 "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
11027 displayStatLine(pArg, "Largest Pcache Allocation:",
11028 "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
11029#ifdef YYTRACKMAXSTACKDEPTH
11030 displayStatLine(pArg, "Deepest Parser Stack:",
11031 "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
11032#endif
11033
11034 if( db ){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011035 if( pArg->shellFlgs & SHFLG_Lookaside ){
11036 iHiwtr = iCur = -1;
11037 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
11038 &iCur, &iHiwtr, bReset);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011039 raw_printf(pArg->out,
11040 "Lookaside Slots Used: %d (max %d)\n",
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011041 iCur, iHiwtr);
11042 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
11043 &iCur, &iHiwtr, bReset);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011044 raw_printf(pArg->out, "Successful lookaside attempts: %d\n",
11045 iHiwtr);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011046 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
11047 &iCur, &iHiwtr, bReset);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011048 raw_printf(pArg->out, "Lookaside failures due to size: %d\n",
11049 iHiwtr);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011050 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
11051 &iCur, &iHiwtr, bReset);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011052 raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n",
11053 iHiwtr);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011054 }
Vasu Noride2b3242010-09-29 15:33:53 -070011055 iHiwtr = iCur = -1;
11056 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011057 raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n",
11058 iCur);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011059 iHiwtr = iCur = -1;
Jeff Brown90ed05d2012-01-19 16:35:19 -080011060 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011061 raw_printf(pArg->out, "Page cache hits: %d\n", iCur);
Jeff Brown90ed05d2012-01-19 16:35:19 -080011062 iHiwtr = iCur = -1;
11063 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011064 raw_printf(pArg->out, "Page cache misses: %d\n", iCur);
Vasu Noride2b3242010-09-29 15:33:53 -070011065 iHiwtr = iCur = -1;
Nick Kralevich8fecf562014-05-29 16:56:33 -070011066 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011067 raw_printf(pArg->out, "Page cache writes: %d\n", iCur);
Nick Kralevich8fecf562014-05-29 16:56:33 -070011068 iHiwtr = iCur = -1;
mydongistiny63ee58c2019-09-21 18:04:30 -070011069 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
11070 raw_printf(pArg->out, "Page cache spills: %d\n", iCur);
11071 iHiwtr = iCur = -1;
Vasu Noride2b3242010-09-29 15:33:53 -070011072 sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011073 raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n",
11074 iCur);
Vasu Noride2b3242010-09-29 15:33:53 -070011075 iHiwtr = iCur = -1;
11076 sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011077 raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
11078 iCur);
Vasu Noride2b3242010-09-29 15:33:53 -070011079 }
11080
mydongistiny63ee58c2019-09-21 18:04:30 -070011081 if( pArg->pStmt ){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011082 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
11083 bReset);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011084 raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
Vasu Noride2b3242010-09-29 15:33:53 -070011085 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011086 raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011087 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011088 raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
Nick Kralevich8fecf562014-05-29 16:56:33 -070011089 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011090 raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
mydongistiny8320bdc2019-10-06 12:50:35 -070011091 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
mydongistiny63ee58c2019-09-21 18:04:30 -070011092 raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
11093 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
11094 raw_printf(pArg->out, "Number of times run: %d\n", iCur);
11095 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
11096 raw_printf(pArg->out, "Memory used by prepared stmt: %d\n", iCur);
Vasu Noride2b3242010-09-29 15:33:53 -070011097 }
11098
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011099#ifdef __linux__
11100 displayLinuxIoStats(pArg->out);
11101#endif
11102
Nick Kralevich253ed642015-12-23 10:07:58 -080011103 /* Do not remove this machine readable comment: extra-stats-output-here */
11104
Vasu Noride2b3242010-09-29 15:33:53 -070011105 return 0;
11106}
11107
11108/*
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011109** Display scan stats.
11110*/
11111static void display_scanstats(
11112 sqlite3 *db, /* Database to query */
11113 ShellState *pArg /* Pointer to ShellState */
11114){
Nick Kralevich253ed642015-12-23 10:07:58 -080011115#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
11116 UNUSED_PARAMETER(db);
11117 UNUSED_PARAMETER(pArg);
11118#else
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011119 int i, k, n, mx;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011120 raw_printf(pArg->out, "-------- scanstats --------\n");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011121 mx = 0;
11122 for(k=0; k<=mx; k++){
11123 double rEstLoop = 1.0;
11124 for(i=n=0; 1; i++){
11125 sqlite3_stmt *p = pArg->pStmt;
11126 sqlite3_int64 nLoop, nVisit;
11127 double rEst;
11128 int iSid;
11129 const char *zExplain;
11130 if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){
11131 break;
11132 }
11133 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
11134 if( iSid>mx ) mx = iSid;
11135 if( iSid!=k ) continue;
11136 if( n==0 ){
11137 rEstLoop = (double)nLoop;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011138 if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011139 }
11140 n++;
11141 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
11142 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
11143 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011144 utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011145 rEstLoop *= rEst;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011146 raw_printf(pArg->out,
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011147 " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
11148 nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
11149 );
11150 }
11151 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011152 raw_printf(pArg->out, "---------------------------\n");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011153#endif
11154}
11155
11156/*
Nick Kralevich8fecf562014-05-29 16:56:33 -070011157** Parameter azArray points to a zero-terminated array of strings. zStr
11158** points to a single nul-terminated string. Return non-zero if zStr
11159** is equal, according to strcmp(), to any of the strings in the array.
11160** Otherwise, return zero.
11161*/
11162static int str_in_array(const char *zStr, const char **azArray){
11163 int i;
11164 for(i=0; azArray[i]; i++){
11165 if( 0==strcmp(zStr, azArray[i]) ) return 1;
11166 }
11167 return 0;
11168}
11169
11170/*
11171** If compiled statement pSql appears to be an EXPLAIN statement, allocate
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011172** and populate the ShellState.aiIndent[] array with the number of
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011173** spaces each opcode should be indented before it is output.
Nick Kralevich8fecf562014-05-29 16:56:33 -070011174**
11175** The indenting rules are:
11176**
11177** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
11178** all opcodes that occur between the p2 jump destination and the opcode
11179** itself by 2 spaces.
11180**
11181** * For each "Goto", if the jump destination is earlier in the program
11182** and ends on one of:
11183** Yield SeekGt SeekLt RowSetRead Rewind
11184** or if the P1 parameter is one instead of zero,
11185** then indent all opcodes between the earlier instruction
11186** and "Goto" by 2 spaces.
11187*/
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011188static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
Nick Kralevich8fecf562014-05-29 16:56:33 -070011189 const char *zSql; /* The text of the SQL statement */
11190 const char *z; /* Used to check if this is an EXPLAIN */
11191 int *abYield = 0; /* True if op is an OP_Yield */
11192 int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
11193 int iOp; /* Index of operation in p->aiIndent[] */
11194
mydongistiny63ee58c2019-09-21 18:04:30 -070011195 const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011196 const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
11197 "Rewind", 0 };
Nick Kralevich8fecf562014-05-29 16:56:33 -070011198 const char *azGoto[] = { "Goto", 0 };
11199
11200 /* Try to figure out if this is really an EXPLAIN statement. If this
11201 ** cannot be verified, return early. */
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011202 if( sqlite3_column_count(pSql)!=8 ){
11203 p->cMode = p->mode;
11204 return;
11205 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070011206 zSql = sqlite3_sql(pSql);
11207 if( zSql==0 ) return;
11208 for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011209 if( sqlite3_strnicmp(z, "explain", 7) ){
11210 p->cMode = p->mode;
11211 return;
11212 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070011213
11214 for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
11215 int i;
11216 int iAddr = sqlite3_column_int(pSql, 0);
11217 const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
11218
11219 /* Set p2 to the P2 field of the current opcode. Then, assuming that
11220 ** p2 is an instruction address, set variable p2op to the index of that
11221 ** instruction in the aiIndent[] array. p2 and p2op may be different if
11222 ** the current instruction is part of a sub-program generated by an
11223 ** SQL trigger or foreign key. */
11224 int p2 = sqlite3_column_int(pSql, 3);
11225 int p2op = (p2 + (iOp-iAddr));
11226
11227 /* Grow the p->aiIndent array as required */
11228 if( iOp>=nAlloc ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011229 if( iOp==0 ){
11230 /* Do further verfication that this is explain output. Abort if
11231 ** it is not */
11232 static const char *explainCols[] = {
11233 "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" };
11234 int jj;
11235 for(jj=0; jj<ArraySize(explainCols); jj++){
11236 if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
11237 p->cMode = p->mode;
11238 sqlite3_reset(pSql);
11239 return;
11240 }
11241 }
11242 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070011243 nAlloc += 100;
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070011244 p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
mydongistiny63ee58c2019-09-21 18:04:30 -070011245 if( p->aiIndent==0 ) shell_out_of_memory();
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070011246 abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
mydongistiny63ee58c2019-09-21 18:04:30 -070011247 if( abYield==0 ) shell_out_of_memory();
Nick Kralevich8fecf562014-05-29 16:56:33 -070011248 }
11249 abYield[iOp] = str_in_array(zOp, azYield);
11250 p->aiIndent[iOp] = 0;
11251 p->nIndent = iOp+1;
11252
11253 if( str_in_array(zOp, azNext) ){
11254 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
11255 }
11256 if( str_in_array(zOp, azGoto) && p2op<p->nIndent
11257 && (abYield[p2op] || sqlite3_column_int(pSql, 2))
11258 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011259 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
Nick Kralevich8fecf562014-05-29 16:56:33 -070011260 }
11261 }
11262
11263 p->iIndent = 0;
11264 sqlite3_free(abYield);
11265 sqlite3_reset(pSql);
11266}
11267
11268/*
11269** Free the array allocated by explain_data_prepare().
11270*/
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011271static void explain_data_delete(ShellState *p){
Nick Kralevich8fecf562014-05-29 16:56:33 -070011272 sqlite3_free(p->aiIndent);
11273 p->aiIndent = 0;
11274 p->nIndent = 0;
11275 p->iIndent = 0;
11276}
11277
11278/*
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011279** Disable and restore .wheretrace and .selecttrace settings.
11280*/
11281#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
11282extern int sqlite3SelectTrace;
11283static int savedSelectTrace;
11284#endif
11285#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
11286extern int sqlite3WhereTrace;
11287static int savedWhereTrace;
11288#endif
11289static void disable_debug_trace_modes(void){
11290#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
11291 savedSelectTrace = sqlite3SelectTrace;
11292 sqlite3SelectTrace = 0;
11293#endif
11294#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
11295 savedWhereTrace = sqlite3WhereTrace;
11296 sqlite3WhereTrace = 0;
11297#endif
11298}
11299static void restore_debug_trace_modes(void){
11300#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
11301 sqlite3SelectTrace = savedSelectTrace;
11302#endif
11303#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
11304 sqlite3WhereTrace = savedWhereTrace;
11305#endif
11306}
11307
mydongistiny63ee58c2019-09-21 18:04:30 -070011308/* Create the TEMP table used to store parameter bindings */
11309static void bind_table_init(ShellState *p){
11310 int wrSchema = 0;
11311 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
11312 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
11313 sqlite3_exec(p->db,
11314 "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
11315 " key TEXT PRIMARY KEY,\n"
11316 " value ANY\n"
11317 ") WITHOUT ROWID;",
11318 0, 0, 0);
11319 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
11320}
11321
11322/*
11323** Bind parameters on a prepared statement.
11324**
11325** Parameter bindings are taken from a TEMP table of the form:
11326**
11327** CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
11328** WITHOUT ROWID;
11329**
11330** No bindings occur if this table does not exist. The special character '$'
11331** is included in the table name to help prevent collisions with actual tables.
11332** The table must be in the TEMP schema.
11333*/
11334static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
11335 int nVar;
11336 int i;
11337 int rc;
11338 sqlite3_stmt *pQ = 0;
11339
11340 nVar = sqlite3_bind_parameter_count(pStmt);
11341 if( nVar==0 ) return; /* Nothing to do */
11342 if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters",
11343 "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
11344 return; /* Parameter table does not exist */
11345 }
11346 rc = sqlite3_prepare_v2(pArg->db,
11347 "SELECT value FROM temp.sqlite_parameters"
11348 " WHERE key=?1", -1, &pQ, 0);
11349 if( rc || pQ==0 ) return;
11350 for(i=1; i<=nVar; i++){
11351 char zNum[30];
11352 const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
11353 if( zVar==0 ){
11354 sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
11355 zVar = zNum;
11356 }
11357 sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
11358 if( sqlite3_step(pQ)==SQLITE_ROW ){
11359 sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
11360 }else{
11361 sqlite3_bind_null(pStmt, i);
11362 }
11363 sqlite3_reset(pQ);
11364 }
11365 sqlite3_finalize(pQ);
11366}
11367
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011368/*
11369** Run a prepared statement
11370*/
11371static void exec_prepared_stmt(
11372 ShellState *pArg, /* Pointer to ShellState */
mydongistiny63ee58c2019-09-21 18:04:30 -070011373 sqlite3_stmt *pStmt /* Statment to run */
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011374){
11375 int rc;
11376
11377 /* perform the first step. this will tell us if we
11378 ** have a result set or not and how wide it is.
11379 */
11380 rc = sqlite3_step(pStmt);
11381 /* if we have a result set... */
11382 if( SQLITE_ROW == rc ){
mydongistiny63ee58c2019-09-21 18:04:30 -070011383 /* allocate space for col name ptr, value ptr, and type */
11384 int nCol = sqlite3_column_count(pStmt);
11385 void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
11386 if( !pData ){
11387 rc = SQLITE_NOMEM;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011388 }else{
mydongistiny63ee58c2019-09-21 18:04:30 -070011389 char **azCols = (char **)pData; /* Names of result columns */
11390 char **azVals = &azCols[nCol]; /* Results */
11391 int *aiTypes = (int *)&azVals[nCol]; /* Result types */
11392 int i, x;
11393 assert(sizeof(int) <= sizeof(char *));
11394 /* save off ptrs to column names */
11395 for(i=0; i<nCol; i++){
11396 azCols[i] = (char *)sqlite3_column_name(pStmt, i);
11397 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011398 do{
mydongistiny63ee58c2019-09-21 18:04:30 -070011399 /* extract the data and data types */
11400 for(i=0; i<nCol; i++){
11401 aiTypes[i] = x = sqlite3_column_type(pStmt, i);
11402 if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
11403 azVals[i] = "";
11404 }else{
11405 azVals[i] = (char*)sqlite3_column_text(pStmt, i);
11406 }
11407 if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
11408 rc = SQLITE_NOMEM;
11409 break; /* from for */
11410 }
11411 } /* end for */
11412
11413 /* if data and types extracted successfully... */
11414 if( SQLITE_ROW == rc ){
11415 /* call the supplied callback with the result row data */
11416 if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){
11417 rc = SQLITE_ABORT;
11418 }else{
11419 rc = sqlite3_step(pStmt);
11420 }
11421 }
11422 } while( SQLITE_ROW == rc );
11423 sqlite3_free(pData);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011424 }
11425 }
11426}
11427
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080011428#ifndef SQLITE_OMIT_VIRTUALTABLE
11429/*
11430** This function is called to process SQL if the previous shell command
11431** was ".expert". It passes the SQL in the second argument directly to
11432** the sqlite3expert object.
11433**
11434** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
11435** code. In this case, (*pzErr) may be set to point to a buffer containing
11436** an English language error message. It is the responsibility of the
11437** caller to eventually free this buffer using sqlite3_free().
11438*/
11439static int expertHandleSQL(
11440 ShellState *pState,
11441 const char *zSql,
11442 char **pzErr
11443){
11444 assert( pState->expert.pExpert );
11445 assert( pzErr==0 || *pzErr==0 );
11446 return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr);
11447}
11448
11449/*
11450** This function is called either to silently clean up the object
11451** created by the ".expert" command (if bCancel==1), or to generate a
11452** report from it and then clean it up (if bCancel==0).
11453**
11454** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
11455** code. In this case, (*pzErr) may be set to point to a buffer containing
11456** an English language error message. It is the responsibility of the
11457** caller to eventually free this buffer using sqlite3_free().
11458*/
11459static int expertFinish(
11460 ShellState *pState,
11461 int bCancel,
11462 char **pzErr
11463){
11464 int rc = SQLITE_OK;
11465 sqlite3expert *p = pState->expert.pExpert;
11466 assert( p );
11467 assert( bCancel || pzErr==0 || *pzErr==0 );
11468 if( bCancel==0 ){
11469 FILE *out = pState->out;
11470 int bVerbose = pState->expert.bVerbose;
11471
11472 rc = sqlite3_expert_analyze(p, pzErr);
11473 if( rc==SQLITE_OK ){
11474 int nQuery = sqlite3_expert_count(p);
11475 int i;
11476
11477 if( bVerbose ){
11478 const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
11479 raw_printf(out, "-- Candidates -----------------------------\n");
11480 raw_printf(out, "%s\n", zCand);
11481 }
11482 for(i=0; i<nQuery; i++){
11483 const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
11484 const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
11485 const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
11486 if( zIdx==0 ) zIdx = "(no new indexes)\n";
11487 if( bVerbose ){
11488 raw_printf(out, "-- Query %d --------------------------------\n",i+1);
11489 raw_printf(out, "%s\n\n", zSql);
11490 }
11491 raw_printf(out, "%s\n", zIdx);
11492 raw_printf(out, "%s\n", zEQP);
11493 }
11494 }
11495 }
11496 sqlite3_expert_destroy(p);
11497 pState->expert.pExpert = 0;
11498 return rc;
11499}
11500
11501/*
11502** Implementation of ".expert" dot command.
11503*/
11504static int expertDotCommand(
11505 ShellState *pState, /* Current shell tool state */
11506 char **azArg, /* Array of arguments passed to dot command */
11507 int nArg /* Number of entries in azArg[] */
11508){
11509 int rc = SQLITE_OK;
11510 char *zErr = 0;
11511 int i;
11512 int iSample = 0;
11513
11514 assert( pState->expert.pExpert==0 );
11515 memset(&pState->expert, 0, sizeof(ExpertInfo));
11516
11517 for(i=1; rc==SQLITE_OK && i<nArg; i++){
11518 char *z = azArg[i];
11519 int n;
11520 if( z[0]=='-' && z[1]=='-' ) z++;
11521 n = strlen30(z);
11522 if( n>=2 && 0==strncmp(z, "-verbose", n) ){
11523 pState->expert.bVerbose = 1;
11524 }
11525 else if( n>=2 && 0==strncmp(z, "-sample", n) ){
11526 if( i==(nArg-1) ){
11527 raw_printf(stderr, "option requires an argument: %s\n", z);
11528 rc = SQLITE_ERROR;
11529 }else{
11530 iSample = (int)integerValue(azArg[++i]);
11531 if( iSample<0 || iSample>100 ){
11532 raw_printf(stderr, "value out of range: %s\n", azArg[i]);
11533 rc = SQLITE_ERROR;
11534 }
11535 }
11536 }
11537 else{
11538 raw_printf(stderr, "unknown option: %s\n", z);
11539 rc = SQLITE_ERROR;
11540 }
11541 }
11542
11543 if( rc==SQLITE_OK ){
11544 pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
11545 if( pState->expert.pExpert==0 ){
11546 raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr);
11547 rc = SQLITE_ERROR;
11548 }else{
11549 sqlite3_expert_config(
11550 pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
11551 );
11552 }
11553 }
11554
11555 return rc;
11556}
11557#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
11558
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011559/*
11560** Execute a statement or set of statements. Print
11561** any result rows/columns depending on the current mode
Vasu Noria4356a02010-01-20 15:10:57 -080011562** set via the supplied callback.
11563**
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011564** This is very similar to SQLite's built-in sqlite3_exec()
11565** function except it takes a slightly different callback
Vasu Noria4356a02010-01-20 15:10:57 -080011566** and callback data argument.
11567*/
11568static int shell_exec(
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011569 ShellState *pArg, /* Pointer to ShellState */
mydongistiny63ee58c2019-09-21 18:04:30 -070011570 const char *zSql, /* SQL to be evaluated */
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011571 char **pzErrMsg /* Error msg written here */
Vasu Noria4356a02010-01-20 15:10:57 -080011572){
11573 sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
11574 int rc = SQLITE_OK; /* Return Code */
Jeff Brown90ed05d2012-01-19 16:35:19 -080011575 int rc2;
Vasu Noria4356a02010-01-20 15:10:57 -080011576 const char *zLeftover; /* Tail of unprocessed SQL */
mydongistiny63ee58c2019-09-21 18:04:30 -070011577 sqlite3 *db = pArg->db;
Vasu Noria4356a02010-01-20 15:10:57 -080011578
11579 if( pzErrMsg ){
11580 *pzErrMsg = NULL;
11581 }
11582
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080011583#ifndef SQLITE_OMIT_VIRTUALTABLE
11584 if( pArg->expert.pExpert ){
11585 rc = expertHandleSQL(pArg, zSql, pzErrMsg);
11586 return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
11587 }
11588#endif
11589
Vasu Noria4356a02010-01-20 15:10:57 -080011590 while( zSql[0] && (SQLITE_OK == rc) ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011591 static const char *zStmtSql;
Vasu Noria4356a02010-01-20 15:10:57 -080011592 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
11593 if( SQLITE_OK != rc ){
11594 if( pzErrMsg ){
11595 *pzErrMsg = save_err_msg(db);
11596 }
11597 }else{
11598 if( !pStmt ){
11599 /* this happens for a comment or white-space */
11600 zSql = zLeftover;
Jeff Brown90ed05d2012-01-19 16:35:19 -080011601 while( IsSpace(zSql[0]) ) zSql++;
Vasu Noria4356a02010-01-20 15:10:57 -080011602 continue;
11603 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011604 zStmtSql = sqlite3_sql(pStmt);
Luca Stefanie7f3e802017-01-02 15:44:22 +010011605 if( zStmtSql==0 ) zStmtSql = "";
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011606 while( IsSpace(zStmtSql[0]) ) zStmtSql++;
Vasu Noria4356a02010-01-20 15:10:57 -080011607
Vasu Noride2b3242010-09-29 15:33:53 -070011608 /* save off the prepared statment handle and reset row count */
11609 if( pArg ){
11610 pArg->pStmt = pStmt;
11611 pArg->cnt = 0;
11612 }
11613
Vasu Nori71504cf2010-06-17 13:59:04 -070011614 /* echo the sql statement if echo on */
Alex Naidisb86c0cf2017-03-31 14:12:35 +020011615 if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011616 utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
Vasu Nori71504cf2010-06-17 13:59:04 -070011617 }
11618
Nick Kralevich8fecf562014-05-29 16:56:33 -070011619 /* Show the EXPLAIN QUERY PLAN if .eqp is on */
mydongistiny63ee58c2019-09-21 18:04:30 -070011620 if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
Nick Kralevich8fecf562014-05-29 16:56:33 -070011621 sqlite3_stmt *pExplain;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011622 char *zEQP;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080011623 int triggerEQP = 0;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011624 disable_debug_trace_modes();
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080011625 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
11626 if( pArg->autoEQP>=AUTOEQP_trigger ){
11627 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
11628 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011629 zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
Nick Kralevich8fecf562014-05-29 16:56:33 -070011630 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
11631 if( rc==SQLITE_OK ){
11632 while( sqlite3_step(pExplain)==SQLITE_ROW ){
mydongistiny63ee58c2019-09-21 18:04:30 -070011633 const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
11634 int iEqpId = sqlite3_column_int(pExplain, 0);
11635 int iParentId = sqlite3_column_int(pExplain, 1);
11636 if( zEQPLine[0]=='-' ) eqp_render(pArg);
11637 eqp_append(pArg, iEqpId, iParentId, zEQPLine);
Nick Kralevich8fecf562014-05-29 16:56:33 -070011638 }
mydongistiny63ee58c2019-09-21 18:04:30 -070011639 eqp_render(pArg);
Nick Kralevich8fecf562014-05-29 16:56:33 -070011640 }
11641 sqlite3_finalize(pExplain);
11642 sqlite3_free(zEQP);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080011643 if( pArg->autoEQP>=AUTOEQP_full ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011644 /* Also do an EXPLAIN for ".eqp full" mode */
11645 zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
11646 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
11647 if( rc==SQLITE_OK ){
11648 pArg->cMode = MODE_Explain;
11649 explain_data_prepare(pArg, pExplain);
mydongistiny63ee58c2019-09-21 18:04:30 -070011650 exec_prepared_stmt(pArg, pExplain);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011651 explain_data_delete(pArg);
Vasu Noria4356a02010-01-20 15:10:57 -080011652 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011653 sqlite3_finalize(pExplain);
11654 sqlite3_free(zEQP);
11655 }
mydongistiny63ee58c2019-09-21 18:04:30 -070011656 if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
11657 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
11658 /* Reprepare pStmt before reactiving trace modes */
11659 sqlite3_finalize(pStmt);
11660 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
11661 if( pArg ) pArg->pStmt = pStmt;
11662 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011663 restore_debug_trace_modes();
11664 }
11665
11666 if( pArg ){
11667 pArg->cMode = pArg->mode;
mydongistiny63ee58c2019-09-21 18:04:30 -070011668 if( pArg->autoExplain ){
11669 if( sqlite3_stmt_isexplain(pStmt)==1 ){
11670 pArg->cMode = MODE_Explain;
11671 }
11672 if( sqlite3_stmt_isexplain(pStmt)==2 ){
11673 pArg->cMode = MODE_EQP;
11674 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011675 }
11676
11677 /* If the shell is currently in ".explain" mode, gather the extra
11678 ** data required to add indents to the output.*/
11679 if( pArg->cMode==MODE_Explain ){
11680 explain_data_prepare(pArg, pStmt);
Vasu Noria4356a02010-01-20 15:10:57 -080011681 }
11682 }
11683
mydongistiny63ee58c2019-09-21 18:04:30 -070011684 bind_prepared_stmt(pArg, pStmt);
11685 exec_prepared_stmt(pArg, pStmt);
Nick Kralevich8fecf562014-05-29 16:56:33 -070011686 explain_data_delete(pArg);
mydongistiny63ee58c2019-09-21 18:04:30 -070011687 eqp_render(pArg);
Nick Kralevich8fecf562014-05-29 16:56:33 -070011688
Vasu Noride2b3242010-09-29 15:33:53 -070011689 /* print usage stats if stats on */
11690 if( pArg && pArg->statsOn ){
11691 display_stats(db, pArg, 0);
11692 }
11693
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011694 /* print loop-counters if required */
11695 if( pArg && pArg->scanstatsOn ){
11696 display_scanstats(db, pArg);
11697 }
11698
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011699 /* Finalize the statement just executed. If this fails, save a
Vasu Noria4356a02010-01-20 15:10:57 -080011700 ** copy of the error message. Otherwise, set zSql to point to the
11701 ** next statement to execute. */
Jeff Brown90ed05d2012-01-19 16:35:19 -080011702 rc2 = sqlite3_finalize(pStmt);
11703 if( rc!=SQLITE_NOMEM ) rc = rc2;
Vasu Noria4356a02010-01-20 15:10:57 -080011704 if( rc==SQLITE_OK ){
11705 zSql = zLeftover;
Jeff Brown90ed05d2012-01-19 16:35:19 -080011706 while( IsSpace(zSql[0]) ) zSql++;
Vasu Noria4356a02010-01-20 15:10:57 -080011707 }else if( pzErrMsg ){
11708 *pzErrMsg = save_err_msg(db);
11709 }
Vasu Noride2b3242010-09-29 15:33:53 -070011710
11711 /* clear saved stmt handle */
11712 if( pArg ){
11713 pArg->pStmt = NULL;
11714 }
Vasu Noria4356a02010-01-20 15:10:57 -080011715 }
11716 } /* end while */
11717
11718 return rc;
11719}
11720
Alex Naidisb86c0cf2017-03-31 14:12:35 +020011721/*
11722** Release memory previously allocated by tableColumnList().
11723*/
11724static void freeColumnList(char **azCol){
11725 int i;
11726 for(i=1; azCol[i]; i++){
11727 sqlite3_free(azCol[i]);
11728 }
11729 /* azCol[0] is a static string */
11730 sqlite3_free(azCol);
11731}
11732
11733/*
11734** Return a list of pointers to strings which are the names of all
11735** columns in table zTab. The memory to hold the names is dynamically
11736** allocated and must be released by the caller using a subsequent call
11737** to freeColumnList().
11738**
11739** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
11740** value that needs to be preserved, then azCol[0] is filled in with the
11741** name of the rowid column.
11742**
11743** The first regular column in the table is azCol[1]. The list is terminated
11744** by an entry with azCol[i]==0.
11745*/
11746static char **tableColumnList(ShellState *p, const char *zTab){
11747 char **azCol = 0;
11748 sqlite3_stmt *pStmt;
11749 char *zSql;
11750 int nCol = 0;
11751 int nAlloc = 0;
11752 int nPK = 0; /* Number of PRIMARY KEY columns seen */
11753 int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
11754 int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
11755 int rc;
11756
11757 zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
11758 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
11759 sqlite3_free(zSql);
11760 if( rc ) return 0;
11761 while( sqlite3_step(pStmt)==SQLITE_ROW ){
11762 if( nCol>=nAlloc-2 ){
11763 nAlloc = nAlloc*2 + nCol + 10;
11764 azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
mydongistiny63ee58c2019-09-21 18:04:30 -070011765 if( azCol==0 ) shell_out_of_memory();
Alex Naidisb86c0cf2017-03-31 14:12:35 +020011766 }
11767 azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
11768 if( sqlite3_column_int(pStmt, 5) ){
11769 nPK++;
11770 if( nPK==1
11771 && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080011772 "INTEGER")==0
Alex Naidisb86c0cf2017-03-31 14:12:35 +020011773 ){
11774 isIPK = 1;
11775 }else{
11776 isIPK = 0;
11777 }
11778 }
11779 }
11780 sqlite3_finalize(pStmt);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080011781 if( azCol==0 ) return 0;
Alex Naidisb86c0cf2017-03-31 14:12:35 +020011782 azCol[0] = 0;
11783 azCol[nCol+1] = 0;
11784
11785 /* The decision of whether or not a rowid really needs to be preserved
11786 ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
11787 ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
11788 ** rowids on tables where the rowid is inaccessible because there are other
11789 ** columns in the table named "rowid", "_rowid_", and "oid".
11790 */
11791 if( preserveRowid && isIPK ){
11792 /* If a single PRIMARY KEY column with type INTEGER was seen, then it
11793 ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID
11794 ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
11795 ** ROWID aliases. To distinguish these cases, check to see if
11796 ** there is a "pk" entry in "PRAGMA index_list". There will be
11797 ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
11798 */
11799 zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
11800 " WHERE origin='pk'", zTab);
11801 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
11802 sqlite3_free(zSql);
11803 if( rc ){
11804 freeColumnList(azCol);
11805 return 0;
11806 }
11807 rc = sqlite3_step(pStmt);
11808 sqlite3_finalize(pStmt);
11809 preserveRowid = rc==SQLITE_ROW;
11810 }
11811 if( preserveRowid ){
11812 /* Only preserve the rowid if we can find a name to use for the
11813 ** rowid */
11814 static char *azRowid[] = { "rowid", "_rowid_", "oid" };
11815 int i, j;
11816 for(j=0; j<3; j++){
11817 for(i=1; i<=nCol; i++){
11818 if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
11819 }
11820 if( i>nCol ){
11821 /* At this point, we know that azRowid[j] is not the name of any
11822 ** ordinary column in the table. Verify that azRowid[j] is a valid
11823 ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
11824 ** tables will fail this last check */
11825 rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
11826 if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
11827 break;
11828 }
11829 }
11830 }
11831 return azCol;
11832}
11833
11834/*
11835** Toggle the reverse_unordered_selects setting.
11836*/
11837static void toggleSelectOrder(sqlite3 *db){
11838 sqlite3_stmt *pStmt = 0;
11839 int iSetting = 0;
11840 char zStmt[100];
11841 sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0);
11842 if( sqlite3_step(pStmt)==SQLITE_ROW ){
11843 iSetting = sqlite3_column_int(pStmt, 0);
11844 }
11845 sqlite3_finalize(pStmt);
11846 sqlite3_snprintf(sizeof(zStmt), zStmt,
11847 "PRAGMA reverse_unordered_selects(%d)", !iSetting);
11848 sqlite3_exec(db, zStmt, 0, 0, 0);
11849}
The Android Open Source Project7790ef52009-03-03 19:30:40 -080011850
11851/*
11852** This is a different callback routine used for dumping the database.
11853** Each row received by this callback consists of a table name,
11854** the table type ("index" or "table") and SQL to create the table.
11855** This routine should print text sufficient to recreate the table.
11856*/
Alex Naidisb86c0cf2017-03-31 14:12:35 +020011857static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080011858 int rc;
11859 const char *zTable;
11860 const char *zType;
11861 const char *zSql;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070011862 ShellState *p = (ShellState *)pArg;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080011863
Alex Naidisb86c0cf2017-03-31 14:12:35 +020011864 UNUSED_PARAMETER(azNotUsed);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080011865 if( nArg!=3 || azArg==0 ) return 0;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080011866 zTable = azArg[0];
11867 zType = azArg[1];
11868 zSql = azArg[2];
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011869
The Android Open Source Project7790ef52009-03-03 19:30:40 -080011870 if( strcmp(zTable, "sqlite_sequence")==0 ){
Alex Naidisb86c0cf2017-03-31 14:12:35 +020011871 raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
Nick Kralevich8fecf562014-05-29 16:56:33 -070011872 }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011873 raw_printf(p->out, "ANALYZE sqlite_master;\n");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080011874 }else if( strncmp(zTable, "sqlite_", 7)==0 ){
11875 return 0;
11876 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
11877 char *zIns;
11878 if( !p->writableSchema ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011879 raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080011880 p->writableSchema = 1;
11881 }
11882 zIns = sqlite3_mprintf(
11883 "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
11884 "VALUES('table','%q','%q',0,'%q');",
11885 zTable, zTable, zSql);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011886 utf8_printf(p->out, "%s\n", zIns);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080011887 sqlite3_free(zIns);
11888 return 0;
11889 }else{
Luca Stefanie7f3e802017-01-02 15:44:22 +010011890 printSchemaLine(p->out, zSql, ";\n");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080011891 }
11892
11893 if( strcmp(zType, "table")==0 ){
Alex Naidisb86c0cf2017-03-31 14:12:35 +020011894 ShellText sSelect;
11895 ShellText sTable;
11896 char **azCol;
11897 int i;
11898 char *savedDestTable;
11899 int savedMode;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011900
Alex Naidisb86c0cf2017-03-31 14:12:35 +020011901 azCol = tableColumnList(p, zTable);
11902 if( azCol==0 ){
11903 p->nErr++;
11904 return 0;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080011905 }
11906
Nick Kralevich8fecf562014-05-29 16:56:33 -070011907 /* Always quote the table name, even if it appears to be pure ascii,
11908 ** in case it is a keyword. Ex: INSERT INTO "table" ... */
Alex Naidisb86c0cf2017-03-31 14:12:35 +020011909 initText(&sTable);
11910 appendText(&sTable, zTable, quoteChar(zTable));
11911 /* If preserving the rowid, add a column list after the table name.
11912 ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
11913 ** instead of the usual "INSERT INTO tab VALUES(...)".
11914 */
11915 if( azCol[0] ){
11916 appendText(&sTable, "(", 0);
11917 appendText(&sTable, azCol[0], 0);
11918 for(i=1; azCol[i]; i++){
11919 appendText(&sTable, ",", 0);
11920 appendText(&sTable, azCol[i], quoteChar(azCol[i]));
The Android Open Source Project7790ef52009-03-03 19:30:40 -080011921 }
Alex Naidisb86c0cf2017-03-31 14:12:35 +020011922 appendText(&sTable, ")", 0);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080011923 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080011924
Alex Naidisb86c0cf2017-03-31 14:12:35 +020011925 /* Build an appropriate SELECT statement */
11926 initText(&sSelect);
11927 appendText(&sSelect, "SELECT ", 0);
11928 if( azCol[0] ){
11929 appendText(&sSelect, azCol[0], 0);
11930 appendText(&sSelect, ",", 0);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080011931 }
Alex Naidisb86c0cf2017-03-31 14:12:35 +020011932 for(i=1; azCol[i]; i++){
11933 appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
11934 if( azCol[i+1] ){
11935 appendText(&sSelect, ",", 0);
11936 }
11937 }
11938 freeColumnList(azCol);
11939 appendText(&sSelect, " FROM ", 0);
11940 appendText(&sSelect, zTable, quoteChar(zTable));
11941
11942 savedDestTable = p->zDestTable;
11943 savedMode = p->mode;
11944 p->zDestTable = sTable.z;
11945 p->mode = p->cMode = MODE_Insert;
mydongistiny63ee58c2019-09-21 18:04:30 -070011946 rc = shell_exec(p, sSelect.z, 0);
Alex Naidisb86c0cf2017-03-31 14:12:35 +020011947 if( (rc&0xff)==SQLITE_CORRUPT ){
11948 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
11949 toggleSelectOrder(p->db);
mydongistiny63ee58c2019-09-21 18:04:30 -070011950 shell_exec(p, sSelect.z, 0);
Alex Naidisb86c0cf2017-03-31 14:12:35 +020011951 toggleSelectOrder(p->db);
11952 }
11953 p->zDestTable = savedDestTable;
11954 p->mode = savedMode;
11955 freeText(&sTable);
11956 freeText(&sSelect);
11957 if( rc ) p->nErr++;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080011958 }
11959 return 0;
11960}
11961
11962/*
11963** Run zQuery. Use dump_callback() as the callback routine so that
11964** the contents of the query are output as SQL statements.
11965**
11966** If we get a SQLITE_CORRUPT error, rerun the query after appending
11967** "ORDER BY rowid DESC" to the end.
11968*/
11969static int run_schema_dump_query(
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011970 ShellState *p,
Jeff Brown90ed05d2012-01-19 16:35:19 -080011971 const char *zQuery
The Android Open Source Project7790ef52009-03-03 19:30:40 -080011972){
11973 int rc;
Jeff Brown90ed05d2012-01-19 16:35:19 -080011974 char *zErr = 0;
11975 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080011976 if( rc==SQLITE_CORRUPT ){
11977 char *zQ2;
Vasu Noria4356a02010-01-20 15:10:57 -080011978 int len = strlen30(zQuery);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011979 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
Jeff Brown90ed05d2012-01-19 16:35:19 -080011980 if( zErr ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011981 utf8_printf(p->out, "/****** %s ******/\n", zErr);
Jeff Brown90ed05d2012-01-19 16:35:19 -080011982 sqlite3_free(zErr);
11983 zErr = 0;
11984 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080011985 zQ2 = malloc( len+100 );
11986 if( zQ2==0 ) return rc;
Nick Kralevich8fecf562014-05-29 16:56:33 -070011987 sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
Jeff Brown90ed05d2012-01-19 16:35:19 -080011988 rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
11989 if( rc ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020011990 utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
Jeff Brown90ed05d2012-01-19 16:35:19 -080011991 }else{
11992 rc = SQLITE_CORRUPT;
11993 }
11994 sqlite3_free(zErr);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080011995 free(zQ2);
11996 }
11997 return rc;
11998}
11999
12000/*
mydongistiny63ee58c2019-09-21 18:04:30 -070012001** Text of help messages.
12002**
12003** The help text for each individual command begins with a line that starts
12004** with ".". Subsequent lines are supplimental information.
12005**
12006** There must be two or more spaces between the end of the command and the
12007** start of the description of what that command does.
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012008*/
mydongistiny63ee58c2019-09-21 18:04:30 -070012009static const char *(azHelp[]) = {
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012010#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
mydongistiny63ee58c2019-09-21 18:04:30 -070012011 ".archive ... Manage SQL archives",
12012 " Each command must have exactly one of the following options:",
12013 " -c, --create Create a new archive",
mydongistiny8320bdc2019-10-06 12:50:35 -070012014 " -u, --update Add or update files with changed mtime",
12015 " -i, --insert Like -u but always add even if unchanged",
mydongistiny63ee58c2019-09-21 18:04:30 -070012016 " -t, --list List contents of archive",
12017 " -x, --extract Extract files from archive",
12018 " Optional arguments:",
12019 " -v, --verbose Print each filename as it is processed",
mydongistiny8320bdc2019-10-06 12:50:35 -070012020 " -f FILE, --file FILE Use archive FILE (default is current db)",
12021 " -a FILE, --append FILE Open FILE using the apndvfs VFS",
12022 " -C DIR, --directory DIR Read/extract files from directory DIR",
mydongistiny63ee58c2019-09-21 18:04:30 -070012023 " -n, --dryrun Show the SQL that would have occurred",
12024 " Examples:",
mydongistiny8320bdc2019-10-06 12:50:35 -070012025 " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
12026 " .ar -tf ARCHIVE # List members of ARCHIVE",
12027 " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE",
mydongistiny63ee58c2019-09-21 18:04:30 -070012028 " See also:",
12029 " http://sqlite.org/cli.html#sqlar_archive_support",
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012030#endif
Alex Naidis08f78cb2016-10-14 15:52:08 +020012031#ifndef SQLITE_OMIT_AUTHORIZATION
mydongistiny63ee58c2019-09-21 18:04:30 -070012032 ".auth ON|OFF Show authorizer callbacks",
Alex Naidis08f78cb2016-10-14 15:52:08 +020012033#endif
mydongistiny63ee58c2019-09-21 18:04:30 -070012034 ".backup ?DB? FILE Backup DB (default \"main\") to FILE",
12035 " --append Use the appendvfs",
mydongistiny8320bdc2019-10-06 12:50:35 -070012036 " --async Write to FILE without journal and fsync()",
mydongistiny63ee58c2019-09-21 18:04:30 -070012037 ".bail on|off Stop after hitting an error. Default OFF",
12038 ".binary on|off Turn binary output on or off. Default OFF",
12039 ".cd DIRECTORY Change the working directory to DIRECTORY",
12040 ".changes on|off Show number of rows changed by SQL",
12041 ".check GLOB Fail if output since .testcase does not match",
12042 ".clone NEWDB Clone data into NEWDB from the existing database",
12043 ".databases List names and files of attached databases",
12044 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
12045 ".dbinfo ?DB? Show status information about the database",
12046 ".dump ?TABLE? ... Render all database content as SQL",
12047 " Options:",
12048 " --preserve-rowids Include ROWID values in the output",
12049 " --newlines Allow unescaped newline characters in output",
12050 " TABLE is a LIKE pattern for the tables to dump",
12051 ".echo on|off Turn command echo on or off",
12052 ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
12053 " Other Modes:",
12054#ifdef SQLITE_DEBUG
12055 " test Show raw EXPLAIN QUERY PLAN output",
mydongistiny8320bdc2019-10-06 12:50:35 -070012056 " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"",
mydongistiny63ee58c2019-09-21 18:04:30 -070012057#endif
12058 " trigger Like \"full\" but also show trigger bytecode",
mydongistiny8320bdc2019-10-06 12:50:35 -070012059 ".excel Display the output of next command in spreadsheet",
mydongistiny63ee58c2019-09-21 18:04:30 -070012060 ".exit ?CODE? Exit this program with return-code CODE",
mydongistiny8320bdc2019-10-06 12:50:35 -070012061 ".expert EXPERIMENTAL. Suggest indexes for queries",
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012062/* Because explain mode comes on automatically now, the ".explain" mode
mydongistiny8320bdc2019-10-06 12:50:35 -070012063** is removed from the help screen. It is still supported for legacy, however */
12064/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off",*/
mydongistiny63ee58c2019-09-21 18:04:30 -070012065 ".filectrl CMD ... Run various sqlite3_file_control() operations",
12066 " Run \".filectrl\" with no arguments for details",
12067 ".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
12068 ".headers on|off Turn display of headers on or off",
12069 ".help ?-all? ?PATTERN? Show help text for PATTERN",
12070 ".import FILE TABLE Import data from FILE into TABLE",
Luca Stefanie7f3e802017-01-02 15:44:22 +010012071#ifndef SQLITE_OMIT_TEST_CONTROL
mydongistiny63ee58c2019-09-21 18:04:30 -070012072 ".imposter INDEX TABLE Create imposter table TABLE on index INDEX",
Luca Stefanie7f3e802017-01-02 15:44:22 +010012073#endif
mydongistiny63ee58c2019-09-21 18:04:30 -070012074 ".indexes ?TABLE? Show names of indexes",
12075 " If TABLE is specified, only show indexes for",
12076 " tables matching TABLE using the LIKE operator.",
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012077#ifdef SQLITE_ENABLE_IOTRACE
mydongistiny63ee58c2019-09-21 18:04:30 -070012078 ".iotrace FILE Enable I/O diagnostic logging to FILE",
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012079#endif
mydongistiny63ee58c2019-09-21 18:04:30 -070012080 ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
12081 ".lint OPTIONS Report potential schema issues.",
12082 " Options:",
12083 " fkey-indexes Find missing foreign key indexes",
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012084#ifndef SQLITE_OMIT_LOAD_EXTENSION
mydongistiny63ee58c2019-09-21 18:04:30 -070012085 ".load FILE ?ENTRY? Load an extension library",
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012086#endif
mydongistiny63ee58c2019-09-21 18:04:30 -070012087 ".log FILE|off Turn logging on or off. FILE can be stderr/stdout",
12088 ".mode MODE ?TABLE? Set output mode",
12089 " MODE is one of:",
12090 " ascii Columns/rows delimited by 0x1F and 0x1E",
12091 " csv Comma-separated values",
12092 " column Left-aligned columns. (See .width)",
12093 " html HTML <table> code",
12094 " insert SQL insert statements for TABLE",
12095 " line One value per line",
12096 " list Values delimited by \"|\"",
12097 " quote Escape answers as for SQL",
12098 " tabs Tab-separated values",
12099 " tcl TCL list elements",
12100 ".nullvalue STRING Use STRING in place of NULL values",
12101 ".once (-e|-x|FILE) Output for the next SQL command only to FILE",
12102 " If FILE begins with '|' then open as a pipe",
12103 " Other options:",
12104 " -e Invoke system text editor",
12105 " -x Open in a spreadsheet",
12106 ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
12107 " Options:",
12108 " --append Use appendvfs to append database to the end of FILE",
12109#ifdef SQLITE_ENABLE_DESERIALIZE
12110 " --deserialize Load into memory useing sqlite3_deserialize()",
mydongistiny8320bdc2019-10-06 12:50:35 -070012111 " --hexdb Load the output of \"dbtotxt\" as an in-memory db",
mydongistiny63ee58c2019-09-21 18:04:30 -070012112 " --maxsize N Maximum size for --hexdb or --deserialized database",
12113#endif
12114 " --new Initialize FILE to an empty database",
12115 " --readonly Open FILE readonly",
12116 " --zip FILE is a ZIP archive",
12117 ".output ?FILE? Send output to FILE or stdout if FILE is omitted",
12118 " If FILE begins with '|' then open it as a pipe.",
12119 ".parameter CMD ... Manage SQL parameter bindings",
12120 " clear Erase all bindings",
12121 " init Initialize the TEMP table that holds bindings",
12122 " list List the current parameter bindings",
12123 " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE",
mydongistiny8320bdc2019-10-06 12:50:35 -070012124 " PARAMETER should start with one of: $ : @ ?",
mydongistiny63ee58c2019-09-21 18:04:30 -070012125 " unset PARAMETER Remove PARAMETER from the binding table",
12126 ".print STRING... Print literal STRING",
12127#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
12128 ".progress N Invoke progress handler after every N opcodes",
12129 " --limit N Interrupt after N progress callbacks",
12130 " --once Do no more than one progress interrupt",
12131 " --quiet|-q No output except at interrupts",
12132 " --reset Reset the count for each input and interrupt",
12133#endif
12134 ".prompt MAIN CONTINUE Replace the standard prompts",
12135 ".quit Exit this program",
12136 ".read FILE Read input from FILE",
12137#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
12138 ".recover Recover as much data as possible from corrupt db.",
mydongistiny8320bdc2019-10-06 12:50:35 -070012139 " --freelist-corrupt Assume the freelist is corrupt",
12140 " --recovery-db NAME Store recovery metadata in database file NAME",
12141 " --lost-and-found TABLE Alternative name for the lost-and-found table",
12142 " --no-rowids Do not attempt to recover rowid values",
12143 " that are not also INTEGER PRIMARY KEYs",
mydongistiny63ee58c2019-09-21 18:04:30 -070012144#endif
12145 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
12146 ".save FILE Write in-memory database into FILE",
12147 ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
12148 ".schema ?PATTERN? Show the CREATE statements matching PATTERN",
12149 " Options:",
12150 " --indent Try to pretty-print the schema",
12151 ".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
12152 " Options:",
12153 " --init Create a new SELFTEST table",
12154 " -v Verbose output",
12155 ".separator COL ?ROW? Change the column and row separators",
Alex Naidis60fa6fd2016-07-10 14:13:38 +020012156#if defined(SQLITE_ENABLE_SESSION)
mydongistiny63ee58c2019-09-21 18:04:30 -070012157 ".session ?NAME? CMD ... Create or control sessions",
12158 " Subcommands:",
12159 " attach TABLE Attach TABLE",
12160 " changeset FILE Write a changeset into FILE",
12161 " close Close one session",
12162 " enable ?BOOLEAN? Set or query the enable bit",
12163 " filter GLOB... Reject tables matching GLOBs",
12164 " indirect ?BOOLEAN? Mark or query the indirect status",
12165 " isempty Query whether the session is empty",
12166 " list List currently open session names",
12167 " open DB NAME Open a new session on DB",
12168 " patchset FILE Write a patchset into FILE",
12169 " If ?NAME? is omitted, the first defined session is used.",
Alex Naidis60fa6fd2016-07-10 14:13:38 +020012170#endif
mydongistiny63ee58c2019-09-21 18:04:30 -070012171 ".sha3sum ... Compute a SHA3 hash of database content",
12172 " Options:",
12173 " --schema Also hash the sqlite_master table",
12174 " --sha3-224 Use the sha3-224 algorithm",
mydongistiny8320bdc2019-10-06 12:50:35 -070012175 " --sha3-256 Use the sha3-256 algorithm (default)",
mydongistiny63ee58c2019-09-21 18:04:30 -070012176 " --sha3-384 Use the sha3-384 algorithm",
12177 " --sha3-512 Use the sha3-512 algorithm",
12178 " Any other argument is a LIKE pattern for tables to hash",
12179#ifndef SQLITE_NOHAVE_SYSTEM
12180 ".shell CMD ARGS... Run CMD ARGS... in a system shell",
12181#endif
12182 ".show Show the current values for various settings",
12183 ".stats ?on|off? Show stats or turn stats on or off",
12184#ifndef SQLITE_NOHAVE_SYSTEM
12185 ".system CMD ARGS... Run CMD ARGS... in a system shell",
12186#endif
12187 ".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
12188 ".testcase NAME Begin redirecting output to 'testcase-out.txt'",
12189 ".testctrl CMD ... Run various sqlite3_test_control() operations",
12190 " Run \".testctrl\" with no arguments for details",
12191 ".timeout MS Try opening locked tables for MS milliseconds",
12192 ".timer on|off Turn SQL timer on or off",
12193#ifndef SQLITE_OMIT_TRACE
12194 ".trace ?OPTIONS? Output each SQL statement as it is run",
12195 " FILE Send output to FILE",
12196 " stdout Send output to stdout",
12197 " stderr Send output to stderr",
12198 " off Disable tracing",
12199 " --expanded Expand query parameters",
12200#ifdef SQLITE_ENABLE_NORMALIZE
12201 " --normalized Normal the SQL statements",
12202#endif
12203 " --plain Show SQL as it is input",
12204 " --stmt Trace statement execution (SQLITE_TRACE_STMT)",
12205 " --profile Profile statements (SQLITE_TRACE_PROFILE)",
12206 " --row Trace each row (SQLITE_TRACE_ROW)",
12207 " --close Trace connection close (SQLITE_TRACE_CLOSE)",
12208#endif /* SQLITE_OMIT_TRACE */
mydongistiny8320bdc2019-10-06 12:50:35 -070012209#ifdef SQLITE_DEBUG
12210 ".unmodule NAME ... Unregister virtual table modules",
12211 " --allexcept Unregister everything except those named",
12212#endif
mydongistiny63ee58c2019-09-21 18:04:30 -070012213 ".vfsinfo ?AUX? Information about the top-level VFS",
12214 ".vfslist List all available VFSes",
12215 ".vfsname ?AUX? Print the name of the VFS stack",
12216 ".width NUM1 NUM2 ... Set column widths for \"column\" mode",
12217 " Negative values right-justify",
12218};
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012219
Alex Naidis60fa6fd2016-07-10 14:13:38 +020012220/*
mydongistiny63ee58c2019-09-21 18:04:30 -070012221** Output help text.
12222**
12223** zPattern describes the set of commands for which help text is provided.
12224** If zPattern is NULL, then show all commands, but only give a one-line
12225** description of each.
12226**
12227** Return the number of matches.
Alex Naidis60fa6fd2016-07-10 14:13:38 +020012228*/
mydongistiny63ee58c2019-09-21 18:04:30 -070012229static int showHelp(FILE *out, const char *zPattern){
12230 int i = 0;
12231 int j = 0;
12232 int n = 0;
12233 char *zPat;
12234 if( zPattern==0
12235 || zPattern[0]=='0'
12236 || strcmp(zPattern,"-a")==0
12237 || strcmp(zPattern,"-all")==0
12238 ){
12239 /* Show all commands, but only one line per command */
12240 if( zPattern==0 ) zPattern = "";
12241 for(i=0; i<ArraySize(azHelp); i++){
12242 if( azHelp[i][0]=='.' || zPattern[0] ){
12243 utf8_printf(out, "%s\n", azHelp[i]);
12244 n++;
12245 }
12246 }
12247 }else{
12248 /* Look for commands that for which zPattern is an exact prefix */
12249 zPat = sqlite3_mprintf(".%s*", zPattern);
12250 for(i=0; i<ArraySize(azHelp); i++){
12251 if( sqlite3_strglob(zPat, azHelp[i])==0 ){
12252 utf8_printf(out, "%s\n", azHelp[i]);
12253 j = i+1;
12254 n++;
12255 }
12256 }
12257 sqlite3_free(zPat);
12258 if( n ){
12259 if( n==1 ){
12260 /* when zPattern is a prefix of exactly one command, then include the
12261 ** details of that command, which should begin at offset j */
12262 while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){
12263 utf8_printf(out, "%s\n", azHelp[j]);
12264 j++;
12265 }
12266 }
12267 return n;
12268 }
12269 /* Look for commands that contain zPattern anywhere. Show the complete
12270 ** text of all commands that match. */
12271 zPat = sqlite3_mprintf("%%%s%%", zPattern);
12272 for(i=0; i<ArraySize(azHelp); i++){
12273 if( azHelp[i][0]=='.' ) j = i;
12274 if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
12275 utf8_printf(out, "%s\n", azHelp[j]);
12276 while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
12277 j++;
12278 utf8_printf(out, "%s\n", azHelp[j]);
12279 }
12280 i = j;
12281 n++;
12282 }
12283 }
12284 sqlite3_free(zPat);
12285 }
12286 return n;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020012287}
Alex Naidis60fa6fd2016-07-10 14:13:38 +020012288
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012289/* Forward reference */
mydongistiny63ee58c2019-09-21 18:04:30 -070012290static int process_input(ShellState *p);
Alex Naidis08f78cb2016-10-14 15:52:08 +020012291
Alex Naidis08f78cb2016-10-14 15:52:08 +020012292/*
Luca Stefanie7f3e802017-01-02 15:44:22 +010012293** Read the content of file zName into memory obtained from sqlite3_malloc64()
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012294** and return a pointer to the buffer. The caller is responsible for freeing
12295** the memory.
Alex Naidis08f78cb2016-10-14 15:52:08 +020012296**
Luca Stefanie7f3e802017-01-02 15:44:22 +010012297** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
12298** read.
12299**
12300** For convenience, a nul-terminator byte is always appended to the data read
12301** from the file before the buffer is returned. This byte is not included in
12302** the final value of (*pnByte), if applicable.
12303**
12304** NULL is returned if any error is encountered. The final value of *pnByte
12305** is undefined in this case.
Alex Naidis08f78cb2016-10-14 15:52:08 +020012306*/
Luca Stefanie7f3e802017-01-02 15:44:22 +010012307static char *readFile(const char *zName, int *pnByte){
Alex Naidis08f78cb2016-10-14 15:52:08 +020012308 FILE *in = fopen(zName, "rb");
12309 long nIn;
12310 size_t nRead;
12311 char *pBuf;
12312 if( in==0 ) return 0;
12313 fseek(in, 0, SEEK_END);
12314 nIn = ftell(in);
12315 rewind(in);
12316 pBuf = sqlite3_malloc64( nIn+1 );
mydongistiny63ee58c2019-09-21 18:04:30 -070012317 if( pBuf==0 ){ fclose(in); return 0; }
Alex Naidis08f78cb2016-10-14 15:52:08 +020012318 nRead = fread(pBuf, nIn, 1, in);
12319 fclose(in);
12320 if( nRead!=1 ){
12321 sqlite3_free(pBuf);
12322 return 0;
12323 }
12324 pBuf[nIn] = 0;
Luca Stefanie7f3e802017-01-02 15:44:22 +010012325 if( pnByte ) *pnByte = nIn;
Alex Naidis08f78cb2016-10-14 15:52:08 +020012326 return pBuf;
12327}
12328
Alex Naidis60fa6fd2016-07-10 14:13:38 +020012329#if defined(SQLITE_ENABLE_SESSION)
12330/*
12331** Close a single OpenSession object and release all of its associated
12332** resources.
12333*/
12334static void session_close(OpenSession *pSession){
12335 int i;
12336 sqlite3session_delete(pSession->p);
12337 sqlite3_free(pSession->zName);
12338 for(i=0; i<pSession->nFilter; i++){
12339 sqlite3_free(pSession->azFilter[i]);
12340 }
12341 sqlite3_free(pSession->azFilter);
12342 memset(pSession, 0, sizeof(OpenSession));
12343}
12344#endif
12345
12346/*
12347** Close all OpenSession objects and release all associated resources.
12348*/
12349#if defined(SQLITE_ENABLE_SESSION)
12350static void session_close_all(ShellState *p){
12351 int i;
12352 for(i=0; i<p->nSession; i++){
12353 session_close(&p->aSession[i]);
12354 }
12355 p->nSession = 0;
12356}
12357#else
12358# define session_close_all(X)
12359#endif
12360
12361/*
12362** Implementation of the xFilter function for an open session. Omit
12363** any tables named by ".session filter" but let all other table through.
12364*/
12365#if defined(SQLITE_ENABLE_SESSION)
12366static int session_filter(void *pCtx, const char *zTab){
12367 OpenSession *pSession = (OpenSession*)pCtx;
12368 int i;
12369 for(i=0; i<pSession->nFilter; i++){
12370 if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
12371 }
12372 return 1;
12373}
12374#endif
12375
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012376/*
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012377** Try to deduce the type of file for zName based on its content. Return
12378** one of the SHELL_OPEN_* constants.
mydongistiny63ee58c2019-09-21 18:04:30 -070012379**
12380** If the file does not exist or is empty but its name looks like a ZIP
12381** archive and the dfltZip flag is true, then assume it is a ZIP archive.
12382** Otherwise, assume an ordinary database regardless of the filename if
12383** the type cannot be determined from content.
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012384*/
mydongistiny63ee58c2019-09-21 18:04:30 -070012385int deduceDatabaseType(const char *zName, int dfltZip){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012386 FILE *f = fopen(zName, "rb");
12387 size_t n;
12388 int rc = SHELL_OPEN_UNSPEC;
12389 char zBuf[100];
mydongistiny63ee58c2019-09-21 18:04:30 -070012390 if( f==0 ){
12391 if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
12392 return SHELL_OPEN_ZIPFILE;
12393 }else{
12394 return SHELL_OPEN_NORMAL;
12395 }
12396 }
12397 n = fread(zBuf, 16, 1, f);
12398 if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
12399 fclose(f);
12400 return SHELL_OPEN_NORMAL;
12401 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012402 fseek(f, -25, SEEK_END);
12403 n = fread(zBuf, 25, 1, f);
12404 if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
12405 rc = SHELL_OPEN_APPENDVFS;
12406 }else{
12407 fseek(f, -22, SEEK_END);
12408 n = fread(zBuf, 22, 1, f);
12409 if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
12410 && zBuf[3]==0x06 ){
12411 rc = SHELL_OPEN_ZIPFILE;
mydongistiny63ee58c2019-09-21 18:04:30 -070012412 }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
12413 rc = SHELL_OPEN_ZIPFILE;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012414 }
12415 }
12416 fclose(f);
12417 return rc;
12418}
12419
mydongistiny63ee58c2019-09-21 18:04:30 -070012420#ifdef SQLITE_ENABLE_DESERIALIZE
12421/*
12422** Reconstruct an in-memory database using the output from the "dbtotxt"
12423** program. Read content from the file in p->zDbFilename. If p->zDbFilename
12424** is 0, then read from standard input.
12425*/
12426static unsigned char *readHexDb(ShellState *p, int *pnData){
12427 unsigned char *a = 0;
12428 int nLine;
12429 int n = 0;
12430 int pgsz = 0;
12431 int iOffset = 0;
12432 int j, k;
12433 int rc;
12434 FILE *in;
12435 unsigned int x[16];
12436 char zLine[1000];
12437 if( p->zDbFilename ){
12438 in = fopen(p->zDbFilename, "r");
12439 if( in==0 ){
12440 utf8_printf(stderr, "cannot open \"%s\" for reading\n", p->zDbFilename);
12441 return 0;
12442 }
12443 nLine = 0;
12444 }else{
12445 in = p->in;
12446 nLine = p->lineno;
12447 if( in==0 ) in = stdin;
12448 }
12449 *pnData = 0;
12450 nLine++;
12451 if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
12452 rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
12453 if( rc!=2 ) goto readHexDb_error;
12454 if( n<0 ) goto readHexDb_error;
mydongistiny8320bdc2019-10-06 12:50:35 -070012455 if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
12456 n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */
mydongistiny63ee58c2019-09-21 18:04:30 -070012457 a = sqlite3_malloc( n ? n : 1 );
12458 if( a==0 ){
12459 utf8_printf(stderr, "Out of memory!\n");
12460 goto readHexDb_error;
12461 }
12462 memset(a, 0, n);
12463 if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
12464 utf8_printf(stderr, "invalid pagesize\n");
12465 goto readHexDb_error;
12466 }
12467 for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
12468 rc = sscanf(zLine, "| page %d offset %d", &j, &k);
12469 if( rc==2 ){
12470 iOffset = k;
12471 continue;
12472 }
12473 if( strncmp(zLine, "| end ", 6)==0 ){
12474 break;
12475 }
12476 rc = sscanf(zLine,"| %d: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
12477 &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
12478 &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
12479 if( rc==17 ){
12480 k = iOffset+j;
12481 if( k+16<=n ){
12482 int ii;
12483 for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
12484 }
12485 }
12486 }
12487 *pnData = n;
12488 if( in!=p->in ){
12489 fclose(in);
12490 }else{
12491 p->lineno = nLine;
12492 }
12493 return a;
12494
12495readHexDb_error:
12496 if( in!=p->in ){
12497 fclose(in);
12498 }else{
12499 while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
12500 nLine++;
12501 if(strncmp(zLine, "| end ", 6)==0 ) break;
12502 }
12503 p->lineno = nLine;
12504 }
12505 sqlite3_free(a);
12506 utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
12507 return 0;
12508}
12509#endif /* SQLITE_ENABLE_DESERIALIZE */
12510
12511/*
12512** Scalar function "shell_int32". The first argument to this function
12513** must be a blob. The second a non-negative integer. This function
12514** reads and returns a 32-bit big-endian integer from byte
12515** offset (4*<arg2>) of the blob.
12516*/
12517static void shellInt32(
12518 sqlite3_context *context,
12519 int argc,
12520 sqlite3_value **argv
12521){
12522 const unsigned char *pBlob;
12523 int nBlob;
12524 int iInt;
12525
12526 UNUSED_PARAMETER(argc);
12527 nBlob = sqlite3_value_bytes(argv[0]);
12528 pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
12529 iInt = sqlite3_value_int(argv[1]);
12530
12531 if( iInt>=0 && (iInt+1)*4<=nBlob ){
12532 const unsigned char *a = &pBlob[iInt*4];
12533 sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24)
12534 + ((sqlite3_int64)a[1]<<16)
12535 + ((sqlite3_int64)a[2]<< 8)
12536 + ((sqlite3_int64)a[3]<< 0);
12537 sqlite3_result_int64(context, iVal);
12538 }
12539}
12540
12541/*
mydongistiny8320bdc2019-10-06 12:50:35 -070012542** Scalar function "shell_idquote(X)" returns string X quoted as an identifier,
12543** using "..." with internal double-quote characters doubled.
12544*/
12545static void shellIdQuote(
12546 sqlite3_context *context,
12547 int argc,
12548 sqlite3_value **argv
12549){
12550 const char *zName = (const char*)sqlite3_value_text(argv[0]);
12551 UNUSED_PARAMETER(argc);
12552 if( zName ){
12553 char *z = sqlite3_mprintf("\"%w\"", zName);
12554 sqlite3_result_text(context, z, -1, sqlite3_free);
12555 }
12556}
12557
12558/*
mydongistiny63ee58c2019-09-21 18:04:30 -070012559** Scalar function "shell_escape_crnl" used by the .recover command.
12560** The argument passed to this function is the output of built-in
12561** function quote(). If the first character of the input is "'",
12562** indicating that the value passed to quote() was a text value,
12563** then this function searches the input for "\n" and "\r" characters
12564** and adds a wrapper similar to the following:
12565**
12566** replace(replace(<input>, '\n', char(10), '\r', char(13));
12567**
12568** Or, if the first character of the input is not "'", then a copy
12569** of the input is returned.
12570*/
12571static void shellEscapeCrnl(
12572 sqlite3_context *context,
12573 int argc,
12574 sqlite3_value **argv
12575){
12576 const char *zText = (const char*)sqlite3_value_text(argv[0]);
12577 UNUSED_PARAMETER(argc);
12578 if( zText[0]=='\'' ){
12579 int nText = sqlite3_value_bytes(argv[0]);
12580 int i;
12581 char zBuf1[20];
12582 char zBuf2[20];
12583 const char *zNL = 0;
12584 const char *zCR = 0;
12585 int nCR = 0;
12586 int nNL = 0;
12587
12588 for(i=0; zText[i]; i++){
12589 if( zNL==0 && zText[i]=='\n' ){
12590 zNL = unused_string(zText, "\\n", "\\012", zBuf1);
12591 nNL = (int)strlen(zNL);
12592 }
12593 if( zCR==0 && zText[i]=='\r' ){
12594 zCR = unused_string(zText, "\\r", "\\015", zBuf2);
12595 nCR = (int)strlen(zCR);
12596 }
12597 }
12598
12599 if( zNL || zCR ){
12600 int iOut = 0;
12601 i64 nMax = (nNL > nCR) ? nNL : nCR;
12602 i64 nAlloc = nMax * nText + (nMax+64)*2;
12603 char *zOut = (char*)sqlite3_malloc64(nAlloc);
12604 if( zOut==0 ){
12605 sqlite3_result_error_nomem(context);
12606 return;
12607 }
12608
12609 if( zNL && zCR ){
12610 memcpy(&zOut[iOut], "replace(replace(", 16);
12611 iOut += 16;
12612 }else{
12613 memcpy(&zOut[iOut], "replace(", 8);
12614 iOut += 8;
12615 }
12616 for(i=0; zText[i]; i++){
12617 if( zText[i]=='\n' ){
12618 memcpy(&zOut[iOut], zNL, nNL);
12619 iOut += nNL;
12620 }else if( zText[i]=='\r' ){
12621 memcpy(&zOut[iOut], zCR, nCR);
12622 iOut += nCR;
12623 }else{
12624 zOut[iOut] = zText[i];
12625 iOut++;
12626 }
12627 }
12628
12629 if( zNL ){
12630 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
12631 memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
12632 memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
12633 }
12634 if( zCR ){
12635 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
12636 memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
12637 memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
12638 }
12639
12640 sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
12641 sqlite3_free(zOut);
12642 return;
12643 }
12644 }
12645
12646 sqlite3_result_value(context, argv[0]);
12647}
12648
12649/* Flags for open_db().
12650**
12651** The default behavior of open_db() is to exit(1) if the database fails to
12652** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
12653** but still returns without calling exit.
12654**
12655** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a
12656** ZIP archive if the file does not exist or is empty and its name matches
12657** the *.zip pattern.
12658*/
12659#define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */
12660#define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */
12661
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012662/*
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012663** Make sure the database is open. If it is not, then open it. If
12664** the database fails to open, print an error message and exit.
12665*/
mydongistiny63ee58c2019-09-21 18:04:30 -070012666static void open_db(ShellState *p, int openFlags){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012667 if( p->db==0 ){
mydongistiny63ee58c2019-09-21 18:04:30 -070012668 if( p->openMode==SHELL_OPEN_UNSPEC ){
12669 if( p->zDbFilename==0 || p->zDbFilename[0]==0 ){
12670 p->openMode = SHELL_OPEN_NORMAL;
12671 }else{
12672 p->openMode = (u8)deduceDatabaseType(p->zDbFilename,
12673 (openFlags & OPEN_DB_ZIPFILE)!=0);
12674 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012675 }
12676 switch( p->openMode ){
12677 case SHELL_OPEN_APPENDVFS: {
12678 sqlite3_open_v2(p->zDbFilename, &p->db,
12679 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "apndvfs");
12680 break;
12681 }
mydongistiny63ee58c2019-09-21 18:04:30 -070012682 case SHELL_OPEN_HEXDB:
12683 case SHELL_OPEN_DESERIALIZE: {
12684 sqlite3_open(0, &p->db);
12685 break;
12686 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012687 case SHELL_OPEN_ZIPFILE: {
12688 sqlite3_open(":memory:", &p->db);
12689 break;
12690 }
mydongistiny63ee58c2019-09-21 18:04:30 -070012691 case SHELL_OPEN_READONLY: {
12692 sqlite3_open_v2(p->zDbFilename, &p->db, SQLITE_OPEN_READONLY, 0);
12693 break;
12694 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012695 case SHELL_OPEN_UNSPEC:
12696 case SHELL_OPEN_NORMAL: {
12697 sqlite3_open(p->zDbFilename, &p->db);
12698 break;
12699 }
12700 }
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070012701 globalDb = p->db;
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070012702 if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020012703 utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070012704 p->zDbFilename, sqlite3_errmsg(p->db));
mydongistiny63ee58c2019-09-21 18:04:30 -070012705 if( openFlags & OPEN_DB_KEEPALIVE ){
12706 sqlite3_open(":memory:", &p->db);
12707 return;
12708 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012709 exit(1);
12710 }
12711#ifndef SQLITE_OMIT_LOAD_EXTENSION
12712 sqlite3_enable_load_extension(p->db, 1);
12713#endif
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012714 sqlite3_fileio_init(p->db, 0, 0);
12715 sqlite3_shathree_init(p->db, 0, 0);
12716 sqlite3_completion_init(p->db, 0, 0);
mydongistiny63ee58c2019-09-21 18:04:30 -070012717#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
12718 sqlite3_dbdata_init(p->db, 0, 0);
12719#endif
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012720#ifdef SQLITE_HAVE_ZLIB
12721 sqlite3_zipfile_init(p->db, 0, 0);
12722 sqlite3_sqlar_init(p->db, 0, 0);
12723#endif
12724 sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
12725 shellAddSchemaName, 0, 0);
12726 sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
12727 shellModuleSchema, 0, 0);
12728 sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
12729 shellPutsFunc, 0, 0);
mydongistiny63ee58c2019-09-21 18:04:30 -070012730 sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0,
12731 shellEscapeCrnl, 0, 0);
12732 sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
12733 shellInt32, 0, 0);
mydongistiny8320bdc2019-10-06 12:50:35 -070012734 sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
12735 shellIdQuote, 0, 0);
mydongistiny63ee58c2019-09-21 18:04:30 -070012736#ifndef SQLITE_NOHAVE_SYSTEM
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012737 sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
12738 editFunc, 0, 0);
12739 sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
12740 editFunc, 0, 0);
mydongistiny63ee58c2019-09-21 18:04:30 -070012741#endif
12742// Begin Android Add
12743#ifndef NO_ANDROID_FUNCS
12744 AIcu_initializeIcuOrDie();
12745 int err = register_localized_collators(p->db, "en_US", 0);
12746 if (err != SQLITE_OK) {
12747 fprintf(stderr, "register_localized_collators() failed\n");
12748 exit(1);
12749 }
12750 err = register_android_functions(p->db, 0);
12751 if (err != SQLITE_OK) {
12752 fprintf(stderr, "register_android_functions() failed\n");
12753 exit(1);
12754 }
12755#endif
12756// End Android Add
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012757 if( p->openMode==SHELL_OPEN_ZIPFILE ){
12758 char *zSql = sqlite3_mprintf(
12759 "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename);
12760 sqlite3_exec(p->db, zSql, 0, 0, 0);
12761 sqlite3_free(zSql);
12762 }
mydongistiny63ee58c2019-09-21 18:04:30 -070012763#ifdef SQLITE_ENABLE_DESERIALIZE
12764 else
12765 if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
12766 int rc;
12767 int nData = 0;
12768 unsigned char *aData;
12769 if( p->openMode==SHELL_OPEN_DESERIALIZE ){
12770 aData = (unsigned char*)readFile(p->zDbFilename, &nData);
12771 }else{
12772 aData = readHexDb(p, &nData);
12773 if( aData==0 ){
12774 return;
12775 }
12776 }
12777 rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
12778 SQLITE_DESERIALIZE_RESIZEABLE |
12779 SQLITE_DESERIALIZE_FREEONCLOSE);
12780 if( rc ){
12781 utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
12782 }
12783 if( p->szMax>0 ){
12784 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
12785 }
12786 }
12787#endif
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012788 }
12789}
12790
mydongistiny63ee58c2019-09-21 18:04:30 -070012791/*
12792** Attempt to close the databaes connection. Report errors.
12793*/
12794void close_db(sqlite3 *db){
12795 int rc = sqlite3_close(db);
12796 if( rc ){
12797 utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
12798 rc, sqlite3_errmsg(db));
12799 }
12800}
12801
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012802#if HAVE_READLINE || HAVE_EDITLINE
12803/*
12804** Readline completion callbacks
12805*/
12806static char *readline_completion_generator(const char *text, int state){
12807 static sqlite3_stmt *pStmt = 0;
12808 char *zRet;
12809 if( state==0 ){
12810 char *zSql;
12811 sqlite3_finalize(pStmt);
12812 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
12813 " FROM completion(%Q) ORDER BY 1", text);
12814 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
12815 sqlite3_free(zSql);
12816 }
12817 if( sqlite3_step(pStmt)==SQLITE_ROW ){
12818 zRet = strdup((const char*)sqlite3_column_text(pStmt, 0));
12819 }else{
12820 sqlite3_finalize(pStmt);
12821 pStmt = 0;
12822 zRet = 0;
12823 }
12824 return zRet;
12825}
12826static char **readline_completion(const char *zText, int iStart, int iEnd){
12827 rl_attempted_completion_over = 1;
12828 return rl_completion_matches(zText, readline_completion_generator);
12829}
12830
12831#elif HAVE_LINENOISE
12832/*
12833** Linenoise completion callback
12834*/
12835static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
12836 int nLine = strlen30(zLine);
12837 int i, iStart;
12838 sqlite3_stmt *pStmt = 0;
12839 char *zSql;
12840 char zBuf[1000];
12841
12842 if( nLine>sizeof(zBuf)-30 ) return;
mydongistiny63ee58c2019-09-21 18:04:30 -070012843 if( zLine[0]=='.' || zLine[0]=='#') return;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012844 for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
12845 if( i==nLine-1 ) return;
12846 iStart = i+1;
12847 memcpy(zBuf, zLine, iStart);
12848 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
12849 " FROM completion(%Q,%Q) ORDER BY 1",
12850 &zLine[iStart], zLine);
12851 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
12852 sqlite3_free(zSql);
12853 sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
12854 while( sqlite3_step(pStmt)==SQLITE_ROW ){
12855 const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
12856 int nCompletion = sqlite3_column_bytes(pStmt, 0);
12857 if( iStart+nCompletion < sizeof(zBuf)-1 ){
12858 memcpy(zBuf+iStart, zCompletion, nCompletion+1);
12859 linenoiseAddCompletion(lc, zBuf);
12860 }
12861 }
12862 sqlite3_finalize(pStmt);
12863}
12864#endif
12865
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012866/*
12867** Do C-language style dequoting.
12868**
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070012869** \a -> alarm
12870** \b -> backspace
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012871** \t -> tab
12872** \n -> newline
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070012873** \v -> vertical tab
12874** \f -> form feed
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012875** \r -> carriage return
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070012876** \s -> space
Nick Kralevich8fecf562014-05-29 16:56:33 -070012877** \" -> "
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070012878** \' -> '
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012879** \\ -> backslash
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070012880** \NNN -> ascii character NNN in octal
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012881*/
12882static void resolve_backslashes(char *z){
Vasu Noria4356a02010-01-20 15:10:57 -080012883 int i, j;
12884 char c;
Nick Kralevich1c7cea32014-06-06 19:53:11 -070012885 while( *z && *z!='\\' ) z++;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012886 for(i=j=0; (c = z[i])!=0; i++, j++){
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070012887 if( c=='\\' && z[i+1]!=0 ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012888 c = z[++i];
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070012889 if( c=='a' ){
12890 c = '\a';
12891 }else if( c=='b' ){
12892 c = '\b';
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012893 }else if( c=='t' ){
12894 c = '\t';
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070012895 }else if( c=='n' ){
12896 c = '\n';
12897 }else if( c=='v' ){
12898 c = '\v';
12899 }else if( c=='f' ){
12900 c = '\f';
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012901 }else if( c=='r' ){
12902 c = '\r';
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070012903 }else if( c=='"' ){
12904 c = '"';
12905 }else if( c=='\'' ){
12906 c = '\'';
Nick Kralevich8fecf562014-05-29 16:56:33 -070012907 }else if( c=='\\' ){
12908 c = '\\';
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012909 }else if( c>='0' && c<='7' ){
12910 c -= '0';
12911 if( z[i+1]>='0' && z[i+1]<='7' ){
12912 i++;
12913 c = (c<<3) + z[i] - '0';
12914 if( z[i+1]>='0' && z[i+1]<='7' ){
12915 i++;
12916 c = (c<<3) + z[i] - '0';
12917 }
12918 }
12919 }
12920 }
12921 z[j] = c;
12922 }
Nick Kralevich1c7cea32014-06-06 19:53:11 -070012923 if( j<i ) z[j] = 0;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012924}
12925
12926/*
Nick Kralevich8fecf562014-05-29 16:56:33 -070012927** Interpret zArg as either an integer or a boolean value. Return 1 or 0
12928** for TRUE and FALSE. Return the integer value if appropriate.
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012929*/
Alex Naidisb86c0cf2017-03-31 14:12:35 +020012930static int booleanValue(const char *zArg){
Nick Kralevich8fecf562014-05-29 16:56:33 -070012931 int i;
12932 if( zArg[0]=='0' && zArg[1]=='x' ){
12933 for(i=2; hexDigitValue(zArg[i])>=0; i++){}
12934 }else{
12935 for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012936 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070012937 if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
12938 if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
12939 return 1;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080012940 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070012941 if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
12942 return 0;
12943 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020012944 utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
Nick Kralevich8fecf562014-05-29 16:56:33 -070012945 zArg);
12946 return 0;
12947}
12948
12949/*
Alex Naidisb86c0cf2017-03-31 14:12:35 +020012950** Set or clear a shell flag according to a boolean value.
12951*/
12952static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){
12953 if( booleanValue(zArg) ){
12954 ShellSetFlag(p, mFlag);
12955 }else{
12956 ShellClearFlag(p, mFlag);
12957 }
12958}
12959
12960/*
Nick Kralevich8fecf562014-05-29 16:56:33 -070012961** Close an output file, assuming it is not stderr or stdout
12962*/
12963static void output_file_close(FILE *f){
12964 if( f && f!=stdout && f!=stderr ) fclose(f);
12965}
12966
12967/*
12968** Try to open an output file. The names "stdout" and "stderr" are
Alex Naidis60fa6fd2016-07-10 14:13:38 +020012969** recognized and do the right thing. NULL is returned if the output
Nick Kralevich8fecf562014-05-29 16:56:33 -070012970** filename is "off".
12971*/
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012972static FILE *output_file_open(const char *zFile, int bTextMode){
Nick Kralevich8fecf562014-05-29 16:56:33 -070012973 FILE *f;
12974 if( strcmp(zFile,"stdout")==0 ){
12975 f = stdout;
12976 }else if( strcmp(zFile, "stderr")==0 ){
12977 f = stderr;
12978 }else if( strcmp(zFile, "off")==0 ){
12979 f = 0;
12980 }else{
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080012981 f = fopen(zFile, bTextMode ? "w" : "wb");
Nick Kralevich8fecf562014-05-29 16:56:33 -070012982 if( f==0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020012983 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
Nick Kralevich8fecf562014-05-29 16:56:33 -070012984 }
12985 }
12986 return f;
12987}
12988
mydongistiny63ee58c2019-09-21 18:04:30 -070012989#ifndef SQLITE_OMIT_TRACE
Nick Kralevich8fecf562014-05-29 16:56:33 -070012990/*
12991** A routine for handling output from sqlite3_trace().
12992*/
Alex Naidis74bd39c2016-08-09 00:53:11 +020012993static int sql_trace_callback(
mydongistiny63ee58c2019-09-21 18:04:30 -070012994 unsigned mType, /* The trace type */
12995 void *pArg, /* The ShellState pointer */
12996 void *pP, /* Usually a pointer to sqlite_stmt */
12997 void *pX /* Auxiliary output */
Alex Naidis74bd39c2016-08-09 00:53:11 +020012998){
mydongistiny63ee58c2019-09-21 18:04:30 -070012999 ShellState *p = (ShellState*)pArg;
13000 sqlite3_stmt *pStmt;
13001 const char *zSql;
13002 int nSql;
13003 if( p->traceOut==0 ) return 0;
13004 if( mType==SQLITE_TRACE_CLOSE ){
13005 utf8_printf(p->traceOut, "-- closing database connection\n");
13006 return 0;
13007 }
13008 if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){
13009 zSql = (const char*)pX;
13010 }else{
13011 pStmt = (sqlite3_stmt*)pP;
13012 switch( p->eTraceType ){
13013 case SHELL_TRACE_EXPANDED: {
13014 zSql = sqlite3_expanded_sql(pStmt);
13015 break;
13016 }
13017#ifdef SQLITE_ENABLE_NORMALIZE
13018 case SHELL_TRACE_NORMALIZED: {
13019 zSql = sqlite3_normalized_sql(pStmt);
13020 break;
13021 }
13022#endif
13023 default: {
13024 zSql = sqlite3_sql(pStmt);
13025 break;
13026 }
13027 }
13028 }
13029 if( zSql==0 ) return 0;
13030 nSql = strlen30(zSql);
13031 while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
13032 switch( mType ){
13033 case SQLITE_TRACE_ROW:
13034 case SQLITE_TRACE_STMT: {
13035 utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql);
13036 break;
13037 }
13038 case SQLITE_TRACE_PROFILE: {
13039 sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
13040 utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec);
13041 break;
13042 }
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013043 }
Alex Naidis74bd39c2016-08-09 00:53:11 +020013044 return 0;
Nick Kralevich8fecf562014-05-29 16:56:33 -070013045}
Luca Stefanie7f3e802017-01-02 15:44:22 +010013046#endif
Nick Kralevich8fecf562014-05-29 16:56:33 -070013047
13048/*
13049** A no-op routine that runs with the ".breakpoint" doc-command. This is
13050** a useful spot to set a debugger breakpoint.
13051*/
13052static void test_breakpoint(void){
13053 static int nCall = 0;
13054 nCall++;
13055}
13056
13057/*
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013058** An object used to read a CSV and other files for import.
Nick Kralevich8fecf562014-05-29 16:56:33 -070013059*/
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013060typedef struct ImportCtx ImportCtx;
13061struct ImportCtx {
Nick Kralevich8fecf562014-05-29 16:56:33 -070013062 const char *zFile; /* Name of the input file */
13063 FILE *in; /* Read the CSV text from this input stream */
13064 char *z; /* Accumulated text for a field */
13065 int n; /* Number of bytes in z */
13066 int nAlloc; /* Space allocated for z[] */
13067 int nLine; /* Current line number */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013068 int bNotFirst; /* True if one or more bytes already read */
Nick Kralevich8fecf562014-05-29 16:56:33 -070013069 int cTerm; /* Character that terminated the most recent field */
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013070 int cColSep; /* The column separator character. (Usually ",") */
13071 int cRowSep; /* The row separator character. (Usually "\n") */
Nick Kralevich8fecf562014-05-29 16:56:33 -070013072};
13073
13074/* Append a single byte to z[] */
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013075static void import_append_char(ImportCtx *p, int c){
Nick Kralevich8fecf562014-05-29 16:56:33 -070013076 if( p->n+1>=p->nAlloc ){
13077 p->nAlloc += p->nAlloc + 100;
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070013078 p->z = sqlite3_realloc64(p->z, p->nAlloc);
mydongistiny63ee58c2019-09-21 18:04:30 -070013079 if( p->z==0 ) shell_out_of_memory();
Nick Kralevich8fecf562014-05-29 16:56:33 -070013080 }
13081 p->z[p->n++] = (char)c;
13082}
13083
13084/* Read a single field of CSV text. Compatible with rfc4180 and extended
13085** with the option of having a separator other than ",".
13086**
13087** + Input comes from p->in.
13088** + Store results in p->z of length p->n. Space to hold p->z comes
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070013089** from sqlite3_malloc64().
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013090** + Use p->cSep as the column separator. The default is ",".
13091** + Use p->rSep as the row separator. The default is "\n".
Nick Kralevich8fecf562014-05-29 16:56:33 -070013092** + Keep track of the line number in p->nLine.
13093** + Store the character that terminates the field in p->cTerm. Store
13094** EOF on end-of-file.
13095** + Report syntax errors on stderr
13096*/
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013097static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
13098 int c;
13099 int cSep = p->cColSep;
13100 int rSep = p->cRowSep;
Nick Kralevich8fecf562014-05-29 16:56:33 -070013101 p->n = 0;
13102 c = fgetc(p->in);
13103 if( c==EOF || seenInterrupt ){
13104 p->cTerm = EOF;
13105 return 0;
13106 }
13107 if( c=='"' ){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013108 int pc, ppc;
Nick Kralevich8fecf562014-05-29 16:56:33 -070013109 int startLine = p->nLine;
13110 int cQuote = c;
13111 pc = ppc = 0;
13112 while( 1 ){
13113 c = fgetc(p->in);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013114 if( c==rSep ) p->nLine++;
Nick Kralevich8fecf562014-05-29 16:56:33 -070013115 if( c==cQuote ){
13116 if( pc==cQuote ){
13117 pc = 0;
13118 continue;
13119 }
13120 }
13121 if( (c==cSep && pc==cQuote)
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013122 || (c==rSep && pc==cQuote)
13123 || (c==rSep && pc=='\r' && ppc==cQuote)
Nick Kralevich8fecf562014-05-29 16:56:33 -070013124 || (c==EOF && pc==cQuote)
13125 ){
13126 do{ p->n--; }while( p->z[p->n]!=cQuote );
13127 p->cTerm = c;
13128 break;
13129 }
13130 if( pc==cQuote && c!='\r' ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013131 utf8_printf(stderr, "%s:%d: unescaped %c character\n",
Nick Kralevich8fecf562014-05-29 16:56:33 -070013132 p->zFile, p->nLine, cQuote);
13133 }
13134 if( c==EOF ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013135 utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
Nick Kralevich8fecf562014-05-29 16:56:33 -070013136 p->zFile, startLine, cQuote);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013137 p->cTerm = c;
Nick Kralevich8fecf562014-05-29 16:56:33 -070013138 break;
13139 }
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013140 import_append_char(p, c);
Nick Kralevich8fecf562014-05-29 16:56:33 -070013141 ppc = pc;
13142 pc = c;
13143 }
13144 }else{
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013145 /* If this is the first field being parsed and it begins with the
13146 ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
13147 if( (c&0xff)==0xef && p->bNotFirst==0 ){
13148 import_append_char(p, c);
13149 c = fgetc(p->in);
13150 if( (c&0xff)==0xbb ){
13151 import_append_char(p, c);
13152 c = fgetc(p->in);
13153 if( (c&0xff)==0xbf ){
13154 p->bNotFirst = 1;
13155 p->n = 0;
13156 return csv_read_one_field(p);
13157 }
13158 }
13159 }
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013160 while( c!=EOF && c!=cSep && c!=rSep ){
13161 import_append_char(p, c);
Nick Kralevich8fecf562014-05-29 16:56:33 -070013162 c = fgetc(p->in);
13163 }
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013164 if( c==rSep ){
Nick Kralevich8fecf562014-05-29 16:56:33 -070013165 p->nLine++;
13166 if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
13167 }
13168 p->cTerm = c;
13169 }
13170 if( p->z ) p->z[p->n] = 0;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013171 p->bNotFirst = 1;
Nick Kralevich8fecf562014-05-29 16:56:33 -070013172 return p->z;
13173}
13174
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013175/* Read a single field of ASCII delimited text.
13176**
13177** + Input comes from p->in.
13178** + Store results in p->z of length p->n. Space to hold p->z comes
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070013179** from sqlite3_malloc64().
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013180** + Use p->cSep as the column separator. The default is "\x1F".
13181** + Use p->rSep as the row separator. The default is "\x1E".
13182** + Keep track of the row number in p->nLine.
13183** + Store the character that terminates the field in p->cTerm. Store
13184** EOF on end-of-file.
13185** + Report syntax errors on stderr
13186*/
13187static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
13188 int c;
13189 int cSep = p->cColSep;
13190 int rSep = p->cRowSep;
13191 p->n = 0;
13192 c = fgetc(p->in);
13193 if( c==EOF || seenInterrupt ){
13194 p->cTerm = EOF;
13195 return 0;
13196 }
13197 while( c!=EOF && c!=cSep && c!=rSep ){
13198 import_append_char(p, c);
13199 c = fgetc(p->in);
13200 }
13201 if( c==rSep ){
13202 p->nLine++;
13203 }
13204 p->cTerm = c;
13205 if( p->z ) p->z[p->n] = 0;
13206 return p->z;
13207}
13208
Nick Kralevich8fecf562014-05-29 16:56:33 -070013209/*
13210** Try to transfer data for table zTable. If an error is seen while
13211** moving forward, try to go backwards. The backwards movement won't
13212** work for WITHOUT ROWID tables.
13213*/
13214static void tryToCloneData(
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013215 ShellState *p,
Nick Kralevich8fecf562014-05-29 16:56:33 -070013216 sqlite3 *newDb,
13217 const char *zTable
13218){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013219 sqlite3_stmt *pQuery = 0;
Nick Kralevich8fecf562014-05-29 16:56:33 -070013220 sqlite3_stmt *pInsert = 0;
13221 char *zQuery = 0;
13222 char *zInsert = 0;
13223 int rc;
13224 int i, j, n;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013225 int nTable = strlen30(zTable);
Nick Kralevich8fecf562014-05-29 16:56:33 -070013226 int k = 0;
13227 int cnt = 0;
13228 const int spinRate = 10000;
13229
13230 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
13231 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
13232 if( rc ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013233 utf8_printf(stderr, "Error %d: %s on [%s]\n",
Nick Kralevich8fecf562014-05-29 16:56:33 -070013234 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
13235 zQuery);
13236 goto end_data_xfer;
13237 }
13238 n = sqlite3_column_count(pQuery);
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070013239 zInsert = sqlite3_malloc64(200 + nTable + n*3);
mydongistiny63ee58c2019-09-21 18:04:30 -070013240 if( zInsert==0 ) shell_out_of_memory();
Nick Kralevich8fecf562014-05-29 16:56:33 -070013241 sqlite3_snprintf(200+nTable,zInsert,
13242 "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013243 i = strlen30(zInsert);
Nick Kralevich8fecf562014-05-29 16:56:33 -070013244 for(j=1; j<n; j++){
13245 memcpy(zInsert+i, ",?", 2);
13246 i += 2;
13247 }
13248 memcpy(zInsert+i, ");", 3);
13249 rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
13250 if( rc ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013251 utf8_printf(stderr, "Error %d: %s on [%s]\n",
Nick Kralevich8fecf562014-05-29 16:56:33 -070013252 sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
13253 zQuery);
13254 goto end_data_xfer;
13255 }
13256 for(k=0; k<2; k++){
13257 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
13258 for(i=0; i<n; i++){
13259 switch( sqlite3_column_type(pQuery, i) ){
13260 case SQLITE_NULL: {
13261 sqlite3_bind_null(pInsert, i+1);
13262 break;
13263 }
13264 case SQLITE_INTEGER: {
13265 sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
13266 break;
13267 }
13268 case SQLITE_FLOAT: {
13269 sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
13270 break;
13271 }
13272 case SQLITE_TEXT: {
13273 sqlite3_bind_text(pInsert, i+1,
13274 (const char*)sqlite3_column_text(pQuery,i),
13275 -1, SQLITE_STATIC);
13276 break;
13277 }
13278 case SQLITE_BLOB: {
13279 sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
13280 sqlite3_column_bytes(pQuery,i),
13281 SQLITE_STATIC);
13282 break;
13283 }
13284 }
13285 } /* End for */
13286 rc = sqlite3_step(pInsert);
13287 if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013288 utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
Nick Kralevich8fecf562014-05-29 16:56:33 -070013289 sqlite3_errmsg(newDb));
13290 }
13291 sqlite3_reset(pInsert);
13292 cnt++;
13293 if( (cnt%spinRate)==0 ){
13294 printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
13295 fflush(stdout);
13296 }
13297 } /* End while */
13298 if( rc==SQLITE_DONE ) break;
13299 sqlite3_finalize(pQuery);
13300 sqlite3_free(zQuery);
13301 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
13302 zTable);
13303 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
13304 if( rc ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013305 utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
Nick Kralevich8fecf562014-05-29 16:56:33 -070013306 break;
13307 }
13308 } /* End for(k=0...) */
13309
13310end_data_xfer:
13311 sqlite3_finalize(pQuery);
13312 sqlite3_finalize(pInsert);
13313 sqlite3_free(zQuery);
13314 sqlite3_free(zInsert);
13315}
13316
13317
13318/*
13319** Try to transfer all rows of the schema that match zWhere. For
13320** each row, invoke xForEach() on the object defined by that row.
13321** If an error is encountered while moving forward through the
13322** sqlite_master table, try again moving backwards.
13323*/
13324static void tryToCloneSchema(
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013325 ShellState *p,
Nick Kralevich8fecf562014-05-29 16:56:33 -070013326 sqlite3 *newDb,
13327 const char *zWhere,
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013328 void (*xForEach)(ShellState*,sqlite3*,const char*)
Nick Kralevich8fecf562014-05-29 16:56:33 -070013329){
13330 sqlite3_stmt *pQuery = 0;
13331 char *zQuery = 0;
13332 int rc;
13333 const unsigned char *zName;
13334 const unsigned char *zSql;
13335 char *zErrMsg = 0;
13336
13337 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
13338 " WHERE %s", zWhere);
13339 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
13340 if( rc ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013341 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
Nick Kralevich8fecf562014-05-29 16:56:33 -070013342 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
13343 zQuery);
13344 goto end_schema_xfer;
13345 }
13346 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
13347 zName = sqlite3_column_text(pQuery, 0);
13348 zSql = sqlite3_column_text(pQuery, 1);
13349 printf("%s... ", zName); fflush(stdout);
13350 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
13351 if( zErrMsg ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013352 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
Nick Kralevich8fecf562014-05-29 16:56:33 -070013353 sqlite3_free(zErrMsg);
13354 zErrMsg = 0;
13355 }
13356 if( xForEach ){
13357 xForEach(p, newDb, (const char*)zName);
13358 }
13359 printf("done\n");
13360 }
13361 if( rc!=SQLITE_DONE ){
13362 sqlite3_finalize(pQuery);
13363 sqlite3_free(zQuery);
13364 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
13365 " WHERE %s ORDER BY rowid DESC", zWhere);
13366 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
13367 if( rc ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013368 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
Nick Kralevich8fecf562014-05-29 16:56:33 -070013369 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
13370 zQuery);
13371 goto end_schema_xfer;
13372 }
13373 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
13374 zName = sqlite3_column_text(pQuery, 0);
13375 zSql = sqlite3_column_text(pQuery, 1);
13376 printf("%s... ", zName); fflush(stdout);
13377 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
13378 if( zErrMsg ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013379 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
Nick Kralevich8fecf562014-05-29 16:56:33 -070013380 sqlite3_free(zErrMsg);
13381 zErrMsg = 0;
13382 }
13383 if( xForEach ){
13384 xForEach(p, newDb, (const char*)zName);
13385 }
13386 printf("done\n");
13387 }
13388 }
13389end_schema_xfer:
13390 sqlite3_finalize(pQuery);
13391 sqlite3_free(zQuery);
13392}
13393
13394/*
13395** Open a new database file named "zNewDb". Try to recover as much information
13396** as possible out of the main database (which might be corrupt) and write it
13397** into zNewDb.
13398*/
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013399static void tryToClone(ShellState *p, const char *zNewDb){
Nick Kralevich8fecf562014-05-29 16:56:33 -070013400 int rc;
13401 sqlite3 *newDb = 0;
13402 if( access(zNewDb,0)==0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013403 utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
Nick Kralevich8fecf562014-05-29 16:56:33 -070013404 return;
13405 }
13406 rc = sqlite3_open(zNewDb, &newDb);
13407 if( rc ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013408 utf8_printf(stderr, "Cannot create output database: %s\n",
Nick Kralevich8fecf562014-05-29 16:56:33 -070013409 sqlite3_errmsg(newDb));
13410 }else{
Nick Kralevich1c7cea32014-06-06 19:53:11 -070013411 sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
Nick Kralevich8fecf562014-05-29 16:56:33 -070013412 sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
13413 tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
13414 tryToCloneSchema(p, newDb, "type!='table'", 0);
13415 sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
Nick Kralevich1c7cea32014-06-06 19:53:11 -070013416 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
Nick Kralevich8fecf562014-05-29 16:56:33 -070013417 }
mydongistiny63ee58c2019-09-21 18:04:30 -070013418 close_db(newDb);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080013419}
13420
13421/*
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013422** Change the output file back to stdout.
13423**
13424** If the p->doXdgOpen flag is set, that means the output was being
13425** redirected to a temporary file named by p->zTempFile. In that case,
13426** launch start/open/xdg-open on that temporary file.
Nick Kralevich1c7cea32014-06-06 19:53:11 -070013427*/
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013428static void output_reset(ShellState *p){
Nick Kralevich1c7cea32014-06-06 19:53:11 -070013429 if( p->outfile[0]=='|' ){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013430#ifndef SQLITE_OMIT_POPEN
Nick Kralevich1c7cea32014-06-06 19:53:11 -070013431 pclose(p->out);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013432#endif
Nick Kralevich1c7cea32014-06-06 19:53:11 -070013433 }else{
13434 output_file_close(p->out);
mydongistiny63ee58c2019-09-21 18:04:30 -070013435#ifndef SQLITE_NOHAVE_SYSTEM
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013436 if( p->doXdgOpen ){
13437 const char *zXdgOpenCmd =
13438#if defined(_WIN32)
13439 "start";
13440#elif defined(__APPLE__)
13441 "open";
13442#else
13443 "xdg-open";
13444#endif
13445 char *zCmd;
13446 zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
13447 if( system(zCmd) ){
13448 utf8_printf(stderr, "Failed: [%s]\n", zCmd);
13449 }
13450 sqlite3_free(zCmd);
13451 outputModePop(p);
13452 p->doXdgOpen = 0;
mydongistiny63ee58c2019-09-21 18:04:30 -070013453 sqlite3_sleep(100);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013454 }
mydongistiny63ee58c2019-09-21 18:04:30 -070013455#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
Nick Kralevich1c7cea32014-06-06 19:53:11 -070013456 }
13457 p->outfile[0] = 0;
13458 p->out = stdout;
13459}
13460
13461/*
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013462** Run an SQL command and return the single integer result.
13463*/
13464static int db_int(ShellState *p, const char *zSql){
13465 sqlite3_stmt *pStmt;
13466 int res = 0;
13467 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
13468 if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
13469 res = sqlite3_column_int(pStmt,0);
13470 }
13471 sqlite3_finalize(pStmt);
13472 return res;
13473}
13474
13475/*
13476** Convert a 2-byte or 4-byte big-endian integer into a native integer
13477*/
Alex Naidis74bd39c2016-08-09 00:53:11 +020013478static unsigned int get2byteInt(unsigned char *a){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013479 return (a[0]<<8) + a[1];
13480}
Alex Naidis74bd39c2016-08-09 00:53:11 +020013481static unsigned int get4byteInt(unsigned char *a){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013482 return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
13483}
13484
13485/*
13486** Implementation of the ".info" command.
13487**
13488** Return 1 on error, 2 to exit, and 0 otherwise.
13489*/
13490static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
13491 static const struct { const char *zName; int ofst; } aField[] = {
13492 { "file change counter:", 24 },
13493 { "database page count:", 28 },
13494 { "freelist page count:", 36 },
13495 { "schema cookie:", 40 },
13496 { "schema format:", 44 },
13497 { "default cache size:", 48 },
13498 { "autovacuum top root:", 52 },
13499 { "incremental vacuum:", 64 },
13500 { "text encoding:", 56 },
13501 { "user version:", 60 },
13502 { "application id:", 68 },
13503 { "software version:", 96 },
13504 };
13505 static const struct { const char *zName; const char *zSql; } aQuery[] = {
13506 { "number of tables:",
13507 "SELECT count(*) FROM %s WHERE type='table'" },
13508 { "number of indexes:",
13509 "SELECT count(*) FROM %s WHERE type='index'" },
13510 { "number of triggers:",
13511 "SELECT count(*) FROM %s WHERE type='trigger'" },
13512 { "number of views:",
13513 "SELECT count(*) FROM %s WHERE type='view'" },
13514 { "schema size:",
13515 "SELECT total(length(sql)) FROM %s" },
13516 };
mydongistiny63ee58c2019-09-21 18:04:30 -070013517 int i, rc;
13518 unsigned iDataVersion;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013519 char *zSchemaTab;
13520 char *zDb = nArg>=2 ? azArg[1] : "main";
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013521 sqlite3_stmt *pStmt = 0;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013522 unsigned char aHdr[100];
13523 open_db(p, 0);
13524 if( p->db==0 ) return 1;
mydongistiny63ee58c2019-09-21 18:04:30 -070013525 rc = sqlite3_prepare_v2(p->db,
13526 "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
13527 -1, &pStmt, 0);
13528 if( rc ){
13529 if( !sqlite3_compileoption_used("ENABLE_DBPAGE_VTAB") ){
13530 utf8_printf(stderr, "the \".dbinfo\" command requires the "
13531 "-DSQLITE_ENABLE_DBPAGE_VTAB compile-time options\n");
13532 }else{
13533 utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
13534 }
13535 sqlite3_finalize(pStmt);
13536 return 1;
13537 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013538 sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
13539 if( sqlite3_step(pStmt)==SQLITE_ROW
13540 && sqlite3_column_bytes(pStmt,0)>100
13541 ){
13542 memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
13543 sqlite3_finalize(pStmt);
13544 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013545 raw_printf(stderr, "unable to read database header\n");
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013546 sqlite3_finalize(pStmt);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013547 return 1;
13548 }
13549 i = get2byteInt(aHdr+16);
13550 if( i==1 ) i = 65536;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013551 utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
13552 utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
13553 utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
13554 utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
Nick Kralevich253ed642015-12-23 10:07:58 -080013555 for(i=0; i<ArraySize(aField); i++){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013556 int ofst = aField[i].ofst;
13557 unsigned int val = get4byteInt(aHdr + ofst);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013558 utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013559 switch( ofst ){
13560 case 56: {
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013561 if( val==1 ) raw_printf(p->out, " (utf8)");
13562 if( val==2 ) raw_printf(p->out, " (utf16le)");
13563 if( val==3 ) raw_printf(p->out, " (utf16be)");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013564 }
13565 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013566 raw_printf(p->out, "\n");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013567 }
13568 if( zDb==0 ){
13569 zSchemaTab = sqlite3_mprintf("main.sqlite_master");
13570 }else if( strcmp(zDb,"temp")==0 ){
13571 zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_master");
13572 }else{
13573 zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_master", zDb);
13574 }
Nick Kralevich253ed642015-12-23 10:07:58 -080013575 for(i=0; i<ArraySize(aQuery); i++){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013576 char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
13577 int val = db_int(p, zSql);
13578 sqlite3_free(zSql);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013579 utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013580 }
13581 sqlite3_free(zSchemaTab);
mydongistiny63ee58c2019-09-21 18:04:30 -070013582 sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
13583 utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070013584 return 0;
13585}
13586
Nick Kralevich253ed642015-12-23 10:07:58 -080013587/*
13588** Print the current sqlite3_errmsg() value to stderr and return 1.
13589*/
13590static int shellDatabaseError(sqlite3 *db){
13591 const char *zErr = sqlite3_errmsg(db);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013592 utf8_printf(stderr, "Error: %s\n", zErr);
Nick Kralevich253ed642015-12-23 10:07:58 -080013593 return 1;
13594}
13595
13596/*
Alex Naidis08f78cb2016-10-14 15:52:08 +020013597** Compare the pattern in zGlob[] against the text in z[]. Return TRUE
13598** if they match and FALSE (0) if they do not match.
13599**
13600** Globbing rules:
13601**
13602** '*' Matches any sequence of zero or more characters.
13603**
13604** '?' Matches exactly one character.
13605**
13606** [...] Matches one character from the enclosed list of
13607** characters.
13608**
13609** [^...] Matches one character not in the enclosed list.
13610**
13611** '#' Matches any sequence of one or more digits with an
13612** optional + or - sign in front
13613**
13614** ' ' Any span of whitespace matches any other span of
13615** whitespace.
13616**
13617** Extra whitespace at the end of z[] is ignored.
13618*/
13619static int testcase_glob(const char *zGlob, const char *z){
13620 int c, c2;
13621 int invert;
13622 int seen;
13623
13624 while( (c = (*(zGlob++)))!=0 ){
13625 if( IsSpace(c) ){
13626 if( !IsSpace(*z) ) return 0;
13627 while( IsSpace(*zGlob) ) zGlob++;
13628 while( IsSpace(*z) ) z++;
13629 }else if( c=='*' ){
13630 while( (c=(*(zGlob++))) == '*' || c=='?' ){
13631 if( c=='?' && (*(z++))==0 ) return 0;
13632 }
13633 if( c==0 ){
13634 return 1;
13635 }else if( c=='[' ){
13636 while( *z && testcase_glob(zGlob-1,z)==0 ){
13637 z++;
13638 }
13639 return (*z)!=0;
13640 }
13641 while( (c2 = (*(z++)))!=0 ){
13642 while( c2!=c ){
13643 c2 = *(z++);
13644 if( c2==0 ) return 0;
13645 }
13646 if( testcase_glob(zGlob,z) ) return 1;
13647 }
13648 return 0;
13649 }else if( c=='?' ){
13650 if( (*(z++))==0 ) return 0;
13651 }else if( c=='[' ){
13652 int prior_c = 0;
13653 seen = 0;
13654 invert = 0;
13655 c = *(z++);
13656 if( c==0 ) return 0;
13657 c2 = *(zGlob++);
13658 if( c2=='^' ){
13659 invert = 1;
13660 c2 = *(zGlob++);
13661 }
13662 if( c2==']' ){
13663 if( c==']' ) seen = 1;
13664 c2 = *(zGlob++);
13665 }
13666 while( c2 && c2!=']' ){
13667 if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
13668 c2 = *(zGlob++);
13669 if( c>=prior_c && c<=c2 ) seen = 1;
13670 prior_c = 0;
13671 }else{
13672 if( c==c2 ){
13673 seen = 1;
13674 }
13675 prior_c = c2;
13676 }
13677 c2 = *(zGlob++);
13678 }
13679 if( c2==0 || (seen ^ invert)==0 ) return 0;
13680 }else if( c=='#' ){
13681 if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++;
13682 if( !IsDigit(z[0]) ) return 0;
13683 z++;
13684 while( IsDigit(z[0]) ){ z++; }
13685 }else{
13686 if( c!=(*(z++)) ) return 0;
13687 }
13688 }
13689 while( IsSpace(*z) ){ z++; }
13690 return *z==0;
13691}
13692
13693
13694/*
Alex Naidis60fa6fd2016-07-10 14:13:38 +020013695** Compare the string as a command-line option with either one or two
13696** initial "-" characters.
13697*/
13698static int optionMatch(const char *zStr, const char *zOpt){
13699 if( zStr[0]!='-' ) return 0;
13700 zStr++;
13701 if( zStr[0]=='-' ) zStr++;
13702 return strcmp(zStr, zOpt)==0;
13703}
13704
13705/*
Alex Naidis08f78cb2016-10-14 15:52:08 +020013706** Delete a file.
13707*/
13708int shellDeleteFile(const char *zFilename){
13709 int rc;
13710#ifdef _WIN32
13711 wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
13712 rc = _wunlink(z);
13713 sqlite3_free(z);
13714#else
13715 rc = unlink(zFilename);
13716#endif
13717 return rc;
13718}
13719
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013720/*
13721** Try to delete the temporary file (if there is one) and free the
13722** memory used to hold the name of the temp file.
13723*/
13724static void clearTempFile(ShellState *p){
13725 if( p->zTempFile==0 ) return;
13726 if( p->doXdgOpen ) return;
13727 if( shellDeleteFile(p->zTempFile) ) return;
13728 sqlite3_free(p->zTempFile);
13729 p->zTempFile = 0;
13730}
13731
13732/*
13733** Create a new temp file name with the given suffix.
13734*/
13735static void newTempFile(ShellState *p, const char *zSuffix){
13736 clearTempFile(p);
13737 sqlite3_free(p->zTempFile);
13738 p->zTempFile = 0;
13739 if( p->db ){
13740 sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
13741 }
13742 if( p->zTempFile==0 ){
13743 sqlite3_uint64 r;
13744 sqlite3_randomness(sizeof(r), &r);
13745 p->zTempFile = sqlite3_mprintf("temp%llx.%s", r, zSuffix);
13746 }else{
13747 p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
13748 }
13749 if( p->zTempFile==0 ){
13750 raw_printf(stderr, "out of memory\n");
13751 exit(1);
13752 }
13753}
13754
Luca Stefanie7f3e802017-01-02 15:44:22 +010013755
13756/*
13757** The implementation of SQL scalar function fkey_collate_clause(), used
13758** by the ".lint fkey-indexes" command. This scalar function is always
13759** called with four arguments - the parent table name, the parent column name,
13760** the child table name and the child column name.
13761**
13762** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
13763**
13764** If either of the named tables or columns do not exist, this function
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013765** returns an empty string. An empty string is also returned if both tables
Luca Stefanie7f3e802017-01-02 15:44:22 +010013766** and columns exist but have the same default collation sequence. Or,
13767** if both exist but the default collation sequences are different, this
13768** function returns the string " COLLATE <parent-collation>", where
13769** <parent-collation> is the default collation sequence of the parent column.
13770*/
13771static void shellFkeyCollateClause(
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013772 sqlite3_context *pCtx,
13773 int nVal,
Luca Stefanie7f3e802017-01-02 15:44:22 +010013774 sqlite3_value **apVal
13775){
13776 sqlite3 *db = sqlite3_context_db_handle(pCtx);
13777 const char *zParent;
13778 const char *zParentCol;
13779 const char *zParentSeq;
13780 const char *zChild;
13781 const char *zChildCol;
13782 const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */
13783 int rc;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013784
Luca Stefanie7f3e802017-01-02 15:44:22 +010013785 assert( nVal==4 );
13786 zParent = (const char*)sqlite3_value_text(apVal[0]);
13787 zParentCol = (const char*)sqlite3_value_text(apVal[1]);
13788 zChild = (const char*)sqlite3_value_text(apVal[2]);
13789 zChildCol = (const char*)sqlite3_value_text(apVal[3]);
13790
13791 sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
13792 rc = sqlite3_table_column_metadata(
13793 db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0
13794 );
13795 if( rc==SQLITE_OK ){
13796 rc = sqlite3_table_column_metadata(
13797 db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0
13798 );
13799 }
13800
13801 if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){
13802 char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq);
13803 sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
13804 sqlite3_free(z);
13805 }
13806}
13807
13808
13809/*
13810** The implementation of dot-command ".lint fkey-indexes".
13811*/
13812static int lintFkeyIndexes(
13813 ShellState *pState, /* Current shell tool state */
13814 char **azArg, /* Array of arguments passed to dot command */
13815 int nArg /* Number of entries in azArg[] */
13816){
13817 sqlite3 *db = pState->db; /* Database handle to query "main" db of */
13818 FILE *out = pState->out; /* Stream to write non-error output to */
13819 int bVerbose = 0; /* If -verbose is present */
13820 int bGroupByParent = 0; /* If -groupbyparent is present */
13821 int i; /* To iterate through azArg[] */
13822 const char *zIndent = ""; /* How much to indent CREATE INDEX by */
13823 int rc; /* Return code */
13824 sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */
13825
13826 /*
13827 ** This SELECT statement returns one row for each foreign key constraint
13828 ** in the schema of the main database. The column values are:
13829 **
13830 ** 0. The text of an SQL statement similar to:
13831 **
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013832 ** "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?"
Luca Stefanie7f3e802017-01-02 15:44:22 +010013833 **
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013834 ** This SELECT is similar to the one that the foreign keys implementation
13835 ** needs to run internally on child tables. If there is an index that can
Luca Stefanie7f3e802017-01-02 15:44:22 +010013836 ** be used to optimize this query, then it can also be used by the FK
13837 ** implementation to optimize DELETE or UPDATE statements on the parent
13838 ** table.
13839 **
13840 ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by
13841 ** the EXPLAIN QUERY PLAN command matches this pattern, then the schema
13842 ** contains an index that can be used to optimize the query.
13843 **
13844 ** 2. Human readable text that describes the child table and columns. e.g.
13845 **
13846 ** "child_table(child_key1, child_key2)"
13847 **
13848 ** 3. Human readable text that describes the parent table and columns. e.g.
13849 **
13850 ** "parent_table(parent_key1, parent_key2)"
13851 **
13852 ** 4. A full CREATE INDEX statement for an index that could be used to
13853 ** optimize DELETE or UPDATE statements on the parent table. e.g.
13854 **
13855 ** "CREATE INDEX child_table_child_key ON child_table(child_key)"
13856 **
13857 ** 5. The name of the parent table.
13858 **
13859 ** These six values are used by the C logic below to generate the report.
13860 */
13861 const char *zSql =
13862 "SELECT "
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013863 " 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
Luca Stefanie7f3e802017-01-02 15:44:22 +010013864 " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
Alex Naidisb94ea7b2017-05-24 19:25:14 +020013865 " || fkey_collate_clause("
13866 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
Luca Stefanie7f3e802017-01-02 15:44:22 +010013867 ", "
13868 " 'SEARCH TABLE ' || s.name || ' USING COVERING INDEX*('"
13869 " || group_concat('*=?', ' AND ') || ')'"
13870 ", "
13871 " s.name || '(' || group_concat(f.[from], ', ') || ')'"
13872 ", "
Alex Naidisb94ea7b2017-05-24 19:25:14 +020013873 " f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
Luca Stefanie7f3e802017-01-02 15:44:22 +010013874 ", "
13875 " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
13876 " || ' ON ' || quote(s.name) || '('"
13877 " || group_concat(quote(f.[from]) ||"
Alex Naidisb94ea7b2017-05-24 19:25:14 +020013878 " fkey_collate_clause("
13879 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
Luca Stefanie7f3e802017-01-02 15:44:22 +010013880 " || ');'"
13881 ", "
13882 " f.[table] "
Luca Stefanie7f3e802017-01-02 15:44:22 +010013883 "FROM sqlite_master AS s, pragma_foreign_key_list(s.name) AS f "
Alex Naidisb94ea7b2017-05-24 19:25:14 +020013884 "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
Luca Stefanie7f3e802017-01-02 15:44:22 +010013885 "GROUP BY s.name, f.id "
13886 "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
13887 ;
Alex Naidisb94ea7b2017-05-24 19:25:14 +020013888 const char *zGlobIPK = "SEARCH TABLE * USING INTEGER PRIMARY KEY (rowid=?)";
Luca Stefanie7f3e802017-01-02 15:44:22 +010013889
13890 for(i=2; i<nArg; i++){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013891 int n = strlen30(azArg[i]);
Luca Stefanie7f3e802017-01-02 15:44:22 +010013892 if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
13893 bVerbose = 1;
13894 }
13895 else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
13896 bGroupByParent = 1;
13897 zIndent = " ";
13898 }
13899 else{
13900 raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
13901 azArg[0], azArg[1]
13902 );
13903 return SQLITE_ERROR;
13904 }
13905 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013906
Luca Stefanie7f3e802017-01-02 15:44:22 +010013907 /* Register the fkey_collate_clause() SQL function */
13908 rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
13909 0, shellFkeyCollateClause, 0, 0
13910 );
13911
13912
13913 if( rc==SQLITE_OK ){
13914 rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
13915 }
13916 if( rc==SQLITE_OK ){
13917 sqlite3_bind_int(pSql, 1, bGroupByParent);
13918 }
13919
13920 if( rc==SQLITE_OK ){
13921 int rc2;
13922 char *zPrev = 0;
13923 while( SQLITE_ROW==sqlite3_step(pSql) ){
13924 int res = -1;
13925 sqlite3_stmt *pExplain = 0;
13926 const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
13927 const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
13928 const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
13929 const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
13930 const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
13931 const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
13932
13933 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
13934 if( rc!=SQLITE_OK ) break;
13935 if( SQLITE_ROW==sqlite3_step(pExplain) ){
13936 const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
Alex Naidisb94ea7b2017-05-24 19:25:14 +020013937 res = (
13938 0==sqlite3_strglob(zGlob, zPlan)
13939 || 0==sqlite3_strglob(zGlobIPK, zPlan)
13940 );
Luca Stefanie7f3e802017-01-02 15:44:22 +010013941 }
13942 rc = sqlite3_finalize(pExplain);
13943 if( rc!=SQLITE_OK ) break;
13944
13945 if( res<0 ){
13946 raw_printf(stderr, "Error: internal error");
13947 break;
13948 }else{
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013949 if( bGroupByParent
Luca Stefanie7f3e802017-01-02 15:44:22 +010013950 && (bVerbose || res==0)
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013951 && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
Luca Stefanie7f3e802017-01-02 15:44:22 +010013952 ){
13953 raw_printf(out, "-- Parent table %s\n", zParent);
13954 sqlite3_free(zPrev);
13955 zPrev = sqlite3_mprintf("%s", zParent);
13956 }
13957
13958 if( res==0 ){
13959 raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
13960 }else if( bVerbose ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013961 raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
Luca Stefanie7f3e802017-01-02 15:44:22 +010013962 zIndent, zFrom, zTarget
13963 );
13964 }
13965 }
13966 }
13967 sqlite3_free(zPrev);
13968
13969 if( rc!=SQLITE_OK ){
13970 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
13971 }
13972
13973 rc2 = sqlite3_finalize(pSql);
13974 if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
13975 rc = rc2;
13976 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
13977 }
13978 }else{
13979 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
13980 }
13981
13982 return rc;
13983}
13984
13985/*
13986** Implementation of ".lint" dot command.
13987*/
13988static int lintDotCommand(
13989 ShellState *pState, /* Current shell tool state */
13990 char **azArg, /* Array of arguments passed to dot command */
13991 int nArg /* Number of entries in azArg[] */
13992){
13993 int n;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080013994 n = (nArg>=2 ? strlen30(azArg[1]) : 0);
Luca Stefanie7f3e802017-01-02 15:44:22 +010013995 if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
13996 return lintFkeyIndexes(pState, azArg, nArg);
13997
13998 usage:
13999 raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
14000 raw_printf(stderr, "Where sub-commands are:\n");
14001 raw_printf(stderr, " fkey-indexes\n");
14002 return SQLITE_ERROR;
14003}
14004
mydongistiny63ee58c2019-09-21 18:04:30 -070014005#if !defined SQLITE_OMIT_VIRTUALTABLE
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014006static void shellPrepare(
14007 sqlite3 *db,
14008 int *pRc,
14009 const char *zSql,
14010 sqlite3_stmt **ppStmt
14011){
14012 *ppStmt = 0;
14013 if( *pRc==SQLITE_OK ){
14014 int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
14015 if( rc!=SQLITE_OK ){
14016 raw_printf(stderr, "sql error: %s (%d)\n",
14017 sqlite3_errmsg(db), sqlite3_errcode(db)
14018 );
14019 *pRc = rc;
14020 }
14021 }
14022}
14023
mydongistiny63ee58c2019-09-21 18:04:30 -070014024/*
14025** Create a prepared statement using printf-style arguments for the SQL.
14026**
14027** This routine is could be marked "static". But it is not always used,
14028** depending on compile-time options. By omitting the "static", we avoid
14029** nuisance compiler warnings about "defined but not used".
14030*/
14031void shellPreparePrintf(
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014032 sqlite3 *db,
14033 int *pRc,
14034 sqlite3_stmt **ppStmt,
14035 const char *zFmt,
14036 ...
14037){
14038 *ppStmt = 0;
14039 if( *pRc==SQLITE_OK ){
14040 va_list ap;
14041 char *z;
14042 va_start(ap, zFmt);
14043 z = sqlite3_vmprintf(zFmt, ap);
mydongistiny63ee58c2019-09-21 18:04:30 -070014044 va_end(ap);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014045 if( z==0 ){
14046 *pRc = SQLITE_NOMEM;
14047 }else{
14048 shellPrepare(db, pRc, z, ppStmt);
14049 sqlite3_free(z);
14050 }
14051 }
14052}
14053
mydongistiny63ee58c2019-09-21 18:04:30 -070014054/* Finalize the prepared statement created using shellPreparePrintf().
14055**
14056** This routine is could be marked "static". But it is not always used,
14057** depending on compile-time options. By omitting the "static", we avoid
14058** nuisance compiler warnings about "defined but not used".
14059*/
14060void shellFinalize(
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014061 int *pRc,
14062 sqlite3_stmt *pStmt
14063){
14064 if( pStmt ){
14065 sqlite3 *db = sqlite3_db_handle(pStmt);
14066 int rc = sqlite3_finalize(pStmt);
14067 if( *pRc==SQLITE_OK ){
14068 if( rc!=SQLITE_OK ){
14069 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
14070 }
14071 *pRc = rc;
14072 }
14073 }
14074}
14075
mydongistiny63ee58c2019-09-21 18:04:30 -070014076/* Reset the prepared statement created using shellPreparePrintf().
14077**
14078** This routine is could be marked "static". But it is not always used,
14079** depending on compile-time options. By omitting the "static", we avoid
14080** nuisance compiler warnings about "defined but not used".
14081*/
14082void shellReset(
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014083 int *pRc,
14084 sqlite3_stmt *pStmt
14085){
14086 int rc = sqlite3_reset(pStmt);
14087 if( *pRc==SQLITE_OK ){
14088 if( rc!=SQLITE_OK ){
14089 sqlite3 *db = sqlite3_db_handle(pStmt);
14090 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
14091 }
14092 *pRc = rc;
14093 }
14094}
mydongistiny63ee58c2019-09-21 18:04:30 -070014095#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
14096
14097#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
mydongistiny8320bdc2019-10-06 12:50:35 -070014098/******************************************************************************
mydongistiny63ee58c2019-09-21 18:04:30 -070014099** The ".archive" or ".ar" command.
14100*/
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014101/*
14102** Structure representing a single ".ar" command.
14103*/
14104typedef struct ArCommand ArCommand;
14105struct ArCommand {
14106 u8 eCmd; /* An AR_CMD_* value */
14107 u8 bVerbose; /* True if --verbose */
14108 u8 bZip; /* True if the archive is a ZIP */
14109 u8 bDryRun; /* True if --dry-run */
14110 u8 bAppend; /* True if --append */
mydongistiny63ee58c2019-09-21 18:04:30 -070014111 u8 fromCmdLine; /* Run from -A instead of .archive */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014112 int nArg; /* Number of command arguments */
14113 char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
14114 const char *zFile; /* --file argument, or NULL */
14115 const char *zDir; /* --directory argument, or NULL */
14116 char **azArg; /* Array of command arguments */
14117 ShellState *p; /* Shell state */
14118 sqlite3 *db; /* Database containing the archive */
14119};
14120
14121/*
14122** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
14123*/
14124static int arUsage(FILE *f){
mydongistiny63ee58c2019-09-21 18:04:30 -070014125 showHelp(f,"archive");
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014126 return SQLITE_ERROR;
14127}
14128
14129/*
14130** Print an error message for the .ar command to stderr and return
14131** SQLITE_ERROR.
14132*/
mydongistiny63ee58c2019-09-21 18:04:30 -070014133static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014134 va_list ap;
14135 char *z;
14136 va_start(ap, zFmt);
14137 z = sqlite3_vmprintf(zFmt, ap);
14138 va_end(ap);
mydongistiny63ee58c2019-09-21 18:04:30 -070014139 utf8_printf(stderr, "Error: %s\n", z);
14140 if( pAr->fromCmdLine ){
14141 utf8_printf(stderr, "Use \"-A\" for more help\n");
14142 }else{
14143 utf8_printf(stderr, "Use \".archive --help\" for more help\n");
14144 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014145 sqlite3_free(z);
14146 return SQLITE_ERROR;
14147}
14148
14149/*
14150** Values for ArCommand.eCmd.
14151*/
14152#define AR_CMD_CREATE 1
mydongistiny63ee58c2019-09-21 18:04:30 -070014153#define AR_CMD_UPDATE 2
14154#define AR_CMD_INSERT 3
14155#define AR_CMD_EXTRACT 4
14156#define AR_CMD_LIST 5
14157#define AR_CMD_HELP 6
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014158
14159/*
14160** Other (non-command) switches.
14161*/
mydongistiny63ee58c2019-09-21 18:04:30 -070014162#define AR_SWITCH_VERBOSE 7
14163#define AR_SWITCH_FILE 8
14164#define AR_SWITCH_DIRECTORY 9
14165#define AR_SWITCH_APPEND 10
14166#define AR_SWITCH_DRYRUN 11
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014167
14168static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
14169 switch( eSwitch ){
14170 case AR_CMD_CREATE:
14171 case AR_CMD_EXTRACT:
14172 case AR_CMD_LIST:
14173 case AR_CMD_UPDATE:
mydongistiny63ee58c2019-09-21 18:04:30 -070014174 case AR_CMD_INSERT:
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014175 case AR_CMD_HELP:
14176 if( pAr->eCmd ){
mydongistiny63ee58c2019-09-21 18:04:30 -070014177 return arErrorMsg(pAr, "multiple command options");
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014178 }
14179 pAr->eCmd = eSwitch;
14180 break;
14181
14182 case AR_SWITCH_DRYRUN:
14183 pAr->bDryRun = 1;
14184 break;
14185 case AR_SWITCH_VERBOSE:
14186 pAr->bVerbose = 1;
14187 break;
14188 case AR_SWITCH_APPEND:
14189 pAr->bAppend = 1;
14190 /* Fall thru into --file */
14191 case AR_SWITCH_FILE:
14192 pAr->zFile = zArg;
14193 break;
14194 case AR_SWITCH_DIRECTORY:
14195 pAr->zDir = zArg;
14196 break;
14197 }
14198
14199 return SQLITE_OK;
14200}
14201
14202/*
14203** Parse the command line for an ".ar" command. The results are written into
14204** structure (*pAr). SQLITE_OK is returned if the command line is parsed
14205** successfully, otherwise an error message is written to stderr and
14206** SQLITE_ERROR returned.
14207*/
14208static int arParseCommand(
14209 char **azArg, /* Array of arguments passed to dot command */
14210 int nArg, /* Number of entries in azArg[] */
14211 ArCommand *pAr /* Populate this object */
14212){
14213 struct ArSwitch {
14214 const char *zLong;
14215 char cShort;
14216 u8 eSwitch;
14217 u8 bArg;
14218 } aSwitch[] = {
14219 { "create", 'c', AR_CMD_CREATE, 0 },
14220 { "extract", 'x', AR_CMD_EXTRACT, 0 },
mydongistiny63ee58c2019-09-21 18:04:30 -070014221 { "insert", 'i', AR_CMD_INSERT, 0 },
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014222 { "list", 't', AR_CMD_LIST, 0 },
14223 { "update", 'u', AR_CMD_UPDATE, 0 },
14224 { "help", 'h', AR_CMD_HELP, 0 },
14225 { "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
14226 { "file", 'f', AR_SWITCH_FILE, 1 },
14227 { "append", 'a', AR_SWITCH_APPEND, 1 },
14228 { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
14229 { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
14230 };
14231 int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
14232 struct ArSwitch *pEnd = &aSwitch[nSwitch];
14233
14234 if( nArg<=1 ){
mydongistiny63ee58c2019-09-21 18:04:30 -070014235 utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014236 return arUsage(stderr);
14237 }else{
14238 char *z = azArg[1];
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014239 if( z[0]!='-' ){
14240 /* Traditional style [tar] invocation */
14241 int i;
14242 int iArg = 2;
14243 for(i=0; z[i]; i++){
14244 const char *zArg = 0;
14245 struct ArSwitch *pOpt;
14246 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
14247 if( z[i]==pOpt->cShort ) break;
14248 }
14249 if( pOpt==pEnd ){
mydongistiny63ee58c2019-09-21 18:04:30 -070014250 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014251 }
14252 if( pOpt->bArg ){
14253 if( iArg>=nArg ){
mydongistiny63ee58c2019-09-21 18:04:30 -070014254 return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014255 }
14256 zArg = azArg[iArg++];
14257 }
14258 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
14259 }
14260 pAr->nArg = nArg-iArg;
14261 if( pAr->nArg>0 ){
14262 pAr->azArg = &azArg[iArg];
14263 }
14264 }else{
14265 /* Non-traditional invocation */
14266 int iArg;
14267 for(iArg=1; iArg<nArg; iArg++){
14268 int n;
14269 z = azArg[iArg];
14270 if( z[0]!='-' ){
14271 /* All remaining command line words are command arguments. */
14272 pAr->azArg = &azArg[iArg];
14273 pAr->nArg = nArg-iArg;
14274 break;
14275 }
14276 n = strlen30(z);
14277
14278 if( z[1]!='-' ){
14279 int i;
14280 /* One or more short options */
14281 for(i=1; i<n; i++){
14282 const char *zArg = 0;
14283 struct ArSwitch *pOpt;
14284 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
14285 if( z[i]==pOpt->cShort ) break;
14286 }
14287 if( pOpt==pEnd ){
mydongistiny63ee58c2019-09-21 18:04:30 -070014288 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014289 }
14290 if( pOpt->bArg ){
14291 if( i<(n-1) ){
14292 zArg = &z[i+1];
14293 i = n;
14294 }else{
14295 if( iArg>=(nArg-1) ){
mydongistiny8320bdc2019-10-06 12:50:35 -070014296 return arErrorMsg(pAr, "option requires an argument: %c",
14297 z[i]);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014298 }
14299 zArg = azArg[++iArg];
14300 }
14301 }
14302 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
14303 }
14304 }else if( z[2]=='\0' ){
14305 /* A -- option, indicating that all remaining command line words
14306 ** are command arguments. */
14307 pAr->azArg = &azArg[iArg+1];
14308 pAr->nArg = nArg-iArg-1;
14309 break;
14310 }else{
14311 /* A long option */
14312 const char *zArg = 0; /* Argument for option, if any */
14313 struct ArSwitch *pMatch = 0; /* Matching option */
14314 struct ArSwitch *pOpt; /* Iterator */
14315 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
14316 const char *zLong = pOpt->zLong;
14317 if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
14318 if( pMatch ){
mydongistiny63ee58c2019-09-21 18:04:30 -070014319 return arErrorMsg(pAr, "ambiguous option: %s",z);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014320 }else{
14321 pMatch = pOpt;
14322 }
14323 }
14324 }
14325
14326 if( pMatch==0 ){
mydongistiny63ee58c2019-09-21 18:04:30 -070014327 return arErrorMsg(pAr, "unrecognized option: %s", z);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014328 }
14329 if( pMatch->bArg ){
14330 if( iArg>=(nArg-1) ){
mydongistiny63ee58c2019-09-21 18:04:30 -070014331 return arErrorMsg(pAr, "option requires an argument: %s", z);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014332 }
14333 zArg = azArg[++iArg];
14334 }
14335 if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
14336 }
14337 }
14338 }
14339 }
14340
14341 return SQLITE_OK;
14342}
14343
14344/*
14345** This function assumes that all arguments within the ArCommand.azArg[]
14346** array refer to archive members, as for the --extract or --list commands.
14347** It checks that each of them are present. If any specified file is not
14348** present in the archive, an error is printed to stderr and an error
14349** code returned. Otherwise, if all specified arguments are present in
14350** the archive, SQLITE_OK is returned.
14351**
14352** This function strips any trailing '/' characters from each argument.
14353** This is consistent with the way the [tar] command seems to work on
14354** Linux.
14355*/
14356static int arCheckEntries(ArCommand *pAr){
14357 int rc = SQLITE_OK;
14358 if( pAr->nArg ){
14359 int i, j;
14360 sqlite3_stmt *pTest = 0;
14361
14362 shellPreparePrintf(pAr->db, &rc, &pTest,
14363 "SELECT name FROM %s WHERE name=$name",
14364 pAr->zSrcTable
14365 );
14366 j = sqlite3_bind_parameter_index(pTest, "$name");
14367 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
14368 char *z = pAr->azArg[i];
14369 int n = strlen30(z);
14370 int bOk = 0;
14371 while( n>0 && z[n-1]=='/' ) n--;
14372 z[n] = '\0';
14373 sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
14374 if( SQLITE_ROW==sqlite3_step(pTest) ){
14375 bOk = 1;
14376 }
14377 shellReset(&rc, pTest);
14378 if( rc==SQLITE_OK && bOk==0 ){
14379 utf8_printf(stderr, "not found in archive: %s\n", z);
14380 rc = SQLITE_ERROR;
14381 }
14382 }
14383 shellFinalize(&rc, pTest);
14384 }
14385 return rc;
14386}
14387
14388/*
14389** Format a WHERE clause that can be used against the "sqlar" table to
14390** identify all archive members that match the command arguments held
14391** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
14392** The caller is responsible for eventually calling sqlite3_free() on
14393** any non-NULL (*pzWhere) value.
14394*/
14395static void arWhereClause(
14396 int *pRc,
14397 ArCommand *pAr,
14398 char **pzWhere /* OUT: New WHERE clause */
14399){
14400 char *zWhere = 0;
14401 if( *pRc==SQLITE_OK ){
14402 if( pAr->nArg==0 ){
14403 zWhere = sqlite3_mprintf("1");
14404 }else{
14405 int i;
14406 const char *zSep = "";
14407 for(i=0; i<pAr->nArg; i++){
14408 const char *z = pAr->azArg[i];
14409 zWhere = sqlite3_mprintf(
14410 "%z%s name = '%q' OR substr(name,1,%d) = '%q/'",
14411 zWhere, zSep, z, strlen30(z)+1, z
14412 );
14413 if( zWhere==0 ){
14414 *pRc = SQLITE_NOMEM;
14415 break;
14416 }
14417 zSep = " OR ";
14418 }
14419 }
14420 }
14421 *pzWhere = zWhere;
14422}
14423
14424/*
14425** Implementation of .ar "lisT" command.
14426*/
14427static int arListCommand(ArCommand *pAr){
14428 const char *zSql = "SELECT %s FROM %s WHERE %s";
14429 const char *azCols[] = {
14430 "name",
14431 "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
14432 };
14433
14434 char *zWhere = 0;
14435 sqlite3_stmt *pSql = 0;
14436 int rc;
14437
14438 rc = arCheckEntries(pAr);
14439 arWhereClause(&rc, pAr, &zWhere);
14440
14441 shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
14442 pAr->zSrcTable, zWhere);
14443 if( pAr->bDryRun ){
14444 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
14445 }else{
14446 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
14447 if( pAr->bVerbose ){
14448 utf8_printf(pAr->p->out, "%s % 10d %s %s\n",
14449 sqlite3_column_text(pSql, 0),
14450 sqlite3_column_int(pSql, 1),
14451 sqlite3_column_text(pSql, 2),
14452 sqlite3_column_text(pSql, 3)
14453 );
14454 }else{
14455 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
14456 }
14457 }
14458 }
14459 shellFinalize(&rc, pSql);
mydongistiny63ee58c2019-09-21 18:04:30 -070014460 sqlite3_free(zWhere);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014461 return rc;
14462}
14463
14464
14465/*
14466** Implementation of .ar "eXtract" command.
14467*/
14468static int arExtractCommand(ArCommand *pAr){
14469 const char *zSql1 =
14470 "SELECT "
14471 " ($dir || name),"
14472 " writefile(($dir || name), %s, mode, mtime) "
mydongistiny63ee58c2019-09-21 18:04:30 -070014473 "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
14474 " AND name NOT GLOB '*..[/\\]*'";
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014475
14476 const char *azExtraArg[] = {
14477 "sqlar_uncompress(data, sz)",
14478 "data"
14479 };
14480
14481 sqlite3_stmt *pSql = 0;
14482 int rc = SQLITE_OK;
14483 char *zDir = 0;
14484 char *zWhere = 0;
14485 int i, j;
14486
14487 /* If arguments are specified, check that they actually exist within
14488 ** the archive before proceeding. And formulate a WHERE clause to
14489 ** match them. */
14490 rc = arCheckEntries(pAr);
14491 arWhereClause(&rc, pAr, &zWhere);
14492
14493 if( rc==SQLITE_OK ){
14494 if( pAr->zDir ){
14495 zDir = sqlite3_mprintf("%s/", pAr->zDir);
14496 }else{
14497 zDir = sqlite3_mprintf("");
14498 }
14499 if( zDir==0 ) rc = SQLITE_NOMEM;
14500 }
14501
14502 shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
14503 azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
14504 );
14505
14506 if( rc==SQLITE_OK ){
14507 j = sqlite3_bind_parameter_index(pSql, "$dir");
14508 sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
14509
14510 /* Run the SELECT statement twice. The first time, writefile() is called
14511 ** for all archive members that should be extracted. The second time,
14512 ** only for the directories. This is because the timestamps for
14513 ** extracted directories must be reset after they are populated (as
14514 ** populating them changes the timestamp). */
14515 for(i=0; i<2; i++){
14516 j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
14517 sqlite3_bind_int(pSql, j, i);
14518 if( pAr->bDryRun ){
14519 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
14520 }else{
14521 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
14522 if( i==0 && pAr->bVerbose ){
14523 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
14524 }
14525 }
14526 }
14527 shellReset(&rc, pSql);
14528 }
14529 shellFinalize(&rc, pSql);
14530 }
14531
14532 sqlite3_free(zDir);
14533 sqlite3_free(zWhere);
14534 return rc;
14535}
14536
14537/*
14538** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out.
14539*/
14540static int arExecSql(ArCommand *pAr, const char *zSql){
14541 int rc;
14542 if( pAr->bDryRun ){
14543 utf8_printf(pAr->p->out, "%s\n", zSql);
14544 rc = SQLITE_OK;
14545 }else{
14546 char *zErr = 0;
14547 rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
14548 if( zErr ){
14549 utf8_printf(stdout, "ERROR: %s\n", zErr);
14550 sqlite3_free(zErr);
14551 }
14552 }
14553 return rc;
14554}
14555
14556
14557/*
mydongistiny63ee58c2019-09-21 18:04:30 -070014558** Implementation of .ar "create", "insert", and "update" commands.
14559**
14560** create -> Create a new SQL archive
14561** insert -> Insert or reinsert all files listed
14562** update -> Insert files that have changed or that were not
14563** previously in the archive
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014564**
14565** Create the "sqlar" table in the database if it does not already exist.
14566** Then add each file in the azFile[] array to the archive. Directories
14567** are added recursively. If argument bVerbose is non-zero, a message is
14568** printed on stdout for each file archived.
14569**
14570** The create command is the same as update, except that it drops
mydongistiny63ee58c2019-09-21 18:04:30 -070014571** any existing "sqlar" table before beginning. The "insert" command
14572** always overwrites every file named on the command-line, where as
14573** "update" only overwrites if the size or mtime or mode has changed.
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014574*/
14575static int arCreateOrUpdateCommand(
14576 ArCommand *pAr, /* Command arguments and options */
mydongistiny63ee58c2019-09-21 18:04:30 -070014577 int bUpdate, /* true for a --create. */
14578 int bOnlyIfChanged /* Only update if file has changed */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014579){
14580 const char *zCreate =
14581 "CREATE TABLE IF NOT EXISTS sqlar(\n"
14582 " name TEXT PRIMARY KEY, -- name of the file\n"
14583 " mode INT, -- access permissions\n"
14584 " mtime INT, -- last modification time\n"
14585 " sz INT, -- original file size\n"
14586 " data BLOB -- compressed content\n"
14587 ")";
14588 const char *zDrop = "DROP TABLE IF EXISTS sqlar";
mydongistiny63ee58c2019-09-21 18:04:30 -070014589 const char *zInsertFmt[2] = {
14590 "REPLACE INTO %s(name,mode,mtime,sz,data)\n"
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014591 " SELECT\n"
14592 " %s,\n"
14593 " mode,\n"
14594 " mtime,\n"
14595 " CASE substr(lsmode(mode),1,1)\n"
14596 " WHEN '-' THEN length(data)\n"
14597 " WHEN 'd' THEN 0\n"
14598 " ELSE -1 END,\n"
mydongistiny63ee58c2019-09-21 18:04:30 -070014599 " sqlar_compress(data)\n"
14600 " FROM fsdir(%Q,%Q) AS disk\n"
14601 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
14602 ,
14603 "REPLACE INTO %s(name,mode,mtime,data)\n"
14604 " SELECT\n"
14605 " %s,\n"
14606 " mode,\n"
14607 " mtime,\n"
14608 " data\n"
14609 " FROM fsdir(%Q,%Q) AS disk\n"
14610 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
14611 };
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014612 int i; /* For iterating through azFile[] */
14613 int rc; /* Return code */
mydongistiny63ee58c2019-09-21 18:04:30 -070014614 const char *zTab = 0; /* SQL table into which to insert */
14615 char *zSql;
14616 char zTemp[50];
14617 char *zExists = 0;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014618
mydongistiny63ee58c2019-09-21 18:04:30 -070014619 arExecSql(pAr, "PRAGMA page_size=512");
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014620 rc = arExecSql(pAr, "SAVEPOINT ar;");
14621 if( rc!=SQLITE_OK ) return rc;
mydongistiny63ee58c2019-09-21 18:04:30 -070014622 zTemp[0] = 0;
14623 if( pAr->bZip ){
14624 /* Initialize the zipfile virtual table, if necessary */
14625 if( pAr->zFile ){
14626 sqlite3_uint64 r;
14627 sqlite3_randomness(sizeof(r),&r);
14628 sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
14629 zTab = zTemp;
14630 zSql = sqlite3_mprintf(
14631 "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)",
14632 zTab, pAr->zFile
14633 );
14634 rc = arExecSql(pAr, zSql);
14635 sqlite3_free(zSql);
14636 }else{
14637 zTab = "zip";
14638 }
14639 }else{
14640 /* Initialize the table for an SQLAR */
14641 zTab = "sqlar";
14642 if( bUpdate==0 ){
14643 rc = arExecSql(pAr, zDrop);
14644 if( rc!=SQLITE_OK ) goto end_ar_transaction;
14645 }
14646 rc = arExecSql(pAr, zCreate);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014647 }
mydongistiny63ee58c2019-09-21 18:04:30 -070014648 if( bOnlyIfChanged ){
14649 zExists = sqlite3_mprintf(
14650 " AND NOT EXISTS("
14651 "SELECT 1 FROM %s AS mem"
14652 " WHERE mem.name=disk.name"
14653 " AND mem.mtime=disk.mtime"
14654 " AND mem.mode=disk.mode)", zTab);
14655 }else{
14656 zExists = sqlite3_mprintf("");
14657 }
14658 if( zExists==0 ) rc = SQLITE_NOMEM;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014659 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
mydongistiny63ee58c2019-09-21 18:04:30 -070014660 char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014661 pAr->bVerbose ? "shell_putsnl(name)" : "name",
mydongistiny63ee58c2019-09-21 18:04:30 -070014662 pAr->azArg[i], pAr->zDir, zExists);
14663 rc = arExecSql(pAr, zSql2);
14664 sqlite3_free(zSql2);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014665 }
mydongistiny63ee58c2019-09-21 18:04:30 -070014666end_ar_transaction:
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014667 if( rc!=SQLITE_OK ){
mydongistiny63ee58c2019-09-21 18:04:30 -070014668 sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014669 }else{
14670 rc = arExecSql(pAr, "RELEASE ar;");
mydongistiny63ee58c2019-09-21 18:04:30 -070014671 if( pAr->bZip && pAr->zFile ){
14672 zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
14673 arExecSql(pAr, zSql);
14674 sqlite3_free(zSql);
14675 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014676 }
mydongistiny63ee58c2019-09-21 18:04:30 -070014677 sqlite3_free(zExists);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014678 return rc;
14679}
14680
14681/*
14682** Implementation of ".ar" dot command.
14683*/
14684static int arDotCommand(
mydongistiny8320bdc2019-10-06 12:50:35 -070014685 ShellState *pState, /* Current shell tool state */
14686 int fromCmdLine, /* True if -A command-line option, not .ar cmd */
14687 char **azArg, /* Array of arguments passed to dot command */
14688 int nArg /* Number of entries in azArg[] */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014689){
14690 ArCommand cmd;
14691 int rc;
14692 memset(&cmd, 0, sizeof(cmd));
mydongistiny63ee58c2019-09-21 18:04:30 -070014693 cmd.fromCmdLine = fromCmdLine;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014694 rc = arParseCommand(azArg, nArg, &cmd);
14695 if( rc==SQLITE_OK ){
14696 int eDbType = SHELL_OPEN_UNSPEC;
14697 cmd.p = pState;
14698 cmd.db = pState->db;
14699 if( cmd.zFile ){
mydongistiny63ee58c2019-09-21 18:04:30 -070014700 eDbType = deduceDatabaseType(cmd.zFile, 1);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014701 }else{
14702 eDbType = pState->openMode;
14703 }
14704 if( eDbType==SHELL_OPEN_ZIPFILE ){
mydongistiny63ee58c2019-09-21 18:04:30 -070014705 if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){
14706 if( cmd.zFile==0 ){
14707 cmd.zSrcTable = sqlite3_mprintf("zip");
14708 }else{
14709 cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
14710 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014711 }
14712 cmd.bZip = 1;
14713 }else if( cmd.zFile ){
14714 int flags;
14715 if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
mydongistiny63ee58c2019-09-21 18:04:30 -070014716 if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
14717 || cmd.eCmd==AR_CMD_UPDATE ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014718 flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
14719 }else{
14720 flags = SQLITE_OPEN_READONLY;
14721 }
14722 cmd.db = 0;
14723 if( cmd.bDryRun ){
14724 utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
14725 eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
14726 }
14727 rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
14728 eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
14729 if( rc!=SQLITE_OK ){
14730 utf8_printf(stderr, "cannot open file: %s (%s)\n",
14731 cmd.zFile, sqlite3_errmsg(cmd.db)
14732 );
14733 goto end_ar_command;
14734 }
14735 sqlite3_fileio_init(cmd.db, 0, 0);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014736 sqlite3_sqlar_init(cmd.db, 0, 0);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014737 sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
14738 shellPutsFunc, 0, 0);
14739
14740 }
mydongistiny63ee58c2019-09-21 18:04:30 -070014741 if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014742 if( cmd.eCmd!=AR_CMD_CREATE
14743 && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
14744 ){
14745 utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
14746 rc = SQLITE_ERROR;
14747 goto end_ar_command;
14748 }
14749 cmd.zSrcTable = sqlite3_mprintf("sqlar");
14750 }
14751
14752 switch( cmd.eCmd ){
14753 case AR_CMD_CREATE:
mydongistiny63ee58c2019-09-21 18:04:30 -070014754 rc = arCreateOrUpdateCommand(&cmd, 0, 0);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014755 break;
14756
14757 case AR_CMD_EXTRACT:
14758 rc = arExtractCommand(&cmd);
14759 break;
14760
14761 case AR_CMD_LIST:
14762 rc = arListCommand(&cmd);
14763 break;
14764
14765 case AR_CMD_HELP:
14766 arUsage(pState->out);
14767 break;
14768
mydongistiny63ee58c2019-09-21 18:04:30 -070014769 case AR_CMD_INSERT:
14770 rc = arCreateOrUpdateCommand(&cmd, 1, 0);
14771 break;
14772
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014773 default:
14774 assert( cmd.eCmd==AR_CMD_UPDATE );
mydongistiny63ee58c2019-09-21 18:04:30 -070014775 rc = arCreateOrUpdateCommand(&cmd, 1, 1);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014776 break;
14777 }
14778 }
14779end_ar_command:
14780 if( cmd.db!=pState->db ){
mydongistiny63ee58c2019-09-21 18:04:30 -070014781 close_db(cmd.db);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014782 }
14783 sqlite3_free(cmd.zSrcTable);
14784
14785 return rc;
14786}
14787/* End of the ".archive" or ".ar" command logic
mydongistiny8320bdc2019-10-06 12:50:35 -070014788*******************************************************************************/
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080014789#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
14790
mydongistiny63ee58c2019-09-21 18:04:30 -070014791#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
14792/*
14793** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
14794** Otherwise, the SQL statement or statements in zSql are executed using
14795** database connection db and the error code written to *pRc before
14796** this function returns.
14797*/
14798static void shellExec(sqlite3 *db, int *pRc, const char *zSql){
14799 int rc = *pRc;
14800 if( rc==SQLITE_OK ){
14801 char *zErr = 0;
14802 rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
14803 if( rc!=SQLITE_OK ){
14804 raw_printf(stderr, "SQL error: %s\n", zErr);
14805 }
14806 *pRc = rc;
14807 }
14808}
14809
14810/*
14811** Like shellExec(), except that zFmt is a printf() style format string.
14812*/
14813static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){
14814 char *z = 0;
14815 if( *pRc==SQLITE_OK ){
14816 va_list ap;
14817 va_start(ap, zFmt);
14818 z = sqlite3_vmprintf(zFmt, ap);
14819 va_end(ap);
14820 if( z==0 ){
14821 *pRc = SQLITE_NOMEM;
14822 }else{
14823 shellExec(db, pRc, z);
14824 }
14825 sqlite3_free(z);
14826 }
14827}
14828
14829/*
14830** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
14831** Otherwise, an attempt is made to allocate, zero and return a pointer
14832** to a buffer nByte bytes in size. If an OOM error occurs, *pRc is set
14833** to SQLITE_NOMEM and NULL returned.
14834*/
14835static void *shellMalloc(int *pRc, sqlite3_int64 nByte){
14836 void *pRet = 0;
14837 if( *pRc==SQLITE_OK ){
14838 pRet = sqlite3_malloc64(nByte);
14839 if( pRet==0 ){
14840 *pRc = SQLITE_NOMEM;
14841 }else{
14842 memset(pRet, 0, nByte);
14843 }
14844 }
14845 return pRet;
14846}
14847
14848/*
14849** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
14850** Otherwise, zFmt is treated as a printf() style string. The result of
14851** formatting it along with any trailing arguments is written into a
14852** buffer obtained from sqlite3_malloc(), and pointer to which is returned.
14853** It is the responsibility of the caller to eventually free this buffer
14854** using a call to sqlite3_free().
14855**
14856** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL
14857** pointer returned.
14858*/
14859static char *shellMPrintf(int *pRc, const char *zFmt, ...){
14860 char *z = 0;
14861 if( *pRc==SQLITE_OK ){
14862 va_list ap;
14863 va_start(ap, zFmt);
14864 z = sqlite3_vmprintf(zFmt, ap);
14865 va_end(ap);
14866 if( z==0 ){
14867 *pRc = SQLITE_NOMEM;
14868 }
14869 }
14870 return z;
14871}
14872
14873/*
14874** When running the ".recover" command, each output table, and the special
14875** orphaned row table if it is required, is represented by an instance
14876** of the following struct.
14877*/
14878typedef struct RecoverTable RecoverTable;
14879struct RecoverTable {
14880 char *zQuoted; /* Quoted version of table name */
14881 int nCol; /* Number of columns in table */
14882 char **azlCol; /* Array of column lists */
14883 int iPk; /* Index of IPK column */
14884};
14885
14886/*
14887** Free a RecoverTable object allocated by recoverFindTable() or
14888** recoverOrphanTable().
14889*/
14890static void recoverFreeTable(RecoverTable *pTab){
14891 if( pTab ){
14892 sqlite3_free(pTab->zQuoted);
14893 if( pTab->azlCol ){
14894 int i;
14895 for(i=0; i<=pTab->nCol; i++){
14896 sqlite3_free(pTab->azlCol[i]);
14897 }
14898 sqlite3_free(pTab->azlCol);
14899 }
14900 sqlite3_free(pTab);
14901 }
14902}
14903
14904/*
14905** This function is a no-op if (*pRc) is not SQLITE_OK when it is called.
14906** Otherwise, it allocates and returns a RecoverTable object based on the
14907** final four arguments passed to this function. It is the responsibility
14908** of the caller to eventually free the returned object using
14909** recoverFreeTable().
14910*/
14911static RecoverTable *recoverNewTable(
14912 int *pRc, /* IN/OUT: Error code */
14913 const char *zName, /* Name of table */
14914 const char *zSql, /* CREATE TABLE statement */
14915 int bIntkey,
14916 int nCol
14917){
14918 sqlite3 *dbtmp = 0; /* sqlite3 handle for testing CREATE TABLE */
14919 int rc = *pRc;
14920 RecoverTable *pTab = 0;
14921
14922 pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable));
14923 if( rc==SQLITE_OK ){
14924 int nSqlCol = 0;
14925 int bSqlIntkey = 0;
14926 sqlite3_stmt *pStmt = 0;
14927
14928 rc = sqlite3_open("", &dbtmp);
14929 if( rc==SQLITE_OK ){
mydongistiny8320bdc2019-10-06 12:50:35 -070014930 sqlite3_create_function(dbtmp, "shell_idquote", 1, SQLITE_UTF8, 0,
14931 shellIdQuote, 0, 0);
14932 }
14933 if( rc==SQLITE_OK ){
mydongistiny63ee58c2019-09-21 18:04:30 -070014934 rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
14935 }
14936 if( rc==SQLITE_OK ){
14937 rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0);
14938 if( rc==SQLITE_ERROR ){
14939 rc = SQLITE_OK;
14940 goto finished;
14941 }
14942 }
14943 shellPreparePrintf(dbtmp, &rc, &pStmt,
14944 "SELECT count(*) FROM pragma_table_info(%Q)", zName
14945 );
14946 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
14947 nSqlCol = sqlite3_column_int(pStmt, 0);
14948 }
14949 shellFinalize(&rc, pStmt);
14950
14951 if( rc!=SQLITE_OK || nSqlCol<nCol ){
14952 goto finished;
14953 }
14954
14955 shellPreparePrintf(dbtmp, &rc, &pStmt,
14956 "SELECT ("
14957 " SELECT substr(data,1,1)==X'0D' FROM sqlite_dbpage WHERE pgno=rootpage"
14958 ") FROM sqlite_master WHERE name = %Q", zName
14959 );
14960 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
14961 bSqlIntkey = sqlite3_column_int(pStmt, 0);
14962 }
14963 shellFinalize(&rc, pStmt);
14964
14965 if( bIntkey==bSqlIntkey ){
14966 int i;
14967 const char *zPk = "_rowid_";
14968 sqlite3_stmt *pPkFinder = 0;
14969
14970 /* If this is an intkey table and there is an INTEGER PRIMARY KEY,
14971 ** set zPk to the name of the PK column, and pTab->iPk to the index
14972 ** of the column, where columns are 0-numbered from left to right.
14973 ** Or, if this is a WITHOUT ROWID table or if there is no IPK column,
14974 ** leave zPk as "_rowid_" and pTab->iPk at -2. */
14975 pTab->iPk = -2;
14976 if( bIntkey ){
14977 shellPreparePrintf(dbtmp, &rc, &pPkFinder,
14978 "SELECT cid, name FROM pragma_table_info(%Q) "
14979 " WHERE pk=1 AND type='integer' COLLATE nocase"
14980 " AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
14981 , zName, zName
14982 );
14983 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){
14984 pTab->iPk = sqlite3_column_int(pPkFinder, 0);
14985 zPk = (const char*)sqlite3_column_text(pPkFinder, 1);
14986 }
14987 }
14988
mydongistiny8320bdc2019-10-06 12:50:35 -070014989 pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName);
mydongistiny63ee58c2019-09-21 18:04:30 -070014990 pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
14991 pTab->nCol = nSqlCol;
14992
14993 if( bIntkey ){
mydongistiny8320bdc2019-10-06 12:50:35 -070014994 pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk);
mydongistiny63ee58c2019-09-21 18:04:30 -070014995 }else{
14996 pTab->azlCol[0] = shellMPrintf(&rc, "");
14997 }
14998 i = 1;
14999 shellPreparePrintf(dbtmp, &rc, &pStmt,
mydongistiny8320bdc2019-10-06 12:50:35 -070015000 "SELECT %Q || group_concat(shell_idquote(name), ', ') "
mydongistiny63ee58c2019-09-21 18:04:30 -070015001 " FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
15002 "FROM pragma_table_info(%Q)",
15003 bIntkey ? ", " : "", pTab->iPk,
15004 bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ",
15005 zName
15006 );
15007 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
15008 const char *zText = (const char*)sqlite3_column_text(pStmt, 0);
15009 pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText);
15010 i++;
15011 }
15012 shellFinalize(&rc, pStmt);
15013
15014 shellFinalize(&rc, pPkFinder);
15015 }
15016 }
15017
15018 finished:
15019 sqlite3_close(dbtmp);
15020 *pRc = rc;
15021 if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){
15022 recoverFreeTable(pTab);
15023 pTab = 0;
15024 }
15025 return pTab;
15026}
15027
15028/*
15029** This function is called to search the schema recovered from the
15030** sqlite_master table of the (possibly) corrupt database as part
15031** of a ".recover" command. Specifically, for a table with root page
15032** iRoot and at least nCol columns. Additionally, if bIntkey is 0, the
15033** table must be a WITHOUT ROWID table, or if non-zero, not one of
15034** those.
15035**
15036** If a table is found, a (RecoverTable*) object is returned. Or, if
15037** no such table is found, but bIntkey is false and iRoot is the
15038** root page of an index in the recovered schema, then (*pbNoop) is
15039** set to true and NULL returned. Or, if there is no such table or
15040** index, NULL is returned and (*pbNoop) set to 0, indicating that
15041** the caller should write data to the orphans table.
15042*/
15043static RecoverTable *recoverFindTable(
15044 ShellState *pState, /* Shell state object */
15045 int *pRc, /* IN/OUT: Error code */
15046 int iRoot, /* Root page of table */
15047 int bIntkey, /* True for an intkey table */
15048 int nCol, /* Number of columns in table */
15049 int *pbNoop /* OUT: True if iRoot is root of index */
15050){
15051 sqlite3_stmt *pStmt = 0;
15052 RecoverTable *pRet = 0;
15053 int bNoop = 0;
15054 const char *zSql = 0;
15055 const char *zName = 0;
15056
15057 /* Search the recovered schema for an object with root page iRoot. */
15058 shellPreparePrintf(pState->db, pRc, &pStmt,
15059 "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot
15060 );
15061 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
15062 const char *zType = (const char*)sqlite3_column_text(pStmt, 0);
15063 if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){
15064 bNoop = 1;
15065 break;
15066 }
15067 if( sqlite3_stricmp(zType, "table")==0 ){
15068 zName = (const char*)sqlite3_column_text(pStmt, 1);
15069 zSql = (const char*)sqlite3_column_text(pStmt, 2);
15070 pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol);
15071 break;
15072 }
15073 }
15074
15075 shellFinalize(pRc, pStmt);
15076 *pbNoop = bNoop;
15077 return pRet;
15078}
15079
15080/*
15081** Return a RecoverTable object representing the orphans table.
15082*/
15083static RecoverTable *recoverOrphanTable(
15084 ShellState *pState, /* Shell state object */
15085 int *pRc, /* IN/OUT: Error code */
15086 const char *zLostAndFound, /* Base name for orphans table */
15087 int nCol /* Number of user data columns */
15088){
15089 RecoverTable *pTab = 0;
15090 if( nCol>=0 && *pRc==SQLITE_OK ){
15091 int i;
15092
15093 /* This block determines the name of the orphan table. The prefered
15094 ** name is zLostAndFound. But if that clashes with another name
15095 ** in the recovered schema, try zLostAndFound_0, zLostAndFound_1
15096 ** and so on until a non-clashing name is found. */
15097 int iTab = 0;
15098 char *zTab = shellMPrintf(pRc, "%s", zLostAndFound);
15099 sqlite3_stmt *pTest = 0;
15100 shellPrepare(pState->db, pRc,
15101 "SELECT 1 FROM recovery.schema WHERE name=?", &pTest
15102 );
15103 if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
15104 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){
15105 shellReset(pRc, pTest);
15106 sqlite3_free(zTab);
15107 zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++);
15108 sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
15109 }
15110 shellFinalize(pRc, pTest);
15111
15112 pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
15113 if( pTab ){
mydongistiny8320bdc2019-10-06 12:50:35 -070015114 pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab);
mydongistiny63ee58c2019-09-21 18:04:30 -070015115 pTab->nCol = nCol;
15116 pTab->iPk = -2;
15117 if( nCol>0 ){
15118 pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1));
15119 if( pTab->azlCol ){
15120 pTab->azlCol[nCol] = shellMPrintf(pRc, "");
15121 for(i=nCol-1; i>=0; i--){
15122 pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]);
15123 }
15124 }
15125 }
15126
15127 if( *pRc!=SQLITE_OK ){
15128 recoverFreeTable(pTab);
15129 pTab = 0;
15130 }else{
15131 raw_printf(pState->out,
15132 "CREATE TABLE %s(rootpgno INTEGER, "
15133 "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted
15134 );
15135 for(i=0; i<nCol; i++){
15136 raw_printf(pState->out, ", c%d", i);
15137 }
15138 raw_printf(pState->out, ");\n");
15139 }
15140 }
15141 sqlite3_free(zTab);
15142 }
15143 return pTab;
15144}
15145
15146/*
15147** This function is called to recover data from the database. A script
15148** to construct a new database containing all recovered data is output
15149** on stream pState->out.
15150*/
15151static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
15152 int rc = SQLITE_OK;
15153 sqlite3_stmt *pLoop = 0; /* Loop through all root pages */
15154 sqlite3_stmt *pPages = 0; /* Loop through all pages in a group */
15155 sqlite3_stmt *pCells = 0; /* Loop through all cells in a page */
15156 const char *zRecoveryDb = ""; /* Name of "recovery" database */
15157 const char *zLostAndFound = "lost_and_found";
15158 int i;
15159 int nOrphan = -1;
15160 RecoverTable *pOrphan = 0;
15161
15162 int bFreelist = 1; /* 0 if --freelist-corrupt is specified */
mydongistiny8320bdc2019-10-06 12:50:35 -070015163 int bRowids = 1; /* 0 if --no-rowids */
mydongistiny63ee58c2019-09-21 18:04:30 -070015164 for(i=1; i<nArg; i++){
15165 char *z = azArg[i];
15166 int n;
15167 if( z[0]=='-' && z[1]=='-' ) z++;
15168 n = strlen30(z);
15169 if( n<=17 && memcmp("-freelist-corrupt", z, n)==0 ){
15170 bFreelist = 0;
15171 }else
15172 if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
15173 i++;
15174 zRecoveryDb = azArg[i];
15175 }else
15176 if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
15177 i++;
15178 zLostAndFound = azArg[i];
mydongistiny8320bdc2019-10-06 12:50:35 -070015179 }else
15180 if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
15181 bRowids = 0;
mydongistiny63ee58c2019-09-21 18:04:30 -070015182 }
15183 else{
mydongistiny8320bdc2019-10-06 12:50:35 -070015184 utf8_printf(stderr, "unexpected option: %s\n", azArg[i]);
15185 showHelp(pState->out, azArg[0]);
mydongistiny63ee58c2019-09-21 18:04:30 -070015186 return 1;
15187 }
15188 }
15189
15190 shellExecPrintf(pState->db, &rc,
15191 /* Attach an in-memory database named 'recovery'. Create an indexed
15192 ** cache of the sqlite_dbptr virtual table. */
mydongistiny8320bdc2019-10-06 12:50:35 -070015193 "PRAGMA writable_schema = on;"
mydongistiny63ee58c2019-09-21 18:04:30 -070015194 "ATTACH %Q AS recovery;"
15195 "DROP TABLE IF EXISTS recovery.dbptr;"
15196 "DROP TABLE IF EXISTS recovery.freelist;"
15197 "DROP TABLE IF EXISTS recovery.map;"
15198 "DROP TABLE IF EXISTS recovery.schema;"
15199 "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb
15200 );
15201
15202 if( bFreelist ){
15203 shellExec(pState->db, &rc,
15204 "WITH trunk(pgno) AS ("
15205 " SELECT shell_int32("
15206 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x "
15207 " WHERE x>0"
15208 " UNION"
15209 " SELECT shell_int32("
15210 " (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x "
15211 " FROM trunk WHERE x>0"
15212 "),"
15213 "freelist(data, n, freepgno) AS ("
15214 " SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno "
15215 " FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno"
15216 " UNION ALL"
15217 " SELECT data, n-1, shell_int32(data, 2+n) "
15218 " FROM freelist WHERE n>=0"
15219 ")"
15220 "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;"
15221 );
15222 }
15223
mydongistiny8320bdc2019-10-06 12:50:35 -070015224 /* If this is an auto-vacuum database, add all pointer-map pages to
15225 ** the freelist table. Do this regardless of whether or not
15226 ** --freelist-corrupt was specified. */
15227 shellExec(pState->db, &rc,
15228 "WITH ptrmap(pgno) AS ("
15229 " SELECT 2 WHERE shell_int32("
15230 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 13"
15231 " )"
15232 " UNION ALL "
15233 " SELECT pgno+1+(SELECT page_size FROM pragma_page_size)/5 AS pp "
15234 " FROM ptrmap WHERE pp<=(SELECT page_count FROM pragma_page_count)"
15235 ")"
15236 "REPLACE INTO recovery.freelist SELECT pgno FROM ptrmap"
15237 );
15238
mydongistiny63ee58c2019-09-21 18:04:30 -070015239 shellExec(pState->db, &rc,
15240 "CREATE TABLE recovery.dbptr("
15241 " pgno, child, PRIMARY KEY(child, pgno)"
15242 ") WITHOUT ROWID;"
15243 "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) "
15244 " SELECT * FROM sqlite_dbptr"
15245 " WHERE pgno NOT IN freelist AND child NOT IN freelist;"
15246
15247 /* Delete any pointer to page 1. This ensures that page 1 is considered
15248 ** a root page, regardless of how corrupt the db is. */
15249 "DELETE FROM recovery.dbptr WHERE child = 1;"
15250
15251 /* Delete all pointers to any pages that have more than one pointer
15252 ** to them. Such pages will be treated as root pages when recovering
15253 ** data. */
15254 "DELETE FROM recovery.dbptr WHERE child IN ("
15255 " SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1"
15256 ");"
15257
15258 /* Create the "map" table that will (eventually) contain instructions
15259 ** for dealing with each page in the db that contains one or more
15260 ** records. */
15261 "CREATE TABLE recovery.map("
15262 "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT"
15263 ");"
15264
15265 /* Populate table [map]. If there are circular loops of pages in the
15266 ** database, the following adds all pages in such a loop to the map
15267 ** as individual root pages. This could be handled better. */
15268 "WITH pages(i, maxlen) AS ("
15269 " SELECT page_count, ("
15270 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count"
15271 " ) FROM pragma_page_count WHERE page_count>0"
15272 " UNION ALL"
15273 " SELECT i-1, ("
15274 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1"
15275 " ) FROM pages WHERE i>=2"
15276 ")"
15277 "INSERT INTO recovery.map(pgno, maxlen, intkey, root) "
15278 " SELECT i, maxlen, NULL, ("
15279 " WITH p(orig, pgno, parent) AS ("
15280 " SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)"
15281 " UNION "
15282 " SELECT i, p.parent, "
15283 " (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p"
15284 " )"
15285 " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
15286 ") "
mydongistiny8320bdc2019-10-06 12:50:35 -070015287 "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;"
mydongistiny63ee58c2019-09-21 18:04:30 -070015288 "UPDATE recovery.map AS o SET intkey = ("
15289 " SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
15290 ");"
15291
15292 /* Extract data from page 1 and any linked pages into table
15293 ** recovery.schema. With the same schema as an sqlite_master table. */
15294 "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
15295 "INSERT INTO recovery.schema SELECT "
15296 " max(CASE WHEN field=0 THEN value ELSE NULL END),"
15297 " max(CASE WHEN field=1 THEN value ELSE NULL END),"
15298 " max(CASE WHEN field=2 THEN value ELSE NULL END),"
15299 " max(CASE WHEN field=3 THEN value ELSE NULL END),"
15300 " max(CASE WHEN field=4 THEN value ELSE NULL END)"
15301 "FROM sqlite_dbdata WHERE pgno IN ("
15302 " SELECT pgno FROM recovery.map WHERE root=1"
15303 ")"
15304 "GROUP BY pgno, cell;"
15305 "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);"
15306 );
15307
15308 /* Open a transaction, then print out all non-virtual, non-"sqlite_%"
15309 ** CREATE TABLE statements that extracted from the existing schema. */
15310 if( rc==SQLITE_OK ){
15311 sqlite3_stmt *pStmt = 0;
mydongistiny8320bdc2019-10-06 12:50:35 -070015312 /* ".recover" might output content in an order which causes immediate
15313 ** foreign key constraints to be violated. So disable foreign-key
15314 ** constraint enforcement to prevent problems when running the output
15315 ** script. */
15316 raw_printf(pState->out, "PRAGMA foreign_keys=OFF;\n");
mydongistiny63ee58c2019-09-21 18:04:30 -070015317 raw_printf(pState->out, "BEGIN;\n");
15318 raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
15319 shellPrepare(pState->db, &rc,
15320 "SELECT sql FROM recovery.schema "
15321 "WHERE type='table' AND sql LIKE 'create table%'", &pStmt
15322 );
15323 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
15324 const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0);
15325 raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n",
15326 &zCreateTable[12]
15327 );
15328 }
15329 shellFinalize(&rc, pStmt);
15330 }
15331
15332 /* Figure out if an orphan table will be required. And if so, how many
15333 ** user columns it should contain */
15334 shellPrepare(pState->db, &rc,
15335 "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1"
15336 , &pLoop
15337 );
15338 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
15339 nOrphan = sqlite3_column_int(pLoop, 0);
15340 }
15341 shellFinalize(&rc, pLoop);
15342 pLoop = 0;
15343
15344 shellPrepare(pState->db, &rc,
15345 "SELECT pgno FROM recovery.map WHERE root=?", &pPages
15346 );
mydongistiny8320bdc2019-10-06 12:50:35 -070015347
mydongistiny63ee58c2019-09-21 18:04:30 -070015348 shellPrepare(pState->db, &rc,
mydongistiny8320bdc2019-10-06 12:50:35 -070015349 "SELECT max(field), group_concat(shell_escape_crnl(quote"
15350 "(case when (? AND field<0) then NULL else value end)"
15351 "), ', ')"
15352 ", min(field) "
mydongistiny63ee58c2019-09-21 18:04:30 -070015353 "FROM sqlite_dbdata WHERE pgno = ? AND field != ?"
15354 "GROUP BY cell", &pCells
15355 );
15356
15357 /* Loop through each root page. */
15358 shellPrepare(pState->db, &rc,
15359 "SELECT root, intkey, max(maxlen) FROM recovery.map"
15360 " WHERE root>1 GROUP BY root, intkey ORDER BY root=("
15361 " SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'"
15362 ")", &pLoop
15363 );
15364 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
15365 int iRoot = sqlite3_column_int(pLoop, 0);
15366 int bIntkey = sqlite3_column_int(pLoop, 1);
15367 int nCol = sqlite3_column_int(pLoop, 2);
15368 int bNoop = 0;
15369 RecoverTable *pTab;
15370
mydongistiny8320bdc2019-10-06 12:50:35 -070015371 assert( bIntkey==0 || bIntkey==1 );
mydongistiny63ee58c2019-09-21 18:04:30 -070015372 pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);
15373 if( bNoop || rc ) continue;
15374 if( pTab==0 ){
15375 if( pOrphan==0 ){
15376 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
15377 }
15378 pTab = pOrphan;
15379 if( pTab==0 ) break;
15380 }
15381
mydongistiny8320bdc2019-10-06 12:50:35 -070015382 if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){
mydongistiny63ee58c2019-09-21 18:04:30 -070015383 raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
15384 }
15385 sqlite3_bind_int(pPages, 1, iRoot);
mydongistiny8320bdc2019-10-06 12:50:35 -070015386 if( bRowids==0 && pTab->iPk<0 ){
15387 sqlite3_bind_int(pCells, 1, 1);
15388 }else{
15389 sqlite3_bind_int(pCells, 1, 0);
15390 }
15391 sqlite3_bind_int(pCells, 3, pTab->iPk);
mydongistiny63ee58c2019-09-21 18:04:30 -070015392
15393 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){
15394 int iPgno = sqlite3_column_int(pPages, 0);
mydongistiny8320bdc2019-10-06 12:50:35 -070015395 sqlite3_bind_int(pCells, 2, iPgno);
mydongistiny63ee58c2019-09-21 18:04:30 -070015396 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){
15397 int nField = sqlite3_column_int(pCells, 0);
mydongistiny8320bdc2019-10-06 12:50:35 -070015398 int iMin = sqlite3_column_int(pCells, 2);
mydongistiny63ee58c2019-09-21 18:04:30 -070015399 const char *zVal = (const char*)sqlite3_column_text(pCells, 1);
15400
mydongistiny8320bdc2019-10-06 12:50:35 -070015401 RecoverTable *pTab2 = pTab;
15402 if( pTab!=pOrphan && (iMin<0)!=bIntkey ){
15403 if( pOrphan==0 ){
15404 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
15405 }
15406 pTab2 = pOrphan;
15407 if( pTab2==0 ) break;
15408 }
15409
mydongistiny63ee58c2019-09-21 18:04:30 -070015410 nField = nField+1;
mydongistiny8320bdc2019-10-06 12:50:35 -070015411 if( pTab2==pOrphan ){
mydongistiny63ee58c2019-09-21 18:04:30 -070015412 raw_printf(pState->out,
15413 "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",
mydongistiny8320bdc2019-10-06 12:50:35 -070015414 pTab2->zQuoted, iRoot, iPgno, nField,
15415 iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField]
mydongistiny63ee58c2019-09-21 18:04:30 -070015416 );
15417 }else{
15418 raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n",
mydongistiny8320bdc2019-10-06 12:50:35 -070015419 pTab2->zQuoted, pTab2->azlCol[nField], zVal
mydongistiny63ee58c2019-09-21 18:04:30 -070015420 );
15421 }
15422 }
15423 shellReset(&rc, pCells);
15424 }
15425 shellReset(&rc, pPages);
15426 if( pTab!=pOrphan ) recoverFreeTable(pTab);
15427 }
15428 shellFinalize(&rc, pLoop);
15429 shellFinalize(&rc, pPages);
15430 shellFinalize(&rc, pCells);
15431 recoverFreeTable(pOrphan);
15432
15433 /* The rest of the schema */
15434 if( rc==SQLITE_OK ){
15435 sqlite3_stmt *pStmt = 0;
15436 shellPrepare(pState->db, &rc,
15437 "SELECT sql, name FROM recovery.schema "
15438 "WHERE sql NOT LIKE 'create table%'", &pStmt
15439 );
15440 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
15441 const char *zSql = (const char*)sqlite3_column_text(pStmt, 0);
15442 if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){
15443 const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
15444 char *zPrint = shellMPrintf(&rc,
15445 "INSERT INTO sqlite_master VALUES('table', %Q, %Q, 0, %Q)",
15446 zName, zName, zSql
15447 );
15448 raw_printf(pState->out, "%s;\n", zPrint);
15449 sqlite3_free(zPrint);
15450 }else{
15451 raw_printf(pState->out, "%s;\n", zSql);
15452 }
15453 }
15454 shellFinalize(&rc, pStmt);
15455 }
15456
15457 if( rc==SQLITE_OK ){
15458 raw_printf(pState->out, "PRAGMA writable_schema = off;\n");
15459 raw_printf(pState->out, "COMMIT;\n");
15460 }
15461 sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
15462 return rc;
15463}
15464#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
15465
Luca Stefanie7f3e802017-01-02 15:44:22 +010015466
Alex Naidis08f78cb2016-10-14 15:52:08 +020015467/*
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015468** If an input line begins with "." then invoke this routine to
15469** process that line.
15470**
15471** Return 1 on error, 2 to exit, and 0 otherwise.
15472*/
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070015473static int do_meta_command(char *zLine, ShellState *p){
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070015474 int h = 1;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015475 int nArg = 0;
15476 int n, c;
15477 int rc = 0;
mydongistiny8320bdc2019-10-06 12:50:35 -070015478 char *azArg[52];
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015479
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080015480#ifndef SQLITE_OMIT_VIRTUALTABLE
15481 if( p->expert.pExpert ){
15482 expertFinish(p, 1, 0);
15483 }
15484#endif
15485
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015486 /* Parse the input line into tokens.
15487 */
mydongistiny8320bdc2019-10-06 12:50:35 -070015488 while( zLine[h] && nArg<ArraySize(azArg)-1 ){
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070015489 while( IsSpace(zLine[h]) ){ h++; }
15490 if( zLine[h]==0 ) break;
15491 if( zLine[h]=='\'' || zLine[h]=='"' ){
15492 int delim = zLine[h++];
15493 azArg[nArg++] = &zLine[h];
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015494 while( zLine[h] && zLine[h]!=delim ){
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070015495 if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015496 h++;
Nick Kralevich8fecf562014-05-29 16:56:33 -070015497 }
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070015498 if( zLine[h]==delim ){
15499 zLine[h++] = 0;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015500 }
15501 if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
15502 }else{
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070015503 azArg[nArg++] = &zLine[h];
15504 while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
15505 if( zLine[h] ) zLine[h++] = 0;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015506 resolve_backslashes(azArg[nArg-1]);
15507 }
15508 }
mydongistiny8320bdc2019-10-06 12:50:35 -070015509 azArg[nArg] = 0;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015510
15511 /* Process the input line.
15512 */
Vasu Noria4356a02010-01-20 15:10:57 -080015513 if( nArg==0 ) return 0; /* no tokens, no error */
15514 n = strlen30(azArg[0]);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015515 c = azArg[0][0];
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080015516 clearTempFile(p);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015517
Alex Naidis08f78cb2016-10-14 15:52:08 +020015518#ifndef SQLITE_OMIT_AUTHORIZATION
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015519 if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
15520 if( nArg!=2 ){
15521 raw_printf(stderr, "Usage: .auth ON|OFF\n");
15522 rc = 1;
15523 goto meta_command_exit;
15524 }
15525 open_db(p, 0);
15526 if( booleanValue(azArg[1]) ){
15527 sqlite3_set_authorizer(p->db, shellAuth, p);
15528 }else{
15529 sqlite3_set_authorizer(p->db, 0, 0);
15530 }
15531 }else
Alex Naidis08f78cb2016-10-14 15:52:08 +020015532#endif
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015533
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080015534#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
15535 if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
15536 open_db(p, 0);
mydongistiny63ee58c2019-09-21 18:04:30 -070015537 rc = arDotCommand(p, 0, azArg, nArg);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080015538 }else
15539#endif
15540
Nick Kralevich8fecf562014-05-29 16:56:33 -070015541 if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
15542 || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
15543 ){
15544 const char *zDestFile = 0;
15545 const char *zDb = 0;
Vasu Noria4356a02010-01-20 15:10:57 -080015546 sqlite3 *pDest;
15547 sqlite3_backup *pBackup;
Nick Kralevich8fecf562014-05-29 16:56:33 -070015548 int j;
mydongistiny63ee58c2019-09-21 18:04:30 -070015549 int bAsync = 0;
15550 const char *zVfs = 0;
Nick Kralevich8fecf562014-05-29 16:56:33 -070015551 for(j=1; j<nArg; j++){
15552 const char *z = azArg[j];
15553 if( z[0]=='-' ){
mydongistiny63ee58c2019-09-21 18:04:30 -070015554 if( z[1]=='-' ) z++;
15555 if( strcmp(z, "-append")==0 ){
15556 zVfs = "apndvfs";
15557 }else
15558 if( strcmp(z, "-async")==0 ){
15559 bAsync = 1;
15560 }else
Nick Kralevich8fecf562014-05-29 16:56:33 -070015561 {
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015562 utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
Nick Kralevich8fecf562014-05-29 16:56:33 -070015563 return 1;
15564 }
15565 }else if( zDestFile==0 ){
15566 zDestFile = azArg[j];
15567 }else if( zDb==0 ){
15568 zDb = zDestFile;
15569 zDestFile = azArg[j];
15570 }else{
mydongistiny63ee58c2019-09-21 18:04:30 -070015571 raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
Nick Kralevich8fecf562014-05-29 16:56:33 -070015572 return 1;
15573 }
Vasu Noria4356a02010-01-20 15:10:57 -080015574 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070015575 if( zDestFile==0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015576 raw_printf(stderr, "missing FILENAME argument on .backup\n");
Nick Kralevich8fecf562014-05-29 16:56:33 -070015577 return 1;
15578 }
15579 if( zDb==0 ) zDb = "main";
mydongistiny63ee58c2019-09-21 18:04:30 -070015580 rc = sqlite3_open_v2(zDestFile, &pDest,
15581 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
Vasu Noria4356a02010-01-20 15:10:57 -080015582 if( rc!=SQLITE_OK ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015583 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
mydongistiny63ee58c2019-09-21 18:04:30 -070015584 close_db(pDest);
Vasu Noria4356a02010-01-20 15:10:57 -080015585 return 1;
15586 }
mydongistiny63ee58c2019-09-21 18:04:30 -070015587 if( bAsync ){
15588 sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
15589 0, 0, 0);
15590 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070015591 open_db(p, 0);
Vasu Noria4356a02010-01-20 15:10:57 -080015592 pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
15593 if( pBackup==0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015594 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
mydongistiny63ee58c2019-09-21 18:04:30 -070015595 close_db(pDest);
Vasu Noria4356a02010-01-20 15:10:57 -080015596 return 1;
15597 }
15598 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
15599 sqlite3_backup_finish(pBackup);
15600 if( rc==SQLITE_DONE ){
15601 rc = 0;
15602 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015603 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
Vasu Noria4356a02010-01-20 15:10:57 -080015604 rc = 1;
15605 }
mydongistiny63ee58c2019-09-21 18:04:30 -070015606 close_db(pDest);
Vasu Noria4356a02010-01-20 15:10:57 -080015607 }else
15608
Nick Kralevich1c7cea32014-06-06 19:53:11 -070015609 if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
15610 if( nArg==2 ){
15611 bail_on_error = booleanValue(azArg[1]);
15612 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015613 raw_printf(stderr, "Usage: .bail on|off\n");
Nick Kralevich1c7cea32014-06-06 19:53:11 -070015614 rc = 1;
15615 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015616 }else
15617
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070015618 if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
15619 if( nArg==2 ){
15620 if( booleanValue(azArg[1]) ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015621 setBinaryMode(p->out, 1);
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070015622 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015623 setTextMode(p->out, 1);
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070015624 }
15625 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015626 raw_printf(stderr, "Usage: .binary on|off\n");
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070015627 rc = 1;
15628 }
15629 }else
15630
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080015631 if( c=='c' && strcmp(azArg[0],"cd")==0 ){
15632 if( nArg==2 ){
15633#if defined(_WIN32) || defined(WIN32)
15634 wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
15635 rc = !SetCurrentDirectoryW(z);
15636 sqlite3_free(z);
15637#else
15638 rc = chdir(azArg[1]);
15639#endif
15640 if( rc ){
15641 utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
15642 rc = 1;
15643 }
15644 }else{
15645 raw_printf(stderr, "Usage: .cd DIRECTORY\n");
15646 rc = 1;
15647 }
15648 }else
15649
Nick Kralevich8fecf562014-05-29 16:56:33 -070015650 /* The undocumented ".breakpoint" command causes a call to the no-op
15651 ** routine named test_breakpoint().
15652 */
15653 if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
15654 test_breakpoint();
15655 }else
15656
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015657 if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
15658 if( nArg==2 ){
Alex Naidisb86c0cf2017-03-31 14:12:35 +020015659 setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015660 }else{
15661 raw_printf(stderr, "Usage: .changes on|off\n");
15662 rc = 1;
15663 }
15664 }else
15665
Alex Naidis08f78cb2016-10-14 15:52:08 +020015666 /* Cancel output redirection, if it is currently set (by .testcase)
15667 ** Then read the content of the testcase-out.txt file and compare against
15668 ** azArg[1]. If there are differences, report an error and exit.
15669 */
15670 if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
15671 char *zRes = 0;
15672 output_reset(p);
15673 if( nArg!=2 ){
15674 raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
15675 rc = 2;
Luca Stefanie7f3e802017-01-02 15:44:22 +010015676 }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
Alex Naidis08f78cb2016-10-14 15:52:08 +020015677 raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
15678 rc = 2;
15679 }else if( testcase_glob(azArg[1],zRes)==0 ){
15680 utf8_printf(stderr,
15681 "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
15682 p->zTestcase, azArg[1], zRes);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080015683 rc = 1;
Alex Naidis08f78cb2016-10-14 15:52:08 +020015684 }else{
15685 utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
15686 p->nCheck++;
15687 }
15688 sqlite3_free(zRes);
15689 }else
15690
Nick Kralevich1c7cea32014-06-06 19:53:11 -070015691 if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
15692 if( nArg==2 ){
15693 tryToClone(p, azArg[1]);
15694 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015695 raw_printf(stderr, "Usage: .clone FILENAME\n");
Nick Kralevich1c7cea32014-06-06 19:53:11 -070015696 rc = 1;
15697 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070015698 }else
15699
Nick Kralevich1c7cea32014-06-06 19:53:11 -070015700 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070015701 ShellState data;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015702 char *zErrMsg = 0;
Nick Kralevich8fecf562014-05-29 16:56:33 -070015703 open_db(p, 0);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015704 memcpy(&data, p, sizeof(data));
Luca Stefanie7f3e802017-01-02 15:44:22 +010015705 data.showHeader = 0;
15706 data.cMode = data.mode = MODE_List;
15707 sqlite3_snprintf(sizeof(data.colSeparator),data.colSeparator,": ");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015708 data.cnt = 0;
Luca Stefanie7f3e802017-01-02 15:44:22 +010015709 sqlite3_exec(p->db, "SELECT name, file FROM pragma_database_list",
15710 callback, &data, &zErrMsg);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015711 if( zErrMsg ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015712 utf8_printf(stderr,"Error: %s\n", zErrMsg);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015713 sqlite3_free(zErrMsg);
Vasu Noria4356a02010-01-20 15:10:57 -080015714 rc = 1;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015715 }
15716 }else
15717
mydongistiny63ee58c2019-09-21 18:04:30 -070015718 if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
15719 static const struct DbConfigChoices {
15720 const char *zName;
15721 int op;
15722 } aDbConfig[] = {
15723 { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
15724 { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
mydongistiny8320bdc2019-10-06 12:50:35 -070015725 { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
mydongistiny63ee58c2019-09-21 18:04:30 -070015726 { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
15727 { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
15728 { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
15729 { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
15730 { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
15731 { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
15732 { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
15733 { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA },
15734 { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
15735 { "dqs_dml", SQLITE_DBCONFIG_DQS_DML },
15736 { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL },
15737 };
15738 int ii, v;
15739 open_db(p, 0);
15740 for(ii=0; ii<ArraySize(aDbConfig); ii++){
15741 if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
15742 if( nArg>=3 ){
15743 sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
15744 }
15745 sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
15746 utf8_printf(p->out, "%18s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
15747 if( nArg>1 ) break;
15748 }
15749 if( nArg>1 && ii==ArraySize(aDbConfig) ){
15750 utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
15751 utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
15752 }
15753 }else
15754
15755 if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070015756 rc = shell_dbinfo_command(p, nArg, azArg);
15757 }else
15758
mydongistiny63ee58c2019-09-21 18:04:30 -070015759#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
15760 if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){
15761 open_db(p, 0);
15762 rc = recoverDatabaseCmd(p, nArg, azArg);
15763 }else
15764#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
15765
Nick Kralevich1c7cea32014-06-06 19:53:11 -070015766 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
Alex Naidisb86c0cf2017-03-31 14:12:35 +020015767 const char *zLike = 0;
15768 int i;
Alex Naidisb94ea7b2017-05-24 19:25:14 +020015769 int savedShowHeader = p->showHeader;
mydongistiny63ee58c2019-09-21 18:04:30 -070015770 int savedShellFlags = p->shellFlgs;
15771 ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo);
Alex Naidisb86c0cf2017-03-31 14:12:35 +020015772 for(i=1; i<nArg; i++){
15773 if( azArg[i][0]=='-' ){
15774 const char *z = azArg[i]+1;
15775 if( z[0]=='-' ) z++;
15776 if( strcmp(z,"preserve-rowids")==0 ){
15777#ifdef SQLITE_OMIT_VIRTUALTABLE
15778 raw_printf(stderr, "The --preserve-rowids option is not compatible"
15779 " with SQLITE_OMIT_VIRTUALTABLE\n");
15780 rc = 1;
15781 goto meta_command_exit;
15782#else
15783 ShellSetFlag(p, SHFLG_PreserveRowid);
15784#endif
15785 }else
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080015786 if( strcmp(z,"newlines")==0 ){
15787 ShellSetFlag(p, SHFLG_Newlines);
15788 }else
Alex Naidisb86c0cf2017-03-31 14:12:35 +020015789 {
15790 raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
15791 rc = 1;
15792 goto meta_command_exit;
15793 }
15794 }else if( zLike ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080015795 raw_printf(stderr, "Usage: .dump ?--preserve-rowids? "
15796 "?--newlines? ?LIKE-PATTERN?\n");
Alex Naidisb86c0cf2017-03-31 14:12:35 +020015797 rc = 1;
15798 goto meta_command_exit;
15799 }else{
15800 zLike = azArg[i];
15801 }
15802 }
mydongistiny63ee58c2019-09-21 18:04:30 -070015803
Nick Kralevich8fecf562014-05-29 16:56:33 -070015804 open_db(p, 0);
mydongistiny63ee58c2019-09-21 18:04:30 -070015805
Vasu Noria4356a02010-01-20 15:10:57 -080015806 /* When playing back a "dump", the content might appear in an order
15807 ** which causes immediate foreign key constraints to be violated.
15808 ** So disable foreign-key constraint enforcement to prevent problems. */
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015809 raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
15810 raw_printf(p->out, "BEGIN TRANSACTION;\n");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015811 p->writableSchema = 0;
Alex Naidisb94ea7b2017-05-24 19:25:14 +020015812 p->showHeader = 0;
Alex Naidisb86c0cf2017-03-31 14:12:35 +020015813 /* Set writable_schema=ON since doing so forces SQLite to initialize
15814 ** as much of the schema as it can even if the sqlite_master table is
15815 ** corrupt. */
Jeff Brown90ed05d2012-01-19 16:35:19 -080015816 sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
15817 p->nErr = 0;
Alex Naidisb86c0cf2017-03-31 14:12:35 +020015818 if( zLike==0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015819 run_schema_dump_query(p,
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015820 "SELECT name, type, sql FROM sqlite_master "
Jeff Brown90ed05d2012-01-19 16:35:19 -080015821 "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'"
Vasu Noria4356a02010-01-20 15:10:57 -080015822 );
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015823 run_schema_dump_query(p,
Vasu Noria4356a02010-01-20 15:10:57 -080015824 "SELECT name, type, sql FROM sqlite_master "
Jeff Brown90ed05d2012-01-19 16:35:19 -080015825 "WHERE name=='sqlite_sequence'"
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015826 );
Jeff Brown90ed05d2012-01-19 16:35:19 -080015827 run_table_dump_query(p,
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015828 "SELECT sql FROM sqlite_master "
Vasu Noria4356a02010-01-20 15:10:57 -080015829 "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015830 );
15831 }else{
Alex Naidisb86c0cf2017-03-31 14:12:35 +020015832 char *zSql;
15833 zSql = sqlite3_mprintf(
15834 "SELECT name, type, sql FROM sqlite_master "
15835 "WHERE tbl_name LIKE %Q AND type=='table'"
15836 " AND sql NOT NULL", zLike);
15837 run_schema_dump_query(p,zSql);
15838 sqlite3_free(zSql);
15839 zSql = sqlite3_mprintf(
15840 "SELECT sql FROM sqlite_master "
15841 "WHERE sql NOT NULL"
15842 " AND type IN ('index','trigger','view')"
15843 " AND tbl_name LIKE %Q", zLike);
15844 run_table_dump_query(p, zSql, 0);
15845 sqlite3_free(zSql);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015846 }
15847 if( p->writableSchema ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015848 raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015849 p->writableSchema = 0;
15850 }
Jeff Brown90ed05d2012-01-19 16:35:19 -080015851 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
15852 sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
mydongistiny63ee58c2019-09-21 18:04:30 -070015853 raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
Alex Naidisb94ea7b2017-05-24 19:25:14 +020015854 p->showHeader = savedShowHeader;
mydongistiny63ee58c2019-09-21 18:04:30 -070015855 p->shellFlgs = savedShellFlags;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015856 }else
15857
Nick Kralevich1c7cea32014-06-06 19:53:11 -070015858 if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
15859 if( nArg==2 ){
Alex Naidisb86c0cf2017-03-31 14:12:35 +020015860 setOrClearFlag(p, SHFLG_Echo, azArg[1]);
Nick Kralevich1c7cea32014-06-06 19:53:11 -070015861 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015862 raw_printf(stderr, "Usage: .echo on|off\n");
Nick Kralevich1c7cea32014-06-06 19:53:11 -070015863 rc = 1;
15864 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015865 }else
15866
Nick Kralevich1c7cea32014-06-06 19:53:11 -070015867 if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
15868 if( nArg==2 ){
mydongistiny63ee58c2019-09-21 18:04:30 -070015869 p->autoEQPtest = 0;
15870 if( p->autoEQPtrace ){
15871 if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
15872 p->autoEQPtrace = 0;
15873 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015874 if( strcmp(azArg[1],"full")==0 ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080015875 p->autoEQP = AUTOEQP_full;
15876 }else if( strcmp(azArg[1],"trigger")==0 ){
15877 p->autoEQP = AUTOEQP_trigger;
mydongistiny63ee58c2019-09-21 18:04:30 -070015878#ifdef SQLITE_DEBUG
15879 }else if( strcmp(azArg[1],"test")==0 ){
15880 p->autoEQP = AUTOEQP_on;
15881 p->autoEQPtest = 1;
15882 }else if( strcmp(azArg[1],"trace")==0 ){
15883 p->autoEQP = AUTOEQP_full;
15884 p->autoEQPtrace = 1;
15885 open_db(p, 0);
15886 sqlite3_exec(p->db, "SELECT name FROM sqlite_master LIMIT 1", 0, 0, 0);
15887 sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
15888#endif
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015889 }else{
mydongistiny63ee58c2019-09-21 18:04:30 -070015890 p->autoEQP = (u8)booleanValue(azArg[1]);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015891 }
Nick Kralevich1c7cea32014-06-06 19:53:11 -070015892 }else{
mydongistiny63ee58c2019-09-21 18:04:30 -070015893 raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
Nick Kralevich1c7cea32014-06-06 19:53:11 -070015894 rc = 1;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015895 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070015896 }else
15897
15898 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
15899 if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015900 rc = 2;
15901 }else
15902
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080015903 /* The ".explain" command is automatic now. It is largely pointless. It
15904 ** retained purely for backwards compatibility */
Nick Kralevich1c7cea32014-06-06 19:53:11 -070015905 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015906 int val = 1;
15907 if( nArg>=2 ){
15908 if( strcmp(azArg[1],"auto")==0 ){
15909 val = 99;
15910 }else{
15911 val = booleanValue(azArg[1]);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015912 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015913 }
15914 if( val==1 && p->mode!=MODE_Explain ){
15915 p->normalMode = p->mode;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015916 p->mode = MODE_Explain;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020015917 p->autoExplain = 0;
15918 }else if( val==0 ){
15919 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
15920 p->autoExplain = 0;
15921 }else if( val==99 ){
15922 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
15923 p->autoExplain = 1;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080015924 }
15925 }else
15926
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080015927#ifndef SQLITE_OMIT_VIRTUALTABLE
15928 if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
15929 open_db(p, 0);
15930 expertDotCommand(p, azArg, nArg);
15931 }else
15932#endif
15933
mydongistiny63ee58c2019-09-21 18:04:30 -070015934 if( c=='f' && strncmp(azArg[0], "filectrl", n)==0 ){
15935 static const struct {
15936 const char *zCtrlName; /* Name of a test-control option */
15937 int ctrlCode; /* Integer code for that option */
15938 const char *zUsage; /* Usage notes */
15939 } aCtrl[] = {
15940 { "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" },
15941 { "chunk_size", SQLITE_FCNTL_CHUNK_SIZE, "SIZE" },
15942 /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/
15943 { "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" },
15944 { "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" },
15945 /* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/
15946 { "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" },
15947 { "has_moved", SQLITE_FCNTL_HAS_MOVED, "" },
15948 { "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" },
15949 };
15950 int filectrl = -1;
15951 int iCtrl = -1;
15952 sqlite3_int64 iRes = 0; /* Integer result to display if rc2==1 */
15953 int isOk = 0; /* 0: usage 1: %lld 2: no-result */
15954 int n2, i;
15955 const char *zCmd = 0;
15956
15957 open_db(p, 0);
15958 zCmd = nArg>=2 ? azArg[1] : "help";
15959
15960 /* The argument can optionally begin with "-" or "--" */
15961 if( zCmd[0]=='-' && zCmd[1] ){
15962 zCmd++;
15963 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
15964 }
15965
15966 /* --help lists all file-controls */
15967 if( strcmp(zCmd,"help")==0 ){
15968 utf8_printf(p->out, "Available file-controls:\n");
15969 for(i=0; i<ArraySize(aCtrl); i++){
15970 utf8_printf(p->out, " .filectrl %s %s\n",
15971 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
15972 }
15973 rc = 1;
15974 goto meta_command_exit;
15975 }
15976
15977 /* convert filectrl text option to value. allow any unique prefix
15978 ** of the option name, or a numerical value. */
15979 n2 = strlen30(zCmd);
15980 for(i=0; i<ArraySize(aCtrl); i++){
15981 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
15982 if( filectrl<0 ){
15983 filectrl = aCtrl[i].ctrlCode;
15984 iCtrl = i;
15985 }else{
15986 utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n"
15987 "Use \".filectrl --help\" for help\n", zCmd);
15988 rc = 1;
15989 goto meta_command_exit;
15990 }
15991 }
15992 }
15993 if( filectrl<0 ){
15994 utf8_printf(stderr,"Error: unknown file-control: %s\n"
15995 "Use \".filectrl --help\" for help\n", zCmd);
15996 }else{
15997 switch(filectrl){
15998 case SQLITE_FCNTL_SIZE_LIMIT: {
15999 if( nArg!=2 && nArg!=3 ) break;
16000 iRes = nArg==3 ? integerValue(azArg[2]) : -1;
16001 sqlite3_file_control(p->db, 0, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
16002 isOk = 1;
16003 break;
16004 }
16005 case SQLITE_FCNTL_LOCK_TIMEOUT:
16006 case SQLITE_FCNTL_CHUNK_SIZE: {
16007 int x;
16008 if( nArg!=3 ) break;
16009 x = (int)integerValue(azArg[2]);
16010 sqlite3_file_control(p->db, 0, filectrl, &x);
16011 isOk = 2;
16012 break;
16013 }
16014 case SQLITE_FCNTL_PERSIST_WAL:
16015 case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
16016 int x;
16017 if( nArg!=2 && nArg!=3 ) break;
16018 x = nArg==3 ? booleanValue(azArg[2]) : -1;
16019 sqlite3_file_control(p->db, 0, filectrl, &x);
16020 iRes = x;
16021 isOk = 1;
16022 break;
16023 }
16024 case SQLITE_FCNTL_HAS_MOVED: {
16025 int x;
16026 if( nArg!=2 ) break;
16027 sqlite3_file_control(p->db, 0, filectrl, &x);
16028 iRes = x;
16029 isOk = 1;
16030 break;
16031 }
16032 case SQLITE_FCNTL_TEMPFILENAME: {
16033 char *z = 0;
16034 if( nArg!=2 ) break;
16035 sqlite3_file_control(p->db, 0, filectrl, &z);
16036 if( z ){
16037 utf8_printf(p->out, "%s\n", z);
16038 sqlite3_free(z);
16039 }
16040 isOk = 2;
16041 break;
16042 }
16043 }
16044 }
16045 if( isOk==0 && iCtrl>=0 ){
16046 utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
16047 rc = 1;
16048 }else if( isOk==1 ){
16049 char zBuf[100];
16050 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
16051 raw_printf(p->out, "%s\n", zBuf);
16052 }
16053 }else
16054
Jeff Brown9bee60b2014-08-20 16:41:25 -070016055 if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016056 ShellState data;
Jeff Brown9bee60b2014-08-20 16:41:25 -070016057 char *zErrMsg = 0;
16058 int doStats = 0;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016059 memcpy(&data, p, sizeof(data));
16060 data.showHeader = 0;
16061 data.cMode = data.mode = MODE_Semi;
16062 if( nArg==2 && optionMatch(azArg[1], "indent") ){
16063 data.cMode = data.mode = MODE_Pretty;
16064 nArg = 1;
16065 }
Jeff Brown9bee60b2014-08-20 16:41:25 -070016066 if( nArg!=1 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016067 raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
Jeff Brown9bee60b2014-08-20 16:41:25 -070016068 rc = 1;
16069 goto meta_command_exit;
16070 }
16071 open_db(p, 0);
Jeff Brown9bee60b2014-08-20 16:41:25 -070016072 rc = sqlite3_exec(p->db,
16073 "SELECT sql FROM"
16074 " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
16075 " FROM sqlite_master UNION ALL"
16076 " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) "
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016077 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
Jeff Brown9bee60b2014-08-20 16:41:25 -070016078 "ORDER BY rowid",
16079 callback, &data, &zErrMsg
16080 );
16081 if( rc==SQLITE_OK ){
16082 sqlite3_stmt *pStmt;
16083 rc = sqlite3_prepare_v2(p->db,
16084 "SELECT rowid FROM sqlite_master"
16085 " WHERE name GLOB 'sqlite_stat[134]'",
16086 -1, &pStmt, 0);
16087 doStats = sqlite3_step(pStmt)==SQLITE_ROW;
16088 sqlite3_finalize(pStmt);
16089 }
16090 if( doStats==0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016091 raw_printf(p->out, "/* No STAT tables available */\n");
Jeff Brown9bee60b2014-08-20 16:41:25 -070016092 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016093 raw_printf(p->out, "ANALYZE sqlite_master;\n");
Jeff Brown9bee60b2014-08-20 16:41:25 -070016094 sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_master'",
16095 callback, &data, &zErrMsg);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016096 data.cMode = data.mode = MODE_Insert;
Jeff Brown9bee60b2014-08-20 16:41:25 -070016097 data.zDestTable = "sqlite_stat1";
mydongistiny63ee58c2019-09-21 18:04:30 -070016098 shell_exec(&data, "SELECT * FROM sqlite_stat1", &zErrMsg);
Jeff Brown9bee60b2014-08-20 16:41:25 -070016099 data.zDestTable = "sqlite_stat4";
mydongistiny63ee58c2019-09-21 18:04:30 -070016100 shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016101 raw_printf(p->out, "ANALYZE sqlite_master;\n");
Jeff Brown9bee60b2014-08-20 16:41:25 -070016102 }
16103 }else
16104
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016105 if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
16106 if( nArg==2 ){
16107 p->showHeader = booleanValue(azArg[1]);
16108 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016109 raw_printf(stderr, "Usage: .headers on|off\n");
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016110 rc = 1;
Vasu Noria4356a02010-01-20 15:10:57 -080016111 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016112 }else
16113
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016114 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
mydongistiny63ee58c2019-09-21 18:04:30 -070016115 if( nArg>=2 ){
16116 n = showHelp(p->out, azArg[1]);
16117 if( n==0 ){
16118 utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
16119 }
16120 }else{
16121 showHelp(p->out, 0);
16122 }
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016123 }else
16124
16125 if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
16126 char *zTable; /* Insert data into this table */
16127 char *zFile; /* Name of file to extra content from */
Vasu Noria4356a02010-01-20 15:10:57 -080016128 sqlite3_stmt *pStmt = NULL; /* A statement */
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016129 int nCol; /* Number of columns in the table */
16130 int nByte; /* Number of bytes in an SQL string */
16131 int i, j; /* Loop counters */
Nick Kralevich8fecf562014-05-29 16:56:33 -070016132 int needCommit; /* True to COMMIT or ROLLBACK at end */
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016133 int nSep; /* Number of bytes in p->colSeparator[] */
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016134 char *zSql; /* An SQL statement */
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016135 ImportCtx sCtx; /* Reader context */
16136 char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
16137 int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close file */
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016138
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016139 if( nArg!=3 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016140 raw_printf(stderr, "Usage: .import FILE TABLE\n");
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016141 goto meta_command_exit;
16142 }
16143 zFile = azArg[1];
16144 zTable = azArg[2];
Nick Kralevich8fecf562014-05-29 16:56:33 -070016145 seenInterrupt = 0;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016146 memset(&sCtx, 0, sizeof(sCtx));
Nick Kralevich8fecf562014-05-29 16:56:33 -070016147 open_db(p, 0);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016148 nSep = strlen30(p->colSeparator);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016149 if( nSep==0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016150 raw_printf(stderr,
16151 "Error: non-null column separator required for import\n");
Vasu Noria4356a02010-01-20 15:10:57 -080016152 return 1;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016153 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070016154 if( nSep>1 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016155 raw_printf(stderr, "Error: multi-character column separators not allowed"
Nick Kralevich8fecf562014-05-29 16:56:33 -070016156 " for import\n");
16157 return 1;
16158 }
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016159 nSep = strlen30(p->rowSeparator);
16160 if( nSep==0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016161 raw_printf(stderr, "Error: non-null row separator required for import\n");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016162 return 1;
16163 }
16164 if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator, SEP_CrLf)==0 ){
16165 /* When importing CSV (only), if the row separator is set to the
16166 ** default output row separator, change it to the default input
16167 ** row separator. This avoids having to maintain different input
16168 ** and output row separators. */
16169 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
16170 nSep = strlen30(p->rowSeparator);
16171 }
16172 if( nSep>1 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016173 raw_printf(stderr, "Error: multi-character row separators not allowed"
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016174 " for import\n");
16175 return 1;
16176 }
16177 sCtx.zFile = zFile;
16178 sCtx.nLine = 1;
16179 if( sCtx.zFile[0]=='|' ){
16180#ifdef SQLITE_OMIT_POPEN
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016181 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016182 return 1;
16183#else
16184 sCtx.in = popen(sCtx.zFile+1, "r");
16185 sCtx.zFile = "<pipe>";
Nick Kralevich8fecf562014-05-29 16:56:33 -070016186 xCloser = pclose;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016187#endif
Nick Kralevich8fecf562014-05-29 16:56:33 -070016188 }else{
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016189 sCtx.in = fopen(sCtx.zFile, "rb");
Nick Kralevich8fecf562014-05-29 16:56:33 -070016190 xCloser = fclose;
16191 }
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016192 if( p->mode==MODE_Ascii ){
16193 xRead = ascii_read_one_field;
16194 }else{
16195 xRead = csv_read_one_field;
16196 }
16197 if( sCtx.in==0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016198 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
Nick Kralevich8fecf562014-05-29 16:56:33 -070016199 return 1;
16200 }
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016201 sCtx.cColSep = p->colSeparator[0];
16202 sCtx.cRowSep = p->rowSeparator[0];
Jeff Brown90ed05d2012-01-19 16:35:19 -080016203 zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
Vasu Noria4356a02010-01-20 15:10:57 -080016204 if( zSql==0 ){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016205 xCloser(sCtx.in);
mydongistiny63ee58c2019-09-21 18:04:30 -070016206 shell_out_of_memory();
Vasu Noria4356a02010-01-20 15:10:57 -080016207 }
16208 nByte = strlen30(zSql);
Nick Kralevich8fecf562014-05-29 16:56:33 -070016209 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016210 import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070016211 if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
Nick Kralevich8fecf562014-05-29 16:56:33 -070016212 char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
16213 char cSep = '(';
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016214 while( xRead(&sCtx) ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016215 zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z);
Nick Kralevich8fecf562014-05-29 16:56:33 -070016216 cSep = ',';
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016217 if( sCtx.cTerm!=sCtx.cColSep ) break;
Nick Kralevich8fecf562014-05-29 16:56:33 -070016218 }
16219 if( cSep=='(' ){
16220 sqlite3_free(zCreate);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016221 sqlite3_free(sCtx.z);
16222 xCloser(sCtx.in);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016223 utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
Nick Kralevich8fecf562014-05-29 16:56:33 -070016224 return 1;
16225 }
16226 zCreate = sqlite3_mprintf("%z\n)", zCreate);
16227 rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
16228 sqlite3_free(zCreate);
16229 if( rc ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016230 utf8_printf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070016231 sqlite3_errmsg(p->db));
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016232 sqlite3_free(sCtx.z);
16233 xCloser(sCtx.in);
Nick Kralevich8fecf562014-05-29 16:56:33 -070016234 return 1;
16235 }
16236 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
16237 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016238 sqlite3_free(zSql);
16239 if( rc ){
Vasu Noria4356a02010-01-20 15:10:57 -080016240 if (pStmt) sqlite3_finalize(pStmt);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016241 utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016242 xCloser(sCtx.in);
Vasu Noria4356a02010-01-20 15:10:57 -080016243 return 1;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016244 }
Vasu Noria4356a02010-01-20 15:10:57 -080016245 nCol = sqlite3_column_count(pStmt);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016246 sqlite3_finalize(pStmt);
Vasu Noria4356a02010-01-20 15:10:57 -080016247 pStmt = 0;
16248 if( nCol==0 ) return 0; /* no columns, no error */
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070016249 zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
Vasu Noria4356a02010-01-20 15:10:57 -080016250 if( zSql==0 ){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016251 xCloser(sCtx.in);
mydongistiny63ee58c2019-09-21 18:04:30 -070016252 shell_out_of_memory();
Vasu Noria4356a02010-01-20 15:10:57 -080016253 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070016254 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
Vasu Noria4356a02010-01-20 15:10:57 -080016255 j = strlen30(zSql);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016256 for(i=1; i<nCol; i++){
16257 zSql[j++] = ',';
16258 zSql[j++] = '?';
16259 }
16260 zSql[j++] = ')';
16261 zSql[j] = 0;
Nick Kralevich8fecf562014-05-29 16:56:33 -070016262 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
16263 sqlite3_free(zSql);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016264 if( rc ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016265 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
Vasu Noria4356a02010-01-20 15:10:57 -080016266 if (pStmt) sqlite3_finalize(pStmt);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016267 xCloser(sCtx.in);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016268 return 1;
16269 }
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070016270 needCommit = sqlite3_get_autocommit(p->db);
16271 if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
Nick Kralevich8fecf562014-05-29 16:56:33 -070016272 do{
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016273 int startLine = sCtx.nLine;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016274 for(i=0; i<nCol; i++){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016275 char *z = xRead(&sCtx);
16276 /*
16277 ** Did we reach end-of-file before finding any columns?
16278 ** If so, stop instead of NULL filling the remaining columns.
16279 */
Nick Kralevich8fecf562014-05-29 16:56:33 -070016280 if( z==0 && i==0 ) break;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016281 /*
16282 ** Did we reach end-of-file OR end-of-line before finding any
16283 ** columns in ASCII mode? If so, stop instead of NULL filling
16284 ** the remaining columns.
16285 */
16286 if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
Nick Kralevich8fecf562014-05-29 16:56:33 -070016287 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016288 if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016289 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
Nick Kralevich8fecf562014-05-29 16:56:33 -070016290 "filling the rest with NULL\n",
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016291 sCtx.zFile, startLine, nCol, i+1);
16292 i += 2;
Jeff Brown9bee60b2014-08-20 16:41:25 -070016293 while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
Jeff Brownc82acac2012-04-19 19:31:30 -070016294 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016295 }
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016296 if( sCtx.cTerm==sCtx.cColSep ){
Nick Kralevich8fecf562014-05-29 16:56:33 -070016297 do{
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016298 xRead(&sCtx);
Nick Kralevich8fecf562014-05-29 16:56:33 -070016299 i++;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016300 }while( sCtx.cTerm==sCtx.cColSep );
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016301 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
Nick Kralevich8fecf562014-05-29 16:56:33 -070016302 "extras ignored\n",
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016303 sCtx.zFile, startLine, nCol, i);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016304 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070016305 if( i>=nCol ){
16306 sqlite3_step(pStmt);
16307 rc = sqlite3_reset(pStmt);
16308 if( rc!=SQLITE_OK ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016309 utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
16310 startLine, sqlite3_errmsg(p->db));
Nick Kralevich8fecf562014-05-29 16:56:33 -070016311 }
16312 }
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016313 }while( sCtx.cTerm!=EOF );
Nick Kralevich8fecf562014-05-29 16:56:33 -070016314
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016315 xCloser(sCtx.in);
16316 sqlite3_free(sCtx.z);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016317 sqlite3_finalize(pStmt);
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070016318 if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016319 }else
16320
Luca Stefanie7f3e802017-01-02 15:44:22 +010016321#ifndef SQLITE_UNTESTABLE
16322 if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
16323 char *zSql;
16324 char *zCollist = 0;
16325 sqlite3_stmt *pStmt;
16326 int tnum = 0;
16327 int i;
mydongistiny63ee58c2019-09-21 18:04:30 -070016328 if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
16329 utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
16330 " .imposter off\n");
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016331 rc = 1;
16332 goto meta_command_exit;
Vasu Noria4356a02010-01-20 15:10:57 -080016333 }
Luca Stefanie7f3e802017-01-02 15:44:22 +010016334 open_db(p, 0);
mydongistiny63ee58c2019-09-21 18:04:30 -070016335 if( nArg==2 ){
16336 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
16337 goto meta_command_exit;
16338 }
Luca Stefanie7f3e802017-01-02 15:44:22 +010016339 zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master"
16340 " WHERE name='%q' AND type='index'", azArg[1]);
16341 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
16342 sqlite3_free(zSql);
16343 if( sqlite3_step(pStmt)==SQLITE_ROW ){
16344 tnum = sqlite3_column_int(pStmt, 0);
16345 }
16346 sqlite3_finalize(pStmt);
16347 if( tnum==0 ){
16348 utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
Vasu Noria4356a02010-01-20 15:10:57 -080016349 rc = 1;
Luca Stefanie7f3e802017-01-02 15:44:22 +010016350 goto meta_command_exit;
16351 }
16352 zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
16353 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
16354 sqlite3_free(zSql);
16355 i = 0;
16356 while( sqlite3_step(pStmt)==SQLITE_ROW ){
16357 char zLabel[20];
16358 const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
16359 i++;
16360 if( zCol==0 ){
16361 if( sqlite3_column_int(pStmt,1)==-1 ){
16362 zCol = "_ROWID_";
16363 }else{
16364 sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
16365 zCol = zLabel;
16366 }
16367 }
16368 if( zCollist==0 ){
16369 zCollist = sqlite3_mprintf("\"%w\"", zCol);
16370 }else{
16371 zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
16372 }
16373 }
16374 sqlite3_finalize(pStmt);
16375 zSql = sqlite3_mprintf(
16376 "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%s))WITHOUT ROWID",
16377 azArg[2], zCollist, zCollist);
16378 sqlite3_free(zCollist);
16379 rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
16380 if( rc==SQLITE_OK ){
16381 rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
16382 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
16383 if( rc ){
16384 utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
16385 }else{
16386 utf8_printf(stdout, "%s;\n", zSql);
16387 raw_printf(stdout,
16388 "WARNING: writing to an imposter table will corrupt the index!\n"
16389 );
16390 }
16391 }else{
16392 raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
Vasu Noria4356a02010-01-20 15:10:57 -080016393 rc = 1;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016394 }
Luca Stefanie7f3e802017-01-02 15:44:22 +010016395 sqlite3_free(zSql);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016396 }else
Luca Stefanie7f3e802017-01-02 15:44:22 +010016397#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016398
16399#ifdef SQLITE_ENABLE_IOTRACE
16400 if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016401 SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016402 if( iotrace && iotrace!=stdout ) fclose(iotrace);
16403 iotrace = 0;
16404 if( nArg<2 ){
16405 sqlite3IoTrace = 0;
16406 }else if( strcmp(azArg[1], "-")==0 ){
16407 sqlite3IoTrace = iotracePrintf;
16408 iotrace = stdout;
16409 }else{
16410 iotrace = fopen(azArg[1], "w");
16411 if( iotrace==0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016412 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016413 sqlite3IoTrace = 0;
Vasu Noria4356a02010-01-20 15:10:57 -080016414 rc = 1;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016415 }else{
16416 sqlite3IoTrace = iotracePrintf;
16417 }
16418 }
16419 }else
16420#endif
Luca Stefanie7f3e802017-01-02 15:44:22 +010016421
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070016422 if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
16423 static const struct {
16424 const char *zLimitName; /* Name of a limit */
16425 int limitCode; /* Integer code for that limit */
16426 } aLimit[] = {
16427 { "length", SQLITE_LIMIT_LENGTH },
16428 { "sql_length", SQLITE_LIMIT_SQL_LENGTH },
16429 { "column", SQLITE_LIMIT_COLUMN },
16430 { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
16431 { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
16432 { "vdbe_op", SQLITE_LIMIT_VDBE_OP },
16433 { "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
16434 { "attached", SQLITE_LIMIT_ATTACHED },
16435 { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
16436 { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER },
16437 { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
16438 { "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
16439 };
16440 int i, n2;
16441 open_db(p, 0);
16442 if( nArg==1 ){
Nick Kralevich253ed642015-12-23 10:07:58 -080016443 for(i=0; i<ArraySize(aLimit); i++){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016444 printf("%20s %d\n", aLimit[i].zLimitName,
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070016445 sqlite3_limit(p->db, aLimit[i].limitCode, -1));
16446 }
16447 }else if( nArg>3 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016448 raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070016449 rc = 1;
16450 goto meta_command_exit;
16451 }else{
16452 int iLimit = -1;
16453 n2 = strlen30(azArg[1]);
Nick Kralevich253ed642015-12-23 10:07:58 -080016454 for(i=0; i<ArraySize(aLimit); i++){
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070016455 if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
16456 if( iLimit<0 ){
16457 iLimit = i;
16458 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016459 utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070016460 rc = 1;
16461 goto meta_command_exit;
16462 }
16463 }
16464 }
16465 if( iLimit<0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016466 utf8_printf(stderr, "unknown limit: \"%s\"\n"
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070016467 "enter \".limits\" with no arguments for a list.\n",
16468 azArg[1]);
16469 rc = 1;
16470 goto meta_command_exit;
16471 }
16472 if( nArg==3 ){
Nick Kralevich693f9c62015-06-12 15:38:51 -070016473 sqlite3_limit(p->db, aLimit[iLimit].limitCode,
16474 (int)integerValue(azArg[2]));
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070016475 }
16476 printf("%20s %d\n", aLimit[iLimit].zLimitName,
16477 sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
16478 }
16479 }else
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016480
Luca Stefanie7f3e802017-01-02 15:44:22 +010016481 if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
16482 open_db(p, 0);
16483 lintDotCommand(p, azArg, nArg);
16484 }else
16485
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016486#ifndef SQLITE_OMIT_LOAD_EXTENSION
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016487 if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016488 const char *zFile, *zProc;
16489 char *zErrMsg = 0;
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016490 if( nArg<2 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016491 raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016492 rc = 1;
16493 goto meta_command_exit;
16494 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016495 zFile = azArg[1];
16496 zProc = nArg>=3 ? azArg[2] : 0;
Nick Kralevich8fecf562014-05-29 16:56:33 -070016497 open_db(p, 0);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016498 rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
16499 if( rc!=SQLITE_OK ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016500 utf8_printf(stderr, "Error: %s\n", zErrMsg);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016501 sqlite3_free(zErrMsg);
16502 rc = 1;
16503 }
16504 }else
16505#endif
16506
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016507 if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
16508 if( nArg!=2 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016509 raw_printf(stderr, "Usage: .log FILENAME\n");
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016510 rc = 1;
16511 }else{
16512 const char *zFile = azArg[1];
16513 output_file_close(p->pLog);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080016514 p->pLog = output_file_open(zFile, 0);
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016515 }
Vasu Noriaae12b82010-03-02 13:00:31 -080016516 }else
16517
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016518 if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
16519 const char *zMode = nArg>=2 ? azArg[1] : "";
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080016520 int n2 = strlen30(zMode);
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016521 int c2 = zMode[0];
16522 if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016523 p->mode = MODE_Line;
Alex Naidis4b7ed962017-02-13 18:23:48 +010016524 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016525 }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016526 p->mode = MODE_Column;
Alex Naidis4b7ed962017-02-13 18:23:48 +010016527 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016528 }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016529 p->mode = MODE_List;
Alex Naidis4b7ed962017-02-13 18:23:48 +010016530 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
16531 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016532 }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016533 p->mode = MODE_Html;
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016534 }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016535 p->mode = MODE_Tcl;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016536 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
Alex Naidis4b7ed962017-02-13 18:23:48 +010016537 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016538 }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016539 p->mode = MODE_Csv;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016540 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
16541 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016542 }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016543 p->mode = MODE_List;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016544 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016545 }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016546 p->mode = MODE_Insert;
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016547 set_table_name(p, nArg>=3 ? azArg[2] : "table");
Luca Stefanie7f3e802017-01-02 15:44:22 +010016548 }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
16549 p->mode = MODE_Quote;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016550 }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
16551 p->mode = MODE_Ascii;
16552 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
16553 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080016554 }else if( nArg==1 ){
16555 raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
16556 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016557 raw_printf(stderr, "Error: mode should be one of: "
Luca Stefanie7f3e802017-01-02 15:44:22 +010016558 "ascii column csv html insert line list quote tabs tcl\n");
Vasu Noria4356a02010-01-20 15:10:57 -080016559 rc = 1;
16560 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016561 p->cMode = p->mode;
Vasu Noria4356a02010-01-20 15:10:57 -080016562 }else
16563
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016564 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
16565 if( nArg==2 ){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016566 sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
16567 "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016568 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016569 raw_printf(stderr, "Usage: .nullvalue STRING\n");
Vasu Noria4356a02010-01-20 15:10:57 -080016570 rc = 1;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016571 }
16572 }else
16573
Nick Kralevich8fecf562014-05-29 16:56:33 -070016574 if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
Alex Naidis08f78cb2016-10-14 15:52:08 +020016575 char *zNewFilename; /* Name of the database file to open */
16576 int iName = 1; /* Index in azArg[] of the filename */
16577 int newFlag = 0; /* True to delete file before opening */
16578 /* Close the existing database */
16579 session_close_all(p);
mydongistiny63ee58c2019-09-21 18:04:30 -070016580 close_db(p->db);
Nick Kralevich8fecf562014-05-29 16:56:33 -070016581 p->db = 0;
Alex Naidisb86c0cf2017-03-31 14:12:35 +020016582 p->zDbFilename = 0;
Alex Naidis08f78cb2016-10-14 15:52:08 +020016583 sqlite3_free(p->zFreeOnClose);
16584 p->zFreeOnClose = 0;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080016585 p->openMode = SHELL_OPEN_UNSPEC;
mydongistiny63ee58c2019-09-21 18:04:30 -070016586 p->szMax = 0;
Alex Naidis08f78cb2016-10-14 15:52:08 +020016587 /* Check for command-line arguments */
16588 for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){
16589 const char *z = azArg[iName];
16590 if( optionMatch(z,"new") ){
16591 newFlag = 1;
mydongistiny63ee58c2019-09-21 18:04:30 -070016592#ifdef SQLITE_HAVE_ZLIB
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080016593 }else if( optionMatch(z, "zip") ){
16594 p->openMode = SHELL_OPEN_ZIPFILE;
16595#endif
16596 }else if( optionMatch(z, "append") ){
16597 p->openMode = SHELL_OPEN_APPENDVFS;
mydongistiny63ee58c2019-09-21 18:04:30 -070016598 }else if( optionMatch(z, "readonly") ){
16599 p->openMode = SHELL_OPEN_READONLY;
16600#ifdef SQLITE_ENABLE_DESERIALIZE
16601 }else if( optionMatch(z, "deserialize") ){
16602 p->openMode = SHELL_OPEN_DESERIALIZE;
16603 }else if( optionMatch(z, "hexdb") ){
16604 p->openMode = SHELL_OPEN_HEXDB;
16605 }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
16606 p->szMax = integerValue(azArg[++iName]);
16607#endif /* SQLITE_ENABLE_DESERIALIZE */
Alex Naidis08f78cb2016-10-14 15:52:08 +020016608 }else if( z[0]=='-' ){
16609 utf8_printf(stderr, "unknown option: %s\n", z);
16610 rc = 1;
16611 goto meta_command_exit;
16612 }
16613 }
16614 /* If a filename is specified, try to open it first */
16615 zNewFilename = nArg>iName ? sqlite3_mprintf("%s", azArg[iName]) : 0;
mydongistiny63ee58c2019-09-21 18:04:30 -070016616 if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
Alex Naidis08f78cb2016-10-14 15:52:08 +020016617 if( newFlag ) shellDeleteFile(zNewFilename);
16618 p->zDbFilename = zNewFilename;
mydongistiny63ee58c2019-09-21 18:04:30 -070016619 open_db(p, OPEN_DB_KEEPALIVE);
Alex Naidis08f78cb2016-10-14 15:52:08 +020016620 if( p->db==0 ){
16621 utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
16622 sqlite3_free(zNewFilename);
16623 }else{
16624 p->zFreeOnClose = zNewFilename;
16625 }
16626 }
16627 if( p->db==0 ){
16628 /* As a fall-back open a TEMP database */
16629 p->zDbFilename = 0;
16630 open_db(p, 0);
Nick Kralevich8fecf562014-05-29 16:56:33 -070016631 }
16632 }else
16633
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080016634 if( (c=='o'
16635 && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
16636 || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016637 ){
16638 const char *zFile = nArg>=2 ? azArg[1] : "stdout";
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080016639 int bTxtMode = 0;
16640 if( azArg[0][0]=='e' ){
16641 /* Transform the ".excel" command into ".once -x" */
16642 nArg = 2;
16643 azArg[0] = "once";
16644 zFile = azArg[1] = "-x";
16645 n = 4;
16646 }
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016647 if( nArg>2 ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080016648 utf8_printf(stderr, "Usage: .%s [-e|-x|FILE]\n", azArg[0]);
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016649 rc = 1;
16650 goto meta_command_exit;
Nick Kralevich8fecf562014-05-29 16:56:33 -070016651 }
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016652 if( n>1 && strncmp(azArg[0], "once", n)==0 ){
16653 if( nArg<2 ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080016654 raw_printf(stderr, "Usage: .once (-e|-x|FILE)\n");
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016655 rc = 1;
16656 goto meta_command_exit;
16657 }
16658 p->outCount = 2;
16659 }else{
16660 p->outCount = 0;
16661 }
16662 output_reset(p);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080016663 if( zFile[0]=='-' && zFile[1]=='-' ) zFile++;
mydongistiny63ee58c2019-09-21 18:04:30 -070016664#ifndef SQLITE_NOHAVE_SYSTEM
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080016665 if( strcmp(zFile, "-e")==0 || strcmp(zFile, "-x")==0 ){
16666 p->doXdgOpen = 1;
16667 outputModePush(p);
16668 if( zFile[1]=='x' ){
16669 newTempFile(p, "csv");
16670 p->mode = MODE_Csv;
16671 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
16672 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
16673 }else{
16674 newTempFile(p, "txt");
16675 bTxtMode = 1;
16676 }
16677 zFile = p->zTempFile;
16678 }
mydongistiny63ee58c2019-09-21 18:04:30 -070016679#endif /* SQLITE_NOHAVE_SYSTEM */
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016680 if( zFile[0]=='|' ){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016681#ifdef SQLITE_OMIT_POPEN
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016682 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016683 rc = 1;
16684 p->out = stdout;
16685#else
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016686 p->out = popen(zFile + 1, "w");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016687 if( p->out==0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016688 utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
Nick Kralevich8fecf562014-05-29 16:56:33 -070016689 p->out = stdout;
16690 rc = 1;
16691 }else{
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016692 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
Nick Kralevich8fecf562014-05-29 16:56:33 -070016693 }
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016694#endif
Nick Kralevich8fecf562014-05-29 16:56:33 -070016695 }else{
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080016696 p->out = output_file_open(zFile, bTxtMode);
Nick Kralevich8fecf562014-05-29 16:56:33 -070016697 if( p->out==0 ){
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016698 if( strcmp(zFile,"off")!=0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016699 utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
Nick Kralevich8fecf562014-05-29 16:56:33 -070016700 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016701 p->out = stdout;
Vasu Noria4356a02010-01-20 15:10:57 -080016702 rc = 1;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016703 } else {
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016704 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016705 }
16706 }
16707 }else
16708
mydongistiny63ee58c2019-09-21 18:04:30 -070016709 if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
16710 open_db(p,0);
16711 if( nArg<=1 ) goto parameter_syntax_error;
16712
16713 /* .parameter clear
16714 ** Clear all bind parameters by dropping the TEMP table that holds them.
16715 */
16716 if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
mydongistiny63ee58c2019-09-21 18:04:30 -070016717 sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
16718 0, 0, 0);
mydongistiny63ee58c2019-09-21 18:04:30 -070016719 }else
16720
16721 /* .parameter list
16722 ** List all bind parameters.
16723 */
16724 if( nArg==2 && strcmp(azArg[1],"list")==0 ){
16725 sqlite3_stmt *pStmt = 0;
16726 int rx;
16727 int len = 0;
16728 rx = sqlite3_prepare_v2(p->db,
16729 "SELECT max(length(key)) "
16730 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
16731 if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
16732 len = sqlite3_column_int(pStmt, 0);
16733 if( len>40 ) len = 40;
16734 }
16735 sqlite3_finalize(pStmt);
16736 pStmt = 0;
16737 if( len ){
16738 rx = sqlite3_prepare_v2(p->db,
16739 "SELECT key, quote(value) "
16740 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
16741 while( sqlite3_step(pStmt)==SQLITE_ROW ){
16742 utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
16743 sqlite3_column_text(pStmt,1));
16744 }
16745 sqlite3_finalize(pStmt);
16746 }
16747 }else
16748
16749 /* .parameter init
16750 ** Make sure the TEMP table used to hold bind parameters exists.
16751 ** Create it if necessary.
16752 */
16753 if( nArg==2 && strcmp(azArg[1],"init")==0 ){
16754 bind_table_init(p);
16755 }else
16756
16757 /* .parameter set NAME VALUE
16758 ** Set or reset a bind parameter. NAME should be the full parameter
16759 ** name exactly as it appears in the query. (ex: $abc, @def). The
16760 ** VALUE can be in either SQL literal notation, or if not it will be
16761 ** understood to be a text string.
16762 */
16763 if( nArg==4 && strcmp(azArg[1],"set")==0 ){
16764 int rx;
16765 char *zSql;
16766 sqlite3_stmt *pStmt;
16767 const char *zKey = azArg[2];
16768 const char *zValue = azArg[3];
16769 bind_table_init(p);
16770 zSql = sqlite3_mprintf(
16771 "REPLACE INTO temp.sqlite_parameters(key,value)"
16772 "VALUES(%Q,%s);", zKey, zValue);
16773 if( zSql==0 ) shell_out_of_memory();
16774 pStmt = 0;
16775 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
16776 sqlite3_free(zSql);
16777 if( rx!=SQLITE_OK ){
16778 sqlite3_finalize(pStmt);
16779 pStmt = 0;
16780 zSql = sqlite3_mprintf(
16781 "REPLACE INTO temp.sqlite_parameters(key,value)"
16782 "VALUES(%Q,%Q);", zKey, zValue);
16783 if( zSql==0 ) shell_out_of_memory();
16784 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
16785 sqlite3_free(zSql);
16786 if( rx!=SQLITE_OK ){
16787 utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
16788 sqlite3_finalize(pStmt);
16789 pStmt = 0;
16790 rc = 1;
16791 }
16792 }
16793 sqlite3_step(pStmt);
16794 sqlite3_finalize(pStmt);
16795 }else
16796
16797 /* .parameter unset NAME
16798 ** Remove the NAME binding from the parameter binding table, if it
16799 ** exists.
16800 */
16801 if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
16802 char *zSql = sqlite3_mprintf(
16803 "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
16804 if( zSql==0 ) shell_out_of_memory();
16805 sqlite3_exec(p->db, zSql, 0, 0, 0);
16806 sqlite3_free(zSql);
16807 }else
16808 /* If no command name matches, show a syntax error */
16809 parameter_syntax_error:
16810 showHelp(p->out, "parameter");
16811 }else
16812
Nick Kralevich8fecf562014-05-29 16:56:33 -070016813 if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
16814 int i;
16815 for(i=1; i<nArg; i++){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016816 if( i>1 ) raw_printf(p->out, " ");
16817 utf8_printf(p->out, "%s", azArg[i]);
Nick Kralevich8fecf562014-05-29 16:56:33 -070016818 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016819 raw_printf(p->out, "\n");
Nick Kralevich8fecf562014-05-29 16:56:33 -070016820 }else
16821
mydongistiny63ee58c2019-09-21 18:04:30 -070016822#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
16823 if( c=='p' && n>=3 && strncmp(azArg[0], "progress", n)==0 ){
16824 int i;
16825 int nn = 0;
16826 p->flgProgress = 0;
16827 p->mxProgress = 0;
16828 p->nProgress = 0;
16829 for(i=1; i<nArg; i++){
16830 const char *z = azArg[i];
16831 if( z[0]=='-' ){
16832 z++;
16833 if( z[0]=='-' ) z++;
16834 if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
16835 p->flgProgress |= SHELL_PROGRESS_QUIET;
16836 continue;
16837 }
16838 if( strcmp(z,"reset")==0 ){
16839 p->flgProgress |= SHELL_PROGRESS_RESET;
16840 continue;
16841 }
16842 if( strcmp(z,"once")==0 ){
16843 p->flgProgress |= SHELL_PROGRESS_ONCE;
16844 continue;
16845 }
16846 if( strcmp(z,"limit")==0 ){
16847 if( i+1>=nArg ){
16848 utf8_printf(stderr, "Error: missing argument on --limit\n");
16849 rc = 1;
16850 goto meta_command_exit;
16851 }else{
16852 p->mxProgress = (int)integerValue(azArg[++i]);
16853 }
16854 continue;
16855 }
16856 utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
16857 rc = 1;
16858 goto meta_command_exit;
16859 }else{
16860 nn = (int)integerValue(z);
16861 }
16862 }
16863 open_db(p, 0);
16864 sqlite3_progress_handler(p->db, nn, progress_handler, p);
16865 }else
16866#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
16867
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016868 if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016869 if( nArg >= 2) {
16870 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
16871 }
16872 if( nArg >= 3) {
16873 strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
16874 }
16875 }else
16876
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016877 if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016878 rc = 2;
16879 }else
16880
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016881 if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
mydongistiny63ee58c2019-09-21 18:04:30 -070016882 FILE *inSaved = p->in;
16883 int savedLineno = p->lineno;
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016884 if( nArg!=2 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016885 raw_printf(stderr, "Usage: .read FILE\n");
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016886 rc = 1;
16887 goto meta_command_exit;
16888 }
mydongistiny63ee58c2019-09-21 18:04:30 -070016889 p->in = fopen(azArg[1], "rb");
16890 if( p->in==0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016891 utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
Vasu Noria4356a02010-01-20 15:10:57 -080016892 rc = 1;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016893 }else{
mydongistiny63ee58c2019-09-21 18:04:30 -070016894 rc = process_input(p);
16895 fclose(p->in);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016896 }
mydongistiny63ee58c2019-09-21 18:04:30 -070016897 p->in = inSaved;
16898 p->lineno = savedLineno;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016899 }else
16900
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016901 if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
Vasu Noria4356a02010-01-20 15:10:57 -080016902 const char *zSrcFile;
16903 const char *zDb;
16904 sqlite3 *pSrc;
16905 sqlite3_backup *pBackup;
16906 int nTimeout = 0;
16907
16908 if( nArg==2 ){
16909 zSrcFile = azArg[1];
16910 zDb = "main";
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016911 }else if( nArg==3 ){
Vasu Noria4356a02010-01-20 15:10:57 -080016912 zSrcFile = azArg[2];
16913 zDb = azArg[1];
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016914 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016915 raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016916 rc = 1;
16917 goto meta_command_exit;
Vasu Noria4356a02010-01-20 15:10:57 -080016918 }
16919 rc = sqlite3_open(zSrcFile, &pSrc);
16920 if( rc!=SQLITE_OK ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016921 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
mydongistiny63ee58c2019-09-21 18:04:30 -070016922 close_db(pSrc);
Vasu Noria4356a02010-01-20 15:10:57 -080016923 return 1;
16924 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070016925 open_db(p, 0);
Vasu Noria4356a02010-01-20 15:10:57 -080016926 pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
16927 if( pBackup==0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016928 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
mydongistiny63ee58c2019-09-21 18:04:30 -070016929 close_db(pSrc);
Vasu Noria4356a02010-01-20 15:10:57 -080016930 return 1;
16931 }
16932 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
16933 || rc==SQLITE_BUSY ){
16934 if( rc==SQLITE_BUSY ){
16935 if( nTimeout++ >= 3 ) break;
16936 sqlite3_sleep(100);
16937 }
16938 }
16939 sqlite3_backup_finish(pBackup);
16940 if( rc==SQLITE_DONE ){
16941 rc = 0;
16942 }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016943 raw_printf(stderr, "Error: source database is busy\n");
Vasu Noria4356a02010-01-20 15:10:57 -080016944 rc = 1;
16945 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016946 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
Vasu Noria4356a02010-01-20 15:10:57 -080016947 rc = 1;
16948 }
mydongistiny63ee58c2019-09-21 18:04:30 -070016949 close_db(pSrc);
Vasu Noria4356a02010-01-20 15:10:57 -080016950 }else
16951
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016952 if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
16953 if( nArg==2 ){
mydongistiny63ee58c2019-09-21 18:04:30 -070016954 p->scanstatsOn = (u8)booleanValue(azArg[1]);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016955#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016956 raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016957#endif
16958 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016959 raw_printf(stderr, "Usage: .scanstats on|off\n");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016960 rc = 1;
16961 }
16962 }else
16963
Nick Kralevich1c7cea32014-06-06 19:53:11 -070016964 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080016965 ShellText sSelect;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070016966 ShellState data;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016967 char *zErrMsg = 0;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080016968 const char *zDiv = "(";
16969 const char *zName = 0;
16970 int iSchema = 0;
16971 int bDebug = 0;
16972 int ii;
16973
Nick Kralevich8fecf562014-05-29 16:56:33 -070016974 open_db(p, 0);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016975 memcpy(&data, p, sizeof(data));
16976 data.showHeader = 0;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020016977 data.cMode = data.mode = MODE_Semi;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080016978 initText(&sSelect);
16979 for(ii=1; ii<nArg; ii++){
16980 if( optionMatch(azArg[ii],"indent") ){
16981 data.cMode = data.mode = MODE_Pretty;
16982 }else if( optionMatch(azArg[ii],"debug") ){
16983 bDebug = 1;
16984 }else if( zName==0 ){
16985 zName = azArg[ii];
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016986 }else{
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080016987 raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n");
16988 rc = 1;
16989 goto meta_command_exit;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080016990 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080016991 }
16992 if( zName!=0 ){
mydongistiny63ee58c2019-09-21 18:04:30 -070016993 int isMaster = sqlite3_strlike(zName, "sqlite_master", '\\')==0;
16994 if( isMaster || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0 ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080016995 char *new_argv[2], *new_colv[2];
16996 new_argv[0] = sqlite3_mprintf(
16997 "CREATE TABLE %s (\n"
16998 " type text,\n"
16999 " name text,\n"
17000 " tbl_name text,\n"
17001 " rootpage integer,\n"
17002 " sql text\n"
17003 ")", isMaster ? "sqlite_master" : "sqlite_temp_master");
17004 new_argv[1] = 0;
17005 new_colv[0] = "sql";
17006 new_colv[1] = 0;
17007 callback(&data, 1, new_argv, new_colv);
17008 sqlite3_free(new_argv[0]);
17009 }
17010 }
17011 if( zDiv ){
17012 sqlite3_stmt *pStmt = 0;
17013 rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
17014 -1, &pStmt, 0);
17015 if( rc ){
17016 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
17017 sqlite3_finalize(pStmt);
17018 rc = 1;
17019 goto meta_command_exit;
17020 }
17021 appendText(&sSelect, "SELECT sql FROM", 0);
17022 iSchema = 0;
17023 while( sqlite3_step(pStmt)==SQLITE_ROW ){
17024 const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
17025 char zScNum[30];
17026 sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
17027 appendText(&sSelect, zDiv, 0);
17028 zDiv = " UNION ALL ";
17029 appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
17030 if( sqlite3_stricmp(zDb, "main")!=0 ){
mydongistiny8320bdc2019-10-06 12:50:35 -070017031 appendText(&sSelect, zDb, '\'');
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017032 }else{
17033 appendText(&sSelect, "NULL", 0);
17034 }
17035 appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0);
17036 appendText(&sSelect, zScNum, 0);
17037 appendText(&sSelect, " AS snum, ", 0);
17038 appendText(&sSelect, zDb, '\'');
17039 appendText(&sSelect, " AS sname FROM ", 0);
mydongistiny8320bdc2019-10-06 12:50:35 -070017040 appendText(&sSelect, zDb, quoteChar(zDb));
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017041 appendText(&sSelect, ".sqlite_master", 0);
17042 }
17043 sqlite3_finalize(pStmt);
mydongistiny8320bdc2019-10-06 12:50:35 -070017044#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017045 if( zName ){
17046 appendText(&sSelect,
17047 " UNION ALL SELECT shell_module_schema(name),"
mydongistiny8320bdc2019-10-06 12:50:35 -070017048 " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
17049 0);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017050 }
17051#endif
17052 appendText(&sSelect, ") WHERE ", 0);
17053 if( zName ){
17054 char *zQarg = sqlite3_mprintf("%Q", zName);
mydongistiny63ee58c2019-09-21 18:04:30 -070017055 int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
17056 strchr(zName, '[') != 0;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017057 if( strchr(zName, '.') ){
17058 appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
17059 }else{
17060 appendText(&sSelect, "lower(tbl_name)", 0);
17061 }
mydongistiny63ee58c2019-09-21 18:04:30 -070017062 appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017063 appendText(&sSelect, zQarg, 0);
mydongistiny63ee58c2019-09-21 18:04:30 -070017064 if( !bGlob ){
17065 appendText(&sSelect, " ESCAPE '\\' ", 0);
17066 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017067 appendText(&sSelect, " AND ", 0);
17068 sqlite3_free(zQarg);
17069 }
17070 appendText(&sSelect, "type!='meta' AND sql IS NOT NULL"
17071 " ORDER BY snum, rowid", 0);
17072 if( bDebug ){
17073 utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
17074 }else{
17075 rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
17076 }
17077 freeText(&sSelect);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080017078 }
17079 if( zErrMsg ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017080 utf8_printf(stderr,"Error: %s\n", zErrMsg);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080017081 sqlite3_free(zErrMsg);
Vasu Noria4356a02010-01-20 15:10:57 -080017082 rc = 1;
17083 }else if( rc != SQLITE_OK ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017084 raw_printf(stderr,"Error: querying schema information\n");
Vasu Noria4356a02010-01-20 15:10:57 -080017085 rc = 1;
17086 }else{
17087 rc = 0;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080017088 }
17089 }else
17090
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070017091#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
17092 if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017093 sqlite3SelectTrace = (int)integerValue(azArg[1]);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070017094 }else
17095#endif
17096
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017097#if defined(SQLITE_ENABLE_SESSION)
17098 if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
17099 OpenSession *pSession = &p->aSession[0];
17100 char **azCmd = &azArg[1];
17101 int iSes = 0;
17102 int nCmd = nArg - 1;
17103 int i;
17104 if( nArg<=1 ) goto session_syntax_error;
17105 open_db(p, 0);
17106 if( nArg>=3 ){
17107 for(iSes=0; iSes<p->nSession; iSes++){
17108 if( strcmp(p->aSession[iSes].zName, azArg[1])==0 ) break;
17109 }
17110 if( iSes<p->nSession ){
17111 pSession = &p->aSession[iSes];
17112 azCmd++;
17113 nCmd--;
17114 }else{
17115 pSession = &p->aSession[0];
17116 iSes = 0;
17117 }
17118 }
17119
17120 /* .session attach TABLE
17121 ** Invoke the sqlite3session_attach() interface to attach a particular
17122 ** table so that it is never filtered.
17123 */
17124 if( strcmp(azCmd[0],"attach")==0 ){
17125 if( nCmd!=2 ) goto session_syntax_error;
17126 if( pSession->p==0 ){
17127 session_not_open:
17128 raw_printf(stderr, "ERROR: No sessions are open\n");
17129 }else{
17130 rc = sqlite3session_attach(pSession->p, azCmd[1]);
17131 if( rc ){
17132 raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
17133 rc = 0;
17134 }
17135 }
17136 }else
17137
17138 /* .session changeset FILE
17139 ** .session patchset FILE
17140 ** Write a changeset or patchset into a file. The file is overwritten.
17141 */
17142 if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
17143 FILE *out = 0;
17144 if( nCmd!=2 ) goto session_syntax_error;
17145 if( pSession->p==0 ) goto session_not_open;
17146 out = fopen(azCmd[1], "wb");
17147 if( out==0 ){
mydongistiny8320bdc2019-10-06 12:50:35 -070017148 utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
17149 azCmd[1]);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017150 }else{
17151 int szChng;
17152 void *pChng;
17153 if( azCmd[0][0]=='c' ){
17154 rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
17155 }else{
17156 rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
17157 }
17158 if( rc ){
17159 printf("Error: error code %d\n", rc);
17160 rc = 0;
17161 }
17162 if( pChng
17163 && fwrite(pChng, szChng, 1, out)!=1 ){
17164 raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
17165 szChng);
17166 }
17167 sqlite3_free(pChng);
17168 fclose(out);
17169 }
17170 }else
17171
17172 /* .session close
17173 ** Close the identified session
17174 */
17175 if( strcmp(azCmd[0], "close")==0 ){
17176 if( nCmd!=1 ) goto session_syntax_error;
17177 if( p->nSession ){
17178 session_close(pSession);
17179 p->aSession[iSes] = p->aSession[--p->nSession];
17180 }
17181 }else
17182
17183 /* .session enable ?BOOLEAN?
17184 ** Query or set the enable flag
17185 */
17186 if( strcmp(azCmd[0], "enable")==0 ){
17187 int ii;
17188 if( nCmd>2 ) goto session_syntax_error;
17189 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
17190 if( p->nSession ){
17191 ii = sqlite3session_enable(pSession->p, ii);
17192 utf8_printf(p->out, "session %s enable flag = %d\n",
17193 pSession->zName, ii);
17194 }
17195 }else
17196
17197 /* .session filter GLOB ....
17198 ** Set a list of GLOB patterns of table names to be excluded.
17199 */
17200 if( strcmp(azCmd[0], "filter")==0 ){
17201 int ii, nByte;
17202 if( nCmd<2 ) goto session_syntax_error;
17203 if( p->nSession ){
17204 for(ii=0; ii<pSession->nFilter; ii++){
17205 sqlite3_free(pSession->azFilter[ii]);
17206 }
17207 sqlite3_free(pSession->azFilter);
17208 nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
17209 pSession->azFilter = sqlite3_malloc( nByte );
17210 if( pSession->azFilter==0 ){
17211 raw_printf(stderr, "Error: out or memory\n");
17212 exit(1);
17213 }
17214 for(ii=1; ii<nCmd; ii++){
17215 pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
17216 }
17217 pSession->nFilter = ii-1;
17218 }
17219 }else
17220
17221 /* .session indirect ?BOOLEAN?
17222 ** Query or set the indirect flag
17223 */
17224 if( strcmp(azCmd[0], "indirect")==0 ){
17225 int ii;
17226 if( nCmd>2 ) goto session_syntax_error;
17227 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
17228 if( p->nSession ){
17229 ii = sqlite3session_indirect(pSession->p, ii);
17230 utf8_printf(p->out, "session %s indirect flag = %d\n",
17231 pSession->zName, ii);
17232 }
17233 }else
17234
17235 /* .session isempty
17236 ** Determine if the session is empty
17237 */
17238 if( strcmp(azCmd[0], "isempty")==0 ){
17239 int ii;
17240 if( nCmd!=1 ) goto session_syntax_error;
17241 if( p->nSession ){
17242 ii = sqlite3session_isempty(pSession->p);
17243 utf8_printf(p->out, "session %s isempty flag = %d\n",
17244 pSession->zName, ii);
17245 }
17246 }else
17247
17248 /* .session list
17249 ** List all currently open sessions
17250 */
17251 if( strcmp(azCmd[0],"list")==0 ){
17252 for(i=0; i<p->nSession; i++){
17253 utf8_printf(p->out, "%d %s\n", i, p->aSession[i].zName);
17254 }
17255 }else
17256
17257 /* .session open DB NAME
17258 ** Open a new session called NAME on the attached database DB.
17259 ** DB is normally "main".
17260 */
17261 if( strcmp(azCmd[0],"open")==0 ){
17262 char *zName;
17263 if( nCmd!=3 ) goto session_syntax_error;
17264 zName = azCmd[2];
17265 if( zName[0]==0 ) goto session_syntax_error;
17266 for(i=0; i<p->nSession; i++){
17267 if( strcmp(p->aSession[i].zName,zName)==0 ){
17268 utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
17269 goto meta_command_exit;
17270 }
17271 }
17272 if( p->nSession>=ArraySize(p->aSession) ){
17273 raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(p->aSession));
17274 goto meta_command_exit;
17275 }
17276 pSession = &p->aSession[p->nSession];
17277 rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
17278 if( rc ){
17279 raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
17280 rc = 0;
17281 goto meta_command_exit;
17282 }
17283 pSession->nFilter = 0;
17284 sqlite3session_table_filter(pSession->p, session_filter, pSession);
17285 p->nSession++;
17286 pSession->zName = sqlite3_mprintf("%s", zName);
17287 }else
17288 /* If no command name matches, show a syntax error */
17289 session_syntax_error:
mydongistiny63ee58c2019-09-21 18:04:30 -070017290 showHelp(p->out, "session");
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017291 }else
17292#endif
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070017293
Nick Kralevich8fecf562014-05-29 16:56:33 -070017294#ifdef SQLITE_DEBUG
17295 /* Undocumented commands for internal testing. Subject to change
17296 ** without notice. */
17297 if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
17298 if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
17299 int i, v;
17300 for(i=1; i<nArg; i++){
17301 v = booleanValue(azArg[i]);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017302 utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
Nick Kralevich8fecf562014-05-29 16:56:33 -070017303 }
17304 }
17305 if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
17306 int i; sqlite3_int64 v;
17307 for(i=1; i<nArg; i++){
17308 char zBuf[200];
17309 v = integerValue(azArg[i]);
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017310 sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017311 utf8_printf(p->out, "%s", zBuf);
Nick Kralevich8fecf562014-05-29 16:56:33 -070017312 }
17313 }
17314 }else
17315#endif
17316
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017317 if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){
17318 int bIsInit = 0; /* True to initialize the SELFTEST table */
17319 int bVerbose = 0; /* Verbose output */
17320 int bSelftestExists; /* True if SELFTEST already exists */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017321 int i, k; /* Loop counters */
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017322 int nTest = 0; /* Number of tests runs */
17323 int nErr = 0; /* Number of errors seen */
17324 ShellText str; /* Answer for a query */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017325 sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017326
17327 open_db(p,0);
17328 for(i=1; i<nArg; i++){
17329 const char *z = azArg[i];
17330 if( z[0]=='-' && z[1]=='-' ) z++;
17331 if( strcmp(z,"-init")==0 ){
17332 bIsInit = 1;
17333 }else
17334 if( strcmp(z,"-v")==0 ){
17335 bVerbose++;
17336 }else
17337 {
17338 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
17339 azArg[i], azArg[0]);
17340 raw_printf(stderr, "Should be one of: --init -v\n");
17341 rc = 1;
17342 goto meta_command_exit;
17343 }
17344 }
17345 if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
17346 != SQLITE_OK ){
17347 bSelftestExists = 0;
17348 }else{
17349 bSelftestExists = 1;
17350 }
17351 if( bIsInit ){
17352 createSelftestTable(p);
17353 bSelftestExists = 1;
17354 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017355 initText(&str);
17356 appendText(&str, "x", 0);
17357 for(k=bSelftestExists; k>=0; k--){
17358 if( k==1 ){
17359 rc = sqlite3_prepare_v2(p->db,
17360 "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
17361 -1, &pStmt, 0);
17362 }else{
17363 rc = sqlite3_prepare_v2(p->db,
17364 "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
17365 " (1,'run','PRAGMA integrity_check','ok')",
17366 -1, &pStmt, 0);
17367 }
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017368 if( rc ){
17369 raw_printf(stderr, "Error querying the selftest table\n");
17370 rc = 1;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017371 sqlite3_finalize(pStmt);
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017372 goto meta_command_exit;
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017373 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017374 for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
17375 int tno = sqlite3_column_int(pStmt, 0);
17376 const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
17377 const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
17378 const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
17379
17380 k = 0;
17381 if( bVerbose>0 ){
17382 char *zQuote = sqlite3_mprintf("%q", zSql);
17383 printf("%d: %s %s\n", tno, zOp, zSql);
17384 sqlite3_free(zQuote);
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017385 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017386 if( strcmp(zOp,"memo")==0 ){
17387 utf8_printf(p->out, "%s\n", zSql);
17388 }else
17389 if( strcmp(zOp,"run")==0 ){
17390 char *zErrMsg = 0;
17391 str.n = 0;
17392 str.z[0] = 0;
17393 rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
17394 nTest++;
17395 if( bVerbose ){
17396 utf8_printf(p->out, "Result: %s\n", str.z);
17397 }
17398 if( rc || zErrMsg ){
17399 nErr++;
17400 rc = 1;
17401 utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
17402 sqlite3_free(zErrMsg);
17403 }else if( strcmp(zAns,str.z)!=0 ){
17404 nErr++;
17405 rc = 1;
17406 utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
17407 utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z);
17408 }
17409 }else
17410 {
17411 utf8_printf(stderr,
17412 "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017413 rc = 1;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017414 break;
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017415 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017416 } /* End loop over rows of content from SELFTEST */
17417 sqlite3_finalize(pStmt);
17418 } /* End loop over k */
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017419 freeText(&str);
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017420 utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
17421 }else
17422
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017423 if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
Jeff Brown9bee60b2014-08-20 16:41:25 -070017424 if( nArg<2 || nArg>3 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017425 raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017426 rc = 1;
17427 }
Jeff Brown9bee60b2014-08-20 16:41:25 -070017428 if( nArg>=2 ){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070017429 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
17430 "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
Jeff Brown9bee60b2014-08-20 16:41:25 -070017431 }
17432 if( nArg>=3 ){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070017433 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator,
17434 "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]);
Jeff Brown9bee60b2014-08-20 16:41:25 -070017435 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080017436 }else
17437
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017438 if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){
17439 const char *zLike = 0; /* Which table to checksum. 0 means everything */
17440 int i; /* Loop counter */
17441 int bSchema = 0; /* Also hash the schema */
17442 int bSeparate = 0; /* Hash each table separately */
17443 int iSize = 224; /* Hash algorithm to use */
17444 int bDebug = 0; /* Only show the query that would have run */
17445 sqlite3_stmt *pStmt; /* For querying tables names */
17446 char *zSql; /* SQL to be run */
17447 char *zSep; /* Separator */
17448 ShellText sSql; /* Complete SQL for the query to run the hash */
17449 ShellText sQuery; /* Set of queries used to read all content */
17450 open_db(p, 0);
17451 for(i=1; i<nArg; i++){
17452 const char *z = azArg[i];
17453 if( z[0]=='-' ){
17454 z++;
17455 if( z[0]=='-' ) z++;
17456 if( strcmp(z,"schema")==0 ){
17457 bSchema = 1;
17458 }else
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017459 if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
17460 || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017461 ){
17462 iSize = atoi(&z[5]);
17463 }else
17464 if( strcmp(z,"debug")==0 ){
17465 bDebug = 1;
17466 }else
17467 {
17468 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
17469 azArg[i], azArg[0]);
mydongistiny8320bdc2019-10-06 12:50:35 -070017470 showHelp(p->out, azArg[0]);
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017471 rc = 1;
17472 goto meta_command_exit;
17473 }
17474 }else if( zLike ){
17475 raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
17476 rc = 1;
17477 goto meta_command_exit;
17478 }else{
17479 zLike = z;
17480 bSeparate = 1;
mydongistiny63ee58c2019-09-21 18:04:30 -070017481 if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1;
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017482 }
17483 }
17484 if( bSchema ){
17485 zSql = "SELECT lower(name) FROM sqlite_master"
17486 " WHERE type='table' AND coalesce(rootpage,0)>1"
17487 " UNION ALL SELECT 'sqlite_master'"
17488 " ORDER BY 1 collate nocase";
17489 }else{
17490 zSql = "SELECT lower(name) FROM sqlite_master"
17491 " WHERE type='table' AND coalesce(rootpage,0)>1"
17492 " AND name NOT LIKE 'sqlite_%'"
17493 " ORDER BY 1 collate nocase";
17494 }
17495 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
17496 initText(&sQuery);
17497 initText(&sSql);
17498 appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
17499 zSep = "VALUES(";
17500 while( SQLITE_ROW==sqlite3_step(pStmt) ){
17501 const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
17502 if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
17503 if( strncmp(zTab, "sqlite_",7)!=0 ){
17504 appendText(&sQuery,"SELECT * FROM ", 0);
17505 appendText(&sQuery,zTab,'"');
17506 appendText(&sQuery," NOT INDEXED;", 0);
17507 }else if( strcmp(zTab, "sqlite_master")==0 ){
17508 appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_master"
17509 " ORDER BY name;", 0);
17510 }else if( strcmp(zTab, "sqlite_sequence")==0 ){
17511 appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
17512 " ORDER BY name;", 0);
17513 }else if( strcmp(zTab, "sqlite_stat1")==0 ){
17514 appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
17515 " ORDER BY tbl,idx;", 0);
mydongistiny8320bdc2019-10-06 12:50:35 -070017516 }else if( strcmp(zTab, "sqlite_stat4")==0 ){
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017517 appendText(&sQuery, "SELECT * FROM ", 0);
17518 appendText(&sQuery, zTab, 0);
17519 appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
17520 }
17521 appendText(&sSql, zSep, 0);
17522 appendText(&sSql, sQuery.z, '\'');
17523 sQuery.n = 0;
17524 appendText(&sSql, ",", 0);
17525 appendText(&sSql, zTab, '\'');
17526 zSep = "),(";
17527 }
17528 sqlite3_finalize(pStmt);
17529 if( bSeparate ){
17530 zSql = sqlite3_mprintf(
17531 "%s))"
17532 " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
17533 " FROM [sha3sum$query]",
17534 sSql.z, iSize);
17535 }else{
17536 zSql = sqlite3_mprintf(
17537 "%s))"
17538 " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
17539 " FROM [sha3sum$query]",
17540 sSql.z, iSize);
17541 }
17542 freeText(&sQuery);
17543 freeText(&sSql);
17544 if( bDebug ){
17545 utf8_printf(p->out, "%s\n", zSql);
17546 }else{
mydongistiny63ee58c2019-09-21 18:04:30 -070017547 shell_exec(p, zSql, 0);
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017548 }
17549 sqlite3_free(zSql);
17550 }else
17551
mydongistiny63ee58c2019-09-21 18:04:30 -070017552#ifndef SQLITE_NOHAVE_SYSTEM
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017553 if( c=='s'
17554 && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
17555 ){
17556 char *zCmd;
Jeff Brown9bee60b2014-08-20 16:41:25 -070017557 int i, x;
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017558 if( nArg<2 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017559 raw_printf(stderr, "Usage: .system COMMAND\n");
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017560 rc = 1;
17561 goto meta_command_exit;
17562 }
17563 zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
17564 for(i=2; i<nArg; i++){
17565 zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
17566 zCmd, azArg[i]);
17567 }
Jeff Brown9bee60b2014-08-20 16:41:25 -070017568 x = system(zCmd);
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017569 sqlite3_free(zCmd);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017570 if( x ) raw_printf(stderr, "System command returns %d\n", x);
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017571 }else
mydongistiny63ee58c2019-09-21 18:04:30 -070017572#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017573
17574 if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017575 static const char *azBool[] = { "off", "on", "trigger", "full"};
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017576 int i;
17577 if( nArg!=1 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017578 raw_printf(stderr, "Usage: .show\n");
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017579 rc = 1;
17580 goto meta_command_exit;
17581 }
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017582 utf8_printf(p->out, "%12.12s: %s\n","echo",
17583 azBool[ShellHasFlag(p, SHFLG_Echo)]);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017584 utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
17585 utf8_printf(p->out, "%12.12s: %s\n","explain",
17586 p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
17587 utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
17588 utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
17589 utf8_printf(p->out, "%12.12s: ", "nullvalue");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070017590 output_c_string(p->out, p->nullValue);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017591 raw_printf(p->out, "\n");
17592 utf8_printf(p->out,"%12.12s: %s\n","output",
Vasu Noria4356a02010-01-20 15:10:57 -080017593 strlen30(p->outfile) ? p->outfile : "stdout");
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017594 utf8_printf(p->out,"%12.12s: ", "colseparator");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070017595 output_c_string(p->out, p->colSeparator);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017596 raw_printf(p->out, "\n");
17597 utf8_printf(p->out,"%12.12s: ", "rowseparator");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070017598 output_c_string(p->out, p->rowSeparator);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017599 raw_printf(p->out, "\n");
17600 utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]);
17601 utf8_printf(p->out, "%12.12s: ", "width");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080017602 for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017603 raw_printf(p->out, "%d ", p->colWidth[i]);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080017604 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017605 raw_printf(p->out, "\n");
Alex Naidis08f78cb2016-10-14 15:52:08 +020017606 utf8_printf(p->out, "%12.12s: %s\n", "filename",
17607 p->zDbFilename ? p->zDbFilename : "");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080017608 }else
17609
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017610 if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
17611 if( nArg==2 ){
mydongistiny63ee58c2019-09-21 18:04:30 -070017612 p->statsOn = (u8)booleanValue(azArg[1]);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017613 }else if( nArg==1 ){
17614 display_stats(p->db, p, 0);
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017615 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017616 raw_printf(stderr, "Usage: .stats ?on|off?\n");
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017617 rc = 1;
17618 }
Vasu Noride2b3242010-09-29 15:33:53 -070017619 }else
17620
Luca Stefanie7f3e802017-01-02 15:44:22 +010017621 if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0)
17622 || (c=='i' && (strncmp(azArg[0], "indices", n)==0
17623 || strncmp(azArg[0], "indexes", n)==0) )
17624 ){
Nick Kralevich8fecf562014-05-29 16:56:33 -070017625 sqlite3_stmt *pStmt;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080017626 char **azResult;
Nick Kralevich8fecf562014-05-29 16:56:33 -070017627 int nRow, nAlloc;
Nick Kralevich8fecf562014-05-29 16:56:33 -070017628 int ii;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017629 ShellText s;
17630 initText(&s);
Nick Kralevich8fecf562014-05-29 16:56:33 -070017631 open_db(p, 0);
17632 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
mydongistiny63ee58c2019-09-21 18:04:30 -070017633 if( rc ){
17634 sqlite3_finalize(pStmt);
17635 return shellDatabaseError(p->db);
17636 }
Nick Kralevich253ed642015-12-23 10:07:58 -080017637
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017638 if( nArg>2 && c=='i' ){
Luca Stefanie7f3e802017-01-02 15:44:22 +010017639 /* It is an historical accident that the .indexes command shows an error
17640 ** when called with the wrong number of arguments whereas the .tables
17641 ** command does not. */
17642 raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
17643 rc = 1;
mydongistiny63ee58c2019-09-21 18:04:30 -070017644 sqlite3_finalize(pStmt);
Luca Stefanie7f3e802017-01-02 15:44:22 +010017645 goto meta_command_exit;
Luca Stefanie7f3e802017-01-02 15:44:22 +010017646 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017647 for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
Nick Kralevich8fecf562014-05-29 16:56:33 -070017648 const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017649 if( zDbName==0 ) continue;
17650 if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0);
17651 if( sqlite3_stricmp(zDbName, "main")==0 ){
17652 appendText(&s, "SELECT name FROM ", 0);
Luca Stefanie7f3e802017-01-02 15:44:22 +010017653 }else{
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017654 appendText(&s, "SELECT ", 0);
17655 appendText(&s, zDbName, '\'');
17656 appendText(&s, "||'.'||name FROM ", 0);
17657 }
17658 appendText(&s, zDbName, '"');
17659 appendText(&s, ".sqlite_master ", 0);
17660 if( c=='t' ){
17661 appendText(&s," WHERE type IN ('table','view')"
17662 " AND name NOT LIKE 'sqlite_%'"
17663 " AND name LIKE ?1", 0);
17664 }else{
17665 appendText(&s," WHERE type='index'"
17666 " AND tbl_name LIKE ?1", 0);
Nick Kralevich8fecf562014-05-29 16:56:33 -070017667 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080017668 }
Nick Kralevich253ed642015-12-23 10:07:58 -080017669 rc = sqlite3_finalize(pStmt);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017670 appendText(&s, " ORDER BY 1", 0);
17671 rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
17672 freeText(&s);
Nick Kralevich253ed642015-12-23 10:07:58 -080017673 if( rc ) return shellDatabaseError(p->db);
17674
17675 /* Run the SQL statement prepared by the above block. Store the results
17676 ** as an array of nul-terminated strings in azResult[]. */
Nick Kralevich8fecf562014-05-29 16:56:33 -070017677 nRow = nAlloc = 0;
17678 azResult = 0;
17679 if( nArg>1 ){
17680 sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
Vasu Noria4356a02010-01-20 15:10:57 -080017681 }else{
Nick Kralevich8fecf562014-05-29 16:56:33 -070017682 sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
17683 }
17684 while( sqlite3_step(pStmt)==SQLITE_ROW ){
17685 if( nRow>=nAlloc ){
17686 char **azNew;
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070017687 int n2 = nAlloc*2 + 10;
17688 azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
mydongistiny63ee58c2019-09-21 18:04:30 -070017689 if( azNew==0 ) shell_out_of_memory();
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070017690 nAlloc = n2;
Nick Kralevich8fecf562014-05-29 16:56:33 -070017691 azResult = azNew;
17692 }
17693 azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
mydongistiny63ee58c2019-09-21 18:04:30 -070017694 if( 0==azResult[nRow] ) shell_out_of_memory();
Nick Kralevich253ed642015-12-23 10:07:58 -080017695 nRow++;
Nick Kralevich8fecf562014-05-29 16:56:33 -070017696 }
Nick Kralevich253ed642015-12-23 10:07:58 -080017697 if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
17698 rc = shellDatabaseError(p->db);
17699 }
17700
17701 /* Pretty-print the contents of array azResult[] to the output */
17702 if( rc==0 && nRow>0 ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080017703 int len, maxlen = 0;
17704 int i, j;
17705 int nPrintCol, nPrintRow;
Nick Kralevich8fecf562014-05-29 16:56:33 -070017706 for(i=0; i<nRow; i++){
Vasu Noria4356a02010-01-20 15:10:57 -080017707 len = strlen30(azResult[i]);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080017708 if( len>maxlen ) maxlen = len;
17709 }
17710 nPrintCol = 80/(maxlen+2);
17711 if( nPrintCol<1 ) nPrintCol = 1;
17712 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
17713 for(i=0; i<nPrintRow; i++){
Nick Kralevich8fecf562014-05-29 16:56:33 -070017714 for(j=i; j<nRow; j+=nPrintRow){
17715 char *zSp = j<nPrintRow ? "" : " ";
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017716 utf8_printf(p->out, "%s%-*s", zSp, maxlen,
17717 azResult[j] ? azResult[j]:"");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080017718 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017719 raw_printf(p->out, "\n");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080017720 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080017721 }
Nick Kralevich253ed642015-12-23 10:07:58 -080017722
Nick Kralevich8fecf562014-05-29 16:56:33 -070017723 for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
17724 sqlite3_free(azResult);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080017725 }else
17726
Alex Naidis08f78cb2016-10-14 15:52:08 +020017727 /* Begin redirecting output to the file "testcase-out.txt" */
17728 if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
17729 output_reset(p);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017730 p->out = output_file_open("testcase-out.txt", 0);
Alex Naidis08f78cb2016-10-14 15:52:08 +020017731 if( p->out==0 ){
Luca Stefanie7f3e802017-01-02 15:44:22 +010017732 raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
Alex Naidis08f78cb2016-10-14 15:52:08 +020017733 }
17734 if( nArg>=2 ){
17735 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
17736 }else{
17737 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
17738 }
17739 }else
17740
Luca Stefanie7f3e802017-01-02 15:44:22 +010017741#ifndef SQLITE_UNTESTABLE
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017742 if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
Jeff Brown90ed05d2012-01-19 16:35:19 -080017743 static const struct {
17744 const char *zCtrlName; /* Name of a test-control option */
17745 int ctrlCode; /* Integer code for that option */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017746 const char *zUsage; /* Usage notes */
Jeff Brown90ed05d2012-01-19 16:35:19 -080017747 } aCtrl[] = {
mydongistiny8320bdc2019-10-06 12:50:35 -070017748 { "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" },
17749 { "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" },
17750 /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/
17751 /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/
17752 { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" },
17753 { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN" },
17754 /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" },*/
17755 { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
17756 { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN" },
17757 { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" },
17758 { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" },
17759 { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" },
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017760#ifdef YYCOVERAGE
mydongistiny8320bdc2019-10-06 12:50:35 -070017761 { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" },
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017762#endif
mydongistiny8320bdc2019-10-06 12:50:35 -070017763 { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " },
17764 { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
17765 { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
17766 { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
17767 { "reserve", SQLITE_TESTCTRL_RESERVE, "BYTES-OF-RESERVE"},
Jeff Brown90ed05d2012-01-19 16:35:19 -080017768 };
17769 int testctrl = -1;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017770 int iCtrl = -1;
17771 int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */
17772 int isOk = 0;
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070017773 int i, n2;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017774 const char *zCmd = 0;
17775
Nick Kralevich8fecf562014-05-29 16:56:33 -070017776 open_db(p, 0);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017777 zCmd = nArg>=2 ? azArg[1] : "help";
17778
17779 /* The argument can optionally begin with "-" or "--" */
17780 if( zCmd[0]=='-' && zCmd[1] ){
17781 zCmd++;
17782 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
17783 }
17784
17785 /* --help lists all test-controls */
17786 if( strcmp(zCmd,"help")==0 ){
17787 utf8_printf(p->out, "Available test-controls:\n");
17788 for(i=0; i<ArraySize(aCtrl); i++){
17789 utf8_printf(p->out, " .testctrl %s %s\n",
17790 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
17791 }
17792 rc = 1;
17793 goto meta_command_exit;
17794 }
Jeff Brown90ed05d2012-01-19 16:35:19 -080017795
17796 /* convert testctrl text option to value. allow any unique prefix
17797 ** of the option name, or a numerical value. */
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017798 n2 = strlen30(zCmd);
Nick Kralevich253ed642015-12-23 10:07:58 -080017799 for(i=0; i<ArraySize(aCtrl); i++){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017800 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
Jeff Brown90ed05d2012-01-19 16:35:19 -080017801 if( testctrl<0 ){
17802 testctrl = aCtrl[i].ctrlCode;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017803 iCtrl = i;
Jeff Brown90ed05d2012-01-19 16:35:19 -080017804 }else{
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017805 utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
17806 "Use \".testctrl --help\" for help\n", zCmd);
17807 rc = 1;
17808 goto meta_command_exit;
Jeff Brown90ed05d2012-01-19 16:35:19 -080017809 }
17810 }
17811 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017812 if( testctrl<0 ){
17813 utf8_printf(stderr,"Error: unknown test-control: %s\n"
17814 "Use \".testctrl --help\" for help\n", zCmd);
Jeff Brown90ed05d2012-01-19 16:35:19 -080017815 }else{
17816 switch(testctrl){
17817
17818 /* sqlite3_test_control(int, db, int) */
17819 case SQLITE_TESTCTRL_OPTIMIZATIONS:
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017820 case SQLITE_TESTCTRL_RESERVE:
Jeff Brown90ed05d2012-01-19 16:35:19 -080017821 if( nArg==3 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017822 int opt = (int)strtol(azArg[2], 0, 0);
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070017823 rc2 = sqlite3_test_control(testctrl, p->db, opt);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017824 isOk = 3;
Jeff Brown90ed05d2012-01-19 16:35:19 -080017825 }
17826 break;
17827
17828 /* sqlite3_test_control(int) */
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017829 case SQLITE_TESTCTRL_PRNG_SAVE:
17830 case SQLITE_TESTCTRL_PRNG_RESTORE:
Jeff Brown90ed05d2012-01-19 16:35:19 -080017831 case SQLITE_TESTCTRL_PRNG_RESET:
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017832 case SQLITE_TESTCTRL_BYTEORDER:
Jeff Brown90ed05d2012-01-19 16:35:19 -080017833 if( nArg==2 ){
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070017834 rc2 = sqlite3_test_control(testctrl);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017835 isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
Jeff Brown90ed05d2012-01-19 16:35:19 -080017836 }
17837 break;
17838
17839 /* sqlite3_test_control(int, uint) */
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017840 case SQLITE_TESTCTRL_PENDING_BYTE:
Jeff Brown90ed05d2012-01-19 16:35:19 -080017841 if( nArg==3 ){
Nick Kralevich8fecf562014-05-29 16:56:33 -070017842 unsigned int opt = (unsigned int)integerValue(azArg[2]);
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070017843 rc2 = sqlite3_test_control(testctrl, opt);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017844 isOk = 3;
Jeff Brown90ed05d2012-01-19 16:35:19 -080017845 }
17846 break;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017847
mydongistiny8320bdc2019-10-06 12:50:35 -070017848 /* sqlite3_test_control(int, int, sqlite3*) */
17849 case SQLITE_TESTCTRL_PRNG_SEED:
17850 if( nArg==3 || nArg==4 ){
17851 int ii = (int)integerValue(azArg[2]);
17852 sqlite3 *db;
17853 if( ii==0 && strcmp(azArg[2],"random")==0 ){
17854 sqlite3_randomness(sizeof(ii),&ii);
17855 printf("-- random seed: %d\n", ii);
17856 }
17857 if( nArg==3 ){
17858 db = 0;
17859 }else{
17860 db = p->db;
17861 /* Make sure the schema has been loaded */
17862 sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);
17863 }
17864 rc2 = sqlite3_test_control(testctrl, ii, db);
17865 isOk = 3;
17866 }
17867 break;
17868
Jeff Brown90ed05d2012-01-19 16:35:19 -080017869 /* sqlite3_test_control(int, int) */
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017870 case SQLITE_TESTCTRL_ASSERT:
17871 case SQLITE_TESTCTRL_ALWAYS:
mydongistiny63ee58c2019-09-21 18:04:30 -070017872 case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017873 if( nArg==3 ){
17874 int opt = booleanValue(azArg[2]);
17875 rc2 = sqlite3_test_control(testctrl, opt);
17876 isOk = 1;
17877 }
17878 break;
17879
17880 /* sqlite3_test_control(int, int) */
17881 case SQLITE_TESTCTRL_LOCALTIME_FAULT:
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017882 case SQLITE_TESTCTRL_NEVER_CORRUPT:
Jeff Brown90ed05d2012-01-19 16:35:19 -080017883 if( nArg==3 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017884 int opt = booleanValue(azArg[2]);
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070017885 rc2 = sqlite3_test_control(testctrl, opt);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017886 isOk = 3;
Jeff Brown90ed05d2012-01-19 16:35:19 -080017887 }
17888 break;
17889
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070017890 case SQLITE_TESTCTRL_IMPOSTER:
17891 if( nArg==5 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017892 rc2 = sqlite3_test_control(testctrl, p->db,
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070017893 azArg[2],
17894 integerValue(azArg[3]),
17895 integerValue(azArg[4]));
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017896 isOk = 3;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070017897 }
17898 break;
17899
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017900#ifdef YYCOVERAGE
17901 case SQLITE_TESTCTRL_PARSER_COVERAGE:
17902 if( nArg==2 ){
17903 sqlite3_test_control(testctrl, p->out);
17904 isOk = 3;
17905 }
17906#endif
Jeff Brown90ed05d2012-01-19 16:35:19 -080017907 }
17908 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017909 if( isOk==0 && iCtrl>=0 ){
mydongistiny8320bdc2019-10-06 12:50:35 -070017910 utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080017911 rc = 1;
17912 }else if( isOk==1 ){
17913 raw_printf(p->out, "%d\n", rc2);
17914 }else if( isOk==2 ){
17915 raw_printf(p->out, "0x%08x\n", rc2);
17916 }
Jeff Brown90ed05d2012-01-19 16:35:19 -080017917 }else
Alex Naidisb86c0cf2017-03-31 14:12:35 +020017918#endif /* !defined(SQLITE_UNTESTABLE) */
Jeff Brown90ed05d2012-01-19 16:35:19 -080017919
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017920 if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
Nick Kralevich8fecf562014-05-29 16:56:33 -070017921 open_db(p, 0);
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017922 sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080017923 }else
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017924
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017925 if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
17926 if( nArg==2 ){
17927 enableTimer = booleanValue(azArg[1]);
17928 if( enableTimer && !HAS_TIMER ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017929 raw_printf(stderr, "Error: timer not available on this system.\n");
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017930 enableTimer = 0;
17931 }
17932 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017933 raw_printf(stderr, "Usage: .timer on|off\n");
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017934 rc = 1;
17935 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080017936 }else
Alex Naidis60fa6fd2016-07-10 14:13:38 +020017937
mydongistiny63ee58c2019-09-21 18:04:30 -070017938#ifndef SQLITE_OMIT_TRACE
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017939 if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
mydongistiny63ee58c2019-09-21 18:04:30 -070017940 int mType = 0;
17941 int jj;
Nick Kralevich8fecf562014-05-29 16:56:33 -070017942 open_db(p, 0);
mydongistiny63ee58c2019-09-21 18:04:30 -070017943 for(jj=1; jj<nArg; jj++){
17944 const char *z = azArg[jj];
17945 if( z[0]=='-' ){
17946 if( optionMatch(z, "expanded") ){
17947 p->eTraceType = SHELL_TRACE_EXPANDED;
17948 }
17949#ifdef SQLITE_ENABLE_NORMALIZE
17950 else if( optionMatch(z, "normalized") ){
17951 p->eTraceType = SHELL_TRACE_NORMALIZED;
17952 }
17953#endif
17954 else if( optionMatch(z, "plain") ){
17955 p->eTraceType = SHELL_TRACE_PLAIN;
17956 }
17957 else if( optionMatch(z, "profile") ){
17958 mType |= SQLITE_TRACE_PROFILE;
17959 }
17960 else if( optionMatch(z, "row") ){
17961 mType |= SQLITE_TRACE_ROW;
17962 }
17963 else if( optionMatch(z, "stmt") ){
17964 mType |= SQLITE_TRACE_STMT;
17965 }
17966 else if( optionMatch(z, "close") ){
17967 mType |= SQLITE_TRACE_CLOSE;
17968 }
17969 else {
17970 raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
17971 rc = 1;
17972 goto meta_command_exit;
17973 }
17974 }else{
17975 output_file_close(p->traceOut);
17976 p->traceOut = output_file_open(azArg[1], 0);
17977 }
Nick Kralevich1c7cea32014-06-06 19:53:11 -070017978 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070017979 if( p->traceOut==0 ){
Alex Naidis74bd39c2016-08-09 00:53:11 +020017980 sqlite3_trace_v2(p->db, 0, 0, 0);
Nick Kralevich8fecf562014-05-29 16:56:33 -070017981 }else{
mydongistiny63ee58c2019-09-21 18:04:30 -070017982 if( mType==0 ) mType = SQLITE_TRACE_STMT;
17983 sqlite3_trace_v2(p->db, mType, sql_trace_callback, p);
Nick Kralevich8fecf562014-05-29 16:56:33 -070017984 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070017985 }else
mydongistiny63ee58c2019-09-21 18:04:30 -070017986#endif /* !defined(SQLITE_OMIT_TRACE) */
Nick Kralevich8fecf562014-05-29 16:56:33 -070017987
mydongistiny8320bdc2019-10-06 12:50:35 -070017988#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
17989 if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){
17990 int ii;
17991 int lenOpt;
17992 char *zOpt;
17993 if( nArg<2 ){
17994 raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
17995 rc = 1;
17996 goto meta_command_exit;
17997 }
17998 open_db(p, 0);
17999 zOpt = azArg[1];
18000 if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
18001 lenOpt = (int)strlen(zOpt);
18002 if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){
18003 assert( azArg[nArg]==0 );
18004 sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0);
18005 }else{
18006 for(ii=1; ii<nArg; ii++){
18007 sqlite3_create_module(p->db, azArg[ii], 0, 0);
18008 }
18009 }
18010 }else
18011#endif
18012
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018013#if SQLITE_USER_AUTHENTICATION
18014 if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
18015 if( nArg<2 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018016 raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018017 rc = 1;
18018 goto meta_command_exit;
18019 }
18020 open_db(p, 0);
18021 if( strcmp(azArg[1],"login")==0 ){
18022 if( nArg!=4 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018023 raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018024 rc = 1;
18025 goto meta_command_exit;
18026 }
mydongistiny8320bdc2019-10-06 12:50:35 -070018027 rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
18028 strlen30(azArg[3]));
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018029 if( rc ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018030 utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018031 rc = 1;
18032 }
18033 }else if( strcmp(azArg[1],"add")==0 ){
18034 if( nArg!=5 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018035 raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018036 rc = 1;
18037 goto meta_command_exit;
18038 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080018039 rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018040 booleanValue(azArg[4]));
18041 if( rc ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018042 raw_printf(stderr, "User-Add failed: %d\n", rc);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018043 rc = 1;
18044 }
18045 }else if( strcmp(azArg[1],"edit")==0 ){
18046 if( nArg!=5 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018047 raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018048 rc = 1;
18049 goto meta_command_exit;
18050 }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080018051 rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018052 booleanValue(azArg[4]));
18053 if( rc ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018054 raw_printf(stderr, "User-Edit failed: %d\n", rc);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018055 rc = 1;
18056 }
18057 }else if( strcmp(azArg[1],"delete")==0 ){
18058 if( nArg!=3 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018059 raw_printf(stderr, "Usage: .user delete USER\n");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018060 rc = 1;
18061 goto meta_command_exit;
18062 }
18063 rc = sqlite3_user_delete(p->db, azArg[2]);
18064 if( rc ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018065 raw_printf(stderr, "User-Delete failed: %d\n", rc);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018066 rc = 1;
18067 }
18068 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018069 raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018070 rc = 1;
18071 goto meta_command_exit;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018072 }
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018073 }else
18074#endif /* SQLITE_USER_AUTHENTICATION */
18075
Jeff Brown90ed05d2012-01-19 16:35:19 -080018076 if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018077 utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
Jeff Brown90ed05d2012-01-19 16:35:19 -080018078 sqlite3_libversion(), sqlite3_sourceid());
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080018079#if SQLITE_HAVE_ZLIB
18080 utf8_printf(p->out, "zlib version %s\n", zlibVersion());
18081#endif
18082#define CTIMEOPT_VAL_(opt) #opt
18083#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
18084#if defined(__clang__) && defined(__clang_major__)
18085 utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
18086 CTIMEOPT_VAL(__clang_minor__) "."
18087 CTIMEOPT_VAL(__clang_patchlevel__) "\n");
18088#elif defined(_MSC_VER)
18089 utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n");
18090#elif defined(__GNUC__) && defined(__VERSION__)
18091 utf8_printf(p->out, "gcc-" __VERSION__ "\n");
18092#endif
Jeff Brown90ed05d2012-01-19 16:35:19 -080018093 }else
18094
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018095 if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
18096 const char *zDbName = nArg==2 ? azArg[1] : "main";
Alex Naidis4b7ed962017-02-13 18:23:48 +010018097 sqlite3_vfs *pVfs = 0;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018098 if( p->db ){
18099 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
18100 if( pVfs ){
18101 utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
18102 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
18103 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
18104 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
18105 }
18106 }
18107 }else
18108
18109 if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){
18110 sqlite3_vfs *pVfs;
18111 sqlite3_vfs *pCurrent = 0;
18112 if( p->db ){
18113 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
18114 }
18115 for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
18116 utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName,
18117 pVfs==pCurrent ? " <--- CURRENT" : "");
18118 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
18119 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
18120 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
18121 if( pVfs->pNext ){
18122 raw_printf(p->out, "-----------------------------------\n");
18123 }
18124 }
18125 }else
18126
Jeff Brown90ed05d2012-01-19 16:35:19 -080018127 if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
18128 const char *zDbName = nArg==2 ? azArg[1] : "main";
18129 char *zVfsName = 0;
18130 if( p->db ){
18131 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
18132 if( zVfsName ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018133 utf8_printf(p->out, "%s\n", zVfsName);
Jeff Brown90ed05d2012-01-19 16:35:19 -080018134 sqlite3_free(zVfsName);
18135 }
18136 }
18137 }else
18138
Nick Kralevich8fecf562014-05-29 16:56:33 -070018139#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
18140 if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
Nick Kralevich1c7cea32014-06-06 19:53:11 -070018141 sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
Nick Kralevich8fecf562014-05-29 16:56:33 -070018142 }else
18143#endif
18144
Nick Kralevich1c7cea32014-06-06 19:53:11 -070018145 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018146 int j;
18147 assert( nArg<=ArraySize(azArg) );
18148 for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
Nick Kralevich8fecf562014-05-29 16:56:33 -070018149 p->colWidth[j-1] = (int)integerValue(azArg[j]);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018150 }
18151 }else
18152
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018153 {
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018154 utf8_printf(stderr, "Error: unknown command or invalid arguments: "
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018155 " \"%s\". Enter \".help\" for help\n", azArg[0]);
Vasu Noria4356a02010-01-20 15:10:57 -080018156 rc = 1;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018157 }
18158
Nick Kralevich1c7cea32014-06-06 19:53:11 -070018159meta_command_exit:
18160 if( p->outCount ){
18161 p->outCount--;
18162 if( p->outCount==0 ) output_reset(p);
18163 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018164 return rc;
18165}
18166
18167/*
18168** Return TRUE if a semicolon occurs anywhere in the first N characters
18169** of string z[].
18170*/
Nick Kralevich8fecf562014-05-29 16:56:33 -070018171static int line_contains_semicolon(const char *z, int N){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018172 int i;
18173 for(i=0; i<N; i++){ if( z[i]==';' ) return 1; }
18174 return 0;
18175}
18176
18177/*
18178** Test to see if a line consists entirely of whitespace.
18179*/
18180static int _all_whitespace(const char *z){
18181 for(; *z; z++){
Jeff Brown90ed05d2012-01-19 16:35:19 -080018182 if( IsSpace(z[0]) ) continue;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018183 if( *z=='/' && z[1]=='*' ){
18184 z += 2;
18185 while( *z && (*z!='*' || z[1]!='/') ){ z++; }
18186 if( *z==0 ) return 0;
18187 z++;
18188 continue;
18189 }
18190 if( *z=='-' && z[1]=='-' ){
18191 z += 2;
18192 while( *z && *z!='\n' ){ z++; }
18193 if( *z==0 ) return 1;
18194 continue;
18195 }
18196 return 0;
18197 }
18198 return 1;
18199}
18200
18201/*
18202** Return TRUE if the line typed in is an SQL command terminator other
18203** than a semi-colon. The SQL Server style "go" command is understood
18204** as is the Oracle "/".
18205*/
Nick Kralevich8fecf562014-05-29 16:56:33 -070018206static int line_is_command_terminator(const char *zLine){
Jeff Brown90ed05d2012-01-19 16:35:19 -080018207 while( IsSpace(zLine[0]) ){ zLine++; };
Vasu Noria4356a02010-01-20 15:10:57 -080018208 if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ){
18209 return 1; /* Oracle */
18210 }
Jeff Brown90ed05d2012-01-19 16:35:19 -080018211 if( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o'
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018212 && _all_whitespace(&zLine[2]) ){
18213 return 1; /* SQL Server */
18214 }
18215 return 0;
18216}
18217
18218/*
mydongistiny63ee58c2019-09-21 18:04:30 -070018219** We need a default sqlite3_complete() implementation to use in case
18220** the shell is compiled with SQLITE_OMIT_COMPLETE. The default assumes
18221** any arbitrary text is a complete SQL statement. This is not very
18222** user-friendly, but it does seem to work.
18223*/
18224#ifdef SQLITE_OMIT_COMPLETE
18225#define sqlite3_complete(x) 1
18226#endif
18227
18228/*
Vasu Noria4356a02010-01-20 15:10:57 -080018229** Return true if zSql is a complete SQL statement. Return false if it
18230** ends in the middle of a string literal or C-style comment.
18231*/
Nick Kralevich8fecf562014-05-29 16:56:33 -070018232static int line_is_complete(char *zSql, int nSql){
Vasu Noria4356a02010-01-20 15:10:57 -080018233 int rc;
18234 if( zSql==0 ) return 1;
18235 zSql[nSql] = ';';
18236 zSql[nSql+1] = 0;
18237 rc = sqlite3_complete(zSql);
18238 zSql[nSql] = 0;
18239 return rc;
18240}
18241
18242/*
mydongistiny63ee58c2019-09-21 18:04:30 -070018243** Run a single line of SQL. Return the number of errors.
Luca Stefanie7f3e802017-01-02 15:44:22 +010018244*/
18245static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
18246 int rc;
18247 char *zErrMsg = 0;
18248
18249 open_db(p, 0);
Alex Naidisb86c0cf2017-03-31 14:12:35 +020018250 if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
mydongistiny63ee58c2019-09-21 18:04:30 -070018251 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
Luca Stefanie7f3e802017-01-02 15:44:22 +010018252 BEGIN_TIMER;
mydongistiny63ee58c2019-09-21 18:04:30 -070018253 rc = shell_exec(p, zSql, &zErrMsg);
Luca Stefanie7f3e802017-01-02 15:44:22 +010018254 END_TIMER;
18255 if( rc || zErrMsg ){
18256 char zPrefix[100];
18257 if( in!=0 || !stdin_is_interactive ){
18258 sqlite3_snprintf(sizeof(zPrefix), zPrefix,
18259 "Error: near line %d:", startline);
18260 }else{
18261 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
18262 }
18263 if( zErrMsg!=0 ){
18264 utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
18265 sqlite3_free(zErrMsg);
18266 zErrMsg = 0;
18267 }else{
18268 utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
18269 }
18270 return 1;
Alex Naidisb86c0cf2017-03-31 14:12:35 +020018271 }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
Luca Stefanie7f3e802017-01-02 15:44:22 +010018272 raw_printf(p->out, "changes: %3d total_changes: %d\n",
18273 sqlite3_changes(p->db), sqlite3_total_changes(p->db));
18274 }
18275 return 0;
18276}
18277
18278
18279/*
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018280** Read input from *in and process it. If *in==0 then input
18281** is interactive - the user is typing it it. Otherwise, input
18282** is coming from a file or device. A prompt is issued and history
18283** is saved only if input is interactive. An interrupt signal will
18284** cause this routine to exit immediately, unless input is interactive.
18285**
18286** Return the number of errors.
18287*/
mydongistiny63ee58c2019-09-21 18:04:30 -070018288static int process_input(ShellState *p){
Nick Kralevich8fecf562014-05-29 16:56:33 -070018289 char *zLine = 0; /* A single input line */
18290 char *zSql = 0; /* Accumulated SQL text */
18291 int nLine; /* Length of current line */
18292 int nSql = 0; /* Bytes of zSql[] used */
18293 int nAlloc = 0; /* Allocated zSql[] space */
18294 int nSqlPrior = 0; /* Bytes of zSql[] used by prior line */
Nick Kralevich8fecf562014-05-29 16:56:33 -070018295 int rc; /* Error code */
18296 int errCnt = 0; /* Number of errors seen */
Nick Kralevich8fecf562014-05-29 16:56:33 -070018297 int startline = 0; /* Line number for start of current input */
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018298
mydongistiny63ee58c2019-09-21 18:04:30 -070018299 p->lineno = 0;
18300 while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018301 fflush(p->out);
mydongistiny63ee58c2019-09-21 18:04:30 -070018302 zLine = one_input_line(p->in, zLine, nSql>0);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018303 if( zLine==0 ){
Nick Kralevich8fecf562014-05-29 16:56:33 -070018304 /* End of input */
mydongistiny63ee58c2019-09-21 18:04:30 -070018305 if( p->in==0 && stdin_is_interactive ) printf("\n");
Nick Kralevich8fecf562014-05-29 16:56:33 -070018306 break;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018307 }
18308 if( seenInterrupt ){
mydongistiny63ee58c2019-09-21 18:04:30 -070018309 if( p->in!=0 ) break;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018310 seenInterrupt = 0;
18311 }
mydongistiny63ee58c2019-09-21 18:04:30 -070018312 p->lineno++;
Nick Kralevich8fecf562014-05-29 16:56:33 -070018313 if( nSql==0 && _all_whitespace(zLine) ){
Alex Naidisb86c0cf2017-03-31 14:12:35 +020018314 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
Nick Kralevich8fecf562014-05-29 16:56:33 -070018315 continue;
18316 }
mydongistiny63ee58c2019-09-21 18:04:30 -070018317 if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
Alex Naidisb86c0cf2017-03-31 14:12:35 +020018318 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
mydongistiny63ee58c2019-09-21 18:04:30 -070018319 if( zLine[0]=='.' ){
18320 rc = do_meta_command(zLine, p);
18321 if( rc==2 ){ /* exit requested */
18322 break;
18323 }else if( rc ){
18324 errCnt++;
18325 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018326 }
18327 continue;
18328 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070018329 if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018330 memcpy(zLine,";",2);
18331 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070018332 nLine = strlen30(zLine);
18333 if( nSql+nLine+2>=nAlloc ){
18334 nAlloc = nSql+nLine+100;
18335 zSql = realloc(zSql, nAlloc);
mydongistiny63ee58c2019-09-21 18:04:30 -070018336 if( zSql==0 ) shell_out_of_memory();
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018337 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070018338 nSqlPrior = nSql;
18339 if( nSql==0 ){
18340 int i;
18341 for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
18342 assert( nAlloc>0 && zSql!=0 );
18343 memcpy(zSql, zLine+i, nLine+1-i);
mydongistiny63ee58c2019-09-21 18:04:30 -070018344 startline = p->lineno;
Nick Kralevich8fecf562014-05-29 16:56:33 -070018345 nSql = nLine-i;
18346 }else{
18347 zSql[nSql++] = '\n';
18348 memcpy(zSql+nSql, zLine, nLine+1);
18349 nSql += nLine;
18350 }
18351 if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018352 && sqlite3_complete(zSql) ){
mydongistiny63ee58c2019-09-21 18:04:30 -070018353 errCnt += runOneSqlLine(p, zSql, p->in, startline);
Nick Kralevich8fecf562014-05-29 16:56:33 -070018354 nSql = 0;
Nick Kralevich1c7cea32014-06-06 19:53:11 -070018355 if( p->outCount ){
18356 output_reset(p);
18357 p->outCount = 0;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080018358 }else{
18359 clearTempFile(p);
Nick Kralevich1c7cea32014-06-06 19:53:11 -070018360 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070018361 }else if( nSql && _all_whitespace(zSql) ){
Alex Naidisb86c0cf2017-03-31 14:12:35 +020018362 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018363 nSql = 0;
18364 }
18365 }
Luca Stefanie7f3e802017-01-02 15:44:22 +010018366 if( nSql && !_all_whitespace(zSql) ){
mydongistiny63ee58c2019-09-21 18:04:30 -070018367 errCnt += runOneSqlLine(p, zSql, p->in, startline);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018368 }
Nick Kralevich253ed642015-12-23 10:07:58 -080018369 free(zSql);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018370 free(zLine);
Nick Kralevich8fecf562014-05-29 16:56:33 -070018371 return errCnt>0;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018372}
18373
18374/*
18375** Return a pathname which is the user's home directory. A
Nick Kralevich8fecf562014-05-29 16:56:33 -070018376** 0 return indicates an error of some kind.
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018377*/
Alex Naidis08f78cb2016-10-14 15:52:08 +020018378static char *find_home_dir(int clearFlag){
Nick Kralevich8fecf562014-05-29 16:56:33 -070018379 static char *home_dir = NULL;
Alex Naidis08f78cb2016-10-14 15:52:08 +020018380 if( clearFlag ){
18381 free(home_dir);
18382 home_dir = 0;
18383 return 0;
18384 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070018385 if( home_dir ) return home_dir;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018386
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018387#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
18388 && !defined(__RTP__) && !defined(_WRS_KERNEL)
Nick Kralevich8fecf562014-05-29 16:56:33 -070018389 {
18390 struct passwd *pwent;
18391 uid_t uid = getuid();
18392 if( (pwent=getpwuid(uid)) != NULL) {
18393 home_dir = pwent->pw_dir;
18394 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018395 }
18396#endif
18397
18398#if defined(_WIN32_WCE)
18399 /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
18400 */
Nick Kralevich8fecf562014-05-29 16:56:33 -070018401 home_dir = "/";
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018402#else
18403
Nick Kralevich8fecf562014-05-29 16:56:33 -070018404#if defined(_WIN32) || defined(WIN32)
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018405 if (!home_dir) {
18406 home_dir = getenv("USERPROFILE");
18407 }
18408#endif
18409
18410 if (!home_dir) {
18411 home_dir = getenv("HOME");
18412 }
18413
Nick Kralevich8fecf562014-05-29 16:56:33 -070018414#if defined(_WIN32) || defined(WIN32)
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018415 if (!home_dir) {
18416 char *zDrive, *zPath;
18417 int n;
18418 zDrive = getenv("HOMEDRIVE");
18419 zPath = getenv("HOMEPATH");
18420 if( zDrive && zPath ){
Vasu Noria4356a02010-01-20 15:10:57 -080018421 n = strlen30(zDrive) + strlen30(zPath) + 1;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018422 home_dir = malloc( n );
18423 if( home_dir==0 ) return 0;
18424 sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
18425 return home_dir;
18426 }
18427 home_dir = "c:\\";
18428 }
18429#endif
18430
18431#endif /* !_WIN32_WCE */
18432
18433 if( home_dir ){
Vasu Noria4356a02010-01-20 15:10:57 -080018434 int n = strlen30(home_dir) + 1;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018435 char *z = malloc( n );
18436 if( z ) memcpy(z, home_dir, n);
18437 home_dir = z;
18438 }
18439
18440 return home_dir;
18441}
18442
18443/*
18444** Read input from the file given by sqliterc_override. Or if that
18445** parameter is NULL, take input from ~/.sqliterc
Vasu Noria4356a02010-01-20 15:10:57 -080018446**
18447** Returns the number of errors.
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018448*/
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018449static void process_sqliterc(
18450 ShellState *p, /* Configuration data */
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018451 const char *sqliterc_override /* Name of config file. NULL to use default */
18452){
18453 char *home_dir = NULL;
18454 const char *sqliterc = sqliterc_override;
18455 char *zBuf = 0;
mydongistiny63ee58c2019-09-21 18:04:30 -070018456 FILE *inSaved = p->in;
18457 int savedLineno = p->lineno;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018458
18459 if (sqliterc == NULL) {
Alex Naidis08f78cb2016-10-14 15:52:08 +020018460 home_dir = find_home_dir(0);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018461 if( home_dir==0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018462 raw_printf(stderr, "-- warning: cannot find home directory;"
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018463 " cannot read ~/.sqliterc\n");
18464 return;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018465 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070018466 zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
18467 sqliterc = zBuf;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018468 }
mydongistiny63ee58c2019-09-21 18:04:30 -070018469 p->in = fopen(sqliterc,"rb");
18470 if( p->in ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018471 if( stdin_is_interactive ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018472 utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018473 }
mydongistiny63ee58c2019-09-21 18:04:30 -070018474 process_input(p);
18475 fclose(p->in);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018476 }
mydongistiny63ee58c2019-09-21 18:04:30 -070018477 p->in = inSaved;
18478 p->lineno = savedLineno;
Nick Kralevich8fecf562014-05-29 16:56:33 -070018479 sqlite3_free(zBuf);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018480}
18481
18482/*
18483** Show available command line options
18484*/
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018485static const char zOptions[] =
mydongistiny63ee58c2019-09-21 18:04:30 -070018486#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
18487 " -A ARGS... run \".archive ARGS\" and exit\n"
18488#endif
18489 " -append append the database to the end of the file\n"
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018490 " -ascii set output mode to 'ascii'\n"
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018491 " -bail stop after hitting an error\n"
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018492 " -batch force batch I/O\n"
18493 " -column set output mode to 'column'\n"
Nick Kralevich8fecf562014-05-29 16:56:33 -070018494 " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018495 " -csv set output mode to 'csv'\n"
mydongistiny63ee58c2019-09-21 18:04:30 -070018496#if defined(SQLITE_ENABLE_DESERIALIZE)
18497 " -deserialize open the database using sqlite3_deserialize()\n"
18498#endif
Jeff Brownc82acac2012-04-19 19:31:30 -070018499 " -echo print commands before execution\n"
Nick Kralevich8fecf562014-05-29 16:56:33 -070018500 " -init FILENAME read/process named file\n"
Jeff Brownc82acac2012-04-19 19:31:30 -070018501 " -[no]header turn headers on or off\n"
Nick Kralevich8fecf562014-05-29 16:56:33 -070018502#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
18503 " -heap SIZE Size of heap for memsys3 or memsys5\n"
18504#endif
Jeff Brownc82acac2012-04-19 19:31:30 -070018505 " -help show this message\n"
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018506 " -html set output mode to HTML\n"
Jeff Brownc82acac2012-04-19 19:31:30 -070018507 " -interactive force interactive I/O\n"
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018508 " -line set output mode to 'line'\n"
18509 " -list set output mode to 'list'\n"
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018510 " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
mydongistiny63ee58c2019-09-21 18:04:30 -070018511#if defined(SQLITE_ENABLE_DESERIALIZE)
18512 " -maxsize N maximum size for a --deserialize database\n"
18513#endif
18514 " -memtrace trace all memory allocations and deallocations\n"
Nick Kralevich8fecf562014-05-29 16:56:33 -070018515 " -mmap N default mmap size set to N\n"
Jeff Brownc82acac2012-04-19 19:31:30 -070018516#ifdef SQLITE_ENABLE_MULTIPLEX
18517 " -multiplex enable the multiplexor VFS\n"
18518#endif
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018519 " -newline SEP set output row separator. Default: '\\n'\n"
Nick Kralevich8fecf562014-05-29 16:56:33 -070018520 " -nullvalue TEXT set text string for NULL values. Default ''\n"
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018521 " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080018522 " -quote set output mode to 'quote'\n"
mydongistiny63ee58c2019-09-21 18:04:30 -070018523 " -readonly open the database read-only\n"
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018524 " -separator SEP set output column separator. Default: '|'\n"
mydongistiny63ee58c2019-09-21 18:04:30 -070018525#ifdef SQLITE_ENABLE_SORTER_REFERENCES
18526 " -sorterref SIZE sorter references threshold size\n"
18527#endif
Vasu Noride2b3242010-09-29 15:33:53 -070018528 " -stats print memory stats before each finalize\n"
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018529 " -version show SQLite version\n"
Jeff Brown90ed05d2012-01-19 16:35:19 -080018530 " -vfs NAME use NAME as the default VFS\n"
18531#ifdef SQLITE_ENABLE_VFSTRACE
18532 " -vfstrace enable tracing of all VFS calls\n"
18533#endif
mydongistiny63ee58c2019-09-21 18:04:30 -070018534#ifdef SQLITE_HAVE_ZLIB
18535 " -zip open the file as a ZIP Archive\n"
18536#endif
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018537;
18538static void usage(int showDetail){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018539 utf8_printf(stderr,
18540 "Usage: %s [OPTIONS] FILENAME [SQL]\n"
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018541 "FILENAME is the name of an SQLite database. A new database is created\n"
18542 "if the file does not previously exist.\n", Argv0);
18543 if( showDetail ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018544 utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018545 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018546 raw_printf(stderr, "Use the -help option for additional information\n");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018547 }
18548 exit(1);
18549}
18550
18551/*
mydongistiny63ee58c2019-09-21 18:04:30 -070018552** Internal check: Verify that the SQLite is uninitialized. Print a
18553** error message if it is initialized.
18554*/
18555static void verify_uninitialized(void){
18556 if( sqlite3_config(-1)==SQLITE_MISUSE ){
18557 utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
18558 " initialization.\n");
18559 }
18560}
18561
18562/*
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018563** Initialize the state information in data
18564*/
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018565static void main_init(ShellState *data) {
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018566 memset(data, 0, sizeof(*data));
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018567 data->normalMode = data->cMode = data->mode = MODE_List;
18568 data->autoExplain = 1;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018569 memcpy(data->colSeparator,SEP_Column, 2);
18570 memcpy(data->rowSeparator,SEP_Row, 2);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018571 data->showHeader = 0;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018572 data->shellFlgs = SHFLG_Lookaside;
mydongistiny63ee58c2019-09-21 18:04:30 -070018573 verify_uninitialized();
Jeff Brown90ed05d2012-01-19 16:35:19 -080018574 sqlite3_config(SQLITE_CONFIG_URI, 1);
Vasu Noriaae12b82010-03-02 13:00:31 -080018575 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018576 sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018577 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
18578 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
18579}
18580
Nick Kralevich8fecf562014-05-29 16:56:33 -070018581/*
18582** Output text to the console in a font that attracts extra attention.
18583*/
18584#ifdef _WIN32
18585static void printBold(const char *zText){
18586 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
18587 CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
18588 GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
18589 SetConsoleTextAttribute(out,
18590 FOREGROUND_RED|FOREGROUND_INTENSITY
18591 );
18592 printf("%s", zText);
18593 SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
18594}
18595#else
18596static void printBold(const char *zText){
18597 printf("\033[1m%s\033[0m", zText);
18598}
18599#endif
18600
18601/*
18602** Get the argument to an --option. Throw an error and die if no argument
18603** is available.
18604*/
18605static char *cmdline_option_value(int argc, char **argv, int i){
18606 if( i==argc ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018607 utf8_printf(stderr, "%s: Error: missing argument to %s\n",
Nick Kralevich8fecf562014-05-29 16:56:33 -070018608 argv[0], argv[argc-1]);
18609 exit(1);
18610 }
18611 return argv[i];
18612}
18613
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018614#ifndef SQLITE_SHELL_IS_UTF8
18615# if (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
18616# define SQLITE_SHELL_IS_UTF8 (0)
18617# else
18618# define SQLITE_SHELL_IS_UTF8 (1)
18619# endif
18620#endif
18621
18622#if SQLITE_SHELL_IS_UTF8
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018623int SQLITE_CDECL main(int argc, char **argv){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018624#else
18625int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
18626 char **argv;
18627#endif
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018628 char *zErrMsg = 0;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018629 ShellState data;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018630 const char *zInitFile = 0;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018631 int i;
18632 int rc = 0;
Nick Kralevich8fecf562014-05-29 16:56:33 -070018633 int warnInmemoryDb = 0;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018634 int readStdin = 1;
18635 int nCmd = 0;
18636 char **azCmd = 0;
mydongistiny63ee58c2019-09-21 18:04:30 -070018637 const char *zVfs = 0; /* Value of -vfs command-line option */
18638#if !SQLITE_SHELL_IS_UTF8
18639 char **argvToFree = 0;
18640 int argcToFree = 0;
18641#endif
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018642
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018643 setBinaryMode(stdin, 0);
18644 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
18645 stdin_is_interactive = isatty(0);
18646 stdout_is_console = isatty(1);
18647
mydongistiny63ee58c2019-09-21 18:04:30 -070018648#if !defined(_WIN32_WCE)
18649 if( getenv("SQLITE_DEBUG_BREAK") ){
18650 if( isatty(0) && isatty(2) ){
18651 fprintf(stderr,
18652 "attach debugger to process %d and press any key to continue.\n",
18653 GETPID());
18654 fgetc(stdin);
18655 }else{
18656#if defined(_WIN32) || defined(WIN32)
18657 DebugBreak();
18658#elif defined(SIGTRAP)
18659 raise(SIGTRAP);
18660#endif
18661 }
18662 }
18663#endif
18664
Nick Kralevich8fecf562014-05-29 16:56:33 -070018665#if USE_SYSTEM_SQLITE+0!=1
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080018666 if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018667 utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
Jeff Brown90ed05d2012-01-19 16:35:19 -080018668 sqlite3_sourceid(), SQLITE_SOURCE_ID);
18669 exit(1);
18670 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070018671#endif
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018672 main_init(&data);
mydongistiny63ee58c2019-09-21 18:04:30 -070018673
18674 /* On Windows, we must translate command-line arguments into UTF-8.
18675 ** The SQLite memory allocator subsystem has to be enabled in order to
18676 ** do this. But we want to run an sqlite3_shutdown() afterwards so that
18677 ** subsequent sqlite3_config() calls will work. So copy all results into
18678 ** memory that does not come from the SQLite memory allocator.
18679 */
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018680#if !SQLITE_SHELL_IS_UTF8
18681 sqlite3_initialize();
mydongistiny63ee58c2019-09-21 18:04:30 -070018682 argvToFree = malloc(sizeof(argv[0])*argc*2);
18683 argcToFree = argc;
18684 argv = argvToFree + argc;
18685 if( argv==0 ) shell_out_of_memory();
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018686 for(i=0; i<argc; i++){
mydongistiny63ee58c2019-09-21 18:04:30 -070018687 char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
18688 int n;
18689 if( z==0 ) shell_out_of_memory();
18690 n = (int)strlen(z);
18691 argv[i] = malloc( n+1 );
18692 if( argv[i]==0 ) shell_out_of_memory();
18693 memcpy(argv[i], z, n+1);
18694 argvToFree[i] = argv[i];
18695 sqlite3_free(z);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018696 }
mydongistiny63ee58c2019-09-21 18:04:30 -070018697 sqlite3_shutdown();
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018698#endif
mydongistiny63ee58c2019-09-21 18:04:30 -070018699
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018700 assert( argc>=1 && argv && argv[0] );
18701 Argv0 = argv[0];
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018702
18703 /* Make sure we have a valid signal handler early, before anything
18704 ** else is done.
18705 */
18706#ifdef SIGINT
18707 signal(SIGINT, interrupt_handler);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080018708#elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
18709 SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018710#endif
18711
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018712#ifdef SQLITE_SHELL_DBNAME_PROC
18713 {
18714 /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
18715 ** of a C-function that will provide the name of the database file. Use
18716 ** this compile-time option to embed this shell program in larger
18717 ** applications. */
18718 extern void SQLITE_SHELL_DBNAME_PROC(const char**);
18719 SQLITE_SHELL_DBNAME_PROC(&data.zDbFilename);
18720 warnInmemoryDb = 0;
18721 }
18722#endif
18723
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018724 /* Do an initial pass through the command-line argument to locate
18725 ** the name of the database file, the name of the initialization file,
Jeff Brown90ed05d2012-01-19 16:35:19 -080018726 ** the size of the alternative malloc heap,
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018727 ** and the first command to execute.
18728 */
mydongistiny63ee58c2019-09-21 18:04:30 -070018729 verify_uninitialized();
Nick Kralevich8fecf562014-05-29 16:56:33 -070018730 for(i=1; i<argc; i++){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018731 char *z;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018732 z = argv[i];
Nick Kralevich8fecf562014-05-29 16:56:33 -070018733 if( z[0]!='-' ){
18734 if( data.zDbFilename==0 ){
18735 data.zDbFilename = z;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018736 }else{
18737 /* Excesss arguments are interpreted as SQL (or dot-commands) and
18738 ** mean that nothing is read from stdin */
18739 readStdin = 0;
18740 nCmd++;
18741 azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
mydongistiny63ee58c2019-09-21 18:04:30 -070018742 if( azCmd==0 ) shell_out_of_memory();
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018743 azCmd[nCmd-1] = z;
Nick Kralevich8fecf562014-05-29 16:56:33 -070018744 }
Nick Kralevich8fecf562014-05-29 16:56:33 -070018745 }
Jeff Brownc82acac2012-04-19 19:31:30 -070018746 if( z[1]=='-' ) z++;
18747 if( strcmp(z,"-separator")==0
18748 || strcmp(z,"-nullvalue")==0
Jeff Brown9bee60b2014-08-20 16:41:25 -070018749 || strcmp(z,"-newline")==0
Jeff Brownc82acac2012-04-19 19:31:30 -070018750 || strcmp(z,"-cmd")==0
18751 ){
Nick Kralevich8fecf562014-05-29 16:56:33 -070018752 (void)cmdline_option_value(argc, argv, ++i);
Jeff Brownc82acac2012-04-19 19:31:30 -070018753 }else if( strcmp(z,"-init")==0 ){
Nick Kralevich8fecf562014-05-29 16:56:33 -070018754 zInitFile = cmdline_option_value(argc, argv, ++i);
Jeff Brownc82acac2012-04-19 19:31:30 -070018755 }else if( strcmp(z,"-batch")==0 ){
Nick Kralevich8fecf562014-05-29 16:56:33 -070018756 /* Need to check for batch mode here to so we can avoid printing
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018757 ** informational messages (like from process_sqliterc) before
Nick Kralevich8fecf562014-05-29 16:56:33 -070018758 ** we do the actual processing of arguments later in a second pass.
18759 */
Vasu Noria4356a02010-01-20 15:10:57 -080018760 stdin_is_interactive = 0;
Jeff Brownc82acac2012-04-19 19:31:30 -070018761 }else if( strcmp(z,"-heap")==0 ){
Jeff Brown90ed05d2012-01-19 16:35:19 -080018762#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
Jeff Brown90ed05d2012-01-19 16:35:19 -080018763 const char *zSize;
18764 sqlite3_int64 szHeap;
18765
Nick Kralevich8fecf562014-05-29 16:56:33 -070018766 zSize = cmdline_option_value(argc, argv, ++i);
18767 szHeap = integerValue(zSize);
Jeff Brown90ed05d2012-01-19 16:35:19 -080018768 if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
18769 sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
Alex Naidis74bd39c2016-08-09 00:53:11 +020018770#else
18771 (void)cmdline_option_value(argc, argv, ++i);
Jeff Brown90ed05d2012-01-19 16:35:19 -080018772#endif
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018773 }else if( strcmp(z,"-pagecache")==0 ){
18774 int n, sz;
18775 sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
18776 if( sz>70000 ) sz = 70000;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018777 if( sz<0 ) sz = 0;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018778 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018779 sqlite3_config(SQLITE_CONFIG_PAGECACHE,
18780 (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018781 data.shellFlgs |= SHFLG_Pagecache;
18782 }else if( strcmp(z,"-lookaside")==0 ){
18783 int n, sz;
18784 sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
18785 if( sz<0 ) sz = 0;
18786 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
18787 if( n<0 ) n = 0;
18788 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
18789 if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
Jeff Brown90ed05d2012-01-19 16:35:19 -080018790#ifdef SQLITE_ENABLE_VFSTRACE
Jeff Brownc82acac2012-04-19 19:31:30 -070018791 }else if( strcmp(z,"-vfstrace")==0 ){
Jeff Brown90ed05d2012-01-19 16:35:19 -080018792 extern int vfstrace_register(
18793 const char *zTraceName,
18794 const char *zOldVfsName,
18795 int (*xOut)(const char*,void*),
18796 void *pOutArg,
18797 int makeDefault
18798 );
18799 vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
18800#endif
18801#ifdef SQLITE_ENABLE_MULTIPLEX
Jeff Brownc82acac2012-04-19 19:31:30 -070018802 }else if( strcmp(z,"-multiplex")==0 ){
Jeff Brown90ed05d2012-01-19 16:35:19 -080018803 extern int sqlite3_multiple_initialize(const char*,int);
18804 sqlite3_multiplex_initialize(0, 1);
18805#endif
Nick Kralevich8fecf562014-05-29 16:56:33 -070018806 }else if( strcmp(z,"-mmap")==0 ){
18807 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
18808 sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
mydongistiny63ee58c2019-09-21 18:04:30 -070018809#ifdef SQLITE_ENABLE_SORTER_REFERENCES
18810 }else if( strcmp(z,"-sorterref")==0 ){
18811 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
18812 sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz);
18813#endif
Jeff Brownc82acac2012-04-19 19:31:30 -070018814 }else if( strcmp(z,"-vfs")==0 ){
mydongistiny63ee58c2019-09-21 18:04:30 -070018815 zVfs = cmdline_option_value(argc, argv, ++i);
18816#ifdef SQLITE_HAVE_ZLIB
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080018817 }else if( strcmp(z,"-zip")==0 ){
18818 data.openMode = SHELL_OPEN_ZIPFILE;
18819#endif
18820 }else if( strcmp(z,"-append")==0 ){
18821 data.openMode = SHELL_OPEN_APPENDVFS;
mydongistiny63ee58c2019-09-21 18:04:30 -070018822#ifdef SQLITE_ENABLE_DESERIALIZE
18823 }else if( strcmp(z,"-deserialize")==0 ){
18824 data.openMode = SHELL_OPEN_DESERIALIZE;
18825 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
18826 data.szMax = integerValue(argv[++i]);
18827#endif
18828 }else if( strcmp(z,"-readonly")==0 ){
18829 data.openMode = SHELL_OPEN_READONLY;
18830#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
18831 }else if( strncmp(z, "-A",2)==0 ){
18832 /* All remaining command-line arguments are passed to the ".archive"
18833 ** command, so ignore them */
18834 break;
18835#endif
18836 }else if( strcmp(z, "-memtrace")==0 ){
18837 sqlite3MemTraceActivate(stderr);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018838 }
18839 }
mydongistiny63ee58c2019-09-21 18:04:30 -070018840 verify_uninitialized();
18841
18842
18843#ifdef SQLITE_SHELL_INIT_PROC
18844 {
18845 /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name
18846 ** of a C-function that will perform initialization actions on SQLite that
18847 ** occur just before or after sqlite3_initialize(). Use this compile-time
18848 ** option to embed this shell program in larger applications. */
18849 extern void SQLITE_SHELL_INIT_PROC(void);
18850 SQLITE_SHELL_INIT_PROC();
18851 }
18852#else
18853 /* All the sqlite3_config() calls have now been made. So it is safe
18854 ** to call sqlite3_initialize() and process any command line -vfs option. */
18855 sqlite3_initialize();
18856#endif
18857
18858 if( zVfs ){
18859 sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
18860 if( pVfs ){
18861 sqlite3_vfs_register(pVfs, 1);
18862 }else{
18863 utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
18864 exit(1);
18865 }
18866 }
18867
Nick Kralevich8fecf562014-05-29 16:56:33 -070018868 if( data.zDbFilename==0 ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018869#ifndef SQLITE_OMIT_MEMORYDB
18870 data.zDbFilename = ":memory:";
Nick Kralevich8fecf562014-05-29 16:56:33 -070018871 warnInmemoryDb = argc==1;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018872#else
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018873 utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
Vasu Noria4356a02010-01-20 15:10:57 -080018874 return 1;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018875#endif
Nick Kralevich8fecf562014-05-29 16:56:33 -070018876 }
18877 data.out = stdout;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080018878 sqlite3_appendvfs_init(0,0,0);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018879
18880 /* Go ahead and open the database file if it already exists. If the
18881 ** file does not exist, delay opening it. This prevents empty database
18882 ** files from being created if a user mistypes the database name argument
18883 ** to the sqlite command-line tool.
18884 */
18885 if( access(data.zDbFilename, 0)==0 ){
Nick Kralevich8fecf562014-05-29 16:56:33 -070018886 open_db(&data, 0);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018887 }
18888
18889 /* Process the initialization file if there is one. If no -init option
18890 ** is given on the command line, look for a file named ~/.sqliterc and
18891 ** try to process it.
18892 */
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018893 process_sqliterc(&data,zInitFile);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018894
18895 /* Make a second pass through the command-line argument and set
18896 ** options. This second pass is delayed until after the initialization
18897 ** file is processed so that the command-line arguments will override
18898 ** settings in the initialization file.
18899 */
Nick Kralevich8fecf562014-05-29 16:56:33 -070018900 for(i=1; i<argc; i++){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018901 char *z = argv[i];
Nick Kralevich8fecf562014-05-29 16:56:33 -070018902 if( z[0]!='-' ) continue;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018903 if( z[1]=='-' ){ z++; }
18904 if( strcmp(z,"-init")==0 ){
18905 i++;
18906 }else if( strcmp(z,"-html")==0 ){
18907 data.mode = MODE_Html;
18908 }else if( strcmp(z,"-list")==0 ){
18909 data.mode = MODE_List;
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080018910 }else if( strcmp(z,"-quote")==0 ){
18911 data.mode = MODE_Quote;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018912 }else if( strcmp(z,"-line")==0 ){
18913 data.mode = MODE_Line;
18914 }else if( strcmp(z,"-column")==0 ){
18915 data.mode = MODE_Column;
18916 }else if( strcmp(z,"-csv")==0 ){
18917 data.mode = MODE_Csv;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018918 memcpy(data.colSeparator,",",2);
mydongistiny63ee58c2019-09-21 18:04:30 -070018919#ifdef SQLITE_HAVE_ZLIB
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080018920 }else if( strcmp(z,"-zip")==0 ){
18921 data.openMode = SHELL_OPEN_ZIPFILE;
18922#endif
18923 }else if( strcmp(z,"-append")==0 ){
18924 data.openMode = SHELL_OPEN_APPENDVFS;
mydongistiny63ee58c2019-09-21 18:04:30 -070018925#ifdef SQLITE_ENABLE_DESERIALIZE
18926 }else if( strcmp(z,"-deserialize")==0 ){
18927 data.openMode = SHELL_OPEN_DESERIALIZE;
18928 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
18929 data.szMax = integerValue(argv[++i]);
18930#endif
18931 }else if( strcmp(z,"-readonly")==0 ){
18932 data.openMode = SHELL_OPEN_READONLY;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018933 }else if( strcmp(z,"-ascii")==0 ){
18934 data.mode = MODE_Ascii;
18935 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
18936 SEP_Unit);
18937 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
18938 SEP_Record);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018939 }else if( strcmp(z,"-separator")==0 ){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018940 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
Nick Kralevich8fecf562014-05-29 16:56:33 -070018941 "%s",cmdline_option_value(argc,argv,++i));
Jeff Brown9bee60b2014-08-20 16:41:25 -070018942 }else if( strcmp(z,"-newline")==0 ){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018943 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
Jeff Brown9bee60b2014-08-20 16:41:25 -070018944 "%s",cmdline_option_value(argc,argv,++i));
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018945 }else if( strcmp(z,"-nullvalue")==0 ){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018946 sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
Nick Kralevich8fecf562014-05-29 16:56:33 -070018947 "%s",cmdline_option_value(argc,argv,++i));
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018948 }else if( strcmp(z,"-header")==0 ){
18949 data.showHeader = 1;
18950 }else if( strcmp(z,"-noheader")==0 ){
18951 data.showHeader = 0;
18952 }else if( strcmp(z,"-echo")==0 ){
Alex Naidisb86c0cf2017-03-31 14:12:35 +020018953 ShellSetFlag(&data, SHFLG_Echo);
Nick Kralevich8fecf562014-05-29 16:56:33 -070018954 }else if( strcmp(z,"-eqp")==0 ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080018955 data.autoEQP = AUTOEQP_on;
Alex Naidis60fa6fd2016-07-10 14:13:38 +020018956 }else if( strcmp(z,"-eqpfull")==0 ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080018957 data.autoEQP = AUTOEQP_full;
Vasu Noride2b3242010-09-29 15:33:53 -070018958 }else if( strcmp(z,"-stats")==0 ){
18959 data.statsOn = 1;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018960 }else if( strcmp(z,"-scanstats")==0 ){
18961 data.scanstatsOn = 1;
Nick Kralevich3a6c79f2015-05-08 11:25:07 -070018962 }else if( strcmp(z,"-backslash")==0 ){
18963 /* Undocumented command-line option: -backslash
18964 ** Causes C-style backslash escapes to be evaluated in SQL statements
18965 ** prior to sending the SQL into SQLite. Useful for injecting
18966 ** crazy bytes in the middle of SQL statements for testing and debugging.
18967 */
Alex Naidisb86c0cf2017-03-31 14:12:35 +020018968 ShellSetFlag(&data, SHFLG_Backslash);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018969 }else if( strcmp(z,"-bail")==0 ){
18970 bail_on_error = 1;
18971 }else if( strcmp(z,"-version")==0 ){
Jeff Brown90ed05d2012-01-19 16:35:19 -080018972 printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
The Android Open Source Project7790ef52009-03-03 19:30:40 -080018973 return 0;
18974 }else if( strcmp(z,"-interactive")==0 ){
18975 stdin_is_interactive = 1;
18976 }else if( strcmp(z,"-batch")==0 ){
18977 stdin_is_interactive = 0;
Jeff Brown90ed05d2012-01-19 16:35:19 -080018978 }else if( strcmp(z,"-heap")==0 ){
18979 i++;
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070018980 }else if( strcmp(z,"-pagecache")==0 ){
18981 i+=2;
18982 }else if( strcmp(z,"-lookaside")==0 ){
18983 i+=2;
Nick Kralevich8fecf562014-05-29 16:56:33 -070018984 }else if( strcmp(z,"-mmap")==0 ){
18985 i++;
mydongistiny63ee58c2019-09-21 18:04:30 -070018986 }else if( strcmp(z,"-memtrace")==0 ){
18987 i++;
18988#ifdef SQLITE_ENABLE_SORTER_REFERENCES
18989 }else if( strcmp(z,"-sorterref")==0 ){
18990 i++;
18991#endif
Jeff Brown90ed05d2012-01-19 16:35:19 -080018992 }else if( strcmp(z,"-vfs")==0 ){
18993 i++;
18994#ifdef SQLITE_ENABLE_VFSTRACE
18995 }else if( strcmp(z,"-vfstrace")==0 ){
18996 i++;
18997#endif
18998#ifdef SQLITE_ENABLE_MULTIPLEX
18999 }else if( strcmp(z,"-multiplex")==0 ){
19000 i++;
19001#endif
Jeff Brownc82acac2012-04-19 19:31:30 -070019002 }else if( strcmp(z,"-help")==0 ){
The Android Open Source Project7790ef52009-03-03 19:30:40 -080019003 usage(1);
Jeff Brownc82acac2012-04-19 19:31:30 -070019004 }else if( strcmp(z,"-cmd")==0 ){
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070019005 /* Run commands that follow -cmd first and separately from commands
19006 ** that simply appear on the command-line. This seems goofy. It would
19007 ** be better if all commands ran in the order that they appear. But
19008 ** we retain the goofy behavior for historical compatibility. */
Jeff Brownc82acac2012-04-19 19:31:30 -070019009 if( i==argc-1 ) break;
Nick Kralevich8fecf562014-05-29 16:56:33 -070019010 z = cmdline_option_value(argc,argv,++i);
Jeff Brownc82acac2012-04-19 19:31:30 -070019011 if( z[0]=='.' ){
19012 rc = do_meta_command(z, &data);
Nick Kralevich8fecf562014-05-29 16:56:33 -070019013 if( rc && bail_on_error ) return rc==2 ? 0 : rc;
Jeff Brownc82acac2012-04-19 19:31:30 -070019014 }else{
Nick Kralevich8fecf562014-05-29 16:56:33 -070019015 open_db(&data, 0);
mydongistiny63ee58c2019-09-21 18:04:30 -070019016 rc = shell_exec(&data, z, &zErrMsg);
Jeff Brownc82acac2012-04-19 19:31:30 -070019017 if( zErrMsg!=0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020019018 utf8_printf(stderr,"Error: %s\n", zErrMsg);
Jeff Brownc82acac2012-04-19 19:31:30 -070019019 if( bail_on_error ) return rc!=0 ? rc : 1;
19020 }else if( rc!=0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020019021 utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
Jeff Brownc82acac2012-04-19 19:31:30 -070019022 if( bail_on_error ) return rc;
19023 }
19024 }
mydongistiny63ee58c2019-09-21 18:04:30 -070019025#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
19026 }else if( strncmp(z, "-A", 2)==0 ){
19027 if( nCmd>0 ){
19028 utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
19029 " with \"%s\"\n", z);
19030 return 1;
19031 }
19032 open_db(&data, OPEN_DB_ZIPFILE);
19033 if( z[2] ){
19034 argv[i] = &z[2];
19035 arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
19036 }else{
19037 arDotCommand(&data, 1, argv+i, argc-i);
19038 }
19039 readStdin = 0;
19040 break;
19041#endif
The Android Open Source Project7790ef52009-03-03 19:30:40 -080019042 }else{
Alex Naidis60fa6fd2016-07-10 14:13:38 +020019043 utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
19044 raw_printf(stderr,"Use -help for a list of options.\n");
The Android Open Source Project7790ef52009-03-03 19:30:40 -080019045 return 1;
19046 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020019047 data.cMode = data.mode;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080019048 }
19049
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070019050 if( !readStdin ){
19051 /* Run all arguments that do not begin with '-' as if they were separate
19052 ** command-line inputs, except for the argToSkip argument which contains
19053 ** the database filename.
The Android Open Source Project7790ef52009-03-03 19:30:40 -080019054 */
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070019055 for(i=0; i<nCmd; i++){
19056 if( azCmd[i][0]=='.' ){
19057 rc = do_meta_command(azCmd[i], &data);
19058 if( rc ) return rc==2 ? 0 : rc;
19059 }else{
19060 open_db(&data, 0);
mydongistiny63ee58c2019-09-21 18:04:30 -070019061 rc = shell_exec(&data, azCmd[i], &zErrMsg);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070019062 if( zErrMsg!=0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020019063 utf8_printf(stderr,"Error: %s\n", zErrMsg);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070019064 return rc!=0 ? rc : 1;
19065 }else if( rc!=0 ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020019066 utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070019067 return rc;
19068 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080019069 }
19070 }
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070019071 free(azCmd);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080019072 }else{
19073 /* Run commands received from standard input
19074 */
19075 if( stdin_is_interactive ){
19076 char *zHome;
mydongistiny63ee58c2019-09-21 18:04:30 -070019077 char *zHistory;
The Android Open Source Project7790ef52009-03-03 19:30:40 -080019078 int nHistory;
19079 printf(
Jeff Brown90ed05d2012-01-19 16:35:19 -080019080 "SQLite version %s %.19s\n" /*extra-version-info*/
Nick Kralevich8fecf562014-05-29 16:56:33 -070019081 "Enter \".help\" for usage hints.\n",
Jeff Brown90ed05d2012-01-19 16:35:19 -080019082 sqlite3_libversion(), sqlite3_sourceid()
The Android Open Source Project7790ef52009-03-03 19:30:40 -080019083 );
Nick Kralevich8fecf562014-05-29 16:56:33 -070019084 if( warnInmemoryDb ){
19085 printf("Connected to a ");
19086 printBold("transient in-memory database");
19087 printf(".\nUse \".open FILENAME\" to reopen on a "
19088 "persistent database.\n");
19089 }
mydongistiny63ee58c2019-09-21 18:04:30 -070019090 zHistory = getenv("SQLITE_HISTORY");
19091 if( zHistory ){
19092 zHistory = strdup(zHistory);
19093 }else if( (zHome = find_home_dir(0))!=0 ){
Vasu Noria4356a02010-01-20 15:10:57 -080019094 nHistory = strlen30(zHome) + 20;
19095 if( (zHistory = malloc(nHistory))!=0 ){
19096 sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
19097 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080019098 }
Nick Kralevich253ed642015-12-23 10:07:58 -080019099 if( zHistory ){ shell_read_history(zHistory); }
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080019100#if HAVE_READLINE || HAVE_EDITLINE
19101 rl_attempted_completion_function = readline_completion;
19102#elif HAVE_LINENOISE
19103 linenoiseSetCompletionCallback(linenoise_completion);
19104#endif
mydongistiny63ee58c2019-09-21 18:04:30 -070019105 data.in = 0;
19106 rc = process_input(&data);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080019107 if( zHistory ){
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080019108 shell_stifle_history(2000);
Nick Kralevich3fcd43a2015-04-08 13:13:26 -070019109 shell_write_history(zHistory);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080019110 free(zHistory);
19111 }
The Android Open Source Project7790ef52009-03-03 19:30:40 -080019112 }else{
mydongistiny63ee58c2019-09-21 18:04:30 -070019113 data.in = stdin;
19114 rc = process_input(&data);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080019115 }
19116 }
19117 set_table_name(&data, 0);
Vasu Nori71504cf2010-06-17 13:59:04 -070019118 if( data.db ){
Alex Naidis60fa6fd2016-07-10 14:13:38 +020019119 session_close_all(&data);
mydongistiny63ee58c2019-09-21 18:04:30 -070019120 close_db(data.db);
The Android Open Source Project7790ef52009-03-03 19:30:40 -080019121 }
Alex Naidis60fa6fd2016-07-10 14:13:38 +020019122 sqlite3_free(data.zFreeOnClose);
Alex Naidis08f78cb2016-10-14 15:52:08 +020019123 find_home_dir(1);
Fyodor Kupolov0181ec22018-02-13 16:45:16 -080019124 output_reset(&data);
19125 data.doXdgOpen = 0;
19126 clearTempFile(&data);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020019127#if !SQLITE_SHELL_IS_UTF8
mydongistiny63ee58c2019-09-21 18:04:30 -070019128 for(i=0; i<argcToFree; i++) free(argvToFree[i]);
19129 free(argvToFree);
Alex Naidis60fa6fd2016-07-10 14:13:38 +020019130#endif
mydongistiny63ee58c2019-09-21 18:04:30 -070019131 /* Clear the global data structure so that valgrind will detect memory
19132 ** leaks */
19133 memset(&data, 0, sizeof(data));
The Android Open Source Project7790ef52009-03-03 19:30:40 -080019134 return rc;
19135}