blob: dd261613d52b10f787dbb5a70ae3ae971cb08dd3 [file] [log] [blame]
drh2ce15c32017-07-11 13:34:40 +00001/*
2** 2001 September 15
3**
4** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
6**
7** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
10**
11*************************************************************************
12** This file contains code to implement the "sqlite" command line
13** utility for accessing SQLite databases.
14*/
15#if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
16/* This needs to come before any includes for MSVC compiler */
17#define _CRT_SECURE_NO_WARNINGS
18#endif
19
20/*
larrybra13c0c72021-07-09 00:12:05 +000021** Optionally #include a user-defined header, whereby compilation options
22** may be set prior to where they take effect, but after platform setup.
23** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include
24** file. Note that this macro has a like effect on sqlite3.c compilation.
25*/
26#ifdef SQLITE_CUSTOM_INCLUDE
27# define INC_STRINGIFY_(f) #f
28# define INC_STRINGIFY(f) INC_STRINGIFY_(f)
29# include INC_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
30#endif
31
32/*
mistachkin43e86272020-04-09 15:31:22 +000033** Determine if we are dealing with WinRT, which provides only a subset of
34** the full Win32 API.
35*/
36#if !defined(SQLITE_OS_WINRT)
37# define SQLITE_OS_WINRT 0
38#endif
39
40/*
drh2ce15c32017-07-11 13:34:40 +000041** Warning pragmas copied from msvc.h in the core.
42*/
43#if defined(_MSC_VER)
44#pragma warning(disable : 4054)
45#pragma warning(disable : 4055)
46#pragma warning(disable : 4100)
47#pragma warning(disable : 4127)
48#pragma warning(disable : 4130)
49#pragma warning(disable : 4152)
50#pragma warning(disable : 4189)
51#pragma warning(disable : 4206)
52#pragma warning(disable : 4210)
53#pragma warning(disable : 4232)
54#pragma warning(disable : 4244)
55#pragma warning(disable : 4305)
56#pragma warning(disable : 4306)
57#pragma warning(disable : 4702)
58#pragma warning(disable : 4706)
59#endif /* defined(_MSC_VER) */
60
61/*
62** No support for loadable extensions in VxWorks.
63*/
64#if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION
65# define SQLITE_OMIT_LOAD_EXTENSION 1
66#endif
67
68/*
69** Enable large-file support for fopen() and friends on unix.
70*/
71#ifndef SQLITE_DISABLE_LFS
72# define _LARGE_FILE 1
73# ifndef _FILE_OFFSET_BITS
74# define _FILE_OFFSET_BITS 64
75# endif
76# define _LARGEFILE_SOURCE 1
77#endif
78
79#include <stdlib.h>
80#include <string.h>
81#include <stdio.h>
82#include <assert.h>
83#include "sqlite3.h"
drh1e506b52018-01-05 21:01:37 +000084typedef sqlite3_int64 i64;
85typedef sqlite3_uint64 u64;
drh1fa6d9f2018-01-06 21:46:01 +000086typedef unsigned char u8;
drh2ce15c32017-07-11 13:34:40 +000087#if SQLITE_USER_AUTHENTICATION
88# include "sqlite3userauth.h"
89#endif
90#include <ctype.h>
91#include <stdarg.h>
92
93#if !defined(_WIN32) && !defined(WIN32)
94# include <signal.h>
95# if !defined(__RTP__) && !defined(_WRS_KERNEL)
96# include <pwd.h>
97# endif
mistachkinacae8c32018-01-05 20:08:46 +000098#endif
mistachkin562f0c82018-01-09 00:28:24 +000099#if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__)
drh2ce15c32017-07-11 13:34:40 +0000100# include <unistd.h>
mistachkinacae8c32018-01-05 20:08:46 +0000101# include <dirent.h>
mistachkin1e8487d2018-07-22 06:25:35 +0000102# define GETPID getpid
mistachkin562f0c82018-01-09 00:28:24 +0000103# if defined(__MINGW32__)
mistachkinacae8c32018-01-05 20:08:46 +0000104# define DIRENT dirent
mistachkin2f74b3c2018-01-05 20:26:06 +0000105# ifndef S_ISLNK
106# define S_ISLNK(mode) (0)
107# endif
mistachkinacae8c32018-01-05 20:08:46 +0000108# endif
mistachkin1e8487d2018-07-22 06:25:35 +0000109#else
110# define GETPID (int)GetCurrentProcessId
drh2ce15c32017-07-11 13:34:40 +0000111#endif
mistachkindfdfd8c2018-01-04 22:46:08 +0000112#include <sys/types.h>
113#include <sys/stat.h>
drh2ce15c32017-07-11 13:34:40 +0000114
115#if HAVE_READLINE
116# include <readline/readline.h>
117# include <readline/history.h>
118#endif
119
120#if HAVE_EDITLINE
121# include <editline/readline.h>
122#endif
123
124#if HAVE_EDITLINE || HAVE_READLINE
125
126# define shell_add_history(X) add_history(X)
127# define shell_read_history(X) read_history(X)
128# define shell_write_history(X) write_history(X)
129# define shell_stifle_history(X) stifle_history(X)
130# define shell_readline(X) readline(X)
131
132#elif HAVE_LINENOISE
133
134# include "linenoise.h"
135# define shell_add_history(X) linenoiseHistoryAdd(X)
136# define shell_read_history(X) linenoiseHistoryLoad(X)
137# define shell_write_history(X) linenoiseHistorySave(X)
138# define shell_stifle_history(X) linenoiseHistorySetMaxLen(X)
139# define shell_readline(X) linenoise(X)
140
141#else
142
143# define shell_read_history(X)
144# define shell_write_history(X)
145# define shell_stifle_history(X)
146
147# define SHELL_USE_LOCAL_GETLINE 1
148#endif
149
150
151#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +0000152# if SQLITE_OS_WINRT
153# define SQLITE_OMIT_POPEN 1
154# else
155# include <io.h>
156# include <fcntl.h>
157# define isatty(h) _isatty(h)
158# ifndef access
159# define access(f,m) _access((f),(m))
160# endif
161# ifndef unlink
162# define unlink _unlink
163# endif
164# ifndef strdup
165# define strdup _strdup
166# endif
167# undef popen
168# define popen _popen
169# undef pclose
170# define pclose _pclose
drh2ce15c32017-07-11 13:34:40 +0000171# endif
drh2ce15c32017-07-11 13:34:40 +0000172#else
173 /* Make sure isatty() has a prototype. */
174 extern int isatty(int);
175
176# 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
184#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
194/* 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
199#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +0000200#if SQLITE_OS_WINRT
201#include <intrin.h>
202#endif
drh2ce15c32017-07-11 13:34:40 +0000203#include <windows.h>
204
205/* string conversion routines only needed on Win32 */
206extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
207extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int);
208extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int);
209extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
210#endif
211
212/* On Windows, we normally run with output mode of TEXT so that \n characters
213** are automatically translated into \r\n. However, this behavior needs
214** to be disabled in some cases (ex: when generating CSV output and when
215** rendering quoted strings that contain \n characters). The following
216** routines take care of that.
217*/
mistachkin43e86272020-04-09 15:31:22 +0000218#if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +0000219static void setBinaryMode(FILE *file, int isOutput){
220 if( isOutput ) fflush(file);
221 _setmode(_fileno(file), _O_BINARY);
222}
223static void setTextMode(FILE *file, int isOutput){
224 if( isOutput ) fflush(file);
225 _setmode(_fileno(file), _O_TEXT);
226}
227#else
228# define setBinaryMode(X,Y)
229# define setTextMode(X,Y)
230#endif
231
232
233/* True if the timer is enabled */
234static int enableTimer = 0;
235
236/* Return the current wall-clock time */
237static sqlite3_int64 timeOfDay(void){
238 static sqlite3_vfs *clockVfs = 0;
239 sqlite3_int64 t;
240 if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
drha959bf52021-06-15 15:15:40 +0000241 if( clockVfs==0 ) return 0; /* Never actually happens */
drh2ce15c32017-07-11 13:34:40 +0000242 if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
243 clockVfs->xCurrentTimeInt64(clockVfs, &t);
244 }else{
245 double r;
246 clockVfs->xCurrentTime(clockVfs, &r);
247 t = (sqlite3_int64)(r*86400000.0);
248 }
249 return t;
250}
251
252#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
253#include <sys/time.h>
254#include <sys/resource.h>
255
256/* VxWorks does not support getrusage() as far as we can determine */
257#if defined(_WRS_KERNEL) || defined(__RTP__)
258struct rusage {
259 struct timeval ru_utime; /* user CPU time used */
260 struct timeval ru_stime; /* system CPU time used */
261};
262#define getrusage(A,B) memset(B,0,sizeof(*B))
263#endif
264
265/* Saved resource information for the beginning of an operation */
266static struct rusage sBegin; /* CPU time at start */
267static sqlite3_int64 iBegin; /* Wall-clock time at start */
268
269/*
270** Begin timing an operation
271*/
272static void beginTimer(void){
273 if( enableTimer ){
274 getrusage(RUSAGE_SELF, &sBegin);
275 iBegin = timeOfDay();
276 }
277}
278
279/* Return the difference of two time_structs in seconds */
280static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
281 return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
282 (double)(pEnd->tv_sec - pStart->tv_sec);
283}
284
285/*
286** Print the timing results.
287*/
288static void endTimer(void){
289 if( enableTimer ){
290 sqlite3_int64 iEnd = timeOfDay();
291 struct rusage sEnd;
292 getrusage(RUSAGE_SELF, &sEnd);
293 printf("Run Time: real %.3f user %f sys %f\n",
294 (iEnd - iBegin)*0.001,
295 timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
296 timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
297 }
298}
299
300#define BEGIN_TIMER beginTimer()
301#define END_TIMER endTimer()
302#define HAS_TIMER 1
303
304#elif (defined(_WIN32) || defined(WIN32))
305
306/* Saved resource information for the beginning of an operation */
307static HANDLE hProcess;
308static FILETIME ftKernelBegin;
309static FILETIME ftUserBegin;
310static sqlite3_int64 ftWallBegin;
311typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
312 LPFILETIME, LPFILETIME);
313static GETPROCTIMES getProcessTimesAddr = NULL;
314
315/*
316** Check to see if we have timer support. Return 1 if necessary
317** support found (or found previously).
318*/
319static int hasTimer(void){
320 if( getProcessTimesAddr ){
321 return 1;
322 } else {
mistachkin43e86272020-04-09 15:31:22 +0000323#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +0000324 /* GetProcessTimes() isn't supported in WIN95 and some other Windows
325 ** versions. See if the version we are running on has it, and if it
326 ** does, save off a pointer to it and the current process handle.
327 */
328 hProcess = GetCurrentProcess();
329 if( hProcess ){
330 HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
331 if( NULL != hinstLib ){
332 getProcessTimesAddr =
333 (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
334 if( NULL != getProcessTimesAddr ){
335 return 1;
336 }
337 FreeLibrary(hinstLib);
338 }
339 }
mistachkin43e86272020-04-09 15:31:22 +0000340#endif
drh2ce15c32017-07-11 13:34:40 +0000341 }
342 return 0;
343}
344
345/*
346** Begin timing an operation
347*/
348static void beginTimer(void){
349 if( enableTimer && getProcessTimesAddr ){
350 FILETIME ftCreation, ftExit;
351 getProcessTimesAddr(hProcess,&ftCreation,&ftExit,
352 &ftKernelBegin,&ftUserBegin);
353 ftWallBegin = timeOfDay();
354 }
355}
356
357/* Return the difference of two FILETIME structs in seconds */
358static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
359 sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
360 sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
361 return (double) ((i64End - i64Start) / 10000000.0);
362}
363
364/*
365** Print the timing results.
366*/
367static void endTimer(void){
368 if( enableTimer && getProcessTimesAddr){
369 FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
370 sqlite3_int64 ftWallEnd = timeOfDay();
371 getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
372 printf("Run Time: real %.3f user %f sys %f\n",
373 (ftWallEnd - ftWallBegin)*0.001,
374 timeDiff(&ftUserBegin, &ftUserEnd),
375 timeDiff(&ftKernelBegin, &ftKernelEnd));
376 }
377}
378
379#define BEGIN_TIMER beginTimer()
380#define END_TIMER endTimer()
381#define HAS_TIMER hasTimer()
382
383#else
384#define BEGIN_TIMER
385#define END_TIMER
386#define HAS_TIMER 0
387#endif
388
389/*
390** Used to prevent warnings about unused parameters
391*/
392#define UNUSED_PARAMETER(x) (void)(x)
393
394/*
drh5af06982018-01-10 00:53:55 +0000395** Number of elements in an array
396*/
397#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
398
399/*
drh2ce15c32017-07-11 13:34:40 +0000400** If the following flag is set, then command execution stops
401** at an error if we are not interactive.
402*/
403static int bail_on_error = 0;
404
405/*
406** Threat stdin as an interactive input if the following variable
407** is true. Otherwise, assume stdin is connected to a file or pipe.
408*/
409static int stdin_is_interactive = 1;
410
411/*
412** On Windows systems we have to know if standard output is a console
413** in order to translate UTF-8 into MBCS. The following variable is
414** true if translation is required.
415*/
416static int stdout_is_console = 1;
417
418/*
419** The following is the open SQLite database. We make a pointer
420** to this database a static variable so that it can be accessed
421** by the SIGINT handler to interrupt database processing.
422*/
423static sqlite3 *globalDb = 0;
424
425/*
426** True if an interrupt (Control-C) has been received.
427*/
428static volatile int seenInterrupt = 0;
429
drh4a3a3eb2020-02-29 15:53:48 +0000430#ifdef SQLITE_DEBUG
431/*
432** Out-of-memory simulator variables
433*/
434static unsigned int oomCounter = 0; /* Simulate OOM when equals 1 */
435static unsigned int oomRepeat = 0; /* Number of OOMs in a row */
436static void*(*defaultMalloc)(int) = 0; /* The low-level malloc routine */
437#endif /* SQLITE_DEBUG */
438
drh2ce15c32017-07-11 13:34:40 +0000439/*
440** This is the name of our program. It is set in main(), used
441** in a number of other places, mostly for error messages.
442*/
443static char *Argv0;
444
445/*
446** Prompt strings. Initialized in main. Settable with
447** .prompt main continue
448*/
449static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/
450static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */
451
452/*
453** Render output like fprintf(). Except, if the output is going to the
454** console and if this is running on a Windows machine, translate the
455** output from UTF-8 into MBCS.
456*/
457#if defined(_WIN32) || defined(WIN32)
458void utf8_printf(FILE *out, const char *zFormat, ...){
459 va_list ap;
460 va_start(ap, zFormat);
461 if( stdout_is_console && (out==stdout || out==stderr) ){
462 char *z1 = sqlite3_vmprintf(zFormat, ap);
463 char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0);
464 sqlite3_free(z1);
465 fputs(z2, out);
466 sqlite3_free(z2);
467 }else{
468 vfprintf(out, zFormat, ap);
469 }
470 va_end(ap);
471}
472#elif !defined(utf8_printf)
473# define utf8_printf fprintf
474#endif
475
476/*
477** Render output like fprintf(). This should not be used on anything that
478** includes string formatting (e.g. "%s").
479*/
480#if !defined(raw_printf)
481# define raw_printf fprintf
482#endif
483
drh4b5345c2018-04-24 13:07:40 +0000484/* Indicate out-of-memory and exit. */
485static void shell_out_of_memory(void){
486 raw_printf(stderr,"Error: out of memory\n");
487 exit(1);
488}
489
drh4a3a3eb2020-02-29 15:53:48 +0000490#ifdef SQLITE_DEBUG
491/* This routine is called when a simulated OOM occurs. It is broken
492** out as a separate routine to make it easy to set a breakpoint on
493** the OOM
494*/
495void shellOomFault(void){
496 if( oomRepeat>0 ){
497 oomRepeat--;
498 }else{
499 oomCounter--;
500 }
501}
502#endif /* SQLITE_DEBUG */
503
504#ifdef SQLITE_DEBUG
505/* This routine is a replacement malloc() that is used to simulate
506** Out-Of-Memory (OOM) errors for testing purposes.
507*/
508static void *oomMalloc(int nByte){
509 if( oomCounter ){
510 if( oomCounter==1 ){
511 shellOomFault();
512 return 0;
513 }else{
514 oomCounter--;
515 }
516 }
517 return defaultMalloc(nByte);
518}
519#endif /* SQLITE_DEBUG */
520
521#ifdef SQLITE_DEBUG
522/* Register the OOM simulator. This must occur before any memory
523** allocations */
524static void registerOomSimulator(void){
525 sqlite3_mem_methods mem;
526 sqlite3_config(SQLITE_CONFIG_GETMALLOC, &mem);
527 defaultMalloc = mem.xMalloc;
528 mem.xMalloc = oomMalloc;
529 sqlite3_config(SQLITE_CONFIG_MALLOC, &mem);
530}
531#endif
532
drh2ce15c32017-07-11 13:34:40 +0000533/*
534** Write I/O traces to the following stream.
535*/
536#ifdef SQLITE_ENABLE_IOTRACE
537static FILE *iotrace = 0;
538#endif
539
540/*
541** This routine works like printf in that its first argument is a
542** format string and subsequent arguments are values to be substituted
543** in place of % fields. The result of formatting this string
544** is written to iotrace.
545*/
546#ifdef SQLITE_ENABLE_IOTRACE
547static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
548 va_list ap;
549 char *z;
550 if( iotrace==0 ) return;
551 va_start(ap, zFormat);
552 z = sqlite3_vmprintf(zFormat, ap);
553 va_end(ap);
554 utf8_printf(iotrace, "%s", z);
555 sqlite3_free(z);
556}
557#endif
558
559/*
560** Output string zUtf to stream pOut as w characters. If w is negative,
561** then right-justify the text. W is the width in UTF-8 characters, not
562** in bytes. This is different from the %*.*s specification in printf
563** since with %*.*s the width is measured in bytes, not characters.
564*/
565static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
566 int i;
567 int n;
568 int aw = w<0 ? -w : w;
drh2ce15c32017-07-11 13:34:40 +0000569 for(i=n=0; zUtf[i]; i++){
570 if( (zUtf[i]&0xc0)!=0x80 ){
571 n++;
572 if( n==aw ){
573 do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
574 break;
575 }
576 }
577 }
578 if( n>=aw ){
579 utf8_printf(pOut, "%.*s", i, zUtf);
580 }else if( w<0 ){
581 utf8_printf(pOut, "%*s%s", aw-n, "", zUtf);
582 }else{
583 utf8_printf(pOut, "%s%*s", zUtf, aw-n, "");
584 }
585}
586
587
588/*
589** Determines if a string is a number of not.
590*/
591static int isNumber(const char *z, int *realnum){
592 if( *z=='-' || *z=='+' ) z++;
593 if( !IsDigit(*z) ){
594 return 0;
595 }
596 z++;
597 if( realnum ) *realnum = 0;
598 while( IsDigit(*z) ){ z++; }
599 if( *z=='.' ){
600 z++;
601 if( !IsDigit(*z) ) return 0;
602 while( IsDigit(*z) ){ z++; }
603 if( realnum ) *realnum = 1;
604 }
605 if( *z=='e' || *z=='E' ){
606 z++;
607 if( *z=='+' || *z=='-' ) z++;
608 if( !IsDigit(*z) ) return 0;
609 while( IsDigit(*z) ){ z++; }
610 if( realnum ) *realnum = 1;
611 }
612 return *z==0;
613}
614
615/*
616** Compute a string length that is limited to what can be stored in
617** lower 30 bits of a 32-bit signed integer.
618*/
619static int strlen30(const char *z){
620 const char *z2 = z;
621 while( *z2 ){ z2++; }
622 return 0x3fffffff & (int)(z2 - z);
623}
624
625/*
626** Return the length of a string in characters. Multibyte UTF8 characters
627** count as a single character.
628*/
629static int strlenChar(const char *z){
630 int n = 0;
631 while( *z ){
632 if( (0xc0&*(z++))!=0x80 ) n++;
633 }
634 return n;
635}
636
637/*
drhbbd620e2020-07-20 23:33:11 +0000638** Return true if zFile does not exist or if it is not an ordinary file.
639*/
640#ifdef _WIN32
641# define notNormalFile(X) 0
642#else
643static int notNormalFile(const char *zFile){
644 struct stat x;
645 int rc;
646 memset(&x, 0, sizeof(x));
647 rc = stat(zFile, &x);
648 return rc || !S_ISREG(x.st_mode);
649}
650#endif
651
652/*
drh2ce15c32017-07-11 13:34:40 +0000653** This routine reads a line of text from FILE in, stores
654** the text in memory obtained from malloc() and returns a pointer
655** to the text. NULL is returned at end of file, or if malloc()
656** fails.
657**
658** If zLine is not NULL then it is a malloced buffer returned from
659** a previous call to this routine that may be reused.
660*/
661static char *local_getline(char *zLine, FILE *in){
662 int nLine = zLine==0 ? 0 : 100;
663 int n = 0;
664
665 while( 1 ){
666 if( n+100>nLine ){
667 nLine = nLine*2 + 100;
668 zLine = realloc(zLine, nLine);
drh884406b2018-07-29 18:56:35 +0000669 if( zLine==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +0000670 }
671 if( fgets(&zLine[n], nLine - n, in)==0 ){
672 if( n==0 ){
673 free(zLine);
674 return 0;
675 }
676 zLine[n] = 0;
677 break;
678 }
679 while( zLine[n] ) n++;
680 if( n>0 && zLine[n-1]=='\n' ){
681 n--;
682 if( n>0 && zLine[n-1]=='\r' ) n--;
683 zLine[n] = 0;
684 break;
685 }
686 }
687#if defined(_WIN32) || defined(WIN32)
688 /* For interactive input on Windows systems, translate the
689 ** multi-byte characterset characters into UTF-8. */
690 if( stdin_is_interactive && in==stdin ){
691 char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
692 if( zTrans ){
693 int nTrans = strlen30(zTrans)+1;
694 if( nTrans>nLine ){
695 zLine = realloc(zLine, nTrans);
drh884406b2018-07-29 18:56:35 +0000696 if( zLine==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +0000697 }
698 memcpy(zLine, zTrans, nTrans);
699 sqlite3_free(zTrans);
700 }
701 }
702#endif /* defined(_WIN32) || defined(WIN32) */
703 return zLine;
704}
705
706/*
707** Retrieve a single line of input text.
708**
709** If in==0 then read from standard input and prompt before each line.
710** If isContinuation is true, then a continuation prompt is appropriate.
711** If isContinuation is zero, then the main prompt should be used.
712**
713** If zPrior is not NULL then it is a buffer from a prior call to this
714** routine that can be reused.
715**
716** The result is stored in space obtained from malloc() and must either
717** be freed by the caller or else passed back into this routine via the
718** zPrior argument for reuse.
719*/
720static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
721 char *zPrompt;
722 char *zResult;
723 if( in!=0 ){
724 zResult = local_getline(zPrior, in);
725 }else{
726 zPrompt = isContinuation ? continuePrompt : mainPrompt;
727#if SHELL_USE_LOCAL_GETLINE
728 printf("%s", zPrompt);
729 fflush(stdout);
730 zResult = local_getline(zPrior, stdin);
731#else
732 free(zPrior);
733 zResult = shell_readline(zPrompt);
734 if( zResult && *zResult ) shell_add_history(zResult);
735#endif
736 }
737 return zResult;
738}
drh5af06982018-01-10 00:53:55 +0000739
740
741/*
742** Return the value of a hexadecimal digit. Return -1 if the input
743** is not a hex digit.
744*/
745static int hexDigitValue(char c){
746 if( c>='0' && c<='9' ) return c - '0';
747 if( c>='a' && c<='f' ) return c - 'a' + 10;
748 if( c>='A' && c<='F' ) return c - 'A' + 10;
749 return -1;
750}
751
752/*
753** Interpret zArg as an integer value, possibly with suffixes.
754*/
755static sqlite3_int64 integerValue(const char *zArg){
756 sqlite3_int64 v = 0;
757 static const struct { char *zSuffix; int iMult; } aMult[] = {
758 { "KiB", 1024 },
759 { "MiB", 1024*1024 },
760 { "GiB", 1024*1024*1024 },
761 { "KB", 1000 },
762 { "MB", 1000000 },
763 { "GB", 1000000000 },
764 { "K", 1000 },
765 { "M", 1000000 },
766 { "G", 1000000000 },
767 };
768 int i;
769 int isNeg = 0;
770 if( zArg[0]=='-' ){
771 isNeg = 1;
772 zArg++;
773 }else if( zArg[0]=='+' ){
774 zArg++;
775 }
776 if( zArg[0]=='0' && zArg[1]=='x' ){
777 int x;
778 zArg += 2;
779 while( (x = hexDigitValue(zArg[0]))>=0 ){
780 v = (v<<4) + x;
781 zArg++;
782 }
783 }else{
784 while( IsDigit(zArg[0]) ){
785 v = v*10 + zArg[0] - '0';
786 zArg++;
787 }
788 }
789 for(i=0; i<ArraySize(aMult); i++){
790 if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
791 v *= aMult[i].iMult;
792 break;
793 }
794 }
795 return isNeg? -v : v;
796}
797
drh2ce15c32017-07-11 13:34:40 +0000798/*
799** A variable length string to which one can append text.
800*/
801typedef struct ShellText ShellText;
802struct ShellText {
803 char *z;
804 int n;
805 int nAlloc;
806};
807
808/*
809** Initialize and destroy a ShellText object
810*/
811static void initText(ShellText *p){
812 memset(p, 0, sizeof(*p));
813}
814static void freeText(ShellText *p){
815 free(p->z);
816 initText(p);
817}
818
819/* zIn is either a pointer to a NULL-terminated string in memory obtained
820** from malloc(), or a NULL pointer. The string pointed to by zAppend is
821** added to zIn, and the result returned in memory obtained from malloc().
822** zIn, if it was not NULL, is freed.
823**
824** If the third argument, quote, is not '\0', then it is used as a
825** quote character for zAppend.
826*/
827static void appendText(ShellText *p, char const *zAppend, char quote){
828 int len;
829 int i;
830 int nAppend = strlen30(zAppend);
831
832 len = nAppend+p->n+1;
833 if( quote ){
834 len += 2;
835 for(i=0; i<nAppend; i++){
836 if( zAppend[i]==quote ) len++;
837 }
838 }
839
840 if( p->n+len>=p->nAlloc ){
841 p->nAlloc = p->nAlloc*2 + len + 20;
842 p->z = realloc(p->z, p->nAlloc);
drh884406b2018-07-29 18:56:35 +0000843 if( p->z==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +0000844 }
845
846 if( quote ){
847 char *zCsr = p->z+p->n;
848 *zCsr++ = quote;
849 for(i=0; i<nAppend; i++){
850 *zCsr++ = zAppend[i];
851 if( zAppend[i]==quote ) *zCsr++ = quote;
852 }
853 *zCsr++ = quote;
854 p->n = (int)(zCsr - p->z);
855 *zCsr = '\0';
856 }else{
857 memcpy(p->z+p->n, zAppend, nAppend);
858 p->n += nAppend;
859 p->z[p->n] = '\0';
860 }
861}
862
863/*
864** Attempt to determine if identifier zName needs to be quoted, either
865** because it contains non-alphanumeric characters, or because it is an
866** SQLite keyword. Be conservative in this estimate: When in doubt assume
867** that quoting is required.
868**
869** Return '"' if quoting is required. Return 0 if no quoting is required.
870*/
871static char quoteChar(const char *zName){
drhfc0ec3e2018-04-25 19:02:48 +0000872 int i;
drh2ce15c32017-07-11 13:34:40 +0000873 if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
874 for(i=0; zName[i]; i++){
875 if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
876 }
drhfc0ec3e2018-04-25 19:02:48 +0000877 return sqlite3_keyword_check(zName, i) ? '"' : 0;
drh2ce15c32017-07-11 13:34:40 +0000878}
879
880/*
drh667a2a22018-01-02 00:04:37 +0000881** Construct a fake object name and column list to describe the structure
882** of the view, virtual table, or table valued function zSchema.zName.
drhceba7922018-01-01 21:28:25 +0000883*/
drh667a2a22018-01-02 00:04:37 +0000884static char *shellFakeSchema(
drhceba7922018-01-01 21:28:25 +0000885 sqlite3 *db, /* The database connection containing the vtab */
886 const char *zSchema, /* Schema of the database holding the vtab */
887 const char *zName /* The name of the virtual table */
888){
889 sqlite3_stmt *pStmt = 0;
890 char *zSql;
drh1d315cf2018-01-01 21:49:43 +0000891 ShellText s;
892 char cQuote;
893 char *zDiv = "(";
drh667a2a22018-01-02 00:04:37 +0000894 int nRow = 0;
drhceba7922018-01-01 21:28:25 +0000895
drh1d315cf2018-01-01 21:49:43 +0000896 zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
897 zSchema ? zSchema : "main", zName);
drhceba7922018-01-01 21:28:25 +0000898 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
899 sqlite3_free(zSql);
drh1d315cf2018-01-01 21:49:43 +0000900 initText(&s);
901 if( zSchema ){
902 cQuote = quoteChar(zSchema);
903 if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0;
904 appendText(&s, zSchema, cQuote);
905 appendText(&s, ".", 0);
drhceba7922018-01-01 21:28:25 +0000906 }
drh1d315cf2018-01-01 21:49:43 +0000907 cQuote = quoteChar(zName);
908 appendText(&s, zName, cQuote);
909 while( sqlite3_step(pStmt)==SQLITE_ROW ){
910 const char *zCol = (const char*)sqlite3_column_text(pStmt, 1);
drh667a2a22018-01-02 00:04:37 +0000911 nRow++;
drh1d315cf2018-01-01 21:49:43 +0000912 appendText(&s, zDiv, 0);
913 zDiv = ",";
914 cQuote = quoteChar(zCol);
915 appendText(&s, zCol, cQuote);
916 }
917 appendText(&s, ")", 0);
drhceba7922018-01-01 21:28:25 +0000918 sqlite3_finalize(pStmt);
drh667a2a22018-01-02 00:04:37 +0000919 if( nRow==0 ){
920 freeText(&s);
921 s.z = 0;
922 }
drh1d315cf2018-01-01 21:49:43 +0000923 return s.z;
drhceba7922018-01-01 21:28:25 +0000924}
925
926/*
drh667a2a22018-01-02 00:04:37 +0000927** SQL function: shell_module_schema(X)
928**
929** Return a fake schema for the table-valued function or eponymous virtual
930** table X.
931*/
932static void shellModuleSchema(
933 sqlite3_context *pCtx,
934 int nVal,
935 sqlite3_value **apVal
936){
937 const char *zName = (const char*)sqlite3_value_text(apVal[0]);
938 char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName);
drhb9685182018-01-17 13:15:23 +0000939 UNUSED_PARAMETER(nVal);
drh667a2a22018-01-02 00:04:37 +0000940 if( zFake ){
dandcfbff92018-01-08 17:05:32 +0000941 sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
drh667a2a22018-01-02 00:04:37 +0000942 -1, sqlite3_free);
dandcfbff92018-01-08 17:05:32 +0000943 free(zFake);
drh667a2a22018-01-02 00:04:37 +0000944 }
945}
946
947/*
drh2ce15c32017-07-11 13:34:40 +0000948** SQL function: shell_add_schema(S,X)
949**
950** Add the schema name X to the CREATE statement in S and return the result.
951** Examples:
952**
953** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x);
954**
955** Also works on
956**
957** CREATE INDEX
958** CREATE UNIQUE INDEX
959** CREATE VIEW
960** CREATE TRIGGER
961** CREATE VIRTUAL TABLE
962**
963** This UDF is used by the .schema command to insert the schema name of
drh067b92b2020-06-19 15:24:12 +0000964** attached databases into the middle of the sqlite_schema.sql field.
drh2ce15c32017-07-11 13:34:40 +0000965*/
966static void shellAddSchemaName(
967 sqlite3_context *pCtx,
968 int nVal,
969 sqlite3_value **apVal
970){
971 static const char *aPrefix[] = {
972 "TABLE",
973 "INDEX",
974 "UNIQUE INDEX",
975 "VIEW",
976 "TRIGGER",
977 "VIRTUAL TABLE"
978 };
979 int i = 0;
980 const char *zIn = (const char*)sqlite3_value_text(apVal[0]);
981 const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
drh667a2a22018-01-02 00:04:37 +0000982 const char *zName = (const char*)sqlite3_value_text(apVal[2]);
drhceba7922018-01-01 21:28:25 +0000983 sqlite3 *db = sqlite3_context_db_handle(pCtx);
drhb9685182018-01-17 13:15:23 +0000984 UNUSED_PARAMETER(nVal);
drh2ce15c32017-07-11 13:34:40 +0000985 if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
drh37407122021-07-23 18:43:58 +0000986 for(i=0; i<ArraySize(aPrefix); i++){
drh2ce15c32017-07-11 13:34:40 +0000987 int n = strlen30(aPrefix[i]);
988 if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
drhceba7922018-01-01 21:28:25 +0000989 char *z = 0;
drh667a2a22018-01-02 00:04:37 +0000990 char *zFake = 0;
drhceba7922018-01-01 21:28:25 +0000991 if( zSchema ){
992 char cQuote = quoteChar(zSchema);
993 if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){
994 z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8);
995 }else{
996 z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8);
997 }
drh2ce15c32017-07-11 13:34:40 +0000998 }
drh667a2a22018-01-02 00:04:37 +0000999 if( zName
1000 && aPrefix[i][0]=='V'
1001 && (zFake = shellFakeSchema(db, zSchema, zName))!=0
1002 ){
1003 if( z==0 ){
dandcfbff92018-01-08 17:05:32 +00001004 z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake);
drh667a2a22018-01-02 00:04:37 +00001005 }else{
dandcfbff92018-01-08 17:05:32 +00001006 z = sqlite3_mprintf("%z\n/* %s */", z, zFake);
drh667a2a22018-01-02 00:04:37 +00001007 }
dandcfbff92018-01-08 17:05:32 +00001008 free(zFake);
drhceba7922018-01-01 21:28:25 +00001009 }
1010 if( z ){
1011 sqlite3_result_text(pCtx, z, -1, sqlite3_free);
1012 return;
1013 }
drh2ce15c32017-07-11 13:34:40 +00001014 }
1015 }
1016 }
1017 sqlite3_result_value(pCtx, apVal[0]);
1018}
1019
1020/*
1021** The source code for several run-time loadable extensions is inserted
1022** below by the ../tool/mkshellc.tcl script. Before processing that included
1023** code, we need to override some macros to make the included program code
1024** work here in the middle of this regular program.
1025*/
1026#define SQLITE_EXTENSION_INIT1
drh89997982017-07-11 18:11:33 +00001027#define SQLITE_EXTENSION_INIT2(X) (void)(X)
drh2ce15c32017-07-11 13:34:40 +00001028
mistachkinacae8c32018-01-05 20:08:46 +00001029#if defined(_WIN32) && defined(_MSC_VER)
drh03491a12018-01-07 21:58:17 +00001030INCLUDE test_windirent.h
mistachkindfdfd8c2018-01-04 22:46:08 +00001031INCLUDE test_windirent.c
1032#define dirent DIRENT
mistachkindfdfd8c2018-01-04 22:46:08 +00001033#endif
drh2ce15c32017-07-11 13:34:40 +00001034INCLUDE ../ext/misc/shathree.c
1035INCLUDE ../ext/misc/fileio.c
drh56eb09b2017-07-11 13:59:07 +00001036INCLUDE ../ext/misc/completion.c
drh8682e122018-01-07 20:38:10 +00001037INCLUDE ../ext/misc/appendvfs.c
drh50b910a2019-01-21 14:55:03 +00001038INCLUDE ../ext/misc/memtrace.c
drhf05dd032020-04-14 15:53:58 +00001039INCLUDE ../ext/misc/uint.c
drhbeb9def2020-06-22 19:12:23 +00001040INCLUDE ../ext/misc/decimal.c
drh8cda77d2020-06-24 15:06:29 +00001041INCLUDE ../ext/misc/ieee754.c
mistachkin72c38d82020-08-28 18:47:39 +00001042INCLUDE ../ext/misc/series.c
drh64689902021-06-03 13:51:31 +00001043INCLUDE ../ext/misc/regexp.c
dan72afc3c2017-12-05 18:32:40 +00001044#ifdef SQLITE_HAVE_ZLIB
dan9ebfaad2017-12-26 20:39:58 +00001045INCLUDE ../ext/misc/zipfile.c
dand1b51d42017-12-16 19:11:26 +00001046INCLUDE ../ext/misc/sqlar.c
dan72afc3c2017-12-05 18:32:40 +00001047#endif
dan43efc182017-12-19 17:42:13 +00001048INCLUDE ../ext/expert/sqlite3expert.h
1049INCLUDE ../ext/expert/sqlite3expert.c
drh2ce15c32017-07-11 13:34:40 +00001050
dan1b162162019-04-27 20:15:15 +00001051#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00001052INCLUDE ../ext/misc/dbdata.c
dan1b162162019-04-27 20:15:15 +00001053#endif
dan68cb86e2019-04-20 20:57:28 +00001054
drh2ce15c32017-07-11 13:34:40 +00001055#if defined(SQLITE_ENABLE_SESSION)
1056/*
1057** State information for a single open session
1058*/
1059typedef struct OpenSession OpenSession;
1060struct OpenSession {
1061 char *zName; /* Symbolic name for this session */
1062 int nFilter; /* Number of xFilter rejection GLOB patterns */
1063 char **azFilter; /* Array of xFilter rejection GLOB patterns */
1064 sqlite3_session *p; /* The open session */
1065};
1066#endif
1067
dan43efc182017-12-19 17:42:13 +00001068typedef struct ExpertInfo ExpertInfo;
1069struct ExpertInfo {
1070 sqlite3expert *pExpert;
1071 int bVerbose;
1072};
1073
drh4b5345c2018-04-24 13:07:40 +00001074/* A single line in the EQP output */
1075typedef struct EQPGraphRow EQPGraphRow;
1076struct EQPGraphRow {
drhe2ca99c2018-05-02 00:33:43 +00001077 int iEqpId; /* ID for this row */
1078 int iParentId; /* ID of the parent row */
drh4b5345c2018-04-24 13:07:40 +00001079 EQPGraphRow *pNext; /* Next row in sequence */
1080 char zText[1]; /* Text to display for this row */
1081};
1082
1083/* All EQP output is collected into an instance of the following */
1084typedef struct EQPGraph EQPGraph;
1085struct EQPGraph {
1086 EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */
1087 EQPGraphRow *pLast; /* Last element of the pRow list */
1088 char zPrefix[100]; /* Graph prefix */
1089};
1090
drh2ce15c32017-07-11 13:34:40 +00001091/*
1092** State information about the database connection is contained in an
1093** instance of the following structure.
1094*/
1095typedef struct ShellState ShellState;
1096struct ShellState {
1097 sqlite3 *db; /* The database */
drh1fa6d9f2018-01-06 21:46:01 +00001098 u8 autoExplain; /* Automatically turn on .explain mode */
1099 u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
drhe2ca99c2018-05-02 00:33:43 +00001100 u8 autoEQPtest; /* autoEQP is in test mode */
drhb4e50392019-01-26 15:40:04 +00001101 u8 autoEQPtrace; /* autoEQP is in trace mode */
drh1fa6d9f2018-01-06 21:46:01 +00001102 u8 scanstatsOn; /* True to display scan stats before each finalize */
1103 u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
drh13c20932018-01-10 21:41:55 +00001104 u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
drh4b5345c2018-04-24 13:07:40 +00001105 u8 nEqpLevel; /* Depth of the EQP output graph */
drh707821f2018-12-05 13:39:06 +00001106 u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
drhb97e2ad2021-08-26 18:31:39 +00001107 u8 bSafeMode; /* True to prohibit unsafe operations */
1108 u8 bSafeModePersist; /* The long-term value of bSafeMode */
drha6e6cf22021-01-09 19:10:04 +00001109 unsigned statsOn; /* True to display memory stats before each finalize */
drh4b5345c2018-04-24 13:07:40 +00001110 unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */
drh2ce15c32017-07-11 13:34:40 +00001111 int outCount; /* Revert to stdout when reaching zero */
1112 int cnt; /* Number of records displayed so far */
drh2c8ee022018-12-13 18:59:30 +00001113 int lineno; /* Line number of last line read from in */
drh0933aad2019-11-18 17:46:38 +00001114 int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */
drh60379d42018-12-13 18:30:01 +00001115 FILE *in; /* Read commands from this stream */
drh2ce15c32017-07-11 13:34:40 +00001116 FILE *out; /* Write results here */
1117 FILE *traceOut; /* Output for sqlite3_trace() */
1118 int nErr; /* Number of errors seen */
1119 int mode; /* An output mode setting */
drh3c484e82018-01-10 22:27:21 +00001120 int modePrior; /* Saved mode */
drh2ce15c32017-07-11 13:34:40 +00001121 int cMode; /* temporary output mode for the current query */
1122 int normalMode; /* Output mode before ".explain on" */
1123 int writableSchema; /* True if PRAGMA writable_schema=ON */
1124 int showHeader; /* True to show column names in List or Column mode */
1125 int nCheck; /* Number of ".check" commands run */
drh3f83f592019-02-04 14:53:18 +00001126 unsigned nProgress; /* Number of progress callbacks encountered */
1127 unsigned mxProgress; /* Maximum progress callbacks before failing */
1128 unsigned flgProgress; /* Flags for the progress callback */
drh2ce15c32017-07-11 13:34:40 +00001129 unsigned shellFlgs; /* Various flags */
drh7a431002020-04-18 14:12:00 +00001130 unsigned priorShFlgs; /* Saved copy of flags */
drh6ca64482019-01-22 16:06:20 +00001131 sqlite3_int64 szMax; /* --maxsize argument to .open */
drh2ce15c32017-07-11 13:34:40 +00001132 char *zDestTable; /* Name of destination table when MODE_Insert */
drh13c20932018-01-10 21:41:55 +00001133 char *zTempFile; /* Temporary file that might need deleting */
drh2ce15c32017-07-11 13:34:40 +00001134 char zTestcase[30]; /* Name of current test case */
1135 char colSeparator[20]; /* Column separator character for several modes */
1136 char rowSeparator[20]; /* Row separator character for MODE_Ascii */
drh3c484e82018-01-10 22:27:21 +00001137 char colSepPrior[20]; /* Saved column separator */
1138 char rowSepPrior[20]; /* Saved row separator */
drh0285d982020-05-29 14:38:43 +00001139 int *colWidth; /* Requested width of each column in columnar modes */
1140 int *actualWidth; /* Actual width of each column */
1141 int nWidth; /* Number of slots in colWidth[] and actualWidth[] */
drh2ce15c32017-07-11 13:34:40 +00001142 char nullValue[20]; /* The text to print when a NULL comes back from
1143 ** the database */
1144 char outfile[FILENAME_MAX]; /* Filename for *out */
drh2ce15c32017-07-11 13:34:40 +00001145 sqlite3_stmt *pStmt; /* Current statement if any. */
1146 FILE *pLog; /* Write log output here */
drh37407122021-07-23 18:43:58 +00001147 struct AuxDb { /* Storage space for auxiliary database connections */
1148 sqlite3 *db; /* Connection pointer */
1149 const char *zDbFilename; /* Filename used to open the connection */
1150 char *zFreeOnClose; /* Free this memory allocation on close */
1151#if defined(SQLITE_ENABLE_SESSION)
1152 int nSession; /* Number of active sessions */
1153 OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */
1154#endif
1155 } aAuxDb[5], /* Array of all database connections */
1156 *pAuxDb; /* Currently active database connection */
drh2ce15c32017-07-11 13:34:40 +00001157 int *aiIndent; /* Array of indents used in MODE_Explain */
1158 int nIndent; /* Size of array aiIndent[] */
1159 int iIndent; /* Index of current op in aiIndent[] */
drhb97e2ad2021-08-26 18:31:39 +00001160 char *zNonce; /* Nonce for temporary safe-mode excapes */
drh4b5345c2018-04-24 13:07:40 +00001161 EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */
drhb97e2ad2021-08-26 18:31:39 +00001162 ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
drh2ce15c32017-07-11 13:34:40 +00001163};
1164
drh1fa6d9f2018-01-06 21:46:01 +00001165
drhada70452017-12-21 21:02:27 +00001166/* Allowed values for ShellState.autoEQP
1167*/
drhe2ca99c2018-05-02 00:33:43 +00001168#define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */
1169#define AUTOEQP_on 1 /* Automatic EQP is on */
1170#define AUTOEQP_trigger 2 /* On and also show plans for triggers */
1171#define AUTOEQP_full 3 /* Show full EXPLAIN */
drhada70452017-12-21 21:02:27 +00001172
drh1fa6d9f2018-01-06 21:46:01 +00001173/* Allowed values for ShellState.openMode
1174*/
drh60f34ae2018-10-30 13:19:49 +00001175#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
1176#define SHELL_OPEN_NORMAL 1 /* Normal database file */
1177#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
1178#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
1179#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
1180#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
drh33746482018-12-13 15:06:26 +00001181#define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */
drh1fa6d9f2018-01-06 21:46:01 +00001182
drh707821f2018-12-05 13:39:06 +00001183/* Allowed values for ShellState.eTraceType
1184*/
1185#define SHELL_TRACE_PLAIN 0 /* Show input SQL text */
1186#define SHELL_TRACE_EXPANDED 1 /* Show expanded SQL text */
1187#define SHELL_TRACE_NORMALIZED 2 /* Show normalized SQL text */
1188
drh3f83f592019-02-04 14:53:18 +00001189/* Bits in the ShellState.flgProgress variable */
drhfc4eeef2019-02-05 19:48:46 +00001190#define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */
1191#define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progres
1192 ** callback limit is reached, and for each
1193 ** top-level SQL statement */
1194#define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */
drh3f83f592019-02-04 14:53:18 +00001195
drh2ce15c32017-07-11 13:34:40 +00001196/*
1197** These are the allowed shellFlgs values
1198*/
drhb2a0f752017-08-28 15:51:35 +00001199#define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */
1200#define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */
1201#define SHFLG_Backslash 0x00000004 /* The --backslash option is used */
1202#define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */
1203#define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
1204#define SHFLG_CountChanges 0x00000020 /* .changes setting */
1205#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
drhc0605082020-06-05 00:54:27 +00001206#define SHFLG_HeaderSet 0x00000080 /* .header has been used */
drhc1962192020-10-12 16:54:28 +00001207#define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */
1208#define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */
drh2ce15c32017-07-11 13:34:40 +00001209
1210/*
1211** Macros for testing and setting shellFlgs
1212*/
1213#define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0)
1214#define ShellSetFlag(P,X) ((P)->shellFlgs|=(X))
1215#define ShellClearFlag(P,X) ((P)->shellFlgs&=(~(X)))
1216
1217/*
1218** These are the allowed modes.
1219*/
1220#define MODE_Line 0 /* One column per line. Blank line between records */
1221#define MODE_Column 1 /* One record per line in neat columns */
1222#define MODE_List 2 /* One record per line with a separator */
1223#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
1224#define MODE_Html 4 /* Generate an XHTML table */
1225#define MODE_Insert 5 /* Generate SQL "insert" statements */
1226#define MODE_Quote 6 /* Quote values as for SQL */
1227#define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */
1228#define MODE_Csv 8 /* Quote strings, numbers are plain */
1229#define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */
1230#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
1231#define MODE_Pretty 11 /* Pretty-print schemas */
drh4b5345c2018-04-24 13:07:40 +00001232#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
drh30c54a02020-05-28 23:49:50 +00001233#define MODE_Json 13 /* Output JSON */
1234#define MODE_Markdown 14 /* Markdown formatting */
1235#define MODE_Table 15 /* MySQL-style table formatting */
drh0908e382020-06-04 18:05:39 +00001236#define MODE_Box 16 /* Unicode box-drawing characters */
drh2ce15c32017-07-11 13:34:40 +00001237
1238static const char *modeDescr[] = {
1239 "line",
1240 "column",
1241 "list",
1242 "semi",
1243 "html",
1244 "insert",
1245 "quote",
1246 "tcl",
1247 "csv",
1248 "explain",
1249 "ascii",
1250 "prettyprint",
drh30c54a02020-05-28 23:49:50 +00001251 "eqp",
1252 "json",
1253 "markdown",
drh0908e382020-06-04 18:05:39 +00001254 "table",
1255 "box"
drh2ce15c32017-07-11 13:34:40 +00001256};
1257
1258/*
1259** These are the column/row/line separators used by the various
1260** import/export modes.
1261*/
1262#define SEP_Column "|"
1263#define SEP_Row "\n"
1264#define SEP_Tab "\t"
1265#define SEP_Space " "
1266#define SEP_Comma ","
1267#define SEP_CrLf "\r\n"
1268#define SEP_Unit "\x1F"
1269#define SEP_Record "\x1E"
1270
1271/*
drh2ce15c32017-07-11 13:34:40 +00001272** A callback for the sqlite3_log() interface.
1273*/
1274static void shellLog(void *pArg, int iErrCode, const char *zMsg){
1275 ShellState *p = (ShellState*)pArg;
1276 if( p->pLog==0 ) return;
1277 utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
1278 fflush(p->pLog);
1279}
1280
1281/*
drh634c70f2018-01-10 16:50:18 +00001282** SQL function: shell_putsnl(X)
1283**
1284** Write the text X to the screen (or whatever output is being directed)
1285** adding a newline at the end, and then return X.
1286*/
1287static void shellPutsFunc(
1288 sqlite3_context *pCtx,
1289 int nVal,
1290 sqlite3_value **apVal
1291){
1292 ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
drhb9685182018-01-17 13:15:23 +00001293 (void)nVal;
drh634c70f2018-01-10 16:50:18 +00001294 utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
1295 sqlite3_result_value(pCtx, apVal[0]);
1296}
1297
1298/*
drhb97e2ad2021-08-26 18:31:39 +00001299** If in safe mode, print an error message described by the arguments
1300** and exit immediately.
1301*/
1302static void failIfSafeMode(
1303 ShellState *p,
1304 const char *zErrMsg,
1305 ...
1306){
1307 if( p->bSafeMode ){
1308 va_list ap;
1309 char *zMsg;
1310 va_start(ap, zErrMsg);
1311 zMsg = sqlite3_vmprintf(zErrMsg, ap);
1312 va_end(ap);
1313 raw_printf(stderr, "line %d: ", p->lineno);
1314 utf8_printf(stderr, "%s\n", zMsg);
1315 exit(1);
1316 }
1317}
1318
1319/*
drh97913132018-01-11 00:04:00 +00001320** SQL function: edit(VALUE)
1321** edit(VALUE,EDITOR)
1322**
1323** These steps:
1324**
1325** (1) Write VALUE into a temporary file.
1326** (2) Run program EDITOR on that temporary file.
1327** (3) Read the temporary file back and return its content as the result.
1328** (4) Delete the temporary file
1329**
1330** If the EDITOR argument is omitted, use the value in the VISUAL
1331** environment variable. If still there is no EDITOR, through an error.
1332**
1333** Also throw an error if the EDITOR program returns a non-zero exit code.
1334*/
drh04a28c32018-01-31 01:38:44 +00001335#ifndef SQLITE_NOHAVE_SYSTEM
drh97913132018-01-11 00:04:00 +00001336static void editFunc(
1337 sqlite3_context *context,
1338 int argc,
1339 sqlite3_value **argv
1340){
1341 const char *zEditor;
1342 char *zTempFile = 0;
1343 sqlite3 *db;
1344 char *zCmd = 0;
1345 int bBin;
1346 int rc;
drhf018fd52018-08-06 02:08:53 +00001347 int hasCRNL = 0;
drh97913132018-01-11 00:04:00 +00001348 FILE *f = 0;
1349 sqlite3_int64 sz;
1350 sqlite3_int64 x;
1351 unsigned char *p = 0;
1352
1353 if( argc==2 ){
1354 zEditor = (const char*)sqlite3_value_text(argv[1]);
1355 }else{
1356 zEditor = getenv("VISUAL");
1357 }
1358 if( zEditor==0 ){
1359 sqlite3_result_error(context, "no editor for edit()", -1);
1360 return;
1361 }
1362 if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
1363 sqlite3_result_error(context, "NULL input to edit()", -1);
1364 return;
1365 }
1366 db = sqlite3_context_db_handle(context);
1367 zTempFile = 0;
1368 sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile);
1369 if( zTempFile==0 ){
1370 sqlite3_uint64 r = 0;
1371 sqlite3_randomness(sizeof(r), &r);
1372 zTempFile = sqlite3_mprintf("temp%llx", r);
1373 if( zTempFile==0 ){
1374 sqlite3_result_error_nomem(context);
1375 return;
1376 }
1377 }
1378 bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB;
drhf018fd52018-08-06 02:08:53 +00001379 /* When writing the file to be edited, do \n to \r\n conversions on systems
1380 ** that want \r\n line endings */
drh97913132018-01-11 00:04:00 +00001381 f = fopen(zTempFile, bBin ? "wb" : "w");
1382 if( f==0 ){
1383 sqlite3_result_error(context, "edit() cannot open temp file", -1);
1384 goto edit_func_end;
1385 }
1386 sz = sqlite3_value_bytes(argv[0]);
1387 if( bBin ){
dan4d02b5f2019-07-17 07:23:06 +00001388 x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001389 }else{
drhf018fd52018-08-06 02:08:53 +00001390 const char *z = (const char*)sqlite3_value_text(argv[0]);
1391 /* Remember whether or not the value originally contained \r\n */
1392 if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
dan4d02b5f2019-07-17 07:23:06 +00001393 x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001394 }
1395 fclose(f);
1396 f = 0;
1397 if( x!=sz ){
1398 sqlite3_result_error(context, "edit() could not write the whole file", -1);
1399 goto edit_func_end;
1400 }
1401 zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile);
1402 if( zCmd==0 ){
1403 sqlite3_result_error_nomem(context);
1404 goto edit_func_end;
1405 }
1406 rc = system(zCmd);
1407 sqlite3_free(zCmd);
1408 if( rc ){
1409 sqlite3_result_error(context, "EDITOR returned non-zero", -1);
1410 goto edit_func_end;
1411 }
drhf018fd52018-08-06 02:08:53 +00001412 f = fopen(zTempFile, "rb");
drh97913132018-01-11 00:04:00 +00001413 if( f==0 ){
1414 sqlite3_result_error(context,
1415 "edit() cannot reopen temp file after edit", -1);
1416 goto edit_func_end;
1417 }
1418 fseek(f, 0, SEEK_END);
1419 sz = ftell(f);
1420 rewind(f);
drhee37f8b2019-08-23 23:05:32 +00001421 p = sqlite3_malloc64( sz+1 );
drh97913132018-01-11 00:04:00 +00001422 if( p==0 ){
1423 sqlite3_result_error_nomem(context);
1424 goto edit_func_end;
1425 }
dan4d02b5f2019-07-17 07:23:06 +00001426 x = fread(p, 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001427 fclose(f);
1428 f = 0;
1429 if( x!=sz ){
1430 sqlite3_result_error(context, "could not read back the whole file", -1);
1431 goto edit_func_end;
1432 }
1433 if( bBin ){
mistachkinb71aa092018-01-23 00:05:18 +00001434 sqlite3_result_blob64(context, p, sz, sqlite3_free);
drh97913132018-01-11 00:04:00 +00001435 }else{
dan60bdcf52018-10-03 11:13:30 +00001436 sqlite3_int64 i, j;
drhf018fd52018-08-06 02:08:53 +00001437 if( hasCRNL ){
1438 /* If the original contains \r\n then do no conversions back to \n */
1439 j = sz;
1440 }else{
1441 /* If the file did not originally contain \r\n then convert any new
1442 ** \r\n back into \n */
1443 for(i=j=0; i<sz; i++){
1444 if( p[i]=='\r' && p[i+1]=='\n' ) i++;
1445 p[j++] = p[i];
1446 }
1447 sz = j;
1448 p[sz] = 0;
1449 }
mistachkinb71aa092018-01-23 00:05:18 +00001450 sqlite3_result_text64(context, (const char*)p, sz,
1451 sqlite3_free, SQLITE_UTF8);
drh97913132018-01-11 00:04:00 +00001452 }
1453 p = 0;
1454
1455edit_func_end:
1456 if( f ) fclose(f);
1457 unlink(zTempFile);
1458 sqlite3_free(zTempFile);
1459 sqlite3_free(p);
1460}
drh04a28c32018-01-31 01:38:44 +00001461#endif /* SQLITE_NOHAVE_SYSTEM */
drh97913132018-01-11 00:04:00 +00001462
1463/*
drh3c484e82018-01-10 22:27:21 +00001464** Save or restore the current output mode
1465*/
1466static void outputModePush(ShellState *p){
1467 p->modePrior = p->mode;
drh7a431002020-04-18 14:12:00 +00001468 p->priorShFlgs = p->shellFlgs;
drh3c484e82018-01-10 22:27:21 +00001469 memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));
1470 memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));
1471}
1472static void outputModePop(ShellState *p){
1473 p->mode = p->modePrior;
drh7a431002020-04-18 14:12:00 +00001474 p->shellFlgs = p->priorShFlgs;
drh3c484e82018-01-10 22:27:21 +00001475 memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
1476 memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
1477}
1478
1479/*
drh2ce15c32017-07-11 13:34:40 +00001480** Output the given string as a hex-encoded blob (eg. X'1234' )
1481*/
1482static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
1483 int i;
1484 char *zBlob = (char *)pBlob;
1485 raw_printf(out,"X'");
1486 for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); }
1487 raw_printf(out,"'");
1488}
1489
1490/*
1491** Find a string that is not found anywhere in z[]. Return a pointer
1492** to that string.
1493**
1494** Try to use zA and zB first. If both of those are already found in z[]
1495** then make up some string and store it in the buffer zBuf.
1496*/
1497static const char *unused_string(
1498 const char *z, /* Result must not appear anywhere in z */
1499 const char *zA, const char *zB, /* Try these first */
1500 char *zBuf /* Space to store a generated string */
1501){
1502 unsigned i = 0;
1503 if( strstr(z, zA)==0 ) return zA;
1504 if( strstr(z, zB)==0 ) return zB;
1505 do{
1506 sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
1507 }while( strstr(z,zBuf)!=0 );
1508 return zBuf;
1509}
1510
1511/*
1512** Output the given string as a quoted string using SQL quoting conventions.
1513**
1514** See also: output_quoted_escaped_string()
1515*/
1516static void output_quoted_string(FILE *out, const char *z){
1517 int i;
1518 char c;
1519 setBinaryMode(out, 1);
1520 for(i=0; (c = z[i])!=0 && c!='\''; i++){}
1521 if( c==0 ){
1522 utf8_printf(out,"'%s'",z);
1523 }else{
1524 raw_printf(out, "'");
1525 while( *z ){
1526 for(i=0; (c = z[i])!=0 && c!='\''; i++){}
1527 if( c=='\'' ) i++;
1528 if( i ){
1529 utf8_printf(out, "%.*s", i, z);
1530 z += i;
1531 }
1532 if( c=='\'' ){
1533 raw_printf(out, "'");
1534 continue;
1535 }
1536 if( c==0 ){
1537 break;
1538 }
1539 z++;
1540 }
1541 raw_printf(out, "'");
1542 }
1543 setTextMode(out, 1);
1544}
1545
1546/*
1547** Output the given string as a quoted string using SQL quoting conventions.
1548** Additionallly , escape the "\n" and "\r" characters so that they do not
1549** get corrupted by end-of-line translation facilities in some operating
1550** systems.
1551**
1552** This is like output_quoted_string() but with the addition of the \r\n
1553** escape mechanism.
1554*/
1555static void output_quoted_escaped_string(FILE *out, const char *z){
1556 int i;
1557 char c;
1558 setBinaryMode(out, 1);
1559 for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
1560 if( c==0 ){
1561 utf8_printf(out,"'%s'",z);
1562 }else{
1563 const char *zNL = 0;
1564 const char *zCR = 0;
1565 int nNL = 0;
1566 int nCR = 0;
1567 char zBuf1[20], zBuf2[20];
1568 for(i=0; z[i]; i++){
1569 if( z[i]=='\n' ) nNL++;
1570 if( z[i]=='\r' ) nCR++;
1571 }
1572 if( nNL ){
1573 raw_printf(out, "replace(");
1574 zNL = unused_string(z, "\\n", "\\012", zBuf1);
1575 }
1576 if( nCR ){
1577 raw_printf(out, "replace(");
1578 zCR = unused_string(z, "\\r", "\\015", zBuf2);
1579 }
1580 raw_printf(out, "'");
1581 while( *z ){
1582 for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
1583 if( c=='\'' ) i++;
1584 if( i ){
1585 utf8_printf(out, "%.*s", i, z);
1586 z += i;
1587 }
1588 if( c=='\'' ){
1589 raw_printf(out, "'");
1590 continue;
1591 }
1592 if( c==0 ){
1593 break;
1594 }
1595 z++;
1596 if( c=='\n' ){
1597 raw_printf(out, "%s", zNL);
1598 continue;
1599 }
1600 raw_printf(out, "%s", zCR);
1601 }
1602 raw_printf(out, "'");
1603 if( nCR ){
1604 raw_printf(out, ",'%s',char(13))", zCR);
1605 }
1606 if( nNL ){
1607 raw_printf(out, ",'%s',char(10))", zNL);
1608 }
1609 }
1610 setTextMode(out, 1);
1611}
1612
1613/*
1614** Output the given string as a quoted according to C or TCL quoting rules.
1615*/
1616static void output_c_string(FILE *out, const char *z){
1617 unsigned int c;
1618 fputc('"', out);
1619 while( (c = *(z++))!=0 ){
1620 if( c=='\\' ){
1621 fputc(c, out);
1622 fputc(c, out);
1623 }else if( c=='"' ){
1624 fputc('\\', out);
1625 fputc('"', out);
1626 }else if( c=='\t' ){
1627 fputc('\\', out);
1628 fputc('t', out);
1629 }else if( c=='\n' ){
1630 fputc('\\', out);
1631 fputc('n', out);
1632 }else if( c=='\r' ){
1633 fputc('\\', out);
1634 fputc('r', out);
1635 }else if( !isprint(c&0xff) ){
1636 raw_printf(out, "\\%03o", c&0xff);
1637 }else{
1638 fputc(c, out);
1639 }
1640 }
1641 fputc('"', out);
1642}
1643
1644/*
drh69c093d2020-05-29 00:21:43 +00001645** Output the given string as a quoted according to JSON quoting rules.
1646*/
1647static void output_json_string(FILE *out, const char *z, int n){
1648 unsigned int c;
1649 if( n<0 ) n = (int)strlen(z);
1650 fputc('"', out);
1651 while( n-- ){
1652 c = *(z++);
1653 if( c=='\\' || c=='"' ){
1654 fputc('\\', out);
1655 fputc(c, out);
1656 }else if( c<=0x1f ){
1657 fputc('\\', out);
1658 if( c=='\b' ){
1659 fputc('b', out);
1660 }else if( c=='\f' ){
1661 fputc('f', out);
1662 }else if( c=='\n' ){
1663 fputc('n', out);
1664 }else if( c=='\r' ){
1665 fputc('r', out);
1666 }else if( c=='\t' ){
1667 fputc('t', out);
1668 }else{
1669 raw_printf(out, "u%04x",c);
1670 }
1671 }else{
1672 fputc(c, out);
1673 }
1674 }
1675 fputc('"', out);
1676}
1677
1678/*
drh2ce15c32017-07-11 13:34:40 +00001679** Output the given string with characters that are special to
1680** HTML escaped.
1681*/
1682static void output_html_string(FILE *out, const char *z){
1683 int i;
1684 if( z==0 ) z = "";
1685 while( *z ){
1686 for(i=0; z[i]
1687 && z[i]!='<'
1688 && z[i]!='&'
1689 && z[i]!='>'
1690 && z[i]!='\"'
1691 && z[i]!='\'';
1692 i++){}
1693 if( i>0 ){
1694 utf8_printf(out,"%.*s",i,z);
1695 }
1696 if( z[i]=='<' ){
1697 raw_printf(out,"&lt;");
1698 }else if( z[i]=='&' ){
1699 raw_printf(out,"&amp;");
1700 }else if( z[i]=='>' ){
1701 raw_printf(out,"&gt;");
1702 }else if( z[i]=='\"' ){
1703 raw_printf(out,"&quot;");
1704 }else if( z[i]=='\'' ){
1705 raw_printf(out,"&#39;");
1706 }else{
1707 break;
1708 }
1709 z += i + 1;
1710 }
1711}
1712
1713/*
1714** If a field contains any character identified by a 1 in the following
1715** array, then the string must be quoted for CSV.
1716*/
1717static const char needCsvQuote[] = {
1718 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1719 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1720 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1721 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1722 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1723 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1724 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1725 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1726 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1727 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1728 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1729 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1730 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1731 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1732 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1733 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1734};
1735
1736/*
1737** Output a single term of CSV. Actually, p->colSeparator is used for
1738** the separator, which may or may not be a comma. p->nullValue is
1739** the null value. Strings are quoted if necessary. The separator
1740** is only issued if bSep is true.
1741*/
1742static void output_csv(ShellState *p, const char *z, int bSep){
1743 FILE *out = p->out;
1744 if( z==0 ){
1745 utf8_printf(out,"%s",p->nullValue);
1746 }else{
1747 int i;
1748 int nSep = strlen30(p->colSeparator);
1749 for(i=0; z[i]; i++){
1750 if( needCsvQuote[((unsigned char*)z)[i]]
1751 || (z[i]==p->colSeparator[0] &&
1752 (nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){
1753 i = 0;
1754 break;
1755 }
1756 }
1757 if( i==0 ){
drh9b7affc2017-11-26 02:14:18 +00001758 char *zQuoted = sqlite3_mprintf("\"%w\"", z);
1759 utf8_printf(out, "%s", zQuoted);
1760 sqlite3_free(zQuoted);
drh2ce15c32017-07-11 13:34:40 +00001761 }else{
1762 utf8_printf(out, "%s", z);
1763 }
1764 }
1765 if( bSep ){
1766 utf8_printf(p->out, "%s", p->colSeparator);
1767 }
1768}
1769
drh2ce15c32017-07-11 13:34:40 +00001770/*
1771** This routine runs when the user presses Ctrl-C
1772*/
1773static void interrupt_handler(int NotUsed){
1774 UNUSED_PARAMETER(NotUsed);
1775 seenInterrupt++;
1776 if( seenInterrupt>2 ) exit(1);
1777 if( globalDb ) sqlite3_interrupt(globalDb);
1778}
mistachkinb4bab902017-10-27 17:09:44 +00001779
1780#if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
1781/*
1782** This routine runs for console events (e.g. Ctrl-C) on Win32
1783*/
1784static BOOL WINAPI ConsoleCtrlHandler(
1785 DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */
1786){
1787 if( dwCtrlType==CTRL_C_EVENT ){
1788 interrupt_handler(0);
1789 return TRUE;
1790 }
1791 return FALSE;
1792}
drh2ce15c32017-07-11 13:34:40 +00001793#endif
1794
1795#ifndef SQLITE_OMIT_AUTHORIZATION
1796/*
drhb97e2ad2021-08-26 18:31:39 +00001797** This authorizer runs in safe mode.
1798*/
1799static int safeModeAuth(
1800 void *pClientData,
1801 int op,
1802 const char *zA1,
1803 const char *zA2,
1804 const char *zA3,
1805 const char *zA4
1806){
1807 ShellState *p = (ShellState*)pClientData;
1808 static const char *azProhibitedFunctions[] = {
1809 "edit",
1810 "fts3_tokenizer",
1811 "load_extension",
1812 "readfile",
1813 "writefile",
1814 "zipfile",
1815 "zipfile_cds",
1816 };
1817 UNUSED_PARAMETER(zA2);
1818 UNUSED_PARAMETER(zA3);
1819 UNUSED_PARAMETER(zA4);
1820 switch( op ){
1821 case SQLITE_ATTACH: {
1822 failIfSafeMode(p, "cannot run ATTACH in safe mode");
1823 break;
1824 }
1825 case SQLITE_FUNCTION: {
1826 int i;
1827 for(i=0; i<ArraySize(azProhibitedFunctions); i++){
1828 if( sqlite3_stricmp(zA1, azProhibitedFunctions[i])==0 ){
1829 failIfSafeMode(p, "cannot use the %s() function in safe mode",
1830 azProhibitedFunctions[i]);
1831 }
1832 }
1833 break;
1834 }
1835 }
1836 return SQLITE_OK;
1837}
1838
1839/*
drh2ce15c32017-07-11 13:34:40 +00001840** When the ".auth ON" is set, the following authorizer callback is
1841** invoked. It always returns SQLITE_OK.
1842*/
1843static int shellAuth(
1844 void *pClientData,
1845 int op,
1846 const char *zA1,
1847 const char *zA2,
1848 const char *zA3,
1849 const char *zA4
1850){
1851 ShellState *p = (ShellState*)pClientData;
1852 static const char *azAction[] = { 0,
1853 "CREATE_INDEX", "CREATE_TABLE", "CREATE_TEMP_INDEX",
1854 "CREATE_TEMP_TABLE", "CREATE_TEMP_TRIGGER", "CREATE_TEMP_VIEW",
1855 "CREATE_TRIGGER", "CREATE_VIEW", "DELETE",
1856 "DROP_INDEX", "DROP_TABLE", "DROP_TEMP_INDEX",
1857 "DROP_TEMP_TABLE", "DROP_TEMP_TRIGGER", "DROP_TEMP_VIEW",
1858 "DROP_TRIGGER", "DROP_VIEW", "INSERT",
1859 "PRAGMA", "READ", "SELECT",
1860 "TRANSACTION", "UPDATE", "ATTACH",
1861 "DETACH", "ALTER_TABLE", "REINDEX",
1862 "ANALYZE", "CREATE_VTABLE", "DROP_VTABLE",
1863 "FUNCTION", "SAVEPOINT", "RECURSIVE"
1864 };
1865 int i;
1866 const char *az[4];
1867 az[0] = zA1;
1868 az[1] = zA2;
1869 az[2] = zA3;
1870 az[3] = zA4;
1871 utf8_printf(p->out, "authorizer: %s", azAction[op]);
1872 for(i=0; i<4; i++){
1873 raw_printf(p->out, " ");
1874 if( az[i] ){
1875 output_c_string(p->out, az[i]);
1876 }else{
1877 raw_printf(p->out, "NULL");
1878 }
1879 }
1880 raw_printf(p->out, "\n");
drhb97e2ad2021-08-26 18:31:39 +00001881 if( p->bSafeMode ) (void)safeModeAuth(pClientData, op, zA1, zA2, zA3, zA4);
drh2ce15c32017-07-11 13:34:40 +00001882 return SQLITE_OK;
1883}
1884#endif
1885
1886/*
1887** Print a schema statement. Part of MODE_Semi and MODE_Pretty output.
1888**
1889** This routine converts some CREATE TABLE statements for shadow tables
1890** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
1891*/
1892static void printSchemaLine(FILE *out, const char *z, const char *zTail){
drh0a0536a2019-05-09 18:13:30 +00001893 if( z==0 ) return;
1894 if( zTail==0 ) return;
drh2ce15c32017-07-11 13:34:40 +00001895 if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
1896 utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
1897 }else{
1898 utf8_printf(out, "%s%s", z, zTail);
1899 }
1900}
1901static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
1902 char c = z[n];
1903 z[n] = 0;
1904 printSchemaLine(out, z, zTail);
1905 z[n] = c;
1906}
1907
1908/*
drh11be81d2018-01-06 15:46:20 +00001909** Return true if string z[] has nothing but whitespace and comments to the
1910** end of the first line.
1911*/
1912static int wsToEol(const char *z){
1913 int i;
1914 for(i=0; z[i]; i++){
1915 if( z[i]=='\n' ) return 1;
1916 if( IsSpace(z[i]) ) continue;
1917 if( z[i]=='-' && z[i+1]=='-' ) return 1;
1918 return 0;
1919 }
1920 return 1;
1921}
drh4b5345c2018-04-24 13:07:40 +00001922
1923/*
1924** Add a new entry to the EXPLAIN QUERY PLAN data
1925*/
drhe2ca99c2018-05-02 00:33:43 +00001926static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
drh4b5345c2018-04-24 13:07:40 +00001927 EQPGraphRow *pNew;
1928 int nText = strlen30(zText);
drhe2ca99c2018-05-02 00:33:43 +00001929 if( p->autoEQPtest ){
1930 utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
1931 }
drh4b5345c2018-04-24 13:07:40 +00001932 pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
1933 if( pNew==0 ) shell_out_of_memory();
drhe2ca99c2018-05-02 00:33:43 +00001934 pNew->iEqpId = iEqpId;
1935 pNew->iParentId = p2;
drh4b5345c2018-04-24 13:07:40 +00001936 memcpy(pNew->zText, zText, nText+1);
1937 pNew->pNext = 0;
1938 if( p->sGraph.pLast ){
1939 p->sGraph.pLast->pNext = pNew;
1940 }else{
1941 p->sGraph.pRow = pNew;
1942 }
1943 p->sGraph.pLast = pNew;
1944}
1945
1946/*
1947** Free and reset the EXPLAIN QUERY PLAN data that has been collected
1948** in p->sGraph.
1949*/
1950static void eqp_reset(ShellState *p){
1951 EQPGraphRow *pRow, *pNext;
1952 for(pRow = p->sGraph.pRow; pRow; pRow = pNext){
1953 pNext = pRow->pNext;
1954 sqlite3_free(pRow);
1955 }
1956 memset(&p->sGraph, 0, sizeof(p->sGraph));
1957}
1958
drhe2ca99c2018-05-02 00:33:43 +00001959/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after
drh4b5345c2018-04-24 13:07:40 +00001960** pOld, or return the first such line if pOld is NULL
1961*/
drhe2ca99c2018-05-02 00:33:43 +00001962static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){
drh4b5345c2018-04-24 13:07:40 +00001963 EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow;
drhe2ca99c2018-05-02 00:33:43 +00001964 while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext;
drh4b5345c2018-04-24 13:07:40 +00001965 return pRow;
1966}
1967
drhe2ca99c2018-05-02 00:33:43 +00001968/* Render a single level of the graph that has iEqpId as its parent. Called
drh4b5345c2018-04-24 13:07:40 +00001969** recursively to render sublevels.
1970*/
drhe2ca99c2018-05-02 00:33:43 +00001971static void eqp_render_level(ShellState *p, int iEqpId){
drh4b5345c2018-04-24 13:07:40 +00001972 EQPGraphRow *pRow, *pNext;
drh4b5345c2018-04-24 13:07:40 +00001973 int n = strlen30(p->sGraph.zPrefix);
1974 char *z;
drhe2ca99c2018-05-02 00:33:43 +00001975 for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
1976 pNext = eqp_next_row(p, iEqpId, pRow);
drh4b5345c2018-04-24 13:07:40 +00001977 z = pRow->zText;
drhe2754c12019-08-26 12:50:01 +00001978 utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
1979 pNext ? "|--" : "`--", z);
drhe2188f02018-05-07 11:37:34 +00001980 if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){
drh4b5345c2018-04-24 13:07:40 +00001981 memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4);
drhe2ca99c2018-05-02 00:33:43 +00001982 eqp_render_level(p, pRow->iEqpId);
drh4b5345c2018-04-24 13:07:40 +00001983 p->sGraph.zPrefix[n] = 0;
1984 }
1985 }
1986}
1987
1988/*
1989** Display and reset the EXPLAIN QUERY PLAN data
1990*/
1991static void eqp_render(ShellState *p){
1992 EQPGraphRow *pRow = p->sGraph.pRow;
1993 if( pRow ){
1994 if( pRow->zText[0]=='-' ){
1995 if( pRow->pNext==0 ){
1996 eqp_reset(p);
1997 return;
1998 }
1999 utf8_printf(p->out, "%s\n", pRow->zText+3);
2000 p->sGraph.pRow = pRow->pNext;
2001 sqlite3_free(pRow);
2002 }else{
2003 utf8_printf(p->out, "QUERY PLAN\n");
2004 }
2005 p->sGraph.zPrefix[0] = 0;
2006 eqp_render_level(p, 0);
2007 eqp_reset(p);
2008 }
2009}
drh11be81d2018-01-06 15:46:20 +00002010
drh569b1d92019-02-05 20:51:41 +00002011#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh11be81d2018-01-06 15:46:20 +00002012/*
drh3f83f592019-02-04 14:53:18 +00002013** Progress handler callback.
2014*/
2015static int progress_handler(void *pClientData) {
2016 ShellState *p = (ShellState*)pClientData;
2017 p->nProgress++;
2018 if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
2019 raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
drhfc4eeef2019-02-05 19:48:46 +00002020 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
2021 if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
drh3f83f592019-02-04 14:53:18 +00002022 return 1;
2023 }
drhfc4eeef2019-02-05 19:48:46 +00002024 if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
drh3f83f592019-02-04 14:53:18 +00002025 raw_printf(p->out, "Progress %u\n", p->nProgress);
2026 }
2027 return 0;
2028}
drh569b1d92019-02-05 20:51:41 +00002029#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
drh3f83f592019-02-04 14:53:18 +00002030
2031/*
drh30c54a02020-05-28 23:49:50 +00002032** Print N dashes
2033*/
2034static void print_dashes(FILE *out, int N){
2035 const char zDash[] = "--------------------------------------------------";
2036 const int nDash = sizeof(zDash) - 1;
2037 while( N>nDash ){
2038 fputs(zDash, out);
2039 N -= nDash;
2040 }
2041 raw_printf(out, "%.*s", N, zDash);
2042}
2043
2044/*
drh0908e382020-06-04 18:05:39 +00002045** Print a markdown or table-style row separator using ascii-art
drh30c54a02020-05-28 23:49:50 +00002046*/
2047static void print_row_separator(
2048 ShellState *p,
2049 int nArg,
2050 const char *zSep
2051){
2052 int i;
drh0908e382020-06-04 18:05:39 +00002053 if( nArg>0 ){
drh30c54a02020-05-28 23:49:50 +00002054 fputs(zSep, p->out);
drh0908e382020-06-04 18:05:39 +00002055 print_dashes(p->out, p->actualWidth[0]+2);
2056 for(i=1; i<nArg; i++){
2057 fputs(zSep, p->out);
2058 print_dashes(p->out, p->actualWidth[i]+2);
2059 }
2060 fputs(zSep, p->out);
drh30c54a02020-05-28 23:49:50 +00002061 }
drh30c54a02020-05-28 23:49:50 +00002062 fputs("\n", p->out);
2063}
2064
2065/*
drh2ce15c32017-07-11 13:34:40 +00002066** This is the callback routine that the shell
2067** invokes for each row of a query result.
2068*/
2069static int shell_callback(
2070 void *pArg,
2071 int nArg, /* Number of result columns */
2072 char **azArg, /* Text of each result column */
2073 char **azCol, /* Column names */
drhd6f25242020-05-29 12:31:53 +00002074 int *aiType /* Column types. Might be NULL */
drh2ce15c32017-07-11 13:34:40 +00002075){
2076 int i;
2077 ShellState *p = (ShellState*)pArg;
2078
drhb3c45232017-08-28 14:33:27 +00002079 if( azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00002080 switch( p->cMode ){
2081 case MODE_Line: {
2082 int w = 5;
2083 if( azArg==0 ) break;
2084 for(i=0; i<nArg; i++){
2085 int len = strlen30(azCol[i] ? azCol[i] : "");
2086 if( len>w ) w = len;
2087 }
2088 if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
2089 for(i=0; i<nArg; i++){
2090 utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
2091 azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
2092 }
2093 break;
2094 }
drh8c748632020-05-29 16:15:58 +00002095 case MODE_Explain: {
2096 static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
2097 if( nArg>ArraySize(aExplainWidth) ){
2098 nArg = ArraySize(aExplainWidth);
drh2ce15c32017-07-11 13:34:40 +00002099 }
2100 if( p->cnt++==0 ){
2101 for(i=0; i<nArg; i++){
drh8c748632020-05-29 16:15:58 +00002102 int w = aExplainWidth[i];
2103 utf8_width_print(p->out, w, azCol[i]);
2104 fputs(i==nArg-1 ? "\n" : " ", p->out);
drh2ce15c32017-07-11 13:34:40 +00002105 }
drhe566ceb2020-05-30 15:34:49 +00002106 for(i=0; i<nArg; i++){
2107 int w = aExplainWidth[i];
2108 print_dashes(p->out, w);
2109 fputs(i==nArg-1 ? "\n" : " ", p->out);
2110 }
drh2ce15c32017-07-11 13:34:40 +00002111 }
2112 if( azArg==0 ) break;
2113 for(i=0; i<nArg; i++){
drh8c748632020-05-29 16:15:58 +00002114 int w = aExplainWidth[i];
drhaa556b02021-01-13 12:59:20 +00002115 if( i==nArg-1 ) w = 0;
drh8c748632020-05-29 16:15:58 +00002116 if( azArg[i] && strlenChar(azArg[i])>w ){
2117 w = strlenChar(azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00002118 }
drh8c748632020-05-29 16:15:58 +00002119 if( i==1 && p->aiIndent && p->pStmt ){
2120 if( p->iIndent<p->nIndent ){
2121 utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
drh2ce15c32017-07-11 13:34:40 +00002122 }
drh8c748632020-05-29 16:15:58 +00002123 p->iIndent++;
drh2ce15c32017-07-11 13:34:40 +00002124 }
2125 utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
drh8c748632020-05-29 16:15:58 +00002126 fputs(i==nArg-1 ? "\n" : " ", p->out);
drh2ce15c32017-07-11 13:34:40 +00002127 }
2128 break;
2129 }
2130 case MODE_Semi: { /* .schema and .fullschema output */
2131 printSchemaLine(p->out, azArg[0], ";\n");
2132 break;
2133 }
2134 case MODE_Pretty: { /* .schema and .fullschema with --indent */
2135 char *z;
2136 int j;
2137 int nParen = 0;
2138 char cEnd = 0;
2139 char c;
2140 int nLine = 0;
2141 assert( nArg==1 );
2142 if( azArg[0]==0 ) break;
2143 if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
2144 || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
2145 ){
2146 utf8_printf(p->out, "%s;\n", azArg[0]);
2147 break;
2148 }
2149 z = sqlite3_mprintf("%s", azArg[0]);
2150 j = 0;
2151 for(i=0; IsSpace(z[i]); i++){}
2152 for(; (c = z[i])!=0; i++){
2153 if( IsSpace(c) ){
drhc3cbd672017-10-05 19:12:10 +00002154 if( z[j-1]=='\r' ) z[j-1] = '\n';
drh2ce15c32017-07-11 13:34:40 +00002155 if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
2156 }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
2157 j--;
2158 }
2159 z[j++] = c;
2160 }
2161 while( j>0 && IsSpace(z[j-1]) ){ j--; }
2162 z[j] = 0;
2163 if( strlen30(z)>=79 ){
drhe2754c12019-08-26 12:50:01 +00002164 for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */
drh2ce15c32017-07-11 13:34:40 +00002165 if( c==cEnd ){
2166 cEnd = 0;
2167 }else if( c=='"' || c=='\'' || c=='`' ){
2168 cEnd = c;
2169 }else if( c=='[' ){
2170 cEnd = ']';
drh11be81d2018-01-06 15:46:20 +00002171 }else if( c=='-' && z[i+1]=='-' ){
2172 cEnd = '\n';
drh2ce15c32017-07-11 13:34:40 +00002173 }else if( c=='(' ){
2174 nParen++;
2175 }else if( c==')' ){
2176 nParen--;
2177 if( nLine>0 && nParen==0 && j>0 ){
2178 printSchemaLineN(p->out, z, j, "\n");
2179 j = 0;
2180 }
2181 }
2182 z[j++] = c;
drh11be81d2018-01-06 15:46:20 +00002183 if( nParen==1 && cEnd==0
2184 && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
2185 ){
drh2ce15c32017-07-11 13:34:40 +00002186 if( c=='\n' ) j--;
2187 printSchemaLineN(p->out, z, j, "\n ");
2188 j = 0;
2189 nLine++;
2190 while( IsSpace(z[i+1]) ){ i++; }
2191 }
2192 }
2193 z[j] = 0;
2194 }
2195 printSchemaLine(p->out, z, ";\n");
2196 sqlite3_free(z);
2197 break;
2198 }
2199 case MODE_List: {
2200 if( p->cnt++==0 && p->showHeader ){
2201 for(i=0; i<nArg; i++){
2202 utf8_printf(p->out,"%s%s",azCol[i],
2203 i==nArg-1 ? p->rowSeparator : p->colSeparator);
2204 }
2205 }
2206 if( azArg==0 ) break;
2207 for(i=0; i<nArg; i++){
2208 char *z = azArg[i];
2209 if( z==0 ) z = p->nullValue;
2210 utf8_printf(p->out, "%s", z);
2211 if( i<nArg-1 ){
2212 utf8_printf(p->out, "%s", p->colSeparator);
2213 }else{
2214 utf8_printf(p->out, "%s", p->rowSeparator);
2215 }
2216 }
2217 break;
2218 }
2219 case MODE_Html: {
2220 if( p->cnt++==0 && p->showHeader ){
2221 raw_printf(p->out,"<TR>");
2222 for(i=0; i<nArg; i++){
2223 raw_printf(p->out,"<TH>");
2224 output_html_string(p->out, azCol[i]);
2225 raw_printf(p->out,"</TH>\n");
2226 }
2227 raw_printf(p->out,"</TR>\n");
2228 }
2229 if( azArg==0 ) break;
2230 raw_printf(p->out,"<TR>");
2231 for(i=0; i<nArg; i++){
2232 raw_printf(p->out,"<TD>");
2233 output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
2234 raw_printf(p->out,"</TD>\n");
2235 }
2236 raw_printf(p->out,"</TR>\n");
2237 break;
2238 }
2239 case MODE_Tcl: {
2240 if( p->cnt++==0 && p->showHeader ){
2241 for(i=0; i<nArg; i++){
2242 output_c_string(p->out,azCol[i] ? azCol[i] : "");
2243 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
2244 }
2245 utf8_printf(p->out, "%s", p->rowSeparator);
2246 }
2247 if( azArg==0 ) break;
2248 for(i=0; i<nArg; i++){
2249 output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
2250 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
2251 }
2252 utf8_printf(p->out, "%s", p->rowSeparator);
2253 break;
2254 }
2255 case MODE_Csv: {
2256 setBinaryMode(p->out, 1);
2257 if( p->cnt++==0 && p->showHeader ){
2258 for(i=0; i<nArg; i++){
2259 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
2260 }
2261 utf8_printf(p->out, "%s", p->rowSeparator);
2262 }
2263 if( nArg>0 ){
2264 for(i=0; i<nArg; i++){
2265 output_csv(p, azArg[i], i<nArg-1);
2266 }
2267 utf8_printf(p->out, "%s", p->rowSeparator);
2268 }
2269 setTextMode(p->out, 1);
2270 break;
2271 }
2272 case MODE_Insert: {
2273 if( azArg==0 ) break;
2274 utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
2275 if( p->showHeader ){
2276 raw_printf(p->out,"(");
2277 for(i=0; i<nArg; i++){
2278 if( i>0 ) raw_printf(p->out, ",");
2279 if( quoteChar(azCol[i]) ){
2280 char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
2281 utf8_printf(p->out, "%s", z);
2282 sqlite3_free(z);
2283 }else{
2284 raw_printf(p->out, "%s", azCol[i]);
2285 }
2286 }
2287 raw_printf(p->out,")");
2288 }
2289 p->cnt++;
2290 for(i=0; i<nArg; i++){
2291 raw_printf(p->out, i>0 ? "," : " VALUES(");
2292 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2293 utf8_printf(p->out,"NULL");
2294 }else if( aiType && aiType[i]==SQLITE_TEXT ){
2295 if( ShellHasFlag(p, SHFLG_Newlines) ){
2296 output_quoted_string(p->out, azArg[i]);
2297 }else{
2298 output_quoted_escaped_string(p->out, azArg[i]);
2299 }
2300 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
2301 utf8_printf(p->out,"%s", azArg[i]);
2302 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2303 char z[50];
2304 double r = sqlite3_column_double(p->pStmt, i);
drh2f1f8802018-06-13 17:19:20 +00002305 sqlite3_uint64 ur;
2306 memcpy(&ur,&r,sizeof(r));
2307 if( ur==0x7ff0000000000000LL ){
2308 raw_printf(p->out, "1e999");
2309 }else if( ur==0xfff0000000000000LL ){
2310 raw_printf(p->out, "-1e999");
2311 }else{
2312 sqlite3_snprintf(50,z,"%!.20g", r);
2313 raw_printf(p->out, "%s", z);
2314 }
drh2ce15c32017-07-11 13:34:40 +00002315 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2316 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2317 int nBlob = sqlite3_column_bytes(p->pStmt, i);
2318 output_hex_blob(p->out, pBlob, nBlob);
2319 }else if( isNumber(azArg[i], 0) ){
2320 utf8_printf(p->out,"%s", azArg[i]);
2321 }else if( ShellHasFlag(p, SHFLG_Newlines) ){
2322 output_quoted_string(p->out, azArg[i]);
2323 }else{
2324 output_quoted_escaped_string(p->out, azArg[i]);
2325 }
2326 }
2327 raw_printf(p->out,");\n");
2328 break;
2329 }
drh30c54a02020-05-28 23:49:50 +00002330 case MODE_Json: {
2331 if( azArg==0 ) break;
2332 if( p->cnt==0 ){
2333 fputs("[{", p->out);
2334 }else{
2335 fputs(",\n{", p->out);
2336 }
2337 p->cnt++;
2338 for(i=0; i<nArg; i++){
drh69c093d2020-05-29 00:21:43 +00002339 output_json_string(p->out, azCol[i], -1);
drh30c54a02020-05-28 23:49:50 +00002340 putc(':', p->out);
2341 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2342 fputs("null",p->out);
2343 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2344 char z[50];
2345 double r = sqlite3_column_double(p->pStmt, i);
2346 sqlite3_uint64 ur;
2347 memcpy(&ur,&r,sizeof(r));
2348 if( ur==0x7ff0000000000000LL ){
2349 raw_printf(p->out, "1e999");
2350 }else if( ur==0xfff0000000000000LL ){
2351 raw_printf(p->out, "-1e999");
2352 }else{
2353 sqlite3_snprintf(50,z,"%!.20g", r);
2354 raw_printf(p->out, "%s", z);
2355 }
2356 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2357 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2358 int nBlob = sqlite3_column_bytes(p->pStmt, i);
drh69c093d2020-05-29 00:21:43 +00002359 output_json_string(p->out, pBlob, nBlob);
drh30c54a02020-05-28 23:49:50 +00002360 }else if( aiType && aiType[i]==SQLITE_TEXT ){
drh69c093d2020-05-29 00:21:43 +00002361 output_json_string(p->out, azArg[i], -1);
drh30c54a02020-05-28 23:49:50 +00002362 }else{
2363 utf8_printf(p->out,"%s", azArg[i]);
2364 }
2365 if( i<nArg-1 ){
2366 putc(',', p->out);
2367 }
2368 }
2369 putc('}', p->out);
2370 break;
2371 }
drh2ce15c32017-07-11 13:34:40 +00002372 case MODE_Quote: {
2373 if( azArg==0 ) break;
2374 if( p->cnt==0 && p->showHeader ){
2375 for(i=0; i<nArg; i++){
drhc6835732020-05-28 20:37:17 +00002376 if( i>0 ) fputs(p->colSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002377 output_quoted_string(p->out, azCol[i]);
2378 }
drhc6835732020-05-28 20:37:17 +00002379 fputs(p->rowSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002380 }
2381 p->cnt++;
2382 for(i=0; i<nArg; i++){
drhc6835732020-05-28 20:37:17 +00002383 if( i>0 ) fputs(p->colSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002384 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2385 utf8_printf(p->out,"NULL");
2386 }else if( aiType && aiType[i]==SQLITE_TEXT ){
2387 output_quoted_string(p->out, azArg[i]);
2388 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
2389 utf8_printf(p->out,"%s", azArg[i]);
2390 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2391 char z[50];
2392 double r = sqlite3_column_double(p->pStmt, i);
2393 sqlite3_snprintf(50,z,"%!.20g", r);
2394 raw_printf(p->out, "%s", z);
2395 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2396 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2397 int nBlob = sqlite3_column_bytes(p->pStmt, i);
2398 output_hex_blob(p->out, pBlob, nBlob);
2399 }else if( isNumber(azArg[i], 0) ){
2400 utf8_printf(p->out,"%s", azArg[i]);
2401 }else{
2402 output_quoted_string(p->out, azArg[i]);
2403 }
2404 }
drhc6835732020-05-28 20:37:17 +00002405 fputs(p->rowSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002406 break;
2407 }
2408 case MODE_Ascii: {
2409 if( p->cnt++==0 && p->showHeader ){
2410 for(i=0; i<nArg; i++){
2411 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
2412 utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
2413 }
2414 utf8_printf(p->out, "%s", p->rowSeparator);
2415 }
2416 if( azArg==0 ) break;
2417 for(i=0; i<nArg; i++){
2418 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
2419 utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
2420 }
2421 utf8_printf(p->out, "%s", p->rowSeparator);
2422 break;
2423 }
drh4b5345c2018-04-24 13:07:40 +00002424 case MODE_EQP: {
drhe2ca99c2018-05-02 00:33:43 +00002425 eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]);
drh4b5345c2018-04-24 13:07:40 +00002426 break;
2427 }
drh2ce15c32017-07-11 13:34:40 +00002428 }
2429 return 0;
2430}
2431
2432/*
2433** This is the callback routine that the SQLite library
2434** invokes for each row of a query result.
2435*/
2436static int callback(void *pArg, int nArg, char **azArg, char **azCol){
2437 /* since we don't have type info, call the shell_callback with a NULL value */
2438 return shell_callback(pArg, nArg, azArg, azCol, NULL);
2439}
2440
2441/*
2442** This is the callback routine from sqlite3_exec() that appends all
2443** output onto the end of a ShellText object.
2444*/
2445static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
2446 ShellText *p = (ShellText*)pArg;
2447 int i;
2448 UNUSED_PARAMETER(az);
drhb3c45232017-08-28 14:33:27 +00002449 if( azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00002450 if( p->n ) appendText(p, "|", 0);
2451 for(i=0; i<nArg; i++){
2452 if( i ) appendText(p, ",", 0);
2453 if( azArg[i] ) appendText(p, azArg[i], 0);
2454 }
2455 return 0;
2456}
2457
2458/*
2459** Generate an appropriate SELFTEST table in the main database.
2460*/
2461static void createSelftestTable(ShellState *p){
2462 char *zErrMsg = 0;
2463 sqlite3_exec(p->db,
2464 "SAVEPOINT selftest_init;\n"
2465 "CREATE TABLE IF NOT EXISTS selftest(\n"
2466 " tno INTEGER PRIMARY KEY,\n" /* Test number */
2467 " op TEXT,\n" /* Operator: memo run */
2468 " cmd TEXT,\n" /* Command text */
2469 " ans TEXT\n" /* Desired answer */
2470 ");"
2471 "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n"
2472 "INSERT INTO [_shell$self](rowid,op,cmd)\n"
2473 " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n"
2474 " 'memo','Tests generated by --init');\n"
2475 "INSERT INTO [_shell$self]\n"
2476 " SELECT 'run',\n"
2477 " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql "
drh067b92b2020-06-19 15:24:12 +00002478 "FROM sqlite_schema ORDER BY 2'',224))',\n"
drh2ce15c32017-07-11 13:34:40 +00002479 " hex(sha3_query('SELECT type,name,tbl_name,sql "
drh067b92b2020-06-19 15:24:12 +00002480 "FROM sqlite_schema ORDER BY 2',224));\n"
drh2ce15c32017-07-11 13:34:40 +00002481 "INSERT INTO [_shell$self]\n"
2482 " SELECT 'run',"
2483 " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||"
2484 " printf('%w',name) || '\" NOT INDEXED'',224))',\n"
2485 " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"
2486 " FROM (\n"
drh067b92b2020-06-19 15:24:12 +00002487 " SELECT name FROM sqlite_schema\n"
drh2ce15c32017-07-11 13:34:40 +00002488 " WHERE type='table'\n"
2489 " AND name<>'selftest'\n"
2490 " AND coalesce(rootpage,0)>0\n"
2491 " )\n"
2492 " ORDER BY name;\n"
2493 "INSERT INTO [_shell$self]\n"
2494 " VALUES('run','PRAGMA integrity_check','ok');\n"
2495 "INSERT INTO selftest(tno,op,cmd,ans)"
2496 " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n"
2497 "DROP TABLE [_shell$self];"
2498 ,0,0,&zErrMsg);
2499 if( zErrMsg ){
2500 utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
2501 sqlite3_free(zErrMsg);
2502 }
2503 sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
2504}
2505
2506
2507/*
2508** Set the destination table field of the ShellState structure to
2509** the name of the table given. Escape any quote characters in the
2510** table name.
2511*/
2512static void set_table_name(ShellState *p, const char *zName){
2513 int i, n;
mistachkin2158a0c2017-09-09 00:51:36 +00002514 char cQuote;
drh2ce15c32017-07-11 13:34:40 +00002515 char *z;
2516
2517 if( p->zDestTable ){
2518 free(p->zDestTable);
2519 p->zDestTable = 0;
2520 }
2521 if( zName==0 ) return;
2522 cQuote = quoteChar(zName);
2523 n = strlen30(zName);
2524 if( cQuote ) n += n+2;
2525 z = p->zDestTable = malloc( n+1 );
drh4b5345c2018-04-24 13:07:40 +00002526 if( z==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00002527 n = 0;
2528 if( cQuote ) z[n++] = cQuote;
2529 for(i=0; zName[i]; i++){
2530 z[n++] = zName[i];
2531 if( zName[i]==cQuote ) z[n++] = cQuote;
2532 }
2533 if( cQuote ) z[n++] = cQuote;
2534 z[n] = 0;
2535}
2536
2537
2538/*
2539** Execute a query statement that will generate SQL output. Print
2540** the result columns, comma-separated, on a line and then add a
2541** semicolon terminator to the end of that line.
2542**
2543** If the number of columns is 1 and that column contains text "--"
2544** then write the semicolon on a separate line. That way, if a
2545** "--" comment occurs at the end of the statement, the comment
2546** won't consume the semicolon terminator.
2547*/
2548static int run_table_dump_query(
2549 ShellState *p, /* Query context */
drh8e9297f2020-03-25 12:50:13 +00002550 const char *zSelect /* SELECT statement to extract content */
drh2ce15c32017-07-11 13:34:40 +00002551){
2552 sqlite3_stmt *pSelect;
2553 int rc;
2554 int nResult;
2555 int i;
2556 const char *z;
2557 rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
2558 if( rc!=SQLITE_OK || !pSelect ){
2559 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
2560 sqlite3_errmsg(p->db));
2561 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
2562 return rc;
2563 }
2564 rc = sqlite3_step(pSelect);
2565 nResult = sqlite3_column_count(pSelect);
2566 while( rc==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00002567 z = (const char*)sqlite3_column_text(pSelect, 0);
2568 utf8_printf(p->out, "%s", z);
2569 for(i=1; i<nResult; i++){
2570 utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
2571 }
2572 if( z==0 ) z = "";
2573 while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
2574 if( z[0] ){
2575 raw_printf(p->out, "\n;\n");
2576 }else{
2577 raw_printf(p->out, ";\n");
2578 }
2579 rc = sqlite3_step(pSelect);
2580 }
2581 rc = sqlite3_finalize(pSelect);
2582 if( rc!=SQLITE_OK ){
2583 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
2584 sqlite3_errmsg(p->db));
2585 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
2586 }
2587 return rc;
2588}
2589
2590/*
2591** Allocate space and save off current error string.
2592*/
2593static char *save_err_msg(
2594 sqlite3 *db /* Database to query */
2595){
2596 int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
2597 char *zErrMsg = sqlite3_malloc64(nErrMsg);
2598 if( zErrMsg ){
2599 memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
2600 }
2601 return zErrMsg;
2602}
2603
2604#ifdef __linux__
2605/*
2606** Attempt to display I/O stats on Linux using /proc/PID/io
2607*/
2608static void displayLinuxIoStats(FILE *out){
2609 FILE *in;
2610 char z[200];
2611 sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
2612 in = fopen(z, "rb");
2613 if( in==0 ) return;
2614 while( fgets(z, sizeof(z), in)!=0 ){
2615 static const struct {
2616 const char *zPattern;
2617 const char *zDesc;
2618 } aTrans[] = {
2619 { "rchar: ", "Bytes received by read():" },
2620 { "wchar: ", "Bytes sent to write():" },
2621 { "syscr: ", "Read() system calls:" },
2622 { "syscw: ", "Write() system calls:" },
2623 { "read_bytes: ", "Bytes read from storage:" },
2624 { "write_bytes: ", "Bytes written to storage:" },
2625 { "cancelled_write_bytes: ", "Cancelled write bytes:" },
2626 };
2627 int i;
2628 for(i=0; i<ArraySize(aTrans); i++){
drhaf2770f2018-01-05 14:55:43 +00002629 int n = strlen30(aTrans[i].zPattern);
drh2ce15c32017-07-11 13:34:40 +00002630 if( strncmp(aTrans[i].zPattern, z, n)==0 ){
2631 utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
2632 break;
2633 }
2634 }
2635 }
2636 fclose(in);
2637}
2638#endif
2639
2640/*
2641** Display a single line of status using 64-bit values.
2642*/
2643static void displayStatLine(
2644 ShellState *p, /* The shell context */
2645 char *zLabel, /* Label for this one line */
2646 char *zFormat, /* Format for the result */
2647 int iStatusCtrl, /* Which status to display */
2648 int bReset /* True to reset the stats */
2649){
2650 sqlite3_int64 iCur = -1;
2651 sqlite3_int64 iHiwtr = -1;
2652 int i, nPercent;
2653 char zLine[200];
2654 sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset);
2655 for(i=0, nPercent=0; zFormat[i]; i++){
2656 if( zFormat[i]=='%' ) nPercent++;
2657 }
2658 if( nPercent>1 ){
2659 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr);
2660 }else{
2661 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
2662 }
2663 raw_printf(p->out, "%-36s %s\n", zLabel, zLine);
2664}
2665
2666/*
2667** Display memory stats.
2668*/
2669static int display_stats(
2670 sqlite3 *db, /* Database to query */
2671 ShellState *pArg, /* Pointer to ShellState */
2672 int bReset /* True to reset the stats */
2673){
2674 int iCur;
2675 int iHiwtr;
drh393344f2018-03-09 16:37:05 +00002676 FILE *out;
2677 if( pArg==0 || pArg->out==0 ) return 0;
2678 out = pArg->out;
drh2ce15c32017-07-11 13:34:40 +00002679
drha6e6cf22021-01-09 19:10:04 +00002680 if( pArg->pStmt && pArg->statsOn==2 ){
drh393344f2018-03-09 16:37:05 +00002681 int nCol, i, x;
2682 sqlite3_stmt *pStmt = pArg->pStmt;
2683 char z[100];
2684 nCol = sqlite3_column_count(pStmt);
2685 raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
2686 for(i=0; i<nCol; i++){
2687 sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
2688 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
drh929cce82018-03-17 16:26:36 +00002689#ifndef SQLITE_OMIT_DECLTYPE
drh393344f2018-03-09 16:37:05 +00002690 sqlite3_snprintf(30, z+x, "declared type:");
2691 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
drh929cce82018-03-17 16:26:36 +00002692#endif
2693#ifdef SQLITE_ENABLE_COLUMN_METADATA
drh393344f2018-03-09 16:37:05 +00002694 sqlite3_snprintf(30, z+x, "database name:");
2695 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
2696 sqlite3_snprintf(30, z+x, "table name:");
2697 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
2698 sqlite3_snprintf(30, z+x, "origin name:");
2699 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
drh929cce82018-03-17 16:26:36 +00002700#endif
drh2ce15c32017-07-11 13:34:40 +00002701 }
drh929cce82018-03-17 16:26:36 +00002702 }
drh2ce15c32017-07-11 13:34:40 +00002703
drha6e6cf22021-01-09 19:10:04 +00002704 if( pArg->statsOn==3 ){
2705 if( pArg->pStmt ){
2706 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
2707 raw_printf(pArg->out, "VM-steps: %d\n", iCur);
2708 }
2709 return 0;
2710 }
2711
drh393344f2018-03-09 16:37:05 +00002712 displayStatLine(pArg, "Memory Used:",
2713 "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
2714 displayStatLine(pArg, "Number of Outstanding Allocations:",
2715 "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
2716 if( pArg->shellFlgs & SHFLG_Pagecache ){
2717 displayStatLine(pArg, "Number of Pcache Pages Used:",
2718 "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
2719 }
2720 displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
2721 "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
2722 displayStatLine(pArg, "Largest Allocation:",
2723 "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
2724 displayStatLine(pArg, "Largest Pcache Allocation:",
2725 "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
2726#ifdef YYTRACKMAXSTACKDEPTH
2727 displayStatLine(pArg, "Deepest Parser Stack:",
2728 "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
2729#endif
2730
2731 if( db ){
drh2ce15c32017-07-11 13:34:40 +00002732 if( pArg->shellFlgs & SHFLG_Lookaside ){
2733 iHiwtr = iCur = -1;
2734 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
2735 &iCur, &iHiwtr, bReset);
2736 raw_printf(pArg->out,
2737 "Lookaside Slots Used: %d (max %d)\n",
2738 iCur, iHiwtr);
2739 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
2740 &iCur, &iHiwtr, bReset);
2741 raw_printf(pArg->out, "Successful lookaside attempts: %d\n",
2742 iHiwtr);
2743 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
2744 &iCur, &iHiwtr, bReset);
2745 raw_printf(pArg->out, "Lookaside failures due to size: %d\n",
2746 iHiwtr);
2747 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
2748 &iCur, &iHiwtr, bReset);
2749 raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n",
2750 iHiwtr);
2751 }
2752 iHiwtr = iCur = -1;
2753 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
2754 raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n",
2755 iCur);
2756 iHiwtr = iCur = -1;
2757 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
2758 raw_printf(pArg->out, "Page cache hits: %d\n", iCur);
2759 iHiwtr = iCur = -1;
2760 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
2761 raw_printf(pArg->out, "Page cache misses: %d\n", iCur);
2762 iHiwtr = iCur = -1;
2763 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
2764 raw_printf(pArg->out, "Page cache writes: %d\n", iCur);
2765 iHiwtr = iCur = -1;
drhffc78a42018-03-14 14:53:50 +00002766 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
2767 raw_printf(pArg->out, "Page cache spills: %d\n", iCur);
2768 iHiwtr = iCur = -1;
drh2ce15c32017-07-11 13:34:40 +00002769 sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
2770 raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n",
2771 iCur);
2772 iHiwtr = iCur = -1;
2773 sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
2774 raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
2775 iCur);
2776 }
2777
drh393344f2018-03-09 16:37:05 +00002778 if( pArg->pStmt ){
drh2ce15c32017-07-11 13:34:40 +00002779 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
2780 bReset);
2781 raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
2782 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
2783 raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
2784 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
2785 raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
2786 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
2787 raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
drhe2754c12019-08-26 12:50:01 +00002788 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
drh393344f2018-03-09 16:37:05 +00002789 raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
2790 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
2791 raw_printf(pArg->out, "Number of times run: %d\n", iCur);
2792 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
2793 raw_printf(pArg->out, "Memory used by prepared stmt: %d\n", iCur);
drh2ce15c32017-07-11 13:34:40 +00002794 }
2795
2796#ifdef __linux__
2797 displayLinuxIoStats(pArg->out);
2798#endif
2799
2800 /* Do not remove this machine readable comment: extra-stats-output-here */
2801
2802 return 0;
2803}
2804
2805/*
2806** Display scan stats.
2807*/
2808static void display_scanstats(
2809 sqlite3 *db, /* Database to query */
2810 ShellState *pArg /* Pointer to ShellState */
2811){
2812#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
2813 UNUSED_PARAMETER(db);
2814 UNUSED_PARAMETER(pArg);
2815#else
2816 int i, k, n, mx;
2817 raw_printf(pArg->out, "-------- scanstats --------\n");
2818 mx = 0;
2819 for(k=0; k<=mx; k++){
2820 double rEstLoop = 1.0;
2821 for(i=n=0; 1; i++){
2822 sqlite3_stmt *p = pArg->pStmt;
2823 sqlite3_int64 nLoop, nVisit;
2824 double rEst;
2825 int iSid;
2826 const char *zExplain;
2827 if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){
2828 break;
2829 }
2830 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
2831 if( iSid>mx ) mx = iSid;
2832 if( iSid!=k ) continue;
2833 if( n==0 ){
2834 rEstLoop = (double)nLoop;
2835 if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k);
2836 }
2837 n++;
2838 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
2839 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
2840 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
2841 utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
2842 rEstLoop *= rEst;
2843 raw_printf(pArg->out,
2844 " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
2845 nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
2846 );
2847 }
2848 }
2849 raw_printf(pArg->out, "---------------------------\n");
2850#endif
2851}
2852
2853/*
2854** Parameter azArray points to a zero-terminated array of strings. zStr
2855** points to a single nul-terminated string. Return non-zero if zStr
2856** is equal, according to strcmp(), to any of the strings in the array.
2857** Otherwise, return zero.
2858*/
2859static int str_in_array(const char *zStr, const char **azArray){
2860 int i;
2861 for(i=0; azArray[i]; i++){
2862 if( 0==strcmp(zStr, azArray[i]) ) return 1;
2863 }
2864 return 0;
2865}
2866
2867/*
2868** If compiled statement pSql appears to be an EXPLAIN statement, allocate
2869** and populate the ShellState.aiIndent[] array with the number of
2870** spaces each opcode should be indented before it is output.
2871**
2872** The indenting rules are:
2873**
2874** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
2875** all opcodes that occur between the p2 jump destination and the opcode
2876** itself by 2 spaces.
2877**
2878** * For each "Goto", if the jump destination is earlier in the program
2879** and ends on one of:
2880** Yield SeekGt SeekLt RowSetRead Rewind
2881** or if the P1 parameter is one instead of zero,
2882** then indent all opcodes between the earlier instruction
2883** and "Goto" by 2 spaces.
2884*/
2885static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
2886 const char *zSql; /* The text of the SQL statement */
2887 const char *z; /* Used to check if this is an EXPLAIN */
2888 int *abYield = 0; /* True if op is an OP_Yield */
2889 int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
2890 int iOp; /* Index of operation in p->aiIndent[] */
2891
drhf1949b62018-06-07 17:32:59 +00002892 const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
drh2ce15c32017-07-11 13:34:40 +00002893 const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
2894 "Rewind", 0 };
2895 const char *azGoto[] = { "Goto", 0 };
2896
2897 /* Try to figure out if this is really an EXPLAIN statement. If this
2898 ** cannot be verified, return early. */
2899 if( sqlite3_column_count(pSql)!=8 ){
2900 p->cMode = p->mode;
2901 return;
2902 }
2903 zSql = sqlite3_sql(pSql);
2904 if( zSql==0 ) return;
2905 for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
2906 if( sqlite3_strnicmp(z, "explain", 7) ){
2907 p->cMode = p->mode;
2908 return;
2909 }
2910
2911 for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
2912 int i;
2913 int iAddr = sqlite3_column_int(pSql, 0);
2914 const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
2915
2916 /* Set p2 to the P2 field of the current opcode. Then, assuming that
2917 ** p2 is an instruction address, set variable p2op to the index of that
2918 ** instruction in the aiIndent[] array. p2 and p2op may be different if
2919 ** the current instruction is part of a sub-program generated by an
2920 ** SQL trigger or foreign key. */
2921 int p2 = sqlite3_column_int(pSql, 3);
2922 int p2op = (p2 + (iOp-iAddr));
2923
2924 /* Grow the p->aiIndent array as required */
2925 if( iOp>=nAlloc ){
2926 if( iOp==0 ){
2927 /* Do further verfication that this is explain output. Abort if
2928 ** it is not */
2929 static const char *explainCols[] = {
2930 "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" };
2931 int jj;
2932 for(jj=0; jj<ArraySize(explainCols); jj++){
2933 if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
2934 p->cMode = p->mode;
2935 sqlite3_reset(pSql);
2936 return;
2937 }
2938 }
2939 }
2940 nAlloc += 100;
2941 p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
drh884406b2018-07-29 18:56:35 +00002942 if( p->aiIndent==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00002943 abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
drh884406b2018-07-29 18:56:35 +00002944 if( abYield==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00002945 }
2946 abYield[iOp] = str_in_array(zOp, azYield);
2947 p->aiIndent[iOp] = 0;
2948 p->nIndent = iOp+1;
2949
2950 if( str_in_array(zOp, azNext) ){
2951 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
2952 }
2953 if( str_in_array(zOp, azGoto) && p2op<p->nIndent
2954 && (abYield[p2op] || sqlite3_column_int(pSql, 2))
2955 ){
2956 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
2957 }
2958 }
2959
2960 p->iIndent = 0;
2961 sqlite3_free(abYield);
2962 sqlite3_reset(pSql);
2963}
2964
2965/*
2966** Free the array allocated by explain_data_prepare().
2967*/
2968static void explain_data_delete(ShellState *p){
2969 sqlite3_free(p->aiIndent);
2970 p->aiIndent = 0;
2971 p->nIndent = 0;
2972 p->iIndent = 0;
2973}
2974
2975/*
2976** Disable and restore .wheretrace and .selecttrace settings.
2977*/
drhc0622a42020-12-04 01:17:57 +00002978static unsigned int savedSelectTrace;
2979static unsigned int savedWhereTrace;
drh2ce15c32017-07-11 13:34:40 +00002980static void disable_debug_trace_modes(void){
drh0a2fb792020-12-04 16:58:20 +00002981 unsigned int zero = 0;
drhc0622a42020-12-04 01:17:57 +00002982 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace);
drh0a2fb792020-12-04 16:58:20 +00002983 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero);
drhc0622a42020-12-04 01:17:57 +00002984 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace);
drh0a2fb792020-12-04 16:58:20 +00002985 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero);
drh2ce15c32017-07-11 13:34:40 +00002986}
2987static void restore_debug_trace_modes(void){
drhc0622a42020-12-04 01:17:57 +00002988 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &savedSelectTrace);
2989 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &savedWhereTrace);
drh2ce15c32017-07-11 13:34:40 +00002990}
2991
drh9cb02642019-02-28 20:10:52 +00002992/* Create the TEMP table used to store parameter bindings */
2993static void bind_table_init(ShellState *p){
drh346f4e22019-03-25 21:35:41 +00002994 int wrSchema = 0;
drh4b86e202020-01-19 20:37:26 +00002995 int defensiveMode = 0;
2996 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
2997 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
drh346f4e22019-03-25 21:35:41 +00002998 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
2999 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
drh9cb02642019-02-28 20:10:52 +00003000 sqlite3_exec(p->db,
drh65c29fd2019-03-25 21:56:26 +00003001 "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
drh9cb02642019-02-28 20:10:52 +00003002 " key TEXT PRIMARY KEY,\n"
larrybrdabada62021-04-04 12:52:58 +00003003 " value\n"
drh9cb02642019-02-28 20:10:52 +00003004 ") WITHOUT ROWID;",
3005 0, 0, 0);
drh346f4e22019-03-25 21:35:41 +00003006 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
drh4b86e202020-01-19 20:37:26 +00003007 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0);
drh9cb02642019-02-28 20:10:52 +00003008}
3009
drh8b738d02019-02-25 18:43:54 +00003010/*
3011** Bind parameters on a prepared statement.
3012**
3013** Parameter bindings are taken from a TEMP table of the form:
3014**
drh1cb02632019-03-25 22:05:22 +00003015** CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
drh8b738d02019-02-25 18:43:54 +00003016** WITHOUT ROWID;
3017**
drh91654b22020-04-02 13:21:10 +00003018** No bindings occur if this table does not exist. The name of the table
3019** begins with "sqlite_" so that it will not collide with ordinary application
3020** tables. The table must be in the TEMP schema.
drh8b738d02019-02-25 18:43:54 +00003021*/
3022static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
3023 int nVar;
3024 int i;
3025 int rc;
3026 sqlite3_stmt *pQ = 0;
3027
3028 nVar = sqlite3_bind_parameter_count(pStmt);
3029 if( nVar==0 ) return; /* Nothing to do */
drh65c29fd2019-03-25 21:56:26 +00003030 if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters",
drh8b738d02019-02-25 18:43:54 +00003031 "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
3032 return; /* Parameter table does not exist */
3033 }
3034 rc = sqlite3_prepare_v2(pArg->db,
drh65c29fd2019-03-25 21:56:26 +00003035 "SELECT value FROM temp.sqlite_parameters"
drh8b738d02019-02-25 18:43:54 +00003036 " WHERE key=?1", -1, &pQ, 0);
3037 if( rc || pQ==0 ) return;
3038 for(i=1; i<=nVar; i++){
3039 char zNum[30];
3040 const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
3041 if( zVar==0 ){
3042 sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
3043 zVar = zNum;
3044 }
3045 sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
3046 if( sqlite3_step(pQ)==SQLITE_ROW ){
3047 sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
3048 }else{
3049 sqlite3_bind_null(pStmt, i);
3050 }
3051 sqlite3_reset(pQ);
3052 }
3053 sqlite3_finalize(pQ);
3054}
3055
drh30c54a02020-05-28 23:49:50 +00003056/*
drh0908e382020-06-04 18:05:39 +00003057** UTF8 box-drawing characters. Imagine box lines like this:
3058**
3059** 1
3060** |
3061** 4 --+-- 2
3062** |
3063** 3
3064**
3065** Each box characters has between 2 and 4 of the lines leading from
3066** the center. The characters are here identified by the numbers of
3067** their corresponding lines.
3068*/
3069#define BOX_24 "\342\224\200" /* U+2500 --- */
3070#define BOX_13 "\342\224\202" /* U+2502 | */
3071#define BOX_23 "\342\224\214" /* U+250c ,- */
3072#define BOX_34 "\342\224\220" /* U+2510 -, */
3073#define BOX_12 "\342\224\224" /* U+2514 '- */
3074#define BOX_14 "\342\224\230" /* U+2518 -' */
3075#define BOX_123 "\342\224\234" /* U+251c |- */
3076#define BOX_134 "\342\224\244" /* U+2524 -| */
3077#define BOX_234 "\342\224\254" /* U+252c -,- */
3078#define BOX_124 "\342\224\264" /* U+2534 -'- */
3079#define BOX_1234 "\342\224\274" /* U+253c -|- */
3080
3081/* Draw horizontal line N characters long using unicode box
3082** characters
3083*/
3084static void print_box_line(FILE *out, int N){
3085 const char zDash[] =
3086 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
3087 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
3088 const int nDash = sizeof(zDash) - 1;
3089 N *= 3;
3090 while( N>nDash ){
3091 utf8_printf(out, zDash);
3092 N -= nDash;
3093 }
3094 utf8_printf(out, "%.*s", N, zDash);
3095}
3096
3097/*
3098** Draw a horizontal separator for a MODE_Box table.
3099*/
3100static void print_box_row_separator(
3101 ShellState *p,
3102 int nArg,
3103 const char *zSep1,
3104 const char *zSep2,
3105 const char *zSep3
3106){
3107 int i;
3108 if( nArg>0 ){
3109 utf8_printf(p->out, "%s", zSep1);
3110 print_box_line(p->out, p->actualWidth[0]+2);
3111 for(i=1; i<nArg; i++){
3112 utf8_printf(p->out, "%s", zSep2);
3113 print_box_line(p->out, p->actualWidth[i]+2);
3114 }
3115 utf8_printf(p->out, "%s", zSep3);
3116 }
3117 fputs("\n", p->out);
3118}
3119
3120
3121
3122/*
drh30c54a02020-05-28 23:49:50 +00003123** Run a prepared statement and output the result in one of the
drh0908e382020-06-04 18:05:39 +00003124** table-oriented formats: MODE_Column, MODE_Markdown, MODE_Table,
3125** or MODE_Box.
drh30c54a02020-05-28 23:49:50 +00003126**
3127** This is different from ordinary exec_prepared_stmt() in that
3128** it has to run the entire query and gather the results into memory
3129** first, in order to determine column widths, before providing
3130** any output.
3131*/
drh8c748632020-05-29 16:15:58 +00003132static void exec_prepared_stmt_columnar(
3133 ShellState *p, /* Pointer to ShellState */
3134 sqlite3_stmt *pStmt /* Statment to run */
drh30c54a02020-05-28 23:49:50 +00003135){
drhf82ce382020-08-06 16:45:22 +00003136 sqlite3_int64 nRow = 0;
drh8c748632020-05-29 16:15:58 +00003137 int nColumn = 0;
3138 char **azData = 0;
drhf82ce382020-08-06 16:45:22 +00003139 sqlite3_int64 nAlloc = 0;
drh8c748632020-05-29 16:15:58 +00003140 const char *z;
3141 int rc;
drhf82ce382020-08-06 16:45:22 +00003142 sqlite3_int64 i, nData;
3143 int j, nTotal, w, n;
drh0908e382020-06-04 18:05:39 +00003144 const char *colSep = 0;
3145 const char *rowSep = 0;
drh30c54a02020-05-28 23:49:50 +00003146
drhf82ce382020-08-06 16:45:22 +00003147 rc = sqlite3_step(pStmt);
3148 if( rc!=SQLITE_ROW ) return;
3149 nColumn = sqlite3_column_count(pStmt);
3150 nAlloc = nColumn*4;
drh01a8ad22021-03-20 23:15:52 +00003151 if( nAlloc<=0 ) nAlloc = 1;
drhf82ce382020-08-06 16:45:22 +00003152 azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
3153 if( azData==0 ) shell_out_of_memory();
3154 for(i=0; i<nColumn; i++){
3155 azData[i] = strdup(sqlite3_column_name(pStmt,i));
drh8c748632020-05-29 16:15:58 +00003156 }
drhf82ce382020-08-06 16:45:22 +00003157 do{
3158 if( (nRow+2)*nColumn >= nAlloc ){
3159 nAlloc *= 2;
3160 azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*));
3161 if( azData==0 ) shell_out_of_memory();
3162 }
3163 nRow++;
3164 for(i=0; i<nColumn; i++){
3165 z = (const char*)sqlite3_column_text(pStmt,i);
3166 azData[nRow*nColumn + i] = z ? strdup(z) : 0;
3167 }
3168 }while( (rc = sqlite3_step(pStmt))==SQLITE_ROW );
drh8c748632020-05-29 16:15:58 +00003169 if( nColumn>p->nWidth ){
3170 p->colWidth = realloc(p->colWidth, nColumn*2*sizeof(int));
3171 if( p->colWidth==0 ) shell_out_of_memory();
3172 for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0;
3173 p->nWidth = nColumn;
3174 p->actualWidth = &p->colWidth[nColumn];
3175 }
3176 memset(p->actualWidth, 0, nColumn*sizeof(int));
3177 for(i=0; i<nColumn; i++){
3178 w = p->colWidth[i];
3179 if( w<0 ) w = -w;
3180 p->actualWidth[i] = w;
3181 }
3182 nTotal = nColumn*(nRow+1);
3183 for(i=0; i<nTotal; i++){
3184 z = azData[i];
3185 if( z==0 ) z = p->nullValue;
3186 n = strlenChar(z);
3187 j = i%nColumn;
3188 if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
3189 }
drh99942982020-06-15 20:05:37 +00003190 if( seenInterrupt ) goto columnar_end;
drh01a8ad22021-03-20 23:15:52 +00003191 if( nColumn==0 ) goto columnar_end;
drh0908e382020-06-04 18:05:39 +00003192 switch( p->cMode ){
3193 case MODE_Column: {
3194 colSep = " ";
3195 rowSep = "\n";
3196 if( p->showHeader ){
3197 for(i=0; i<nColumn; i++){
3198 w = p->actualWidth[i];
3199 if( p->colWidth[i]<0 ) w = -w;
3200 utf8_width_print(p->out, w, azData[i]);
3201 fputs(i==nColumn-1?"\n":" ", p->out);
3202 }
3203 for(i=0; i<nColumn; i++){
3204 print_dashes(p->out, p->actualWidth[i]);
3205 fputs(i==nColumn-1?"\n":" ", p->out);
3206 }
3207 }
3208 break;
3209 }
3210 case MODE_Table: {
3211 colSep = " | ";
3212 rowSep = " |\n";
3213 print_row_separator(p, nColumn, "+");
3214 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003215 for(i=0; i<nColumn; i++){
3216 w = p->actualWidth[i];
drh0908e382020-06-04 18:05:39 +00003217 n = strlenChar(azData[i]);
3218 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
3219 fputs(i==nColumn-1?" |\n":" | ", p->out);
drh8c748632020-05-29 16:15:58 +00003220 }
drh0908e382020-06-04 18:05:39 +00003221 print_row_separator(p, nColumn, "+");
3222 break;
3223 }
3224 case MODE_Markdown: {
3225 colSep = " | ";
3226 rowSep = " |\n";
3227 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003228 for(i=0; i<nColumn; i++){
drh0908e382020-06-04 18:05:39 +00003229 w = p->actualWidth[i];
3230 n = strlenChar(azData[i]);
3231 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
3232 fputs(i==nColumn-1?" |\n":" | ", p->out);
drh8c748632020-05-29 16:15:58 +00003233 }
drh0908e382020-06-04 18:05:39 +00003234 print_row_separator(p, nColumn, "|");
3235 break;
drh8c748632020-05-29 16:15:58 +00003236 }
drh0908e382020-06-04 18:05:39 +00003237 case MODE_Box: {
3238 colSep = " " BOX_13 " ";
3239 rowSep = " " BOX_13 "\n";
3240 print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34);
3241 utf8_printf(p->out, BOX_13 " ");
3242 for(i=0; i<nColumn; i++){
3243 w = p->actualWidth[i];
3244 n = strlenChar(azData[i]);
3245 utf8_printf(p->out, "%*s%s%*s%s",
3246 (w-n)/2, "", azData[i], (w-n+1)/2, "",
3247 i==nColumn-1?" "BOX_13"\n":" "BOX_13" ");
3248 }
3249 print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
3250 break;
drh8c748632020-05-29 16:15:58 +00003251 }
drh8c748632020-05-29 16:15:58 +00003252 }
3253 for(i=nColumn, j=0; i<nTotal; i++, j++){
drh0908e382020-06-04 18:05:39 +00003254 if( j==0 && p->cMode!=MODE_Column ){
3255 utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| ");
3256 }
drh8c748632020-05-29 16:15:58 +00003257 z = azData[i];
3258 if( z==0 ) z = p->nullValue;
3259 w = p->actualWidth[j];
3260 if( p->colWidth[j]<0 ) w = -w;
3261 utf8_width_print(p->out, w, z);
3262 if( j==nColumn-1 ){
drh0908e382020-06-04 18:05:39 +00003263 utf8_printf(p->out, "%s", rowSep);
drh8c748632020-05-29 16:15:58 +00003264 j = -1;
drhdd853c32020-06-16 17:34:40 +00003265 if( seenInterrupt ) goto columnar_end;
drh8c748632020-05-29 16:15:58 +00003266 }else{
drh0908e382020-06-04 18:05:39 +00003267 utf8_printf(p->out, "%s", colSep);
drh8c748632020-05-29 16:15:58 +00003268 }
3269 }
3270 if( p->cMode==MODE_Table ){
3271 print_row_separator(p, nColumn, "+");
drh0908e382020-06-04 18:05:39 +00003272 }else if( p->cMode==MODE_Box ){
3273 print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14);
drh8c748632020-05-29 16:15:58 +00003274 }
drh99942982020-06-15 20:05:37 +00003275columnar_end:
drhdd853c32020-06-16 17:34:40 +00003276 if( seenInterrupt ){
3277 utf8_printf(p->out, "Interrupt\n");
3278 }
drhf82ce382020-08-06 16:45:22 +00003279 nData = (nRow+1)*nColumn;
3280 for(i=0; i<nData; i++) free(azData[i]);
3281 sqlite3_free(azData);
drh30c54a02020-05-28 23:49:50 +00003282}
drh30c54a02020-05-28 23:49:50 +00003283
drh2ce15c32017-07-11 13:34:40 +00003284/*
3285** Run a prepared statement
3286*/
3287static void exec_prepared_stmt(
3288 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003289 sqlite3_stmt *pStmt /* Statment to run */
drh2ce15c32017-07-11 13:34:40 +00003290){
3291 int rc;
3292
drh8c748632020-05-29 16:15:58 +00003293 if( pArg->cMode==MODE_Column
3294 || pArg->cMode==MODE_Table
drh0908e382020-06-04 18:05:39 +00003295 || pArg->cMode==MODE_Box
drh8c748632020-05-29 16:15:58 +00003296 || pArg->cMode==MODE_Markdown
3297 ){
3298 exec_prepared_stmt_columnar(pArg, pStmt);
3299 return;
3300 }
3301
drh2ce15c32017-07-11 13:34:40 +00003302 /* perform the first step. this will tell us if we
3303 ** have a result set or not and how wide it is.
3304 */
3305 rc = sqlite3_step(pStmt);
3306 /* if we have a result set... */
3307 if( SQLITE_ROW == rc ){
drha10b9992018-03-09 15:24:33 +00003308 /* allocate space for col name ptr, value ptr, and type */
3309 int nCol = sqlite3_column_count(pStmt);
3310 void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
3311 if( !pData ){
3312 rc = SQLITE_NOMEM;
drh2ce15c32017-07-11 13:34:40 +00003313 }else{
drha10b9992018-03-09 15:24:33 +00003314 char **azCols = (char **)pData; /* Names of result columns */
3315 char **azVals = &azCols[nCol]; /* Results */
3316 int *aiTypes = (int *)&azVals[nCol]; /* Result types */
3317 int i, x;
3318 assert(sizeof(int) <= sizeof(char *));
3319 /* save off ptrs to column names */
3320 for(i=0; i<nCol; i++){
3321 azCols[i] = (char *)sqlite3_column_name(pStmt, i);
3322 }
drh2ce15c32017-07-11 13:34:40 +00003323 do{
drha10b9992018-03-09 15:24:33 +00003324 /* extract the data and data types */
3325 for(i=0; i<nCol; i++){
3326 aiTypes[i] = x = sqlite3_column_type(pStmt, i);
3327 if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
3328 azVals[i] = "";
3329 }else{
3330 azVals[i] = (char*)sqlite3_column_text(pStmt, i);
3331 }
3332 if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
3333 rc = SQLITE_NOMEM;
3334 break; /* from for */
3335 }
3336 } /* end for */
3337
3338 /* if data and types extracted successfully... */
3339 if( SQLITE_ROW == rc ){
3340 /* call the supplied callback with the result row data */
3341 if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){
3342 rc = SQLITE_ABORT;
3343 }else{
3344 rc = sqlite3_step(pStmt);
3345 }
3346 }
3347 } while( SQLITE_ROW == rc );
3348 sqlite3_free(pData);
drh0908e382020-06-04 18:05:39 +00003349 if( pArg->cMode==MODE_Json ){
drh30c54a02020-05-28 23:49:50 +00003350 fputs("]\n", pArg->out);
3351 }
drh2ce15c32017-07-11 13:34:40 +00003352 }
3353 }
3354}
3355
dan6b046be2018-01-09 15:25:55 +00003356#ifndef SQLITE_OMIT_VIRTUALTABLE
drh2ce15c32017-07-11 13:34:40 +00003357/*
dan43efc182017-12-19 17:42:13 +00003358** This function is called to process SQL if the previous shell command
3359** was ".expert". It passes the SQL in the second argument directly to
3360** the sqlite3expert object.
3361**
3362** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3363** code. In this case, (*pzErr) may be set to point to a buffer containing
3364** an English language error message. It is the responsibility of the
3365** caller to eventually free this buffer using sqlite3_free().
3366*/
3367static int expertHandleSQL(
3368 ShellState *pState,
3369 const char *zSql,
3370 char **pzErr
3371){
3372 assert( pState->expert.pExpert );
3373 assert( pzErr==0 || *pzErr==0 );
3374 return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr);
3375}
3376
3377/*
3378** This function is called either to silently clean up the object
3379** created by the ".expert" command (if bCancel==1), or to generate a
3380** report from it and then clean it up (if bCancel==0).
3381**
3382** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3383** code. In this case, (*pzErr) may be set to point to a buffer containing
3384** an English language error message. It is the responsibility of the
3385** caller to eventually free this buffer using sqlite3_free().
3386*/
3387static int expertFinish(
3388 ShellState *pState,
3389 int bCancel,
3390 char **pzErr
3391){
3392 int rc = SQLITE_OK;
3393 sqlite3expert *p = pState->expert.pExpert;
3394 assert( p );
3395 assert( bCancel || pzErr==0 || *pzErr==0 );
3396 if( bCancel==0 ){
3397 FILE *out = pState->out;
3398 int bVerbose = pState->expert.bVerbose;
3399
3400 rc = sqlite3_expert_analyze(p, pzErr);
3401 if( rc==SQLITE_OK ){
3402 int nQuery = sqlite3_expert_count(p);
3403 int i;
3404
3405 if( bVerbose ){
3406 const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
3407 raw_printf(out, "-- Candidates -----------------------------\n");
3408 raw_printf(out, "%s\n", zCand);
3409 }
3410 for(i=0; i<nQuery; i++){
3411 const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
3412 const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
3413 const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
3414 if( zIdx==0 ) zIdx = "(no new indexes)\n";
3415 if( bVerbose ){
3416 raw_printf(out, "-- Query %d --------------------------------\n",i+1);
3417 raw_printf(out, "%s\n\n", zSql);
3418 }
3419 raw_printf(out, "%s\n", zIdx);
3420 raw_printf(out, "%s\n", zEQP);
3421 }
3422 }
3423 }
3424 sqlite3_expert_destroy(p);
3425 pState->expert.pExpert = 0;
3426 return rc;
3427}
3428
dan6b046be2018-01-09 15:25:55 +00003429/*
3430** Implementation of ".expert" dot command.
3431*/
3432static int expertDotCommand(
3433 ShellState *pState, /* Current shell tool state */
3434 char **azArg, /* Array of arguments passed to dot command */
3435 int nArg /* Number of entries in azArg[] */
3436){
3437 int rc = SQLITE_OK;
3438 char *zErr = 0;
3439 int i;
3440 int iSample = 0;
3441
3442 assert( pState->expert.pExpert==0 );
3443 memset(&pState->expert, 0, sizeof(ExpertInfo));
3444
3445 for(i=1; rc==SQLITE_OK && i<nArg; i++){
3446 char *z = azArg[i];
3447 int n;
3448 if( z[0]=='-' && z[1]=='-' ) z++;
3449 n = strlen30(z);
3450 if( n>=2 && 0==strncmp(z, "-verbose", n) ){
3451 pState->expert.bVerbose = 1;
3452 }
3453 else if( n>=2 && 0==strncmp(z, "-sample", n) ){
3454 if( i==(nArg-1) ){
3455 raw_printf(stderr, "option requires an argument: %s\n", z);
3456 rc = SQLITE_ERROR;
3457 }else{
3458 iSample = (int)integerValue(azArg[++i]);
3459 if( iSample<0 || iSample>100 ){
3460 raw_printf(stderr, "value out of range: %s\n", azArg[i]);
3461 rc = SQLITE_ERROR;
3462 }
3463 }
3464 }
3465 else{
3466 raw_printf(stderr, "unknown option: %s\n", z);
3467 rc = SQLITE_ERROR;
3468 }
3469 }
3470
3471 if( rc==SQLITE_OK ){
3472 pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
3473 if( pState->expert.pExpert==0 ){
3474 raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr);
3475 rc = SQLITE_ERROR;
3476 }else{
3477 sqlite3_expert_config(
3478 pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
3479 );
3480 }
3481 }
3482
3483 return rc;
3484}
3485#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
dan43efc182017-12-19 17:42:13 +00003486
3487/*
drh2ce15c32017-07-11 13:34:40 +00003488** Execute a statement or set of statements. Print
3489** any result rows/columns depending on the current mode
3490** set via the supplied callback.
3491**
3492** This is very similar to SQLite's built-in sqlite3_exec()
3493** function except it takes a slightly different callback
3494** and callback data argument.
3495*/
3496static int shell_exec(
drh2ce15c32017-07-11 13:34:40 +00003497 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003498 const char *zSql, /* SQL to be evaluated */
drh2ce15c32017-07-11 13:34:40 +00003499 char **pzErrMsg /* Error msg written here */
3500){
3501 sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
3502 int rc = SQLITE_OK; /* Return Code */
3503 int rc2;
3504 const char *zLeftover; /* Tail of unprocessed SQL */
drha10b9992018-03-09 15:24:33 +00003505 sqlite3 *db = pArg->db;
drh2ce15c32017-07-11 13:34:40 +00003506
3507 if( pzErrMsg ){
3508 *pzErrMsg = NULL;
3509 }
3510
dan6b046be2018-01-09 15:25:55 +00003511#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00003512 if( pArg->expert.pExpert ){
3513 rc = expertHandleSQL(pArg, zSql, pzErrMsg);
3514 return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
3515 }
dan6b046be2018-01-09 15:25:55 +00003516#endif
dan43efc182017-12-19 17:42:13 +00003517
drh2ce15c32017-07-11 13:34:40 +00003518 while( zSql[0] && (SQLITE_OK == rc) ){
3519 static const char *zStmtSql;
3520 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
3521 if( SQLITE_OK != rc ){
3522 if( pzErrMsg ){
3523 *pzErrMsg = save_err_msg(db);
3524 }
3525 }else{
3526 if( !pStmt ){
3527 /* this happens for a comment or white-space */
3528 zSql = zLeftover;
3529 while( IsSpace(zSql[0]) ) zSql++;
3530 continue;
3531 }
3532 zStmtSql = sqlite3_sql(pStmt);
3533 if( zStmtSql==0 ) zStmtSql = "";
3534 while( IsSpace(zStmtSql[0]) ) zStmtSql++;
3535
3536 /* save off the prepared statment handle and reset row count */
3537 if( pArg ){
3538 pArg->pStmt = pStmt;
3539 pArg->cnt = 0;
3540 }
3541
3542 /* echo the sql statement if echo on */
3543 if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
3544 utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
3545 }
3546
3547 /* Show the EXPLAIN QUERY PLAN if .eqp is on */
drh39c5c4a2019-03-06 14:53:27 +00003548 if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
drh2ce15c32017-07-11 13:34:40 +00003549 sqlite3_stmt *pExplain;
3550 char *zEQP;
drhada70452017-12-21 21:02:27 +00003551 int triggerEQP = 0;
drh2ce15c32017-07-11 13:34:40 +00003552 disable_debug_trace_modes();
drhada70452017-12-21 21:02:27 +00003553 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
3554 if( pArg->autoEQP>=AUTOEQP_trigger ){
3555 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
3556 }
drh2ce15c32017-07-11 13:34:40 +00003557 zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
3558 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3559 if( rc==SQLITE_OK ){
3560 while( sqlite3_step(pExplain)==SQLITE_ROW ){
drh4b5345c2018-04-24 13:07:40 +00003561 const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
drhe2ca99c2018-05-02 00:33:43 +00003562 int iEqpId = sqlite3_column_int(pExplain, 0);
3563 int iParentId = sqlite3_column_int(pExplain, 1);
drh7e088a62020-05-02 00:01:39 +00003564 if( zEQPLine==0 ) zEQPLine = "";
drh4b5345c2018-04-24 13:07:40 +00003565 if( zEQPLine[0]=='-' ) eqp_render(pArg);
drhe2ca99c2018-05-02 00:33:43 +00003566 eqp_append(pArg, iEqpId, iParentId, zEQPLine);
drh2ce15c32017-07-11 13:34:40 +00003567 }
drh4b5345c2018-04-24 13:07:40 +00003568 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003569 }
3570 sqlite3_finalize(pExplain);
3571 sqlite3_free(zEQP);
drhada70452017-12-21 21:02:27 +00003572 if( pArg->autoEQP>=AUTOEQP_full ){
drh2ce15c32017-07-11 13:34:40 +00003573 /* Also do an EXPLAIN for ".eqp full" mode */
3574 zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
3575 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3576 if( rc==SQLITE_OK ){
3577 pArg->cMode = MODE_Explain;
3578 explain_data_prepare(pArg, pExplain);
drha10b9992018-03-09 15:24:33 +00003579 exec_prepared_stmt(pArg, pExplain);
drh2ce15c32017-07-11 13:34:40 +00003580 explain_data_delete(pArg);
3581 }
3582 sqlite3_finalize(pExplain);
3583 sqlite3_free(zEQP);
3584 }
drh51efe092018-03-20 12:04:38 +00003585 if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
3586 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
3587 /* Reprepare pStmt before reactiving trace modes */
3588 sqlite3_finalize(pStmt);
3589 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
drh3c49eaf2018-06-07 15:23:43 +00003590 if( pArg ) pArg->pStmt = pStmt;
drh51efe092018-03-20 12:04:38 +00003591 }
drh2ce15c32017-07-11 13:34:40 +00003592 restore_debug_trace_modes();
3593 }
3594
3595 if( pArg ){
3596 pArg->cMode = pArg->mode;
drh4b5345c2018-04-24 13:07:40 +00003597 if( pArg->autoExplain ){
drh39c5c4a2019-03-06 14:53:27 +00003598 if( sqlite3_stmt_isexplain(pStmt)==1 ){
drh4b5345c2018-04-24 13:07:40 +00003599 pArg->cMode = MODE_Explain;
3600 }
drh39c5c4a2019-03-06 14:53:27 +00003601 if( sqlite3_stmt_isexplain(pStmt)==2 ){
drh4b5345c2018-04-24 13:07:40 +00003602 pArg->cMode = MODE_EQP;
3603 }
drh2ce15c32017-07-11 13:34:40 +00003604 }
3605
3606 /* If the shell is currently in ".explain" mode, gather the extra
3607 ** data required to add indents to the output.*/
3608 if( pArg->cMode==MODE_Explain ){
3609 explain_data_prepare(pArg, pStmt);
3610 }
3611 }
3612
drh8b738d02019-02-25 18:43:54 +00003613 bind_prepared_stmt(pArg, pStmt);
drha10b9992018-03-09 15:24:33 +00003614 exec_prepared_stmt(pArg, pStmt);
drh2ce15c32017-07-11 13:34:40 +00003615 explain_data_delete(pArg);
drh4b5345c2018-04-24 13:07:40 +00003616 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003617
3618 /* print usage stats if stats on */
3619 if( pArg && pArg->statsOn ){
3620 display_stats(db, pArg, 0);
3621 }
3622
3623 /* print loop-counters if required */
3624 if( pArg && pArg->scanstatsOn ){
3625 display_scanstats(db, pArg);
3626 }
3627
3628 /* Finalize the statement just executed. If this fails, save a
3629 ** copy of the error message. Otherwise, set zSql to point to the
3630 ** next statement to execute. */
3631 rc2 = sqlite3_finalize(pStmt);
3632 if( rc!=SQLITE_NOMEM ) rc = rc2;
3633 if( rc==SQLITE_OK ){
3634 zSql = zLeftover;
3635 while( IsSpace(zSql[0]) ) zSql++;
3636 }else if( pzErrMsg ){
3637 *pzErrMsg = save_err_msg(db);
3638 }
3639
3640 /* clear saved stmt handle */
3641 if( pArg ){
3642 pArg->pStmt = NULL;
3643 }
3644 }
3645 } /* end while */
3646
3647 return rc;
3648}
3649
3650/*
3651** Release memory previously allocated by tableColumnList().
3652*/
3653static void freeColumnList(char **azCol){
3654 int i;
3655 for(i=1; azCol[i]; i++){
3656 sqlite3_free(azCol[i]);
3657 }
3658 /* azCol[0] is a static string */
3659 sqlite3_free(azCol);
3660}
3661
3662/*
3663** Return a list of pointers to strings which are the names of all
3664** columns in table zTab. The memory to hold the names is dynamically
3665** allocated and must be released by the caller using a subsequent call
3666** to freeColumnList().
3667**
3668** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
3669** value that needs to be preserved, then azCol[0] is filled in with the
3670** name of the rowid column.
3671**
3672** The first regular column in the table is azCol[1]. The list is terminated
3673** by an entry with azCol[i]==0.
3674*/
3675static char **tableColumnList(ShellState *p, const char *zTab){
3676 char **azCol = 0;
3677 sqlite3_stmt *pStmt;
3678 char *zSql;
3679 int nCol = 0;
3680 int nAlloc = 0;
3681 int nPK = 0; /* Number of PRIMARY KEY columns seen */
3682 int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
3683 int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
3684 int rc;
3685
3686 zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
3687 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3688 sqlite3_free(zSql);
3689 if( rc ) return 0;
3690 while( sqlite3_step(pStmt)==SQLITE_ROW ){
3691 if( nCol>=nAlloc-2 ){
3692 nAlloc = nAlloc*2 + nCol + 10;
3693 azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
drh4b5345c2018-04-24 13:07:40 +00003694 if( azCol==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00003695 }
3696 azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
3697 if( sqlite3_column_int(pStmt, 5) ){
3698 nPK++;
3699 if( nPK==1
3700 && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
3701 "INTEGER")==0
3702 ){
3703 isIPK = 1;
3704 }else{
3705 isIPK = 0;
3706 }
3707 }
3708 }
3709 sqlite3_finalize(pStmt);
drh4c6cddc2017-10-12 10:28:30 +00003710 if( azCol==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00003711 azCol[0] = 0;
3712 azCol[nCol+1] = 0;
3713
3714 /* The decision of whether or not a rowid really needs to be preserved
3715 ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
3716 ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
3717 ** rowids on tables where the rowid is inaccessible because there are other
3718 ** columns in the table named "rowid", "_rowid_", and "oid".
3719 */
3720 if( preserveRowid && isIPK ){
3721 /* If a single PRIMARY KEY column with type INTEGER was seen, then it
3722 ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID
3723 ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
3724 ** ROWID aliases. To distinguish these cases, check to see if
3725 ** there is a "pk" entry in "PRAGMA index_list". There will be
3726 ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
3727 */
3728 zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
3729 " WHERE origin='pk'", zTab);
3730 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3731 sqlite3_free(zSql);
3732 if( rc ){
3733 freeColumnList(azCol);
3734 return 0;
3735 }
3736 rc = sqlite3_step(pStmt);
3737 sqlite3_finalize(pStmt);
3738 preserveRowid = rc==SQLITE_ROW;
3739 }
3740 if( preserveRowid ){
3741 /* Only preserve the rowid if we can find a name to use for the
3742 ** rowid */
3743 static char *azRowid[] = { "rowid", "_rowid_", "oid" };
3744 int i, j;
3745 for(j=0; j<3; j++){
3746 for(i=1; i<=nCol; i++){
3747 if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
3748 }
3749 if( i>nCol ){
3750 /* At this point, we know that azRowid[j] is not the name of any
3751 ** ordinary column in the table. Verify that azRowid[j] is a valid
3752 ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
3753 ** tables will fail this last check */
3754 rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
3755 if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
3756 break;
3757 }
3758 }
3759 }
3760 return azCol;
3761}
3762
3763/*
3764** Toggle the reverse_unordered_selects setting.
3765*/
3766static void toggleSelectOrder(sqlite3 *db){
3767 sqlite3_stmt *pStmt = 0;
3768 int iSetting = 0;
3769 char zStmt[100];
3770 sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0);
3771 if( sqlite3_step(pStmt)==SQLITE_ROW ){
3772 iSetting = sqlite3_column_int(pStmt, 0);
3773 }
3774 sqlite3_finalize(pStmt);
3775 sqlite3_snprintf(sizeof(zStmt), zStmt,
3776 "PRAGMA reverse_unordered_selects(%d)", !iSetting);
3777 sqlite3_exec(db, zStmt, 0, 0, 0);
3778}
3779
3780/*
3781** This is a different callback routine used for dumping the database.
3782** Each row received by this callback consists of a table name,
3783** the table type ("index" or "table") and SQL to create the table.
3784** This routine should print text sufficient to recreate the table.
3785*/
3786static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
3787 int rc;
3788 const char *zTable;
3789 const char *zType;
3790 const char *zSql;
3791 ShellState *p = (ShellState *)pArg;
mistachkina00a0162020-10-18 18:35:34 +00003792 int dataOnly;
3793 int noSys;
drh2ce15c32017-07-11 13:34:40 +00003794
3795 UNUSED_PARAMETER(azNotUsed);
drhb3c45232017-08-28 14:33:27 +00003796 if( nArg!=3 || azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00003797 zTable = azArg[0];
3798 zType = azArg[1];
3799 zSql = azArg[2];
mistachkina00a0162020-10-18 18:35:34 +00003800 dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
3801 noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
drh2ce15c32017-07-11 13:34:40 +00003802
drhc1962192020-10-12 16:54:28 +00003803 if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
3804 if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
3805 }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
3806 if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00003807 }else if( strncmp(zTable, "sqlite_", 7)==0 ){
3808 return 0;
drhc1962192020-10-12 16:54:28 +00003809 }else if( dataOnly ){
3810 /* no-op */
drh2ce15c32017-07-11 13:34:40 +00003811 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
3812 char *zIns;
3813 if( !p->writableSchema ){
3814 raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
3815 p->writableSchema = 1;
3816 }
3817 zIns = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00003818 "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
drh2ce15c32017-07-11 13:34:40 +00003819 "VALUES('table','%q','%q',0,'%q');",
3820 zTable, zTable, zSql);
3821 utf8_printf(p->out, "%s\n", zIns);
3822 sqlite3_free(zIns);
3823 return 0;
3824 }else{
3825 printSchemaLine(p->out, zSql, ";\n");
3826 }
3827
3828 if( strcmp(zType, "table")==0 ){
3829 ShellText sSelect;
3830 ShellText sTable;
3831 char **azCol;
3832 int i;
3833 char *savedDestTable;
3834 int savedMode;
3835
3836 azCol = tableColumnList(p, zTable);
3837 if( azCol==0 ){
3838 p->nErr++;
3839 return 0;
3840 }
3841
3842 /* Always quote the table name, even if it appears to be pure ascii,
3843 ** in case it is a keyword. Ex: INSERT INTO "table" ... */
3844 initText(&sTable);
3845 appendText(&sTable, zTable, quoteChar(zTable));
3846 /* If preserving the rowid, add a column list after the table name.
3847 ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
3848 ** instead of the usual "INSERT INTO tab VALUES(...)".
3849 */
3850 if( azCol[0] ){
3851 appendText(&sTable, "(", 0);
3852 appendText(&sTable, azCol[0], 0);
3853 for(i=1; azCol[i]; i++){
3854 appendText(&sTable, ",", 0);
3855 appendText(&sTable, azCol[i], quoteChar(azCol[i]));
3856 }
3857 appendText(&sTable, ")", 0);
3858 }
3859
3860 /* Build an appropriate SELECT statement */
3861 initText(&sSelect);
3862 appendText(&sSelect, "SELECT ", 0);
3863 if( azCol[0] ){
3864 appendText(&sSelect, azCol[0], 0);
3865 appendText(&sSelect, ",", 0);
3866 }
3867 for(i=1; azCol[i]; i++){
3868 appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
3869 if( azCol[i+1] ){
3870 appendText(&sSelect, ",", 0);
3871 }
3872 }
3873 freeColumnList(azCol);
3874 appendText(&sSelect, " FROM ", 0);
3875 appendText(&sSelect, zTable, quoteChar(zTable));
3876
3877 savedDestTable = p->zDestTable;
3878 savedMode = p->mode;
3879 p->zDestTable = sTable.z;
3880 p->mode = p->cMode = MODE_Insert;
drha10b9992018-03-09 15:24:33 +00003881 rc = shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00003882 if( (rc&0xff)==SQLITE_CORRUPT ){
3883 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
3884 toggleSelectOrder(p->db);
drha10b9992018-03-09 15:24:33 +00003885 shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00003886 toggleSelectOrder(p->db);
3887 }
3888 p->zDestTable = savedDestTable;
3889 p->mode = savedMode;
3890 freeText(&sTable);
3891 freeText(&sSelect);
3892 if( rc ) p->nErr++;
3893 }
3894 return 0;
3895}
3896
3897/*
3898** Run zQuery. Use dump_callback() as the callback routine so that
3899** the contents of the query are output as SQL statements.
3900**
3901** If we get a SQLITE_CORRUPT error, rerun the query after appending
3902** "ORDER BY rowid DESC" to the end.
3903*/
3904static int run_schema_dump_query(
3905 ShellState *p,
3906 const char *zQuery
3907){
3908 int rc;
3909 char *zErr = 0;
3910 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
3911 if( rc==SQLITE_CORRUPT ){
3912 char *zQ2;
3913 int len = strlen30(zQuery);
3914 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
3915 if( zErr ){
3916 utf8_printf(p->out, "/****** %s ******/\n", zErr);
3917 sqlite3_free(zErr);
3918 zErr = 0;
3919 }
3920 zQ2 = malloc( len+100 );
3921 if( zQ2==0 ) return rc;
3922 sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
3923 rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
3924 if( rc ){
3925 utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
3926 }else{
3927 rc = SQLITE_CORRUPT;
3928 }
3929 sqlite3_free(zErr);
3930 free(zQ2);
3931 }
3932 return rc;
3933}
3934
3935/*
drh98aa2ab2018-09-26 16:53:51 +00003936** Text of help messages.
3937**
3938** The help text for each individual command begins with a line that starts
3939** with ".". Subsequent lines are supplimental information.
3940**
3941** There must be two or more spaces between the end of the command and the
3942** start of the description of what that command does.
drh2ce15c32017-07-11 13:34:40 +00003943*/
drh98aa2ab2018-09-26 16:53:51 +00003944static const char *(azHelp[]) = {
drhe37c0e12018-01-06 19:19:50 +00003945#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drh98aa2ab2018-09-26 16:53:51 +00003946 ".archive ... Manage SQL archives",
3947 " Each command must have exactly one of the following options:",
3948 " -c, --create Create a new archive",
drhe2754c12019-08-26 12:50:01 +00003949 " -u, --update Add or update files with changed mtime",
3950 " -i, --insert Like -u but always add even if unchanged",
drh98aa2ab2018-09-26 16:53:51 +00003951 " -t, --list List contents of archive",
3952 " -x, --extract Extract files from archive",
3953 " Optional arguments:",
3954 " -v, --verbose Print each filename as it is processed",
drhe2754c12019-08-26 12:50:01 +00003955 " -f FILE, --file FILE Use archive FILE (default is current db)",
3956 " -a FILE, --append FILE Open FILE using the apndvfs VFS",
3957 " -C DIR, --directory DIR Read/extract files from directory DIR",
drh98aa2ab2018-09-26 16:53:51 +00003958 " -n, --dryrun Show the SQL that would have occurred",
3959 " Examples:",
drhe2754c12019-08-26 12:50:01 +00003960 " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
3961 " .ar -tf ARCHIVE # List members of ARCHIVE",
3962 " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE",
drh98aa2ab2018-09-26 16:53:51 +00003963 " See also:",
larrybrbd0d62c2021-06-13 08:23:28 +00003964 " http://sqlite.org/cli.html#sqlite_archive_support",
drhe37c0e12018-01-06 19:19:50 +00003965#endif
drh2ce15c32017-07-11 13:34:40 +00003966#ifndef SQLITE_OMIT_AUTHORIZATION
drh98aa2ab2018-09-26 16:53:51 +00003967 ".auth ON|OFF Show authorizer callbacks",
drh2ce15c32017-07-11 13:34:40 +00003968#endif
drh98aa2ab2018-09-26 16:53:51 +00003969 ".backup ?DB? FILE Backup DB (default \"main\") to FILE",
3970 " --append Use the appendvfs",
drhe2754c12019-08-26 12:50:01 +00003971 " --async Write to FILE without journal and fsync()",
drh98aa2ab2018-09-26 16:53:51 +00003972 ".bail on|off Stop after hitting an error. Default OFF",
3973 ".binary on|off Turn binary output on or off. Default OFF",
3974 ".cd DIRECTORY Change the working directory to DIRECTORY",
3975 ".changes on|off Show number of rows changed by SQL",
3976 ".check GLOB Fail if output since .testcase does not match",
3977 ".clone NEWDB Clone data into NEWDB from the existing database",
drh37407122021-07-23 18:43:58 +00003978 ".connection [close] [#] Open or close an auxiliary database connection",
drh98aa2ab2018-09-26 16:53:51 +00003979 ".databases List names and files of attached databases",
3980 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
3981 ".dbinfo ?DB? Show status information about the database",
larrybr7bdbe592021-03-15 12:56:00 +00003982 ".dump ?OBJECTS? Render database content as SQL",
drheb7f2a02018-09-26 18:02:32 +00003983 " Options:",
drhc1962192020-10-12 16:54:28 +00003984 " --data-only Output only INSERT statements",
drheb7f2a02018-09-26 18:02:32 +00003985 " --newlines Allow unescaped newline characters in output",
drhc1962192020-10-12 16:54:28 +00003986 " --nosys Omit system tables (ex: \"sqlite_stat1\")",
3987 " --preserve-rowids Include ROWID values in the output",
larrybr7bdbe592021-03-15 12:56:00 +00003988 " OBJECTS is a LIKE pattern for tables, indexes, triggers or views to dump",
drh8e9297f2020-03-25 12:50:13 +00003989 " Additional LIKE patterns can be given in subsequent arguments",
drh98aa2ab2018-09-26 16:53:51 +00003990 ".echo on|off Turn command echo on or off",
drhb4e50392019-01-26 15:40:04 +00003991 ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
3992 " Other Modes:",
3993#ifdef SQLITE_DEBUG
3994 " test Show raw EXPLAIN QUERY PLAN output",
drhe2754c12019-08-26 12:50:01 +00003995 " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"",
drhb4e50392019-01-26 15:40:04 +00003996#endif
3997 " trigger Like \"full\" but also show trigger bytecode",
drhe2754c12019-08-26 12:50:01 +00003998 ".excel Display the output of next command in spreadsheet",
drh7a431002020-04-18 14:12:00 +00003999 " --bom Put a UTF8 byte-order mark on intermediate file",
drheb7f2a02018-09-26 18:02:32 +00004000 ".exit ?CODE? Exit this program with return-code CODE",
drhe2754c12019-08-26 12:50:01 +00004001 ".expert EXPERIMENTAL. Suggest indexes for queries",
drh978256f2019-11-02 00:00:14 +00004002 ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto",
drhd985f722019-06-05 14:29:53 +00004003 ".filectrl CMD ... Run various sqlite3_file_control() operations",
drh541ef2c2020-04-20 16:21:30 +00004004 " --schema SCHEMA Use SCHEMA instead of \"main\"",
4005 " --help Show CMD details",
drh98aa2ab2018-09-26 16:53:51 +00004006 ".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
4007 ".headers on|off Turn display of headers on or off",
4008 ".help ?-all? ?PATTERN? Show help text for PATTERN",
4009 ".import FILE TABLE Import data from FILE into TABLE",
drhccb37812020-03-09 15:39:39 +00004010 " Options:",
4011 " --ascii Use \\037 and \\036 as column and row separators",
4012 " --csv Use , and \\n as column and row separators",
4013 " --skip N Skip the first N rows of input",
4014 " -v \"Verbose\" - increase auxiliary output",
4015 " Notes:",
4016 " * If TABLE does not exist, it is created. The first row of input",
4017 " determines the column names.",
4018 " * If neither --csv or --ascii are used, the input mode is derived",
4019 " from the \".mode\" output mode",
4020 " * If FILE begins with \"|\" then it is a command that generates the",
4021 " input text.",
drh2ce15c32017-07-11 13:34:40 +00004022#ifndef SQLITE_OMIT_TEST_CONTROL
drh98aa2ab2018-09-26 16:53:51 +00004023 ".imposter INDEX TABLE Create imposter table TABLE on index INDEX",
drh2ce15c32017-07-11 13:34:40 +00004024#endif
drh98aa2ab2018-09-26 16:53:51 +00004025 ".indexes ?TABLE? Show names of indexes",
4026 " If TABLE is specified, only show indexes for",
4027 " tables matching TABLE using the LIKE operator.",
drh2ce15c32017-07-11 13:34:40 +00004028#ifdef SQLITE_ENABLE_IOTRACE
drh98aa2ab2018-09-26 16:53:51 +00004029 ".iotrace FILE Enable I/O diagnostic logging to FILE",
drh2ce15c32017-07-11 13:34:40 +00004030#endif
drh98aa2ab2018-09-26 16:53:51 +00004031 ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
4032 ".lint OPTIONS Report potential schema issues.",
4033 " Options:",
4034 " fkey-indexes Find missing foreign key indexes",
drh2ce15c32017-07-11 13:34:40 +00004035#ifndef SQLITE_OMIT_LOAD_EXTENSION
drh98aa2ab2018-09-26 16:53:51 +00004036 ".load FILE ?ENTRY? Load an extension library",
drh2ce15c32017-07-11 13:34:40 +00004037#endif
drh98aa2ab2018-09-26 16:53:51 +00004038 ".log FILE|off Turn logging on or off. FILE can be stderr/stdout",
4039 ".mode MODE ?TABLE? Set output mode",
4040 " MODE is one of:",
drh7da29a32020-05-29 19:17:20 +00004041 " ascii Columns/rows delimited by 0x1F and 0x1E",
drh0908e382020-06-04 18:05:39 +00004042 " box Tables using unicode box-drawing characters",
drh7da29a32020-05-29 19:17:20 +00004043 " csv Comma-separated values",
4044 " column Output in columns. (See .width)",
4045 " html HTML <table> code",
4046 " insert SQL insert statements for TABLE",
4047 " json Results in a JSON array",
4048 " line One value per line",
4049 " list Values delimited by \"|\"",
4050 " markdown Markdown table format",
4051 " quote Escape answers as for SQL",
4052 " table ASCII-art table",
4053 " tabs Tab-separated values",
4054 " tcl TCL list elements",
drhb97e2ad2021-08-26 18:31:39 +00004055 ".nonce STRING Disable safe mode for one command if the nonce matches",
drh98aa2ab2018-09-26 16:53:51 +00004056 ".nullvalue STRING Use STRING in place of NULL values",
drh7a431002020-04-18 14:12:00 +00004057 ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE",
drh98aa2ab2018-09-26 16:53:51 +00004058 " If FILE begins with '|' then open as a pipe",
drh7a431002020-04-18 14:12:00 +00004059 " --bom Put a UTF8 byte-order mark at the beginning",
4060 " -e Send output to the system text editor",
4061 " -x Send output as CSV to a spreadsheet (same as \".excel\")",
drh4a3a3eb2020-02-29 15:53:48 +00004062#ifdef SQLITE_DEBUG
drhc0605082020-06-05 00:54:27 +00004063 ".oom ?--repeat M? ?N? Simulate an OOM error on the N-th allocation",
drh4a3a3eb2020-02-29 15:53:48 +00004064#endif
drh98aa2ab2018-09-26 16:53:51 +00004065 ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
4066 " Options:",
drh60f34ae2018-10-30 13:19:49 +00004067 " --append Use appendvfs to append database to the end of FILE",
drh8d889af2021-05-08 17:18:23 +00004068#ifndef SQLITE_OMIT_DESERIALIZE
drhd10c3ca2021-05-08 11:57:35 +00004069 " --deserialize Load into memory using sqlite3_deserialize()",
drhe2754c12019-08-26 12:50:01 +00004070 " --hexdb Load the output of \"dbtotxt\" as an in-memory db",
drh6ca64482019-01-22 16:06:20 +00004071 " --maxsize N Maximum size for --hexdb or --deserialized database",
drha751f392018-10-30 15:31:22 +00004072#endif
drh60f34ae2018-10-30 13:19:49 +00004073 " --new Initialize FILE to an empty database",
drh0933aad2019-11-18 17:46:38 +00004074 " --nofollow Do not follow symbolic links",
drh60f34ae2018-10-30 13:19:49 +00004075 " --readonly Open FILE readonly",
4076 " --zip FILE is a ZIP archive",
drh98aa2ab2018-09-26 16:53:51 +00004077 ".output ?FILE? Send output to FILE or stdout if FILE is omitted",
drh7a431002020-04-18 14:12:00 +00004078 " If FILE begins with '|' then open it as a pipe.",
4079 " Options:",
4080 " --bom Prefix output with a UTF8 byte-order mark",
4081 " -e Send output to the system text editor",
4082 " -x Send output as CSV to a spreadsheet",
drh9cb02642019-02-28 20:10:52 +00004083 ".parameter CMD ... Manage SQL parameter bindings",
4084 " clear Erase all bindings",
4085 " init Initialize the TEMP table that holds bindings",
4086 " list List the current parameter bindings",
4087 " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE",
drhe2754c12019-08-26 12:50:01 +00004088 " PARAMETER should start with one of: $ : @ ?",
drh9cb02642019-02-28 20:10:52 +00004089 " unset PARAMETER Remove PARAMETER from the binding table",
drh98aa2ab2018-09-26 16:53:51 +00004090 ".print STRING... Print literal STRING",
drh569b1d92019-02-05 20:51:41 +00004091#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh3f83f592019-02-04 14:53:18 +00004092 ".progress N Invoke progress handler after every N opcodes",
4093 " --limit N Interrupt after N progress callbacks",
4094 " --once Do no more than one progress interrupt",
4095 " --quiet|-q No output except at interrupts",
4096 " --reset Reset the count for each input and interrupt",
drh569b1d92019-02-05 20:51:41 +00004097#endif
drh98aa2ab2018-09-26 16:53:51 +00004098 ".prompt MAIN CONTINUE Replace the standard prompts",
4099 ".quit Exit this program",
4100 ".read FILE Read input from FILE",
dan1b162162019-04-27 20:15:15 +00004101#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan42ebb012019-04-27 18:47:03 +00004102 ".recover Recover as much data as possible from corrupt db.",
drhe2754c12019-08-26 12:50:01 +00004103 " --freelist-corrupt Assume the freelist is corrupt",
4104 " --recovery-db NAME Store recovery metadata in database file NAME",
4105 " --lost-and-found TABLE Alternative name for the lost-and-found table",
dan8cce6b82019-09-14 16:44:51 +00004106 " --no-rowids Do not attempt to recover rowid values",
4107 " that are not also INTEGER PRIMARY KEYs",
dan1b162162019-04-27 20:15:15 +00004108#endif
drh98aa2ab2018-09-26 16:53:51 +00004109 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
4110 ".save FILE Write in-memory database into FILE",
4111 ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
4112 ".schema ?PATTERN? Show the CREATE statements matching PATTERN",
drhbbb29ec2020-10-12 14:56:47 +00004113 " Options:",
4114 " --indent Try to pretty-print the schema",
4115 " --nosys Omit objects whose names start with \"sqlite_\"",
drheb7f2a02018-09-26 18:02:32 +00004116 ".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
4117 " Options:",
4118 " --init Create a new SELFTEST table",
4119 " -v Verbose output",
drh98aa2ab2018-09-26 16:53:51 +00004120 ".separator COL ?ROW? Change the column and row separators",
drh2ce15c32017-07-11 13:34:40 +00004121#if defined(SQLITE_ENABLE_SESSION)
drheb7f2a02018-09-26 18:02:32 +00004122 ".session ?NAME? CMD ... Create or control sessions",
4123 " Subcommands:",
4124 " attach TABLE Attach TABLE",
4125 " changeset FILE Write a changeset into FILE",
4126 " close Close one session",
4127 " enable ?BOOLEAN? Set or query the enable bit",
4128 " filter GLOB... Reject tables matching GLOBs",
4129 " indirect ?BOOLEAN? Mark or query the indirect status",
4130 " isempty Query whether the session is empty",
4131 " list List currently open session names",
4132 " open DB NAME Open a new session on DB",
4133 " patchset FILE Write a patchset into FILE",
4134 " If ?NAME? is omitted, the first defined session is used.",
drh2ce15c32017-07-11 13:34:40 +00004135#endif
drheb7f2a02018-09-26 18:02:32 +00004136 ".sha3sum ... Compute a SHA3 hash of database content",
4137 " Options:",
drh067b92b2020-06-19 15:24:12 +00004138 " --schema Also hash the sqlite_schema table",
drheb7f2a02018-09-26 18:02:32 +00004139 " --sha3-224 Use the sha3-224 algorithm",
drhe2754c12019-08-26 12:50:01 +00004140 " --sha3-256 Use the sha3-256 algorithm (default)",
drheb7f2a02018-09-26 18:02:32 +00004141 " --sha3-384 Use the sha3-384 algorithm",
4142 " --sha3-512 Use the sha3-512 algorithm",
4143 " Any other argument is a LIKE pattern for tables to hash",
drh04a28c32018-01-31 01:38:44 +00004144#ifndef SQLITE_NOHAVE_SYSTEM
drh98aa2ab2018-09-26 16:53:51 +00004145 ".shell CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004146#endif
drh98aa2ab2018-09-26 16:53:51 +00004147 ".show Show the current values for various settings",
drha6e6cf22021-01-09 19:10:04 +00004148 ".stats ?ARG? Show stats or turn stats on or off",
4149 " off Turn off automatic stat display",
4150 " on Turn on automatic stat display",
4151 " stmt Show statement stats",
4152 " vmstep Show the virtual machine step count only",
drh04a28c32018-01-31 01:38:44 +00004153#ifndef SQLITE_NOHAVE_SYSTEM
drh98aa2ab2018-09-26 16:53:51 +00004154 ".system CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004155#endif
drh98aa2ab2018-09-26 16:53:51 +00004156 ".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
4157 ".testcase NAME Begin redirecting output to 'testcase-out.txt'",
drhd985f722019-06-05 14:29:53 +00004158 ".testctrl CMD ... Run various sqlite3_test_control() operations",
4159 " Run \".testctrl\" with no arguments for details",
drh98aa2ab2018-09-26 16:53:51 +00004160 ".timeout MS Try opening locked tables for MS milliseconds",
4161 ".timer on|off Turn SQL timer on or off",
drh707821f2018-12-05 13:39:06 +00004162#ifndef SQLITE_OMIT_TRACE
4163 ".trace ?OPTIONS? Output each SQL statement as it is run",
4164 " FILE Send output to FILE",
4165 " stdout Send output to stdout",
4166 " stderr Send output to stderr",
4167 " off Disable tracing",
4168 " --expanded Expand query parameters",
4169#ifdef SQLITE_ENABLE_NORMALIZE
4170 " --normalized Normal the SQL statements",
4171#endif
4172 " --plain Show SQL as it is input",
4173 " --stmt Trace statement execution (SQLITE_TRACE_STMT)",
4174 " --profile Profile statements (SQLITE_TRACE_PROFILE)",
4175 " --row Trace each row (SQLITE_TRACE_ROW)",
4176 " --close Trace connection close (SQLITE_TRACE_CLOSE)",
4177#endif /* SQLITE_OMIT_TRACE */
drhcc5979d2019-08-16 22:58:29 +00004178#ifdef SQLITE_DEBUG
4179 ".unmodule NAME ... Unregister virtual table modules",
drh5df84282019-08-17 19:45:25 +00004180 " --allexcept Unregister everything except those named",
drhcc5979d2019-08-16 22:58:29 +00004181#endif
drh98aa2ab2018-09-26 16:53:51 +00004182 ".vfsinfo ?AUX? Information about the top-level VFS",
4183 ".vfslist List all available VFSes",
4184 ".vfsname ?AUX? Print the name of the VFS stack",
drh7da29a32020-05-29 19:17:20 +00004185 ".width NUM1 NUM2 ... Set minimum column widths for columnar output",
drh98aa2ab2018-09-26 16:53:51 +00004186 " Negative values right-justify",
4187};
4188
4189/*
4190** Output help text.
4191**
4192** zPattern describes the set of commands for which help text is provided.
4193** If zPattern is NULL, then show all commands, but only give a one-line
4194** description of each.
4195**
4196** Return the number of matches.
4197*/
4198static int showHelp(FILE *out, const char *zPattern){
drhe93f8262018-10-11 16:53:37 +00004199 int i = 0;
4200 int j = 0;
drh98aa2ab2018-09-26 16:53:51 +00004201 int n = 0;
4202 char *zPat;
drh488cddf2018-10-06 14:38:17 +00004203 if( zPattern==0
4204 || zPattern[0]=='0'
4205 || strcmp(zPattern,"-a")==0
4206 || strcmp(zPattern,"-all")==0
drh7a431002020-04-18 14:12:00 +00004207 || strcmp(zPattern,"--all")==0
drh488cddf2018-10-06 14:38:17 +00004208 ){
drh98aa2ab2018-09-26 16:53:51 +00004209 /* Show all commands, but only one line per command */
drh488cddf2018-10-06 14:38:17 +00004210 if( zPattern==0 ) zPattern = "";
drh98aa2ab2018-09-26 16:53:51 +00004211 for(i=0; i<ArraySize(azHelp); i++){
drh488cddf2018-10-06 14:38:17 +00004212 if( azHelp[i][0]=='.' || zPattern[0] ){
drh98aa2ab2018-09-26 16:53:51 +00004213 utf8_printf(out, "%s\n", azHelp[i]);
4214 n++;
4215 }
4216 }
4217 }else{
4218 /* Look for commands that for which zPattern is an exact prefix */
4219 zPat = sqlite3_mprintf(".%s*", zPattern);
4220 for(i=0; i<ArraySize(azHelp); i++){
4221 if( sqlite3_strglob(zPat, azHelp[i])==0 ){
4222 utf8_printf(out, "%s\n", azHelp[i]);
drheb7f2a02018-09-26 18:02:32 +00004223 j = i+1;
drh98aa2ab2018-09-26 16:53:51 +00004224 n++;
4225 }
4226 }
4227 sqlite3_free(zPat);
drheb7f2a02018-09-26 18:02:32 +00004228 if( n ){
4229 if( n==1 ){
4230 /* when zPattern is a prefix of exactly one command, then include the
4231 ** details of that command, which should begin at offset j */
4232 while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){
4233 utf8_printf(out, "%s\n", azHelp[j]);
4234 j++;
4235 }
4236 }
4237 return n;
4238 }
4239 /* Look for commands that contain zPattern anywhere. Show the complete
4240 ** text of all commands that match. */
drh98aa2ab2018-09-26 16:53:51 +00004241 zPat = sqlite3_mprintf("%%%s%%", zPattern);
4242 for(i=0; i<ArraySize(azHelp); i++){
4243 if( azHelp[i][0]=='.' ) j = i;
4244 if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
4245 utf8_printf(out, "%s\n", azHelp[j]);
4246 while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
4247 j++;
4248 utf8_printf(out, "%s\n", azHelp[j]);
4249 }
4250 i = j;
4251 n++;
4252 }
4253 }
4254 sqlite3_free(zPat);
4255 }
4256 return n;
4257}
drh2ce15c32017-07-11 13:34:40 +00004258
drh2ce15c32017-07-11 13:34:40 +00004259/* Forward reference */
drh60379d42018-12-13 18:30:01 +00004260static int process_input(ShellState *p);
drh2ce15c32017-07-11 13:34:40 +00004261
4262/*
4263** Read the content of file zName into memory obtained from sqlite3_malloc64()
4264** and return a pointer to the buffer. The caller is responsible for freeing
4265** the memory.
4266**
4267** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
4268** read.
4269**
4270** For convenience, a nul-terminator byte is always appended to the data read
4271** from the file before the buffer is returned. This byte is not included in
4272** the final value of (*pnByte), if applicable.
4273**
4274** NULL is returned if any error is encountered. The final value of *pnByte
4275** is undefined in this case.
4276*/
4277static char *readFile(const char *zName, int *pnByte){
4278 FILE *in = fopen(zName, "rb");
4279 long nIn;
4280 size_t nRead;
4281 char *pBuf;
4282 if( in==0 ) return 0;
4283 fseek(in, 0, SEEK_END);
4284 nIn = ftell(in);
4285 rewind(in);
4286 pBuf = sqlite3_malloc64( nIn+1 );
drh1dbb1472018-10-11 10:37:24 +00004287 if( pBuf==0 ){ fclose(in); return 0; }
drh2ce15c32017-07-11 13:34:40 +00004288 nRead = fread(pBuf, nIn, 1, in);
4289 fclose(in);
4290 if( nRead!=1 ){
4291 sqlite3_free(pBuf);
4292 return 0;
4293 }
4294 pBuf[nIn] = 0;
4295 if( pnByte ) *pnByte = nIn;
4296 return pBuf;
4297}
4298
4299#if defined(SQLITE_ENABLE_SESSION)
4300/*
4301** Close a single OpenSession object and release all of its associated
4302** resources.
4303*/
4304static void session_close(OpenSession *pSession){
4305 int i;
4306 sqlite3session_delete(pSession->p);
4307 sqlite3_free(pSession->zName);
4308 for(i=0; i<pSession->nFilter; i++){
4309 sqlite3_free(pSession->azFilter[i]);
4310 }
4311 sqlite3_free(pSession->azFilter);
4312 memset(pSession, 0, sizeof(OpenSession));
4313}
4314#endif
4315
4316/*
4317** Close all OpenSession objects and release all associated resources.
4318*/
4319#if defined(SQLITE_ENABLE_SESSION)
drh37407122021-07-23 18:43:58 +00004320static void session_close_all(ShellState *p, int i){
4321 int j;
4322 struct AuxDb *pAuxDb = i<0 ? p->pAuxDb : &p->aAuxDb[i];
4323 for(j=0; j<pAuxDb->nSession; j++){
4324 session_close(&pAuxDb->aSession[j]);
drh2ce15c32017-07-11 13:34:40 +00004325 }
drh37407122021-07-23 18:43:58 +00004326 pAuxDb->nSession = 0;
drh2ce15c32017-07-11 13:34:40 +00004327}
4328#else
drh37407122021-07-23 18:43:58 +00004329# define session_close_all(X,Y)
drh2ce15c32017-07-11 13:34:40 +00004330#endif
4331
4332/*
4333** Implementation of the xFilter function for an open session. Omit
4334** any tables named by ".session filter" but let all other table through.
4335*/
4336#if defined(SQLITE_ENABLE_SESSION)
4337static int session_filter(void *pCtx, const char *zTab){
4338 OpenSession *pSession = (OpenSession*)pCtx;
4339 int i;
4340 for(i=0; i<pSession->nFilter; i++){
4341 if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
4342 }
4343 return 1;
4344}
4345#endif
4346
4347/*
drh1fa6d9f2018-01-06 21:46:01 +00004348** Try to deduce the type of file for zName based on its content. Return
4349** one of the SHELL_OPEN_* constants.
drh1bf208c2018-03-09 21:54:01 +00004350**
4351** If the file does not exist or is empty but its name looks like a ZIP
4352** archive and the dfltZip flag is true, then assume it is a ZIP archive.
4353** Otherwise, assume an ordinary database regardless of the filename if
4354** the type cannot be determined from content.
drh1fa6d9f2018-01-06 21:46:01 +00004355*/
drhfc97c1c2018-05-14 00:41:12 +00004356int deduceDatabaseType(const char *zName, int dfltZip){
drh1fa6d9f2018-01-06 21:46:01 +00004357 FILE *f = fopen(zName, "rb");
4358 size_t n;
4359 int rc = SHELL_OPEN_UNSPEC;
4360 char zBuf[100];
drh1bf208c2018-03-09 21:54:01 +00004361 if( f==0 ){
drhbe4ccb22018-05-17 20:04:24 +00004362 if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
4363 return SHELL_OPEN_ZIPFILE;
4364 }else{
4365 return SHELL_OPEN_NORMAL;
4366 }
drh1bf208c2018-03-09 21:54:01 +00004367 }
drh2b3c4af2018-10-30 14:36:21 +00004368 n = fread(zBuf, 16, 1, f);
4369 if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
4370 fclose(f);
4371 return SHELL_OPEN_NORMAL;
4372 }
drh1fa6d9f2018-01-06 21:46:01 +00004373 fseek(f, -25, SEEK_END);
4374 n = fread(zBuf, 25, 1, f);
4375 if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
4376 rc = SHELL_OPEN_APPENDVFS;
4377 }else{
4378 fseek(f, -22, SEEK_END);
4379 n = fread(zBuf, 22, 1, f);
4380 if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
4381 && zBuf[3]==0x06 ){
4382 rc = SHELL_OPEN_ZIPFILE;
drh1bf208c2018-03-09 21:54:01 +00004383 }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
mistachkina3926f42018-05-14 12:23:04 +00004384 rc = SHELL_OPEN_ZIPFILE;
drh1fa6d9f2018-01-06 21:46:01 +00004385 }
4386 }
4387 fclose(f);
4388 return rc;
4389}
4390
drh8d889af2021-05-08 17:18:23 +00004391#ifndef SQLITE_OMIT_DESERIALIZE
drh33746482018-12-13 15:06:26 +00004392/*
4393** Reconstruct an in-memory database using the output from the "dbtotxt"
drh37407122021-07-23 18:43:58 +00004394** program. Read content from the file in p->aAuxDb[].zDbFilename.
4395** If p->aAuxDb[].zDbFilename is 0, then read from standard input.
drh33746482018-12-13 15:06:26 +00004396*/
4397static unsigned char *readHexDb(ShellState *p, int *pnData){
4398 unsigned char *a = 0;
drh2c8ee022018-12-13 18:59:30 +00004399 int nLine;
drh33746482018-12-13 15:06:26 +00004400 int n = 0;
4401 int pgsz = 0;
4402 int iOffset = 0;
4403 int j, k;
4404 int rc;
4405 FILE *in;
drh37407122021-07-23 18:43:58 +00004406 const char *zDbFilename = p->pAuxDb->zDbFilename;
drh3ea557e2019-04-23 15:30:58 +00004407 unsigned int x[16];
drh2c8ee022018-12-13 18:59:30 +00004408 char zLine[1000];
drh37407122021-07-23 18:43:58 +00004409 if( zDbFilename ){
4410 in = fopen(zDbFilename, "r");
drh33746482018-12-13 15:06:26 +00004411 if( in==0 ){
drh37407122021-07-23 18:43:58 +00004412 utf8_printf(stderr, "cannot open \"%s\" for reading\n", zDbFilename);
drh33746482018-12-13 15:06:26 +00004413 return 0;
4414 }
drh2c8ee022018-12-13 18:59:30 +00004415 nLine = 0;
drh33746482018-12-13 15:06:26 +00004416 }else{
drh60379d42018-12-13 18:30:01 +00004417 in = p->in;
drh2c8ee022018-12-13 18:59:30 +00004418 nLine = p->lineno;
drh5bf46442019-05-03 02:41:36 +00004419 if( in==0 ) in = stdin;
drh33746482018-12-13 15:06:26 +00004420 }
4421 *pnData = 0;
drh2c8ee022018-12-13 18:59:30 +00004422 nLine++;
drh33746482018-12-13 15:06:26 +00004423 if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
4424 rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
4425 if( rc!=2 ) goto readHexDb_error;
drh68feae52019-05-09 11:18:41 +00004426 if( n<0 ) goto readHexDb_error;
drh09ea1252019-07-17 15:05:16 +00004427 if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
4428 n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */
drh68feae52019-05-09 11:18:41 +00004429 a = sqlite3_malloc( n ? n : 1 );
drh33746482018-12-13 15:06:26 +00004430 if( a==0 ){
4431 utf8_printf(stderr, "Out of memory!\n");
4432 goto readHexDb_error;
4433 }
4434 memset(a, 0, n);
4435 if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
4436 utf8_printf(stderr, "invalid pagesize\n");
4437 goto readHexDb_error;
4438 }
drh2c8ee022018-12-13 18:59:30 +00004439 for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
drh33746482018-12-13 15:06:26 +00004440 rc = sscanf(zLine, "| page %d offset %d", &j, &k);
4441 if( rc==2 ){
4442 iOffset = k;
4443 continue;
4444 }
4445 if( strncmp(zLine, "| end ", 6)==0 ){
4446 break;
4447 }
drh3ea557e2019-04-23 15:30:58 +00004448 rc = sscanf(zLine,"| %d: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
drh33746482018-12-13 15:06:26 +00004449 &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
4450 &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
4451 if( rc==17 ){
4452 k = iOffset+j;
drhf354e772018-12-13 22:58:52 +00004453 if( k+16<=n ){
drh3ea557e2019-04-23 15:30:58 +00004454 int ii;
4455 for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
drh33746482018-12-13 15:06:26 +00004456 }
drh33746482018-12-13 15:06:26 +00004457 }
4458 }
4459 *pnData = n;
drh2c8ee022018-12-13 18:59:30 +00004460 if( in!=p->in ){
4461 fclose(in);
4462 }else{
4463 p->lineno = nLine;
4464 }
drh33746482018-12-13 15:06:26 +00004465 return a;
4466
4467readHexDb_error:
drh68feae52019-05-09 11:18:41 +00004468 if( in!=p->in ){
drh33746482018-12-13 15:06:26 +00004469 fclose(in);
4470 }else{
drh60379d42018-12-13 18:30:01 +00004471 while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
drh2c8ee022018-12-13 18:59:30 +00004472 nLine++;
drh33746482018-12-13 15:06:26 +00004473 if(strncmp(zLine, "| end ", 6)==0 ) break;
4474 }
drh2c8ee022018-12-13 18:59:30 +00004475 p->lineno = nLine;
drh33746482018-12-13 15:06:26 +00004476 }
4477 sqlite3_free(a);
4478 utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
4479 return 0;
4480}
drh8d889af2021-05-08 17:18:23 +00004481#endif /* SQLITE_OMIT_DESERIALIZE */
drh33746482018-12-13 15:06:26 +00004482
danb1825882019-04-23 20:48:32 +00004483/*
dan9c014f82019-04-25 19:23:15 +00004484** Scalar function "shell_int32". The first argument to this function
4485** must be a blob. The second a non-negative integer. This function
4486** reads and returns a 32-bit big-endian integer from byte
4487** offset (4*<arg2>) of the blob.
4488*/
4489static void shellInt32(
4490 sqlite3_context *context,
4491 int argc,
4492 sqlite3_value **argv
4493){
4494 const unsigned char *pBlob;
4495 int nBlob;
4496 int iInt;
drh9546c762019-05-10 17:50:33 +00004497
4498 UNUSED_PARAMETER(argc);
dan9c014f82019-04-25 19:23:15 +00004499 nBlob = sqlite3_value_bytes(argv[0]);
4500 pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
4501 iInt = sqlite3_value_int(argv[1]);
4502
4503 if( iInt>=0 && (iInt+1)*4<=nBlob ){
4504 const unsigned char *a = &pBlob[iInt*4];
4505 sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24)
4506 + ((sqlite3_int64)a[1]<<16)
4507 + ((sqlite3_int64)a[2]<< 8)
4508 + ((sqlite3_int64)a[3]<< 0);
4509 sqlite3_result_int64(context, iVal);
4510 }
4511}
4512
4513/*
drha2de66c2019-08-06 20:26:17 +00004514** Scalar function "shell_idquote(X)" returns string X quoted as an identifier,
4515** using "..." with internal double-quote characters doubled.
4516*/
4517static void shellIdQuote(
4518 sqlite3_context *context,
4519 int argc,
4520 sqlite3_value **argv
4521){
4522 const char *zName = (const char*)sqlite3_value_text(argv[0]);
drh51755a72019-08-08 19:40:29 +00004523 UNUSED_PARAMETER(argc);
drha2de66c2019-08-06 20:26:17 +00004524 if( zName ){
4525 char *z = sqlite3_mprintf("\"%w\"", zName);
4526 sqlite3_result_text(context, z, -1, sqlite3_free);
4527 }
4528}
4529
4530/*
drhddcfe922020-09-15 12:29:35 +00004531** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
4532*/
4533static void shellUSleepFunc(
4534 sqlite3_context *context,
drhd36f5882020-11-25 16:28:04 +00004535 int argcUnused,
drhddcfe922020-09-15 12:29:35 +00004536 sqlite3_value **argv
4537){
4538 int sleep = sqlite3_value_int(argv[0]);
drhd36f5882020-11-25 16:28:04 +00004539 (void)argcUnused;
drhddcfe922020-09-15 12:29:35 +00004540 sqlite3_sleep(sleep/1000);
4541 sqlite3_result_int(context, sleep);
4542}
4543
4544/*
danb1825882019-04-23 20:48:32 +00004545** Scalar function "shell_escape_crnl" used by the .recover command.
4546** The argument passed to this function is the output of built-in
4547** function quote(). If the first character of the input is "'",
4548** indicating that the value passed to quote() was a text value,
4549** then this function searches the input for "\n" and "\r" characters
4550** and adds a wrapper similar to the following:
4551**
4552** replace(replace(<input>, '\n', char(10), '\r', char(13));
4553**
4554** Or, if the first character of the input is not "'", then a copy
4555** of the input is returned.
4556*/
4557static void shellEscapeCrnl(
4558 sqlite3_context *context,
4559 int argc,
4560 sqlite3_value **argv
4561){
4562 const char *zText = (const char*)sqlite3_value_text(argv[0]);
drh9546c762019-05-10 17:50:33 +00004563 UNUSED_PARAMETER(argc);
danb1825882019-04-23 20:48:32 +00004564 if( zText[0]=='\'' ){
4565 int nText = sqlite3_value_bytes(argv[0]);
4566 int i;
4567 char zBuf1[20];
4568 char zBuf2[20];
4569 const char *zNL = 0;
4570 const char *zCR = 0;
4571 int nCR = 0;
4572 int nNL = 0;
4573
4574 for(i=0; zText[i]; i++){
4575 if( zNL==0 && zText[i]=='\n' ){
4576 zNL = unused_string(zText, "\\n", "\\012", zBuf1);
4577 nNL = (int)strlen(zNL);
4578 }
4579 if( zCR==0 && zText[i]=='\r' ){
4580 zCR = unused_string(zText, "\\r", "\\015", zBuf2);
4581 nCR = (int)strlen(zCR);
4582 }
4583 }
4584
4585 if( zNL || zCR ){
4586 int iOut = 0;
4587 i64 nMax = (nNL > nCR) ? nNL : nCR;
dan51f5ffa2019-04-29 11:41:46 +00004588 i64 nAlloc = nMax * nText + (nMax+64)*2;
danb1825882019-04-23 20:48:32 +00004589 char *zOut = (char*)sqlite3_malloc64(nAlloc);
4590 if( zOut==0 ){
4591 sqlite3_result_error_nomem(context);
4592 return;
4593 }
4594
4595 if( zNL && zCR ){
4596 memcpy(&zOut[iOut], "replace(replace(", 16);
4597 iOut += 16;
4598 }else{
4599 memcpy(&zOut[iOut], "replace(", 8);
4600 iOut += 8;
4601 }
4602 for(i=0; zText[i]; i++){
4603 if( zText[i]=='\n' ){
4604 memcpy(&zOut[iOut], zNL, nNL);
4605 iOut += nNL;
4606 }else if( zText[i]=='\r' ){
4607 memcpy(&zOut[iOut], zCR, nCR);
4608 iOut += nCR;
4609 }else{
4610 zOut[iOut] = zText[i];
4611 iOut++;
4612 }
4613 }
4614
4615 if( zNL ){
4616 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
4617 memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
4618 memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
4619 }
4620 if( zCR ){
4621 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
4622 memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
4623 memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
4624 }
4625
4626 sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
4627 sqlite3_free(zOut);
4628 return;
4629 }
4630 }
4631
4632 sqlite3_result_value(context, argv[0]);
4633}
4634
drhbe4ccb22018-05-17 20:04:24 +00004635/* Flags for open_db().
4636**
4637** The default behavior of open_db() is to exit(1) if the database fails to
4638** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
4639** but still returns without calling exit.
4640**
4641** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a
4642** ZIP archive if the file does not exist or is empty and its name matches
4643** the *.zip pattern.
4644*/
4645#define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */
4646#define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */
4647
drh1fa6d9f2018-01-06 21:46:01 +00004648/*
drh2ce15c32017-07-11 13:34:40 +00004649** Make sure the database is open. If it is not, then open it. If
4650** the database fails to open, print an error message and exit.
4651*/
drhbe4ccb22018-05-17 20:04:24 +00004652static void open_db(ShellState *p, int openFlags){
drh2ce15c32017-07-11 13:34:40 +00004653 if( p->db==0 ){
drh37407122021-07-23 18:43:58 +00004654 const char *zDbFilename = p->pAuxDb->zDbFilename;
drhf2072d12018-05-11 15:10:11 +00004655 if( p->openMode==SHELL_OPEN_UNSPEC ){
drh37407122021-07-23 18:43:58 +00004656 if( zDbFilename==0 || zDbFilename[0]==0 ){
drhf2072d12018-05-11 15:10:11 +00004657 p->openMode = SHELL_OPEN_NORMAL;
drhbe4ccb22018-05-17 20:04:24 +00004658 }else{
drh37407122021-07-23 18:43:58 +00004659 p->openMode = (u8)deduceDatabaseType(zDbFilename,
drhbe4ccb22018-05-17 20:04:24 +00004660 (openFlags & OPEN_DB_ZIPFILE)!=0);
drhf2072d12018-05-11 15:10:11 +00004661 }
drh1fa6d9f2018-01-06 21:46:01 +00004662 }
4663 switch( p->openMode ){
4664 case SHELL_OPEN_APPENDVFS: {
drh37407122021-07-23 18:43:58 +00004665 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004666 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
drh1fa6d9f2018-01-06 21:46:01 +00004667 break;
4668 }
drh33746482018-12-13 15:06:26 +00004669 case SHELL_OPEN_HEXDB:
drh60f34ae2018-10-30 13:19:49 +00004670 case SHELL_OPEN_DESERIALIZE: {
4671 sqlite3_open(0, &p->db);
4672 break;
4673 }
drh1fa6d9f2018-01-06 21:46:01 +00004674 case SHELL_OPEN_ZIPFILE: {
4675 sqlite3_open(":memory:", &p->db);
4676 break;
4677 }
drhee269a62018-02-14 23:27:43 +00004678 case SHELL_OPEN_READONLY: {
drh37407122021-07-23 18:43:58 +00004679 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004680 SQLITE_OPEN_READONLY|p->openFlags, 0);
drhee269a62018-02-14 23:27:43 +00004681 break;
4682 }
drh1fa6d9f2018-01-06 21:46:01 +00004683 case SHELL_OPEN_UNSPEC:
4684 case SHELL_OPEN_NORMAL: {
drh37407122021-07-23 18:43:58 +00004685 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004686 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
drh1fa6d9f2018-01-06 21:46:01 +00004687 break;
4688 }
4689 }
drh2ce15c32017-07-11 13:34:40 +00004690 globalDb = p->db;
4691 if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
4692 utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
drh37407122021-07-23 18:43:58 +00004693 zDbFilename, sqlite3_errmsg(p->db));
drhf25cc4f2019-01-04 14:29:21 +00004694 if( openFlags & OPEN_DB_KEEPALIVE ){
4695 sqlite3_open(":memory:", &p->db);
4696 return;
4697 }
drh2ce15c32017-07-11 13:34:40 +00004698 exit(1);
4699 }
4700#ifndef SQLITE_OMIT_LOAD_EXTENSION
4701 sqlite3_enable_load_extension(p->db, 1);
4702#endif
4703 sqlite3_fileio_init(p->db, 0, 0);
4704 sqlite3_shathree_init(p->db, 0, 0);
drh56eb09b2017-07-11 13:59:07 +00004705 sqlite3_completion_init(p->db, 0, 0);
drhf05dd032020-04-14 15:53:58 +00004706 sqlite3_uint_init(p->db, 0, 0);
drhbeb9def2020-06-22 19:12:23 +00004707 sqlite3_decimal_init(p->db, 0, 0);
drh64689902021-06-03 13:51:31 +00004708 sqlite3_regexp_init(p->db, 0, 0);
drh8cda77d2020-06-24 15:06:29 +00004709 sqlite3_ieee_init(p->db, 0, 0);
mistachkin72c38d82020-08-28 18:47:39 +00004710 sqlite3_series_init(p->db, 0, 0);
dan1b162162019-04-27 20:15:15 +00004711#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00004712 sqlite3_dbdata_init(p->db, 0, 0);
dan1b162162019-04-27 20:15:15 +00004713#endif
dan72afc3c2017-12-05 18:32:40 +00004714#ifdef SQLITE_HAVE_ZLIB
dan9ebfaad2017-12-26 20:39:58 +00004715 sqlite3_zipfile_init(p->db, 0, 0);
dand1b51d42017-12-16 19:11:26 +00004716 sqlite3_sqlar_init(p->db, 0, 0);
dan72afc3c2017-12-05 18:32:40 +00004717#endif
drhceba7922018-01-01 21:28:25 +00004718 sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
drh2ce15c32017-07-11 13:34:40 +00004719 shellAddSchemaName, 0, 0);
drh667a2a22018-01-02 00:04:37 +00004720 sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
4721 shellModuleSchema, 0, 0);
drh634c70f2018-01-10 16:50:18 +00004722 sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
4723 shellPutsFunc, 0, 0);
danb1825882019-04-23 20:48:32 +00004724 sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0,
4725 shellEscapeCrnl, 0, 0);
dan9c014f82019-04-25 19:23:15 +00004726 sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
4727 shellInt32, 0, 0);
drha2de66c2019-08-06 20:26:17 +00004728 sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
4729 shellIdQuote, 0, 0);
drhddcfe922020-09-15 12:29:35 +00004730 sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
4731 shellUSleepFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00004732#ifndef SQLITE_NOHAVE_SYSTEM
drh97913132018-01-11 00:04:00 +00004733 sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
4734 editFunc, 0, 0);
4735 sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
4736 editFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00004737#endif
drh1fa6d9f2018-01-06 21:46:01 +00004738 if( p->openMode==SHELL_OPEN_ZIPFILE ){
4739 char *zSql = sqlite3_mprintf(
drh37407122021-07-23 18:43:58 +00004740 "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename);
drh1fa6d9f2018-01-06 21:46:01 +00004741 sqlite3_exec(p->db, zSql, 0, 0, 0);
4742 sqlite3_free(zSql);
drha751f392018-10-30 15:31:22 +00004743 }
drh8d889af2021-05-08 17:18:23 +00004744#ifndef SQLITE_OMIT_DESERIALIZE
drh33746482018-12-13 15:06:26 +00004745 else
4746 if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
mistachkin99490932018-12-17 22:19:57 +00004747 int rc;
drh60f34ae2018-10-30 13:19:49 +00004748 int nData = 0;
drh33746482018-12-13 15:06:26 +00004749 unsigned char *aData;
4750 if( p->openMode==SHELL_OPEN_DESERIALIZE ){
drh37407122021-07-23 18:43:58 +00004751 aData = (unsigned char*)readFile(zDbFilename, &nData);
drh33746482018-12-13 15:06:26 +00004752 }else{
4753 aData = readHexDb(p, &nData);
4754 if( aData==0 ){
drh33746482018-12-13 15:06:26 +00004755 return;
4756 }
4757 }
mistachkin99490932018-12-17 22:19:57 +00004758 rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
drh60f34ae2018-10-30 13:19:49 +00004759 SQLITE_DESERIALIZE_RESIZEABLE |
4760 SQLITE_DESERIALIZE_FREEONCLOSE);
4761 if( rc ){
4762 utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
4763 }
drh6ca64482019-01-22 16:06:20 +00004764 if( p->szMax>0 ){
4765 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
4766 }
drh1fa6d9f2018-01-06 21:46:01 +00004767 }
drha751f392018-10-30 15:31:22 +00004768#endif
drh2ce15c32017-07-11 13:34:40 +00004769 }
drhb97e2ad2021-08-26 18:31:39 +00004770 if( p->bSafeModePersist && p->db!=0 ){
4771 sqlite3_set_authorizer(p->db, safeModeAuth, p);
4772 }
drh2ce15c32017-07-11 13:34:40 +00004773}
4774
drh9e804032018-05-18 17:11:50 +00004775/*
4776** Attempt to close the databaes connection. Report errors.
4777*/
4778void close_db(sqlite3 *db){
4779 int rc = sqlite3_close(db);
4780 if( rc ){
4781 utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
4782 rc, sqlite3_errmsg(db));
4783 }
4784}
4785
drh56eb09b2017-07-11 13:59:07 +00004786#if HAVE_READLINE || HAVE_EDITLINE
4787/*
4788** Readline completion callbacks
4789*/
4790static char *readline_completion_generator(const char *text, int state){
4791 static sqlite3_stmt *pStmt = 0;
4792 char *zRet;
4793 if( state==0 ){
4794 char *zSql;
drh56eb09b2017-07-11 13:59:07 +00004795 sqlite3_finalize(pStmt);
4796 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
4797 " FROM completion(%Q) ORDER BY 1", text);
4798 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
4799 sqlite3_free(zSql);
4800 }
4801 if( sqlite3_step(pStmt)==SQLITE_ROW ){
drh968d8712017-07-14 00:28:28 +00004802 zRet = strdup((const char*)sqlite3_column_text(pStmt, 0));
drh56eb09b2017-07-11 13:59:07 +00004803 }else{
4804 sqlite3_finalize(pStmt);
4805 pStmt = 0;
4806 zRet = 0;
4807 }
4808 return zRet;
4809}
4810static char **readline_completion(const char *zText, int iStart, int iEnd){
4811 rl_attempted_completion_over = 1;
4812 return rl_completion_matches(zText, readline_completion_generator);
4813}
4814
4815#elif HAVE_LINENOISE
4816/*
4817** Linenoise completion callback
4818*/
4819static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
drhaf2770f2018-01-05 14:55:43 +00004820 int nLine = strlen30(zLine);
drh56eb09b2017-07-11 13:59:07 +00004821 int i, iStart;
4822 sqlite3_stmt *pStmt = 0;
4823 char *zSql;
4824 char zBuf[1000];
4825
4826 if( nLine>sizeof(zBuf)-30 ) return;
drh1615c372018-05-12 23:56:22 +00004827 if( zLine[0]=='.' || zLine[0]=='#') return;
drh56eb09b2017-07-11 13:59:07 +00004828 for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
4829 if( i==nLine-1 ) return;
4830 iStart = i+1;
4831 memcpy(zBuf, zLine, iStart);
4832 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
4833 " FROM completion(%Q,%Q) ORDER BY 1",
4834 &zLine[iStart], zLine);
4835 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
4836 sqlite3_free(zSql);
4837 sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
4838 while( sqlite3_step(pStmt)==SQLITE_ROW ){
4839 const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
4840 int nCompletion = sqlite3_column_bytes(pStmt, 0);
4841 if( iStart+nCompletion < sizeof(zBuf)-1 ){
4842 memcpy(zBuf+iStart, zCompletion, nCompletion+1);
4843 linenoiseAddCompletion(lc, zBuf);
4844 }
4845 }
4846 sqlite3_finalize(pStmt);
4847}
4848#endif
4849
drh2ce15c32017-07-11 13:34:40 +00004850/*
4851** Do C-language style dequoting.
4852**
4853** \a -> alarm
4854** \b -> backspace
4855** \t -> tab
4856** \n -> newline
4857** \v -> vertical tab
4858** \f -> form feed
4859** \r -> carriage return
4860** \s -> space
4861** \" -> "
4862** \' -> '
4863** \\ -> backslash
4864** \NNN -> ascii character NNN in octal
4865*/
4866static void resolve_backslashes(char *z){
4867 int i, j;
4868 char c;
4869 while( *z && *z!='\\' ) z++;
4870 for(i=j=0; (c = z[i])!=0; i++, j++){
4871 if( c=='\\' && z[i+1]!=0 ){
4872 c = z[++i];
4873 if( c=='a' ){
4874 c = '\a';
4875 }else if( c=='b' ){
4876 c = '\b';
4877 }else if( c=='t' ){
4878 c = '\t';
4879 }else if( c=='n' ){
4880 c = '\n';
4881 }else if( c=='v' ){
4882 c = '\v';
4883 }else if( c=='f' ){
4884 c = '\f';
4885 }else if( c=='r' ){
4886 c = '\r';
4887 }else if( c=='"' ){
4888 c = '"';
4889 }else if( c=='\'' ){
4890 c = '\'';
4891 }else if( c=='\\' ){
4892 c = '\\';
4893 }else if( c>='0' && c<='7' ){
4894 c -= '0';
4895 if( z[i+1]>='0' && z[i+1]<='7' ){
4896 i++;
4897 c = (c<<3) + z[i] - '0';
4898 if( z[i+1]>='0' && z[i+1]<='7' ){
4899 i++;
4900 c = (c<<3) + z[i] - '0';
4901 }
4902 }
4903 }
4904 }
4905 z[j] = c;
4906 }
4907 if( j<i ) z[j] = 0;
4908}
4909
4910/*
drh2ce15c32017-07-11 13:34:40 +00004911** Interpret zArg as either an integer or a boolean value. Return 1 or 0
4912** for TRUE and FALSE. Return the integer value if appropriate.
4913*/
4914static int booleanValue(const char *zArg){
4915 int i;
4916 if( zArg[0]=='0' && zArg[1]=='x' ){
4917 for(i=2; hexDigitValue(zArg[i])>=0; i++){}
4918 }else{
4919 for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
4920 }
4921 if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
4922 if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
4923 return 1;
4924 }
4925 if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
4926 return 0;
4927 }
4928 utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
4929 zArg);
4930 return 0;
4931}
4932
4933/*
4934** Set or clear a shell flag according to a boolean value.
4935*/
4936static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){
4937 if( booleanValue(zArg) ){
4938 ShellSetFlag(p, mFlag);
4939 }else{
4940 ShellClearFlag(p, mFlag);
4941 }
4942}
4943
4944/*
4945** Close an output file, assuming it is not stderr or stdout
4946*/
4947static void output_file_close(FILE *f){
4948 if( f && f!=stdout && f!=stderr ) fclose(f);
4949}
4950
4951/*
4952** Try to open an output file. The names "stdout" and "stderr" are
4953** recognized and do the right thing. NULL is returned if the output
4954** filename is "off".
4955*/
drha92a01a2018-01-10 22:15:37 +00004956static FILE *output_file_open(const char *zFile, int bTextMode){
drh2ce15c32017-07-11 13:34:40 +00004957 FILE *f;
4958 if( strcmp(zFile,"stdout")==0 ){
4959 f = stdout;
4960 }else if( strcmp(zFile, "stderr")==0 ){
4961 f = stderr;
4962 }else if( strcmp(zFile, "off")==0 ){
4963 f = 0;
4964 }else{
drha92a01a2018-01-10 22:15:37 +00004965 f = fopen(zFile, bTextMode ? "w" : "wb");
drh2ce15c32017-07-11 13:34:40 +00004966 if( f==0 ){
4967 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
4968 }
4969 }
4970 return f;
4971}
4972
drh707821f2018-12-05 13:39:06 +00004973#ifndef SQLITE_OMIT_TRACE
drh2ce15c32017-07-11 13:34:40 +00004974/*
4975** A routine for handling output from sqlite3_trace().
4976*/
4977static int sql_trace_callback(
drh707821f2018-12-05 13:39:06 +00004978 unsigned mType, /* The trace type */
4979 void *pArg, /* The ShellState pointer */
4980 void *pP, /* Usually a pointer to sqlite_stmt */
4981 void *pX /* Auxiliary output */
drh2ce15c32017-07-11 13:34:40 +00004982){
drh707821f2018-12-05 13:39:06 +00004983 ShellState *p = (ShellState*)pArg;
4984 sqlite3_stmt *pStmt;
4985 const char *zSql;
4986 int nSql;
4987 if( p->traceOut==0 ) return 0;
4988 if( mType==SQLITE_TRACE_CLOSE ){
4989 utf8_printf(p->traceOut, "-- closing database connection\n");
4990 return 0;
4991 }
4992 if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){
4993 zSql = (const char*)pX;
4994 }else{
4995 pStmt = (sqlite3_stmt*)pP;
4996 switch( p->eTraceType ){
4997 case SHELL_TRACE_EXPANDED: {
4998 zSql = sqlite3_expanded_sql(pStmt);
4999 break;
5000 }
5001#ifdef SQLITE_ENABLE_NORMALIZE
5002 case SHELL_TRACE_NORMALIZED: {
5003 zSql = sqlite3_normalized_sql(pStmt);
5004 break;
5005 }
5006#endif
5007 default: {
5008 zSql = sqlite3_sql(pStmt);
5009 break;
5010 }
5011 }
5012 }
5013 if( zSql==0 ) return 0;
5014 nSql = strlen30(zSql);
5015 while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
5016 switch( mType ){
5017 case SQLITE_TRACE_ROW:
5018 case SQLITE_TRACE_STMT: {
5019 utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql);
5020 break;
5021 }
5022 case SQLITE_TRACE_PROFILE: {
5023 sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
5024 utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec);
5025 break;
5026 }
drh2ce15c32017-07-11 13:34:40 +00005027 }
5028 return 0;
5029}
5030#endif
drh2ce15c32017-07-11 13:34:40 +00005031
5032/*
5033** A no-op routine that runs with the ".breakpoint" doc-command. This is
5034** a useful spot to set a debugger breakpoint.
5035*/
5036static void test_breakpoint(void){
5037 static int nCall = 0;
5038 nCall++;
5039}
5040
5041/*
5042** An object used to read a CSV and other files for import.
5043*/
5044typedef struct ImportCtx ImportCtx;
5045struct ImportCtx {
5046 const char *zFile; /* Name of the input file */
5047 FILE *in; /* Read the CSV text from this input stream */
drh97767842020-05-29 19:39:35 +00005048 int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */
drh2ce15c32017-07-11 13:34:40 +00005049 char *z; /* Accumulated text for a field */
5050 int n; /* Number of bytes in z */
5051 int nAlloc; /* Space allocated for z[] */
5052 int nLine; /* Current line number */
drhccb37812020-03-09 15:39:39 +00005053 int nRow; /* Number of rows imported */
5054 int nErr; /* Number of errors encountered */
drh2ce15c32017-07-11 13:34:40 +00005055 int bNotFirst; /* True if one or more bytes already read */
5056 int cTerm; /* Character that terminated the most recent field */
5057 int cColSep; /* The column separator character. (Usually ",") */
5058 int cRowSep; /* The row separator character. (Usually "\n") */
5059};
5060
drh97767842020-05-29 19:39:35 +00005061/* Clean up resourced used by an ImportCtx */
5062static void import_cleanup(ImportCtx *p){
drh42c2a042020-05-29 20:16:19 +00005063 if( p->in!=0 && p->xCloser!=0 ){
drh97767842020-05-29 19:39:35 +00005064 p->xCloser(p->in);
5065 p->in = 0;
5066 }
5067 sqlite3_free(p->z);
5068 p->z = 0;
5069}
5070
drh2ce15c32017-07-11 13:34:40 +00005071/* Append a single byte to z[] */
5072static void import_append_char(ImportCtx *p, int c){
5073 if( p->n+1>=p->nAlloc ){
5074 p->nAlloc += p->nAlloc + 100;
5075 p->z = sqlite3_realloc64(p->z, p->nAlloc);
drh4b5345c2018-04-24 13:07:40 +00005076 if( p->z==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00005077 }
5078 p->z[p->n++] = (char)c;
5079}
5080
5081/* Read a single field of CSV text. Compatible with rfc4180 and extended
5082** with the option of having a separator other than ",".
5083**
5084** + Input comes from p->in.
5085** + Store results in p->z of length p->n. Space to hold p->z comes
5086** from sqlite3_malloc64().
5087** + Use p->cSep as the column separator. The default is ",".
5088** + Use p->rSep as the row separator. The default is "\n".
5089** + Keep track of the line number in p->nLine.
5090** + Store the character that terminates the field in p->cTerm. Store
5091** EOF on end-of-file.
5092** + Report syntax errors on stderr
5093*/
5094static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
5095 int c;
5096 int cSep = p->cColSep;
5097 int rSep = p->cRowSep;
5098 p->n = 0;
5099 c = fgetc(p->in);
5100 if( c==EOF || seenInterrupt ){
5101 p->cTerm = EOF;
5102 return 0;
5103 }
5104 if( c=='"' ){
5105 int pc, ppc;
5106 int startLine = p->nLine;
5107 int cQuote = c;
5108 pc = ppc = 0;
5109 while( 1 ){
5110 c = fgetc(p->in);
5111 if( c==rSep ) p->nLine++;
5112 if( c==cQuote ){
5113 if( pc==cQuote ){
5114 pc = 0;
5115 continue;
5116 }
5117 }
5118 if( (c==cSep && pc==cQuote)
5119 || (c==rSep && pc==cQuote)
5120 || (c==rSep && pc=='\r' && ppc==cQuote)
5121 || (c==EOF && pc==cQuote)
5122 ){
5123 do{ p->n--; }while( p->z[p->n]!=cQuote );
5124 p->cTerm = c;
5125 break;
5126 }
5127 if( pc==cQuote && c!='\r' ){
5128 utf8_printf(stderr, "%s:%d: unescaped %c character\n",
5129 p->zFile, p->nLine, cQuote);
5130 }
5131 if( c==EOF ){
5132 utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
5133 p->zFile, startLine, cQuote);
5134 p->cTerm = c;
5135 break;
5136 }
5137 import_append_char(p, c);
5138 ppc = pc;
5139 pc = c;
5140 }
5141 }else{
5142 /* If this is the first field being parsed and it begins with the
5143 ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
5144 if( (c&0xff)==0xef && p->bNotFirst==0 ){
5145 import_append_char(p, c);
5146 c = fgetc(p->in);
5147 if( (c&0xff)==0xbb ){
5148 import_append_char(p, c);
5149 c = fgetc(p->in);
5150 if( (c&0xff)==0xbf ){
5151 p->bNotFirst = 1;
5152 p->n = 0;
5153 return csv_read_one_field(p);
5154 }
5155 }
5156 }
5157 while( c!=EOF && c!=cSep && c!=rSep ){
5158 import_append_char(p, c);
5159 c = fgetc(p->in);
5160 }
5161 if( c==rSep ){
5162 p->nLine++;
5163 if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
5164 }
5165 p->cTerm = c;
5166 }
5167 if( p->z ) p->z[p->n] = 0;
5168 p->bNotFirst = 1;
5169 return p->z;
5170}
5171
5172/* Read a single field of ASCII delimited text.
5173**
5174** + Input comes from p->in.
5175** + Store results in p->z of length p->n. Space to hold p->z comes
5176** from sqlite3_malloc64().
5177** + Use p->cSep as the column separator. The default is "\x1F".
5178** + Use p->rSep as the row separator. The default is "\x1E".
5179** + Keep track of the row number in p->nLine.
5180** + Store the character that terminates the field in p->cTerm. Store
5181** EOF on end-of-file.
5182** + Report syntax errors on stderr
5183*/
5184static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
5185 int c;
5186 int cSep = p->cColSep;
5187 int rSep = p->cRowSep;
5188 p->n = 0;
5189 c = fgetc(p->in);
5190 if( c==EOF || seenInterrupt ){
5191 p->cTerm = EOF;
5192 return 0;
5193 }
5194 while( c!=EOF && c!=cSep && c!=rSep ){
5195 import_append_char(p, c);
5196 c = fgetc(p->in);
5197 }
5198 if( c==rSep ){
5199 p->nLine++;
5200 }
5201 p->cTerm = c;
5202 if( p->z ) p->z[p->n] = 0;
5203 return p->z;
5204}
5205
5206/*
5207** Try to transfer data for table zTable. If an error is seen while
5208** moving forward, try to go backwards. The backwards movement won't
5209** work for WITHOUT ROWID tables.
5210*/
5211static void tryToCloneData(
5212 ShellState *p,
5213 sqlite3 *newDb,
5214 const char *zTable
5215){
5216 sqlite3_stmt *pQuery = 0;
5217 sqlite3_stmt *pInsert = 0;
5218 char *zQuery = 0;
5219 char *zInsert = 0;
5220 int rc;
5221 int i, j, n;
drhaf2770f2018-01-05 14:55:43 +00005222 int nTable = strlen30(zTable);
drh2ce15c32017-07-11 13:34:40 +00005223 int k = 0;
5224 int cnt = 0;
5225 const int spinRate = 10000;
5226
5227 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
5228 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5229 if( rc ){
5230 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5231 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5232 zQuery);
5233 goto end_data_xfer;
5234 }
5235 n = sqlite3_column_count(pQuery);
5236 zInsert = sqlite3_malloc64(200 + nTable + n*3);
drh4b5345c2018-04-24 13:07:40 +00005237 if( zInsert==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00005238 sqlite3_snprintf(200+nTable,zInsert,
5239 "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
drhaf2770f2018-01-05 14:55:43 +00005240 i = strlen30(zInsert);
drh2ce15c32017-07-11 13:34:40 +00005241 for(j=1; j<n; j++){
5242 memcpy(zInsert+i, ",?", 2);
5243 i += 2;
5244 }
5245 memcpy(zInsert+i, ");", 3);
5246 rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
5247 if( rc ){
5248 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5249 sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
5250 zQuery);
5251 goto end_data_xfer;
5252 }
5253 for(k=0; k<2; k++){
5254 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5255 for(i=0; i<n; i++){
5256 switch( sqlite3_column_type(pQuery, i) ){
5257 case SQLITE_NULL: {
5258 sqlite3_bind_null(pInsert, i+1);
5259 break;
5260 }
5261 case SQLITE_INTEGER: {
5262 sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
5263 break;
5264 }
5265 case SQLITE_FLOAT: {
5266 sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
5267 break;
5268 }
5269 case SQLITE_TEXT: {
5270 sqlite3_bind_text(pInsert, i+1,
5271 (const char*)sqlite3_column_text(pQuery,i),
5272 -1, SQLITE_STATIC);
5273 break;
5274 }
5275 case SQLITE_BLOB: {
5276 sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
5277 sqlite3_column_bytes(pQuery,i),
5278 SQLITE_STATIC);
5279 break;
5280 }
5281 }
5282 } /* End for */
5283 rc = sqlite3_step(pInsert);
5284 if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
5285 utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
5286 sqlite3_errmsg(newDb));
5287 }
5288 sqlite3_reset(pInsert);
5289 cnt++;
5290 if( (cnt%spinRate)==0 ){
5291 printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
5292 fflush(stdout);
5293 }
5294 } /* End while */
5295 if( rc==SQLITE_DONE ) break;
5296 sqlite3_finalize(pQuery);
5297 sqlite3_free(zQuery);
5298 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
5299 zTable);
5300 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5301 if( rc ){
5302 utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
5303 break;
5304 }
5305 } /* End for(k=0...) */
5306
5307end_data_xfer:
5308 sqlite3_finalize(pQuery);
5309 sqlite3_finalize(pInsert);
5310 sqlite3_free(zQuery);
5311 sqlite3_free(zInsert);
5312}
5313
5314
5315/*
5316** Try to transfer all rows of the schema that match zWhere. For
5317** each row, invoke xForEach() on the object defined by that row.
5318** If an error is encountered while moving forward through the
drh067b92b2020-06-19 15:24:12 +00005319** sqlite_schema table, try again moving backwards.
drh2ce15c32017-07-11 13:34:40 +00005320*/
5321static void tryToCloneSchema(
5322 ShellState *p,
5323 sqlite3 *newDb,
5324 const char *zWhere,
5325 void (*xForEach)(ShellState*,sqlite3*,const char*)
5326){
5327 sqlite3_stmt *pQuery = 0;
5328 char *zQuery = 0;
5329 int rc;
5330 const unsigned char *zName;
5331 const unsigned char *zSql;
5332 char *zErrMsg = 0;
5333
drh067b92b2020-06-19 15:24:12 +00005334 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005335 " WHERE %s", zWhere);
5336 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5337 if( rc ){
5338 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5339 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5340 zQuery);
5341 goto end_schema_xfer;
5342 }
5343 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5344 zName = sqlite3_column_text(pQuery, 0);
5345 zSql = sqlite3_column_text(pQuery, 1);
5346 printf("%s... ", zName); fflush(stdout);
5347 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5348 if( zErrMsg ){
5349 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5350 sqlite3_free(zErrMsg);
5351 zErrMsg = 0;
5352 }
5353 if( xForEach ){
5354 xForEach(p, newDb, (const char*)zName);
5355 }
5356 printf("done\n");
5357 }
5358 if( rc!=SQLITE_DONE ){
5359 sqlite3_finalize(pQuery);
5360 sqlite3_free(zQuery);
drh067b92b2020-06-19 15:24:12 +00005361 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005362 " WHERE %s ORDER BY rowid DESC", zWhere);
5363 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5364 if( rc ){
5365 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5366 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5367 zQuery);
5368 goto end_schema_xfer;
5369 }
5370 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5371 zName = sqlite3_column_text(pQuery, 0);
5372 zSql = sqlite3_column_text(pQuery, 1);
5373 printf("%s... ", zName); fflush(stdout);
5374 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5375 if( zErrMsg ){
5376 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5377 sqlite3_free(zErrMsg);
5378 zErrMsg = 0;
5379 }
5380 if( xForEach ){
5381 xForEach(p, newDb, (const char*)zName);
5382 }
5383 printf("done\n");
5384 }
5385 }
5386end_schema_xfer:
5387 sqlite3_finalize(pQuery);
5388 sqlite3_free(zQuery);
5389}
5390
5391/*
5392** Open a new database file named "zNewDb". Try to recover as much information
5393** as possible out of the main database (which might be corrupt) and write it
5394** into zNewDb.
5395*/
5396static void tryToClone(ShellState *p, const char *zNewDb){
5397 int rc;
5398 sqlite3 *newDb = 0;
5399 if( access(zNewDb,0)==0 ){
5400 utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
5401 return;
5402 }
5403 rc = sqlite3_open(zNewDb, &newDb);
5404 if( rc ){
5405 utf8_printf(stderr, "Cannot create output database: %s\n",
5406 sqlite3_errmsg(newDb));
5407 }else{
5408 sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
5409 sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
5410 tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
5411 tryToCloneSchema(p, newDb, "type!='table'", 0);
5412 sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
5413 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
5414 }
drh9e804032018-05-18 17:11:50 +00005415 close_db(newDb);
drh2ce15c32017-07-11 13:34:40 +00005416}
5417
5418/*
drh13c20932018-01-10 21:41:55 +00005419** Change the output file back to stdout.
5420**
5421** If the p->doXdgOpen flag is set, that means the output was being
5422** redirected to a temporary file named by p->zTempFile. In that case,
5423** launch start/open/xdg-open on that temporary file.
drh2ce15c32017-07-11 13:34:40 +00005424*/
5425static void output_reset(ShellState *p){
5426 if( p->outfile[0]=='|' ){
5427#ifndef SQLITE_OMIT_POPEN
5428 pclose(p->out);
5429#endif
5430 }else{
5431 output_file_close(p->out);
drh04a28c32018-01-31 01:38:44 +00005432#ifndef SQLITE_NOHAVE_SYSTEM
drh13c20932018-01-10 21:41:55 +00005433 if( p->doXdgOpen ){
5434 const char *zXdgOpenCmd =
5435#if defined(_WIN32)
5436 "start";
5437#elif defined(__APPLE__)
5438 "open";
5439#else
5440 "xdg-open";
5441#endif
5442 char *zCmd;
5443 zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
drha92a01a2018-01-10 22:15:37 +00005444 if( system(zCmd) ){
5445 utf8_printf(stderr, "Failed: [%s]\n", zCmd);
drh1d9ea272020-04-17 23:46:54 +00005446 }else{
5447 /* Give the start/open/xdg-open command some time to get
5448 ** going before we continue, and potential delete the
5449 ** p->zTempFile data file out from under it */
5450 sqlite3_sleep(2000);
drha92a01a2018-01-10 22:15:37 +00005451 }
drh13c20932018-01-10 21:41:55 +00005452 sqlite3_free(zCmd);
drh3c484e82018-01-10 22:27:21 +00005453 outputModePop(p);
drh13c20932018-01-10 21:41:55 +00005454 p->doXdgOpen = 0;
5455 }
drh04a28c32018-01-31 01:38:44 +00005456#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
drh2ce15c32017-07-11 13:34:40 +00005457 }
5458 p->outfile[0] = 0;
5459 p->out = stdout;
5460}
5461
5462/*
5463** Run an SQL command and return the single integer result.
5464*/
5465static int db_int(ShellState *p, const char *zSql){
5466 sqlite3_stmt *pStmt;
5467 int res = 0;
5468 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
5469 if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
5470 res = sqlite3_column_int(pStmt,0);
5471 }
5472 sqlite3_finalize(pStmt);
5473 return res;
5474}
5475
5476/*
5477** Convert a 2-byte or 4-byte big-endian integer into a native integer
5478*/
5479static unsigned int get2byteInt(unsigned char *a){
5480 return (a[0]<<8) + a[1];
5481}
5482static unsigned int get4byteInt(unsigned char *a){
5483 return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
5484}
5485
5486/*
drh76c12062020-01-14 13:13:19 +00005487** Implementation of the ".dbinfo" command.
drh2ce15c32017-07-11 13:34:40 +00005488**
5489** Return 1 on error, 2 to exit, and 0 otherwise.
5490*/
5491static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
5492 static const struct { const char *zName; int ofst; } aField[] = {
5493 { "file change counter:", 24 },
5494 { "database page count:", 28 },
5495 { "freelist page count:", 36 },
5496 { "schema cookie:", 40 },
5497 { "schema format:", 44 },
5498 { "default cache size:", 48 },
5499 { "autovacuum top root:", 52 },
5500 { "incremental vacuum:", 64 },
5501 { "text encoding:", 56 },
5502 { "user version:", 60 },
5503 { "application id:", 68 },
5504 { "software version:", 96 },
5505 };
5506 static const struct { const char *zName; const char *zSql; } aQuery[] = {
5507 { "number of tables:",
5508 "SELECT count(*) FROM %s WHERE type='table'" },
5509 { "number of indexes:",
5510 "SELECT count(*) FROM %s WHERE type='index'" },
5511 { "number of triggers:",
5512 "SELECT count(*) FROM %s WHERE type='trigger'" },
5513 { "number of views:",
5514 "SELECT count(*) FROM %s WHERE type='view'" },
5515 { "schema size:",
5516 "SELECT total(length(sql)) FROM %s" },
5517 };
drh87c889c2019-03-20 18:22:51 +00005518 int i, rc;
drhea99a312018-07-18 19:09:07 +00005519 unsigned iDataVersion;
drh2ce15c32017-07-11 13:34:40 +00005520 char *zSchemaTab;
5521 char *zDb = nArg>=2 ? azArg[1] : "main";
drh512e6c32017-10-11 17:51:08 +00005522 sqlite3_stmt *pStmt = 0;
drh2ce15c32017-07-11 13:34:40 +00005523 unsigned char aHdr[100];
5524 open_db(p, 0);
5525 if( p->db==0 ) return 1;
drh87c889c2019-03-20 18:22:51 +00005526 rc = sqlite3_prepare_v2(p->db,
5527 "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
5528 -1, &pStmt, 0);
5529 if( rc ){
drh451f89a2020-04-28 23:09:56 +00005530 utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
drh87c889c2019-03-20 18:22:51 +00005531 sqlite3_finalize(pStmt);
5532 return 1;
5533 }
drh512e6c32017-10-11 17:51:08 +00005534 sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
5535 if( sqlite3_step(pStmt)==SQLITE_ROW
5536 && sqlite3_column_bytes(pStmt,0)>100
5537 ){
5538 memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
5539 sqlite3_finalize(pStmt);
5540 }else{
drh2ce15c32017-07-11 13:34:40 +00005541 raw_printf(stderr, "unable to read database header\n");
drh512e6c32017-10-11 17:51:08 +00005542 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00005543 return 1;
5544 }
5545 i = get2byteInt(aHdr+16);
5546 if( i==1 ) i = 65536;
5547 utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
5548 utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
5549 utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
5550 utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
5551 for(i=0; i<ArraySize(aField); i++){
5552 int ofst = aField[i].ofst;
5553 unsigned int val = get4byteInt(aHdr + ofst);
5554 utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
5555 switch( ofst ){
5556 case 56: {
5557 if( val==1 ) raw_printf(p->out, " (utf8)");
5558 if( val==2 ) raw_printf(p->out, " (utf16le)");
5559 if( val==3 ) raw_printf(p->out, " (utf16be)");
5560 }
5561 }
5562 raw_printf(p->out, "\n");
5563 }
5564 if( zDb==0 ){
drh067b92b2020-06-19 15:24:12 +00005565 zSchemaTab = sqlite3_mprintf("main.sqlite_schema");
drh2ce15c32017-07-11 13:34:40 +00005566 }else if( strcmp(zDb,"temp")==0 ){
drh067b92b2020-06-19 15:24:12 +00005567 zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
drh2ce15c32017-07-11 13:34:40 +00005568 }else{
drh067b92b2020-06-19 15:24:12 +00005569 zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
drh2ce15c32017-07-11 13:34:40 +00005570 }
5571 for(i=0; i<ArraySize(aQuery); i++){
5572 char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
5573 int val = db_int(p, zSql);
5574 sqlite3_free(zSql);
5575 utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
5576 }
5577 sqlite3_free(zSchemaTab);
drhea99a312018-07-18 19:09:07 +00005578 sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
5579 utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
drh2ce15c32017-07-11 13:34:40 +00005580 return 0;
5581}
5582
5583/*
5584** Print the current sqlite3_errmsg() value to stderr and return 1.
5585*/
5586static int shellDatabaseError(sqlite3 *db){
5587 const char *zErr = sqlite3_errmsg(db);
5588 utf8_printf(stderr, "Error: %s\n", zErr);
5589 return 1;
5590}
5591
5592/*
drh2ce15c32017-07-11 13:34:40 +00005593** Compare the pattern in zGlob[] against the text in z[]. Return TRUE
5594** if they match and FALSE (0) if they do not match.
5595**
5596** Globbing rules:
5597**
5598** '*' Matches any sequence of zero or more characters.
5599**
5600** '?' Matches exactly one character.
5601**
5602** [...] Matches one character from the enclosed list of
5603** characters.
5604**
5605** [^...] Matches one character not in the enclosed list.
5606**
5607** '#' Matches any sequence of one or more digits with an
5608** optional + or - sign in front
5609**
5610** ' ' Any span of whitespace matches any other span of
5611** whitespace.
5612**
5613** Extra whitespace at the end of z[] is ignored.
5614*/
5615static int testcase_glob(const char *zGlob, const char *z){
5616 int c, c2;
5617 int invert;
5618 int seen;
5619
5620 while( (c = (*(zGlob++)))!=0 ){
5621 if( IsSpace(c) ){
5622 if( !IsSpace(*z) ) return 0;
5623 while( IsSpace(*zGlob) ) zGlob++;
5624 while( IsSpace(*z) ) z++;
5625 }else if( c=='*' ){
5626 while( (c=(*(zGlob++))) == '*' || c=='?' ){
5627 if( c=='?' && (*(z++))==0 ) return 0;
5628 }
5629 if( c==0 ){
5630 return 1;
5631 }else if( c=='[' ){
5632 while( *z && testcase_glob(zGlob-1,z)==0 ){
5633 z++;
5634 }
5635 return (*z)!=0;
5636 }
5637 while( (c2 = (*(z++)))!=0 ){
5638 while( c2!=c ){
5639 c2 = *(z++);
5640 if( c2==0 ) return 0;
5641 }
5642 if( testcase_glob(zGlob,z) ) return 1;
5643 }
5644 return 0;
5645 }else if( c=='?' ){
5646 if( (*(z++))==0 ) return 0;
5647 }else if( c=='[' ){
5648 int prior_c = 0;
5649 seen = 0;
5650 invert = 0;
5651 c = *(z++);
5652 if( c==0 ) return 0;
5653 c2 = *(zGlob++);
5654 if( c2=='^' ){
5655 invert = 1;
5656 c2 = *(zGlob++);
5657 }
5658 if( c2==']' ){
5659 if( c==']' ) seen = 1;
5660 c2 = *(zGlob++);
5661 }
5662 while( c2 && c2!=']' ){
5663 if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
5664 c2 = *(zGlob++);
5665 if( c>=prior_c && c<=c2 ) seen = 1;
5666 prior_c = 0;
5667 }else{
5668 if( c==c2 ){
5669 seen = 1;
5670 }
5671 prior_c = c2;
5672 }
5673 c2 = *(zGlob++);
5674 }
5675 if( c2==0 || (seen ^ invert)==0 ) return 0;
5676 }else if( c=='#' ){
5677 if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++;
5678 if( !IsDigit(z[0]) ) return 0;
5679 z++;
5680 while( IsDigit(z[0]) ){ z++; }
5681 }else{
5682 if( c!=(*(z++)) ) return 0;
5683 }
5684 }
5685 while( IsSpace(*z) ){ z++; }
5686 return *z==0;
5687}
5688
5689
5690/*
5691** Compare the string as a command-line option with either one or two
5692** initial "-" characters.
5693*/
5694static int optionMatch(const char *zStr, const char *zOpt){
5695 if( zStr[0]!='-' ) return 0;
5696 zStr++;
5697 if( zStr[0]=='-' ) zStr++;
5698 return strcmp(zStr, zOpt)==0;
5699}
5700
5701/*
5702** Delete a file.
5703*/
5704int shellDeleteFile(const char *zFilename){
5705 int rc;
5706#ifdef _WIN32
5707 wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
5708 rc = _wunlink(z);
5709 sqlite3_free(z);
5710#else
5711 rc = unlink(zFilename);
5712#endif
5713 return rc;
5714}
5715
drh13c20932018-01-10 21:41:55 +00005716/*
5717** Try to delete the temporary file (if there is one) and free the
5718** memory used to hold the name of the temp file.
5719*/
5720static void clearTempFile(ShellState *p){
5721 if( p->zTempFile==0 ) return;
drh536c3452018-01-11 00:38:39 +00005722 if( p->doXdgOpen ) return;
drh13c20932018-01-10 21:41:55 +00005723 if( shellDeleteFile(p->zTempFile) ) return;
5724 sqlite3_free(p->zTempFile);
5725 p->zTempFile = 0;
5726}
5727
5728/*
5729** Create a new temp file name with the given suffix.
5730*/
5731static void newTempFile(ShellState *p, const char *zSuffix){
5732 clearTempFile(p);
5733 sqlite3_free(p->zTempFile);
5734 p->zTempFile = 0;
drh7f3bf8a2018-01-10 21:50:08 +00005735 if( p->db ){
5736 sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
5737 }
drh13c20932018-01-10 21:41:55 +00005738 if( p->zTempFile==0 ){
drh1d9ea272020-04-17 23:46:54 +00005739 /* If p->db is an in-memory database then the TEMPFILENAME file-control
5740 ** will not work and we will need to fallback to guessing */
5741 char *zTemp;
drh13c20932018-01-10 21:41:55 +00005742 sqlite3_uint64 r;
5743 sqlite3_randomness(sizeof(r), &r);
drh1d9ea272020-04-17 23:46:54 +00005744 zTemp = getenv("TEMP");
5745 if( zTemp==0 ) zTemp = getenv("TMP");
5746 if( zTemp==0 ){
5747#ifdef _WIN32
5748 zTemp = "\\tmp";
5749#else
5750 zTemp = "/tmp";
5751#endif
5752 }
5753 p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix);
drh13c20932018-01-10 21:41:55 +00005754 }else{
5755 p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
5756 }
5757 if( p->zTempFile==0 ){
5758 raw_printf(stderr, "out of memory\n");
5759 exit(1);
5760 }
5761}
5762
drh2ce15c32017-07-11 13:34:40 +00005763
5764/*
5765** The implementation of SQL scalar function fkey_collate_clause(), used
5766** by the ".lint fkey-indexes" command. This scalar function is always
5767** called with four arguments - the parent table name, the parent column name,
5768** the child table name and the child column name.
5769**
5770** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
5771**
5772** If either of the named tables or columns do not exist, this function
5773** returns an empty string. An empty string is also returned if both tables
5774** and columns exist but have the same default collation sequence. Or,
5775** if both exist but the default collation sequences are different, this
5776** function returns the string " COLLATE <parent-collation>", where
5777** <parent-collation> is the default collation sequence of the parent column.
5778*/
5779static void shellFkeyCollateClause(
5780 sqlite3_context *pCtx,
5781 int nVal,
5782 sqlite3_value **apVal
5783){
5784 sqlite3 *db = sqlite3_context_db_handle(pCtx);
5785 const char *zParent;
5786 const char *zParentCol;
5787 const char *zParentSeq;
5788 const char *zChild;
5789 const char *zChildCol;
5790 const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */
5791 int rc;
5792
5793 assert( nVal==4 );
5794 zParent = (const char*)sqlite3_value_text(apVal[0]);
5795 zParentCol = (const char*)sqlite3_value_text(apVal[1]);
5796 zChild = (const char*)sqlite3_value_text(apVal[2]);
5797 zChildCol = (const char*)sqlite3_value_text(apVal[3]);
5798
5799 sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
5800 rc = sqlite3_table_column_metadata(
5801 db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0
5802 );
5803 if( rc==SQLITE_OK ){
5804 rc = sqlite3_table_column_metadata(
5805 db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0
5806 );
5807 }
5808
5809 if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){
5810 char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq);
5811 sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
5812 sqlite3_free(z);
5813 }
5814}
5815
5816
5817/*
5818** The implementation of dot-command ".lint fkey-indexes".
5819*/
5820static int lintFkeyIndexes(
5821 ShellState *pState, /* Current shell tool state */
5822 char **azArg, /* Array of arguments passed to dot command */
5823 int nArg /* Number of entries in azArg[] */
5824){
5825 sqlite3 *db = pState->db; /* Database handle to query "main" db of */
5826 FILE *out = pState->out; /* Stream to write non-error output to */
5827 int bVerbose = 0; /* If -verbose is present */
5828 int bGroupByParent = 0; /* If -groupbyparent is present */
5829 int i; /* To iterate through azArg[] */
5830 const char *zIndent = ""; /* How much to indent CREATE INDEX by */
5831 int rc; /* Return code */
5832 sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */
5833
5834 /*
5835 ** This SELECT statement returns one row for each foreign key constraint
5836 ** in the schema of the main database. The column values are:
5837 **
5838 ** 0. The text of an SQL statement similar to:
5839 **
danf9679312017-12-01 18:40:18 +00005840 ** "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?"
drh2ce15c32017-07-11 13:34:40 +00005841 **
danf9679312017-12-01 18:40:18 +00005842 ** This SELECT is similar to the one that the foreign keys implementation
5843 ** needs to run internally on child tables. If there is an index that can
drh2ce15c32017-07-11 13:34:40 +00005844 ** be used to optimize this query, then it can also be used by the FK
5845 ** implementation to optimize DELETE or UPDATE statements on the parent
5846 ** table.
5847 **
5848 ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by
5849 ** the EXPLAIN QUERY PLAN command matches this pattern, then the schema
5850 ** contains an index that can be used to optimize the query.
5851 **
5852 ** 2. Human readable text that describes the child table and columns. e.g.
5853 **
5854 ** "child_table(child_key1, child_key2)"
5855 **
5856 ** 3. Human readable text that describes the parent table and columns. e.g.
5857 **
5858 ** "parent_table(parent_key1, parent_key2)"
5859 **
5860 ** 4. A full CREATE INDEX statement for an index that could be used to
5861 ** optimize DELETE or UPDATE statements on the parent table. e.g.
5862 **
5863 ** "CREATE INDEX child_table_child_key ON child_table(child_key)"
5864 **
5865 ** 5. The name of the parent table.
5866 **
5867 ** These six values are used by the C logic below to generate the report.
5868 */
5869 const char *zSql =
5870 "SELECT "
danf9679312017-12-01 18:40:18 +00005871 " 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
drh2ce15c32017-07-11 13:34:40 +00005872 " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
5873 " || fkey_collate_clause("
5874 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
5875 ", "
drh82102332021-03-20 15:11:29 +00005876 " 'SEARCH ' || s.name || ' USING COVERING INDEX*('"
drh2ce15c32017-07-11 13:34:40 +00005877 " || group_concat('*=?', ' AND ') || ')'"
5878 ", "
5879 " s.name || '(' || group_concat(f.[from], ', ') || ')'"
5880 ", "
5881 " f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
5882 ", "
5883 " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
5884 " || ' ON ' || quote(s.name) || '('"
5885 " || group_concat(quote(f.[from]) ||"
5886 " fkey_collate_clause("
5887 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
5888 " || ');'"
5889 ", "
5890 " f.[table] "
drh067b92b2020-06-19 15:24:12 +00005891 "FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f "
drh2ce15c32017-07-11 13:34:40 +00005892 "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
5893 "GROUP BY s.name, f.id "
5894 "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
5895 ;
drh82102332021-03-20 15:11:29 +00005896 const char *zGlobIPK = "SEARCH * USING INTEGER PRIMARY KEY (rowid=?)";
drh2ce15c32017-07-11 13:34:40 +00005897
5898 for(i=2; i<nArg; i++){
drhaf2770f2018-01-05 14:55:43 +00005899 int n = strlen30(azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00005900 if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
5901 bVerbose = 1;
5902 }
5903 else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
5904 bGroupByParent = 1;
5905 zIndent = " ";
5906 }
5907 else{
5908 raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
5909 azArg[0], azArg[1]
5910 );
5911 return SQLITE_ERROR;
5912 }
5913 }
5914
5915 /* Register the fkey_collate_clause() SQL function */
5916 rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
5917 0, shellFkeyCollateClause, 0, 0
5918 );
5919
5920
5921 if( rc==SQLITE_OK ){
5922 rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
5923 }
5924 if( rc==SQLITE_OK ){
5925 sqlite3_bind_int(pSql, 1, bGroupByParent);
5926 }
5927
5928 if( rc==SQLITE_OK ){
5929 int rc2;
5930 char *zPrev = 0;
5931 while( SQLITE_ROW==sqlite3_step(pSql) ){
5932 int res = -1;
5933 sqlite3_stmt *pExplain = 0;
5934 const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
5935 const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
5936 const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
5937 const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
5938 const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
5939 const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
5940
5941 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
5942 if( rc!=SQLITE_OK ) break;
5943 if( SQLITE_ROW==sqlite3_step(pExplain) ){
5944 const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
5945 res = (
5946 0==sqlite3_strglob(zGlob, zPlan)
5947 || 0==sqlite3_strglob(zGlobIPK, zPlan)
5948 );
5949 }
5950 rc = sqlite3_finalize(pExplain);
5951 if( rc!=SQLITE_OK ) break;
5952
5953 if( res<0 ){
5954 raw_printf(stderr, "Error: internal error");
5955 break;
5956 }else{
5957 if( bGroupByParent
5958 && (bVerbose || res==0)
5959 && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
5960 ){
5961 raw_printf(out, "-- Parent table %s\n", zParent);
5962 sqlite3_free(zPrev);
5963 zPrev = sqlite3_mprintf("%s", zParent);
5964 }
5965
5966 if( res==0 ){
5967 raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
5968 }else if( bVerbose ){
5969 raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
5970 zIndent, zFrom, zTarget
5971 );
5972 }
5973 }
5974 }
5975 sqlite3_free(zPrev);
5976
5977 if( rc!=SQLITE_OK ){
5978 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
5979 }
5980
5981 rc2 = sqlite3_finalize(pSql);
5982 if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
5983 rc = rc2;
5984 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
5985 }
5986 }else{
5987 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
5988 }
5989
5990 return rc;
5991}
5992
5993/*
5994** Implementation of ".lint" dot command.
5995*/
5996static int lintDotCommand(
5997 ShellState *pState, /* Current shell tool state */
5998 char **azArg, /* Array of arguments passed to dot command */
5999 int nArg /* Number of entries in azArg[] */
6000){
6001 int n;
drhaf2770f2018-01-05 14:55:43 +00006002 n = (nArg>=2 ? strlen30(azArg[1]) : 0);
drh2ce15c32017-07-11 13:34:40 +00006003 if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
6004 return lintFkeyIndexes(pState, azArg, nArg);
6005
6006 usage:
6007 raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
6008 raw_printf(stderr, "Where sub-commands are:\n");
6009 raw_printf(stderr, " fkey-indexes\n");
6010 return SQLITE_ERROR;
6011}
6012
dan1b162162019-04-27 20:15:15 +00006013#if !defined SQLITE_OMIT_VIRTUALTABLE
danfd0245d2017-12-07 15:44:29 +00006014static void shellPrepare(
dand4b56e52017-12-12 20:04:59 +00006015 sqlite3 *db,
danfd0245d2017-12-07 15:44:29 +00006016 int *pRc,
6017 const char *zSql,
6018 sqlite3_stmt **ppStmt
6019){
6020 *ppStmt = 0;
6021 if( *pRc==SQLITE_OK ){
dand4b56e52017-12-12 20:04:59 +00006022 int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
danfd0245d2017-12-07 15:44:29 +00006023 if( rc!=SQLITE_OK ){
6024 raw_printf(stderr, "sql error: %s (%d)\n",
dand4b56e52017-12-12 20:04:59 +00006025 sqlite3_errmsg(db), sqlite3_errcode(db)
danfd0245d2017-12-07 15:44:29 +00006026 );
6027 *pRc = rc;
6028 }
6029 }
6030}
6031
drh9546c762019-05-10 17:50:33 +00006032/*
6033** Create a prepared statement using printf-style arguments for the SQL.
6034**
6035** This routine is could be marked "static". But it is not always used,
6036** depending on compile-time options. By omitting the "static", we avoid
6037** nuisance compiler warnings about "defined but not used".
6038*/
6039void shellPreparePrintf(
dan3f67ddf2017-12-13 20:04:53 +00006040 sqlite3 *db,
6041 int *pRc,
danac15e2d2017-12-14 19:15:07 +00006042 sqlite3_stmt **ppStmt,
6043 const char *zFmt,
6044 ...
dan3f67ddf2017-12-13 20:04:53 +00006045){
danac15e2d2017-12-14 19:15:07 +00006046 *ppStmt = 0;
6047 if( *pRc==SQLITE_OK ){
6048 va_list ap;
6049 char *z;
6050 va_start(ap, zFmt);
6051 z = sqlite3_vmprintf(zFmt, ap);
drh1dbb1472018-10-11 10:37:24 +00006052 va_end(ap);
dan3f67ddf2017-12-13 20:04:53 +00006053 if( z==0 ){
6054 *pRc = SQLITE_NOMEM;
6055 }else{
6056 shellPrepare(db, pRc, z, ppStmt);
6057 sqlite3_free(z);
6058 }
dan3f67ddf2017-12-13 20:04:53 +00006059 }
6060}
6061
drh9546c762019-05-10 17:50:33 +00006062/* Finalize the prepared statement created using shellPreparePrintf().
6063**
6064** This routine is could be marked "static". But it is not always used,
6065** depending on compile-time options. By omitting the "static", we avoid
6066** nuisance compiler warnings about "defined but not used".
6067*/
6068void shellFinalize(
danfd0245d2017-12-07 15:44:29 +00006069 int *pRc,
6070 sqlite3_stmt *pStmt
6071){
dan25c12182017-12-07 21:03:33 +00006072 if( pStmt ){
6073 sqlite3 *db = sqlite3_db_handle(pStmt);
6074 int rc = sqlite3_finalize(pStmt);
6075 if( *pRc==SQLITE_OK ){
6076 if( rc!=SQLITE_OK ){
6077 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
6078 }
6079 *pRc = rc;
6080 }
6081 }
danfd0245d2017-12-07 15:44:29 +00006082}
6083
drh9546c762019-05-10 17:50:33 +00006084/* Reset the prepared statement created using shellPreparePrintf().
6085**
6086** This routine is could be marked "static". But it is not always used,
6087** depending on compile-time options. By omitting the "static", we avoid
6088** nuisance compiler warnings about "defined but not used".
6089*/
6090void shellReset(
danfd0245d2017-12-07 15:44:29 +00006091 int *pRc,
6092 sqlite3_stmt *pStmt
6093){
6094 int rc = sqlite3_reset(pStmt);
dan5a78b812017-12-27 18:54:11 +00006095 if( *pRc==SQLITE_OK ){
6096 if( rc!=SQLITE_OK ){
6097 sqlite3 *db = sqlite3_db_handle(pStmt);
6098 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
6099 }
6100 *pRc = rc;
6101 }
danfd0245d2017-12-07 15:44:29 +00006102}
dan1b162162019-04-27 20:15:15 +00006103#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
6104
6105#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drhe2754c12019-08-26 12:50:01 +00006106/******************************************************************************
dan1b162162019-04-27 20:15:15 +00006107** The ".archive" or ".ar" command.
6108*/
drhe37c0e12018-01-06 19:19:50 +00006109/*
dan88be0202017-12-09 17:58:02 +00006110** Structure representing a single ".ar" command.
6111*/
6112typedef struct ArCommand ArCommand;
6113struct ArCommand {
drhb376b3d2018-01-10 13:11:51 +00006114 u8 eCmd; /* An AR_CMD_* value */
6115 u8 bVerbose; /* True if --verbose */
drha5676c42018-01-10 15:17:34 +00006116 u8 bZip; /* True if the archive is a ZIP */
drhb376b3d2018-01-10 13:11:51 +00006117 u8 bDryRun; /* True if --dry-run */
drha5676c42018-01-10 15:17:34 +00006118 u8 bAppend; /* True if --append */
drhd0f9cdc2018-05-17 14:09:06 +00006119 u8 fromCmdLine; /* Run from -A instead of .archive */
drhb376b3d2018-01-10 13:11:51 +00006120 int nArg; /* Number of command arguments */
drha5676c42018-01-10 15:17:34 +00006121 char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
dan88be0202017-12-09 17:58:02 +00006122 const char *zFile; /* --file argument, or NULL */
6123 const char *zDir; /* --directory argument, or NULL */
dan88be0202017-12-09 17:58:02 +00006124 char **azArg; /* Array of command arguments */
drhb376b3d2018-01-10 13:11:51 +00006125 ShellState *p; /* Shell state */
6126 sqlite3 *db; /* Database containing the archive */
dan88be0202017-12-09 17:58:02 +00006127};
6128
6129/*
6130** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
6131*/
dan0d0547f2017-12-14 15:40:42 +00006132static int arUsage(FILE *f){
drh98aa2ab2018-09-26 16:53:51 +00006133 showHelp(f,"archive");
dan0d0547f2017-12-14 15:40:42 +00006134 return SQLITE_ERROR;
6135}
6136
6137/*
6138** Print an error message for the .ar command to stderr and return
6139** SQLITE_ERROR.
6140*/
drhd0f9cdc2018-05-17 14:09:06 +00006141static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
dan0d0547f2017-12-14 15:40:42 +00006142 va_list ap;
6143 char *z;
6144 va_start(ap, zFmt);
6145 z = sqlite3_vmprintf(zFmt, ap);
6146 va_end(ap);
drhd0f9cdc2018-05-17 14:09:06 +00006147 utf8_printf(stderr, "Error: %s\n", z);
6148 if( pAr->fromCmdLine ){
6149 utf8_printf(stderr, "Use \"-A\" for more help\n");
6150 }else{
6151 utf8_printf(stderr, "Use \".archive --help\" for more help\n");
6152 }
dan0d0547f2017-12-14 15:40:42 +00006153 sqlite3_free(z);
dan88be0202017-12-09 17:58:02 +00006154 return SQLITE_ERROR;
6155}
6156
6157/*
6158** Values for ArCommand.eCmd.
6159*/
dand4b56e52017-12-12 20:04:59 +00006160#define AR_CMD_CREATE 1
drhb17ea912019-03-25 14:24:19 +00006161#define AR_CMD_UPDATE 2
6162#define AR_CMD_INSERT 3
6163#define AR_CMD_EXTRACT 4
6164#define AR_CMD_LIST 5
6165#define AR_CMD_HELP 6
dand4b56e52017-12-12 20:04:59 +00006166
6167/*
6168** Other (non-command) switches.
6169*/
drhb17ea912019-03-25 14:24:19 +00006170#define AR_SWITCH_VERBOSE 7
6171#define AR_SWITCH_FILE 8
6172#define AR_SWITCH_DIRECTORY 9
6173#define AR_SWITCH_APPEND 10
6174#define AR_SWITCH_DRYRUN 11
dand4b56e52017-12-12 20:04:59 +00006175
6176static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
6177 switch( eSwitch ){
6178 case AR_CMD_CREATE:
6179 case AR_CMD_EXTRACT:
6180 case AR_CMD_LIST:
6181 case AR_CMD_UPDATE:
drhb17ea912019-03-25 14:24:19 +00006182 case AR_CMD_INSERT:
dan0d0547f2017-12-14 15:40:42 +00006183 case AR_CMD_HELP:
6184 if( pAr->eCmd ){
drhd0f9cdc2018-05-17 14:09:06 +00006185 return arErrorMsg(pAr, "multiple command options");
dan0d0547f2017-12-14 15:40:42 +00006186 }
dand4b56e52017-12-12 20:04:59 +00006187 pAr->eCmd = eSwitch;
6188 break;
6189
drhb376b3d2018-01-10 13:11:51 +00006190 case AR_SWITCH_DRYRUN:
6191 pAr->bDryRun = 1;
6192 break;
dand4b56e52017-12-12 20:04:59 +00006193 case AR_SWITCH_VERBOSE:
6194 pAr->bVerbose = 1;
6195 break;
drha5676c42018-01-10 15:17:34 +00006196 case AR_SWITCH_APPEND:
6197 pAr->bAppend = 1;
drhca7733b2018-01-10 18:09:20 +00006198 /* Fall thru into --file */
dand4b56e52017-12-12 20:04:59 +00006199 case AR_SWITCH_FILE:
6200 pAr->zFile = zArg;
6201 break;
6202 case AR_SWITCH_DIRECTORY:
6203 pAr->zDir = zArg;
6204 break;
6205 }
6206
6207 return SQLITE_OK;
6208}
dan88be0202017-12-09 17:58:02 +00006209
6210/*
6211** Parse the command line for an ".ar" command. The results are written into
6212** structure (*pAr). SQLITE_OK is returned if the command line is parsed
6213** successfully, otherwise an error message is written to stderr and
6214** SQLITE_ERROR returned.
6215*/
6216static int arParseCommand(
6217 char **azArg, /* Array of arguments passed to dot command */
6218 int nArg, /* Number of entries in azArg[] */
6219 ArCommand *pAr /* Populate this object */
6220){
dand4b56e52017-12-12 20:04:59 +00006221 struct ArSwitch {
dand4b56e52017-12-12 20:04:59 +00006222 const char *zLong;
drhb376b3d2018-01-10 13:11:51 +00006223 char cShort;
6224 u8 eSwitch;
6225 u8 bArg;
dand4b56e52017-12-12 20:04:59 +00006226 } aSwitch[] = {
drhb376b3d2018-01-10 13:11:51 +00006227 { "create", 'c', AR_CMD_CREATE, 0 },
6228 { "extract", 'x', AR_CMD_EXTRACT, 0 },
drhb17ea912019-03-25 14:24:19 +00006229 { "insert", 'i', AR_CMD_INSERT, 0 },
drhb376b3d2018-01-10 13:11:51 +00006230 { "list", 't', AR_CMD_LIST, 0 },
6231 { "update", 'u', AR_CMD_UPDATE, 0 },
6232 { "help", 'h', AR_CMD_HELP, 0 },
6233 { "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
6234 { "file", 'f', AR_SWITCH_FILE, 1 },
drhca7733b2018-01-10 18:09:20 +00006235 { "append", 'a', AR_SWITCH_APPEND, 1 },
drhb376b3d2018-01-10 13:11:51 +00006236 { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
drhb376b3d2018-01-10 13:11:51 +00006237 { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
dand4b56e52017-12-12 20:04:59 +00006238 };
6239 int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
6240 struct ArSwitch *pEnd = &aSwitch[nSwitch];
6241
dan88be0202017-12-09 17:58:02 +00006242 if( nArg<=1 ){
drh98aa2ab2018-09-26 16:53:51 +00006243 utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
dan0d0547f2017-12-14 15:40:42 +00006244 return arUsage(stderr);
dan88be0202017-12-09 17:58:02 +00006245 }else{
6246 char *z = azArg[1];
dan88be0202017-12-09 17:58:02 +00006247 if( z[0]!='-' ){
6248 /* Traditional style [tar] invocation */
6249 int i;
6250 int iArg = 2;
6251 for(i=0; z[i]; i++){
dand4b56e52017-12-12 20:04:59 +00006252 const char *zArg = 0;
6253 struct ArSwitch *pOpt;
6254 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6255 if( z[i]==pOpt->cShort ) break;
dan88be0202017-12-09 17:58:02 +00006256 }
dan0d0547f2017-12-14 15:40:42 +00006257 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006258 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006259 }
dand4b56e52017-12-12 20:04:59 +00006260 if( pOpt->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006261 if( iArg>=nArg ){
drhd0f9cdc2018-05-17 14:09:06 +00006262 return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
dan0d0547f2017-12-14 15:40:42 +00006263 }
dand4b56e52017-12-12 20:04:59 +00006264 zArg = azArg[iArg++];
6265 }
6266 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
dan88be0202017-12-09 17:58:02 +00006267 }
dan88be0202017-12-09 17:58:02 +00006268 pAr->nArg = nArg-iArg;
6269 if( pAr->nArg>0 ){
6270 pAr->azArg = &azArg[iArg];
6271 }
dand4b56e52017-12-12 20:04:59 +00006272 }else{
6273 /* Non-traditional invocation */
6274 int iArg;
6275 for(iArg=1; iArg<nArg; iArg++){
6276 int n;
6277 z = azArg[iArg];
6278 if( z[0]!='-' ){
6279 /* All remaining command line words are command arguments. */
6280 pAr->azArg = &azArg[iArg];
6281 pAr->nArg = nArg-iArg;
6282 break;
6283 }
drhaf2770f2018-01-05 14:55:43 +00006284 n = strlen30(z);
dand4b56e52017-12-12 20:04:59 +00006285
6286 if( z[1]!='-' ){
6287 int i;
6288 /* One or more short options */
6289 for(i=1; i<n; i++){
6290 const char *zArg = 0;
6291 struct ArSwitch *pOpt;
6292 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6293 if( z[i]==pOpt->cShort ) break;
6294 }
dan0d0547f2017-12-14 15:40:42 +00006295 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006296 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006297 }
dand4b56e52017-12-12 20:04:59 +00006298 if( pOpt->bArg ){
6299 if( i<(n-1) ){
6300 zArg = &z[i+1];
6301 i = n;
6302 }else{
dan0d0547f2017-12-14 15:40:42 +00006303 if( iArg>=(nArg-1) ){
drhe2754c12019-08-26 12:50:01 +00006304 return arErrorMsg(pAr, "option requires an argument: %c",
6305 z[i]);
dan0d0547f2017-12-14 15:40:42 +00006306 }
dand4b56e52017-12-12 20:04:59 +00006307 zArg = azArg[++iArg];
6308 }
6309 }
6310 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
6311 }
6312 }else if( z[2]=='\0' ){
6313 /* A -- option, indicating that all remaining command line words
6314 ** are command arguments. */
6315 pAr->azArg = &azArg[iArg+1];
6316 pAr->nArg = nArg-iArg-1;
6317 break;
6318 }else{
6319 /* A long option */
6320 const char *zArg = 0; /* Argument for option, if any */
6321 struct ArSwitch *pMatch = 0; /* Matching option */
6322 struct ArSwitch *pOpt; /* Iterator */
6323 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6324 const char *zLong = pOpt->zLong;
drhaf2770f2018-01-05 14:55:43 +00006325 if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
dand4b56e52017-12-12 20:04:59 +00006326 if( pMatch ){
drhd0f9cdc2018-05-17 14:09:06 +00006327 return arErrorMsg(pAr, "ambiguous option: %s",z);
dand4b56e52017-12-12 20:04:59 +00006328 }else{
6329 pMatch = pOpt;
6330 }
6331 }
6332 }
6333
6334 if( pMatch==0 ){
drhd0f9cdc2018-05-17 14:09:06 +00006335 return arErrorMsg(pAr, "unrecognized option: %s", z);
dand4b56e52017-12-12 20:04:59 +00006336 }
6337 if( pMatch->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006338 if( iArg>=(nArg-1) ){
drhd0f9cdc2018-05-17 14:09:06 +00006339 return arErrorMsg(pAr, "option requires an argument: %s", z);
dan0d0547f2017-12-14 15:40:42 +00006340 }
dand4b56e52017-12-12 20:04:59 +00006341 zArg = azArg[++iArg];
6342 }
6343 if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
6344 }
6345 }
dan88be0202017-12-09 17:58:02 +00006346 }
6347 }
6348
6349 return SQLITE_OK;
6350}
6351
6352/*
dan3f67ddf2017-12-13 20:04:53 +00006353** This function assumes that all arguments within the ArCommand.azArg[]
6354** array refer to archive members, as for the --extract or --list commands.
6355** It checks that each of them are present. If any specified file is not
6356** present in the archive, an error is printed to stderr and an error
6357** code returned. Otherwise, if all specified arguments are present in
6358** the archive, SQLITE_OK is returned.
6359**
6360** This function strips any trailing '/' characters from each argument.
6361** This is consistent with the way the [tar] command seems to work on
6362** Linux.
6363*/
drhb376b3d2018-01-10 13:11:51 +00006364static int arCheckEntries(ArCommand *pAr){
dan3f67ddf2017-12-13 20:04:53 +00006365 int rc = SQLITE_OK;
6366 if( pAr->nArg ){
drhb376b3d2018-01-10 13:11:51 +00006367 int i, j;
dan3f67ddf2017-12-13 20:04:53 +00006368 sqlite3_stmt *pTest = 0;
6369
drhb376b3d2018-01-10 13:11:51 +00006370 shellPreparePrintf(pAr->db, &rc, &pTest,
6371 "SELECT name FROM %s WHERE name=$name",
6372 pAr->zSrcTable
dan5a78b812017-12-27 18:54:11 +00006373 );
drhb376b3d2018-01-10 13:11:51 +00006374 j = sqlite3_bind_parameter_index(pTest, "$name");
dan3f67ddf2017-12-13 20:04:53 +00006375 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
6376 char *z = pAr->azArg[i];
drhaf2770f2018-01-05 14:55:43 +00006377 int n = strlen30(z);
dan3f67ddf2017-12-13 20:04:53 +00006378 int bOk = 0;
6379 while( n>0 && z[n-1]=='/' ) n--;
6380 z[n] = '\0';
drhb376b3d2018-01-10 13:11:51 +00006381 sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
dan3f67ddf2017-12-13 20:04:53 +00006382 if( SQLITE_ROW==sqlite3_step(pTest) ){
6383 bOk = 1;
6384 }
6385 shellReset(&rc, pTest);
6386 if( rc==SQLITE_OK && bOk==0 ){
drhb376b3d2018-01-10 13:11:51 +00006387 utf8_printf(stderr, "not found in archive: %s\n", z);
dan3f67ddf2017-12-13 20:04:53 +00006388 rc = SQLITE_ERROR;
6389 }
6390 }
6391 shellFinalize(&rc, pTest);
6392 }
dan3f67ddf2017-12-13 20:04:53 +00006393 return rc;
6394}
6395
6396/*
6397** Format a WHERE clause that can be used against the "sqlar" table to
6398** identify all archive members that match the command arguments held
6399** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
6400** The caller is responsible for eventually calling sqlite3_free() on
6401** any non-NULL (*pzWhere) value.
6402*/
6403static void arWhereClause(
6404 int *pRc,
6405 ArCommand *pAr,
danac15e2d2017-12-14 19:15:07 +00006406 char **pzWhere /* OUT: New WHERE clause */
dan3f67ddf2017-12-13 20:04:53 +00006407){
6408 char *zWhere = 0;
6409 if( *pRc==SQLITE_OK ){
danac15e2d2017-12-14 19:15:07 +00006410 if( pAr->nArg==0 ){
6411 zWhere = sqlite3_mprintf("1");
6412 }else{
6413 int i;
6414 const char *zSep = "";
6415 for(i=0; i<pAr->nArg; i++){
6416 const char *z = pAr->azArg[i];
6417 zWhere = sqlite3_mprintf(
drhb376b3d2018-01-10 13:11:51 +00006418 "%z%s name = '%q' OR substr(name,1,%d) = '%q/'",
6419 zWhere, zSep, z, strlen30(z)+1, z
6420 );
danac15e2d2017-12-14 19:15:07 +00006421 if( zWhere==0 ){
6422 *pRc = SQLITE_NOMEM;
6423 break;
6424 }
6425 zSep = " OR ";
dan3f67ddf2017-12-13 20:04:53 +00006426 }
dan3f67ddf2017-12-13 20:04:53 +00006427 }
6428 }
6429 *pzWhere = zWhere;
6430}
6431
6432/*
dan88be0202017-12-09 17:58:02 +00006433** Implementation of .ar "lisT" command.
6434*/
drhb376b3d2018-01-10 13:11:51 +00006435static int arListCommand(ArCommand *pAr){
danb5090e42017-12-27 21:13:21 +00006436 const char *zSql = "SELECT %s FROM %s WHERE %s";
danb5090e42017-12-27 21:13:21 +00006437 const char *azCols[] = {
6438 "name",
drh410cad92018-01-10 17:19:16 +00006439 "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
danb5090e42017-12-27 21:13:21 +00006440 };
dan5a78b812017-12-27 18:54:11 +00006441
dan3f67ddf2017-12-13 20:04:53 +00006442 char *zWhere = 0;
6443 sqlite3_stmt *pSql = 0;
6444 int rc;
6445
drhb376b3d2018-01-10 13:11:51 +00006446 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006447 arWhereClause(&rc, pAr, &zWhere);
6448
drhb376b3d2018-01-10 13:11:51 +00006449 shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
6450 pAr->zSrcTable, zWhere);
drhb376b3d2018-01-10 13:11:51 +00006451 if( pAr->bDryRun ){
6452 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
6453 }else{
6454 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
6455 if( pAr->bVerbose ){
drh410cad92018-01-10 17:19:16 +00006456 utf8_printf(pAr->p->out, "%s % 10d %s %s\n",
6457 sqlite3_column_text(pSql, 0),
drhb376b3d2018-01-10 13:11:51 +00006458 sqlite3_column_int(pSql, 1),
6459 sqlite3_column_text(pSql, 2),
6460 sqlite3_column_text(pSql, 3)
6461 );
6462 }else{
6463 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
6464 }
danb5090e42017-12-27 21:13:21 +00006465 }
dan3f67ddf2017-12-13 20:04:53 +00006466 }
dan5a78b812017-12-27 18:54:11 +00006467 shellFinalize(&rc, pSql);
drhd0f9cdc2018-05-17 14:09:06 +00006468 sqlite3_free(zWhere);
dan3f67ddf2017-12-13 20:04:53 +00006469 return rc;
dan88be0202017-12-09 17:58:02 +00006470}
6471
6472
danfd0245d2017-12-07 15:44:29 +00006473/*
6474** Implementation of .ar "eXtract" command.
6475*/
drhb376b3d2018-01-10 13:11:51 +00006476static int arExtractCommand(ArCommand *pAr){
dan25c12182017-12-07 21:03:33 +00006477 const char *zSql1 =
dand1b51d42017-12-16 19:11:26 +00006478 "SELECT "
drhb376b3d2018-01-10 13:11:51 +00006479 " ($dir || name),"
6480 " writefile(($dir || name), %s, mode, mtime) "
drh0cfd46a2018-06-06 01:18:01 +00006481 "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
6482 " AND name NOT GLOB '*..[/\\]*'";
dan5a78b812017-12-27 18:54:11 +00006483
6484 const char *azExtraArg[] = {
6485 "sqlar_uncompress(data, sz)",
dan7c15ac12018-01-08 19:59:59 +00006486 "data"
dan5a78b812017-12-27 18:54:11 +00006487 };
dan5a78b812017-12-27 18:54:11 +00006488
danfd0245d2017-12-07 15:44:29 +00006489 sqlite3_stmt *pSql = 0;
6490 int rc = SQLITE_OK;
dan2ad09492017-12-09 18:28:22 +00006491 char *zDir = 0;
dan3f67ddf2017-12-13 20:04:53 +00006492 char *zWhere = 0;
drhb376b3d2018-01-10 13:11:51 +00006493 int i, j;
dan2ad09492017-12-09 18:28:22 +00006494
dan3f67ddf2017-12-13 20:04:53 +00006495 /* If arguments are specified, check that they actually exist within
6496 ** the archive before proceeding. And formulate a WHERE clause to
6497 ** match them. */
drhb376b3d2018-01-10 13:11:51 +00006498 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006499 arWhereClause(&rc, pAr, &zWhere);
6500
6501 if( rc==SQLITE_OK ){
6502 if( pAr->zDir ){
6503 zDir = sqlite3_mprintf("%s/", pAr->zDir);
6504 }else{
6505 zDir = sqlite3_mprintf("");
6506 }
6507 if( zDir==0 ) rc = SQLITE_NOMEM;
dan2ad09492017-12-09 18:28:22 +00006508 }
danfd0245d2017-12-07 15:44:29 +00006509
drhb376b3d2018-01-10 13:11:51 +00006510 shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
6511 azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
dan5a78b812017-12-27 18:54:11 +00006512 );
6513
dan2ad09492017-12-09 18:28:22 +00006514 if( rc==SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00006515 j = sqlite3_bind_parameter_index(pSql, "$dir");
6516 sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
dan25c12182017-12-07 21:03:33 +00006517
danac15e2d2017-12-14 19:15:07 +00006518 /* Run the SELECT statement twice. The first time, writefile() is called
6519 ** for all archive members that should be extracted. The second time,
6520 ** only for the directories. This is because the timestamps for
6521 ** extracted directories must be reset after they are populated (as
6522 ** populating them changes the timestamp). */
6523 for(i=0; i<2; i++){
drhb376b3d2018-01-10 13:11:51 +00006524 j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
6525 sqlite3_bind_int(pSql, j, i);
6526 if( pAr->bDryRun ){
6527 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
6528 }else{
6529 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
6530 if( i==0 && pAr->bVerbose ){
6531 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
6532 }
danac15e2d2017-12-14 19:15:07 +00006533 }
6534 }
6535 shellReset(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00006536 }
danac15e2d2017-12-14 19:15:07 +00006537 shellFinalize(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00006538 }
dan25c12182017-12-07 21:03:33 +00006539
dan2ad09492017-12-09 18:28:22 +00006540 sqlite3_free(zDir);
dan3f67ddf2017-12-13 20:04:53 +00006541 sqlite3_free(zWhere);
danfd0245d2017-12-07 15:44:29 +00006542 return rc;
6543}
6544
drhb376b3d2018-01-10 13:11:51 +00006545/*
6546** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out.
6547*/
6548static int arExecSql(ArCommand *pAr, const char *zSql){
6549 int rc;
6550 if( pAr->bDryRun ){
6551 utf8_printf(pAr->p->out, "%s\n", zSql);
6552 rc = SQLITE_OK;
6553 }else{
drh410cad92018-01-10 17:19:16 +00006554 char *zErr = 0;
6555 rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
6556 if( zErr ){
6557 utf8_printf(stdout, "ERROR: %s\n", zErr);
6558 sqlite3_free(zErr);
6559 }
drhb376b3d2018-01-10 13:11:51 +00006560 }
6561 return rc;
6562}
6563
dan1ad3f612017-12-11 20:22:02 +00006564
danfd0245d2017-12-07 15:44:29 +00006565/*
drhb17ea912019-03-25 14:24:19 +00006566** Implementation of .ar "create", "insert", and "update" commands.
6567**
6568** create -> Create a new SQL archive
6569** insert -> Insert or reinsert all files listed
6570** update -> Insert files that have changed or that were not
6571** previously in the archive
danfd0245d2017-12-07 15:44:29 +00006572**
6573** Create the "sqlar" table in the database if it does not already exist.
6574** Then add each file in the azFile[] array to the archive. Directories
6575** are added recursively. If argument bVerbose is non-zero, a message is
6576** printed on stdout for each file archived.
dan06741a32017-12-13 20:17:18 +00006577**
6578** The create command is the same as update, except that it drops
drhb17ea912019-03-25 14:24:19 +00006579** any existing "sqlar" table before beginning. The "insert" command
6580** always overwrites every file named on the command-line, where as
6581** "update" only overwrites if the size or mtime or mode has changed.
danfd0245d2017-12-07 15:44:29 +00006582*/
drhb376b3d2018-01-10 13:11:51 +00006583static int arCreateOrUpdateCommand(
dan06741a32017-12-13 20:17:18 +00006584 ArCommand *pAr, /* Command arguments and options */
drhb17ea912019-03-25 14:24:19 +00006585 int bUpdate, /* true for a --create. */
6586 int bOnlyIfChanged /* Only update if file has changed */
danfd0245d2017-12-07 15:44:29 +00006587){
dand4b56e52017-12-12 20:04:59 +00006588 const char *zCreate =
drhafba1802018-01-06 15:49:57 +00006589 "CREATE TABLE IF NOT EXISTS sqlar(\n"
6590 " name TEXT PRIMARY KEY, -- name of the file\n"
6591 " mode INT, -- access permissions\n"
6592 " mtime INT, -- last modification time\n"
6593 " sz INT, -- original file size\n"
6594 " data BLOB -- compressed content\n"
6595 ")";
dand4b56e52017-12-12 20:04:59 +00006596 const char *zDrop = "DROP TABLE IF EXISTS sqlar";
drh1bf208c2018-03-09 21:54:01 +00006597 const char *zInsertFmt[2] = {
6598 "REPLACE INTO %s(name,mode,mtime,sz,data)\n"
drh634c70f2018-01-10 16:50:18 +00006599 " SELECT\n"
6600 " %s,\n"
6601 " mode,\n"
6602 " mtime,\n"
drh410cad92018-01-10 17:19:16 +00006603 " CASE substr(lsmode(mode),1,1)\n"
6604 " WHEN '-' THEN length(data)\n"
6605 " WHEN 'd' THEN 0\n"
drh634c70f2018-01-10 16:50:18 +00006606 " ELSE -1 END,\n"
drh69d2d352018-03-09 22:18:53 +00006607 " sqlar_compress(data)\n"
drhb17ea912019-03-25 14:24:19 +00006608 " FROM fsdir(%Q,%Q) AS disk\n"
6609 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
6610 ,
drh1bf208c2018-03-09 21:54:01 +00006611 "REPLACE INTO %s(name,mode,mtime,data)\n"
6612 " SELECT\n"
6613 " %s,\n"
6614 " mode,\n"
6615 " mtime,\n"
6616 " data\n"
drhb17ea912019-03-25 14:24:19 +00006617 " FROM fsdir(%Q,%Q) AS disk\n"
6618 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
drh1bf208c2018-03-09 21:54:01 +00006619 };
danfd0245d2017-12-07 15:44:29 +00006620 int i; /* For iterating through azFile[] */
6621 int rc; /* Return code */
drh1bf208c2018-03-09 21:54:01 +00006622 const char *zTab = 0; /* SQL table into which to insert */
6623 char *zSql;
6624 char zTemp[50];
drhb17ea912019-03-25 14:24:19 +00006625 char *zExists = 0;
danfd0245d2017-12-07 15:44:29 +00006626
drh1bf208c2018-03-09 21:54:01 +00006627 arExecSql(pAr, "PRAGMA page_size=512");
drhb376b3d2018-01-10 13:11:51 +00006628 rc = arExecSql(pAr, "SAVEPOINT ar;");
danfd0245d2017-12-07 15:44:29 +00006629 if( rc!=SQLITE_OK ) return rc;
drh1bf208c2018-03-09 21:54:01 +00006630 zTemp[0] = 0;
6631 if( pAr->bZip ){
6632 /* Initialize the zipfile virtual table, if necessary */
6633 if( pAr->zFile ){
6634 sqlite3_uint64 r;
6635 sqlite3_randomness(sizeof(r),&r);
6636 sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
6637 zTab = zTemp;
6638 zSql = sqlite3_mprintf(
6639 "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)",
6640 zTab, pAr->zFile
6641 );
6642 rc = arExecSql(pAr, zSql);
6643 sqlite3_free(zSql);
6644 }else{
6645 zTab = "zip";
6646 }
6647 }else{
6648 /* Initialize the table for an SQLAR */
6649 zTab = "sqlar";
6650 if( bUpdate==0 ){
6651 rc = arExecSql(pAr, zDrop);
6652 if( rc!=SQLITE_OK ) goto end_ar_transaction;
6653 }
6654 rc = arExecSql(pAr, zCreate);
dan06741a32017-12-13 20:17:18 +00006655 }
drhb17ea912019-03-25 14:24:19 +00006656 if( bOnlyIfChanged ){
6657 zExists = sqlite3_mprintf(
6658 " AND NOT EXISTS("
6659 "SELECT 1 FROM %s AS mem"
6660 " WHERE mem.name=disk.name"
6661 " AND mem.mtime=disk.mtime"
6662 " AND mem.mode=disk.mode)", zTab);
6663 }else{
6664 zExists = sqlite3_mprintf("");
6665 }
6666 if( zExists==0 ) rc = SQLITE_NOMEM;
dan88be0202017-12-09 17:58:02 +00006667 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
mistachkince2052b2018-03-23 00:31:53 +00006668 char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
drh634c70f2018-01-10 16:50:18 +00006669 pAr->bVerbose ? "shell_putsnl(name)" : "name",
drhb17ea912019-03-25 14:24:19 +00006670 pAr->azArg[i], pAr->zDir, zExists);
mistachkince2052b2018-03-23 00:31:53 +00006671 rc = arExecSql(pAr, zSql2);
6672 sqlite3_free(zSql2);
danfd0245d2017-12-07 15:44:29 +00006673 }
drh1bf208c2018-03-09 21:54:01 +00006674end_ar_transaction:
danfd0245d2017-12-07 15:44:29 +00006675 if( rc!=SQLITE_OK ){
drh2bd207f2019-01-11 17:19:59 +00006676 sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
danfd0245d2017-12-07 15:44:29 +00006677 }else{
drhb376b3d2018-01-10 13:11:51 +00006678 rc = arExecSql(pAr, "RELEASE ar;");
drh1bf208c2018-03-09 21:54:01 +00006679 if( pAr->bZip && pAr->zFile ){
6680 zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
6681 arExecSql(pAr, zSql);
6682 sqlite3_free(zSql);
6683 }
danfd0245d2017-12-07 15:44:29 +00006684 }
drhb17ea912019-03-25 14:24:19 +00006685 sqlite3_free(zExists);
danfd0245d2017-12-07 15:44:29 +00006686 return rc;
6687}
6688
6689/*
6690** Implementation of ".ar" dot command.
6691*/
6692static int arDotCommand(
drhe2754c12019-08-26 12:50:01 +00006693 ShellState *pState, /* Current shell tool state */
6694 int fromCmdLine, /* True if -A command-line option, not .ar cmd */
6695 char **azArg, /* Array of arguments passed to dot command */
6696 int nArg /* Number of entries in azArg[] */
danfd0245d2017-12-07 15:44:29 +00006697){
dan88be0202017-12-09 17:58:02 +00006698 ArCommand cmd;
6699 int rc;
drh34660642018-01-10 17:39:54 +00006700 memset(&cmd, 0, sizeof(cmd));
drhd0f9cdc2018-05-17 14:09:06 +00006701 cmd.fromCmdLine = fromCmdLine;
dan88be0202017-12-09 17:58:02 +00006702 rc = arParseCommand(azArg, nArg, &cmd);
6703 if( rc==SQLITE_OK ){
drha5676c42018-01-10 15:17:34 +00006704 int eDbType = SHELL_OPEN_UNSPEC;
drhb376b3d2018-01-10 13:11:51 +00006705 cmd.p = pState;
6706 cmd.db = pState->db;
drha5676c42018-01-10 15:17:34 +00006707 if( cmd.zFile ){
drh1bf208c2018-03-09 21:54:01 +00006708 eDbType = deduceDatabaseType(cmd.zFile, 1);
drha5676c42018-01-10 15:17:34 +00006709 }else{
6710 eDbType = pState->openMode;
6711 }
6712 if( eDbType==SHELL_OPEN_ZIPFILE ){
drh1bf208c2018-03-09 21:54:01 +00006713 if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){
6714 if( cmd.zFile==0 ){
6715 cmd.zSrcTable = sqlite3_mprintf("zip");
6716 }else{
6717 cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
6718 }
dan5a78b812017-12-27 18:54:11 +00006719 }
drha5676c42018-01-10 15:17:34 +00006720 cmd.bZip = 1;
dan5a78b812017-12-27 18:54:11 +00006721 }else if( cmd.zFile ){
dand4b56e52017-12-12 20:04:59 +00006722 int flags;
drha5676c42018-01-10 15:17:34 +00006723 if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
drhb17ea912019-03-25 14:24:19 +00006724 if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
6725 || cmd.eCmd==AR_CMD_UPDATE ){
dand4b56e52017-12-12 20:04:59 +00006726 flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
6727 }else{
6728 flags = SQLITE_OPEN_READONLY;
6729 }
drha82c95b2018-01-10 14:00:00 +00006730 cmd.db = 0;
drha5676c42018-01-10 15:17:34 +00006731 if( cmd.bDryRun ){
6732 utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
6733 eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
6734 }
6735 rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
6736 eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
dand4b56e52017-12-12 20:04:59 +00006737 if( rc!=SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00006738 utf8_printf(stderr, "cannot open file: %s (%s)\n",
6739 cmd.zFile, sqlite3_errmsg(cmd.db)
dand4b56e52017-12-12 20:04:59 +00006740 );
drha5676c42018-01-10 15:17:34 +00006741 goto end_ar_command;
dand4b56e52017-12-12 20:04:59 +00006742 }
drhb376b3d2018-01-10 13:11:51 +00006743 sqlite3_fileio_init(cmd.db, 0, 0);
drhb376b3d2018-01-10 13:11:51 +00006744 sqlite3_sqlar_init(cmd.db, 0, 0);
drh34660642018-01-10 17:39:54 +00006745 sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
6746 shellPutsFunc, 0, 0);
6747
dand4b56e52017-12-12 20:04:59 +00006748 }
drhd0f9cdc2018-05-17 14:09:06 +00006749 if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
drh634c70f2018-01-10 16:50:18 +00006750 if( cmd.eCmd!=AR_CMD_CREATE
6751 && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
6752 ){
drha5676c42018-01-10 15:17:34 +00006753 utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
6754 rc = SQLITE_ERROR;
6755 goto end_ar_command;
6756 }
6757 cmd.zSrcTable = sqlite3_mprintf("sqlar");
6758 }
dand4b56e52017-12-12 20:04:59 +00006759
dan88be0202017-12-09 17:58:02 +00006760 switch( cmd.eCmd ){
6761 case AR_CMD_CREATE:
drhb17ea912019-03-25 14:24:19 +00006762 rc = arCreateOrUpdateCommand(&cmd, 0, 0);
dan88be0202017-12-09 17:58:02 +00006763 break;
danfd0245d2017-12-07 15:44:29 +00006764
dan88be0202017-12-09 17:58:02 +00006765 case AR_CMD_EXTRACT:
drhb376b3d2018-01-10 13:11:51 +00006766 rc = arExtractCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00006767 break;
6768
6769 case AR_CMD_LIST:
drhb376b3d2018-01-10 13:11:51 +00006770 rc = arListCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00006771 break;
6772
dan0d0547f2017-12-14 15:40:42 +00006773 case AR_CMD_HELP:
6774 arUsage(pState->out);
6775 break;
6776
drhb17ea912019-03-25 14:24:19 +00006777 case AR_CMD_INSERT:
6778 rc = arCreateOrUpdateCommand(&cmd, 1, 0);
6779 break;
6780
dan88be0202017-12-09 17:58:02 +00006781 default:
6782 assert( cmd.eCmd==AR_CMD_UPDATE );
drhb17ea912019-03-25 14:24:19 +00006783 rc = arCreateOrUpdateCommand(&cmd, 1, 1);
dan88be0202017-12-09 17:58:02 +00006784 break;
danfd0245d2017-12-07 15:44:29 +00006785 }
6786 }
drha5676c42018-01-10 15:17:34 +00006787end_ar_command:
6788 if( cmd.db!=pState->db ){
drh9e804032018-05-18 17:11:50 +00006789 close_db(cmd.db);
drha5676c42018-01-10 15:17:34 +00006790 }
6791 sqlite3_free(cmd.zSrcTable);
danfd0245d2017-12-07 15:44:29 +00006792
dan88be0202017-12-09 17:58:02 +00006793 return rc;
danfd0245d2017-12-07 15:44:29 +00006794}
drhe37c0e12018-01-06 19:19:50 +00006795/* End of the ".archive" or ".ar" command logic
drhe2754c12019-08-26 12:50:01 +00006796*******************************************************************************/
drhe37c0e12018-01-06 19:19:50 +00006797#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
danfd0245d2017-12-07 15:44:29 +00006798
dan1b162162019-04-27 20:15:15 +00006799#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan42ebb012019-04-27 18:47:03 +00006800/*
6801** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
6802** Otherwise, the SQL statement or statements in zSql are executed using
6803** database connection db and the error code written to *pRc before
6804** this function returns.
6805*/
dan68cb86e2019-04-20 20:57:28 +00006806static void shellExec(sqlite3 *db, int *pRc, const char *zSql){
6807 int rc = *pRc;
6808 if( rc==SQLITE_OK ){
6809 char *zErr = 0;
6810 rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
6811 if( rc!=SQLITE_OK ){
6812 raw_printf(stderr, "SQL error: %s\n", zErr);
6813 }
drhf83d5012021-05-03 13:35:00 +00006814 sqlite3_free(zErr);
dan68cb86e2019-04-20 20:57:28 +00006815 *pRc = rc;
6816 }
6817}
6818
dan42ebb012019-04-27 18:47:03 +00006819/*
6820** Like shellExec(), except that zFmt is a printf() style format string.
6821*/
danc0b42432019-04-26 15:14:53 +00006822static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){
6823 char *z = 0;
6824 if( *pRc==SQLITE_OK ){
6825 va_list ap;
6826 va_start(ap, zFmt);
6827 z = sqlite3_vmprintf(zFmt, ap);
6828 va_end(ap);
6829 if( z==0 ){
6830 *pRc = SQLITE_NOMEM;
6831 }else{
6832 shellExec(db, pRc, z);
6833 }
6834 sqlite3_free(z);
6835 }
6836}
6837
dan42ebb012019-04-27 18:47:03 +00006838/*
6839** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
6840** Otherwise, an attempt is made to allocate, zero and return a pointer
6841** to a buffer nByte bytes in size. If an OOM error occurs, *pRc is set
6842** to SQLITE_NOMEM and NULL returned.
6843*/
dan68cb86e2019-04-20 20:57:28 +00006844static void *shellMalloc(int *pRc, sqlite3_int64 nByte){
6845 void *pRet = 0;
6846 if( *pRc==SQLITE_OK ){
6847 pRet = sqlite3_malloc64(nByte);
6848 if( pRet==0 ){
6849 *pRc = SQLITE_NOMEM;
6850 }else{
6851 memset(pRet, 0, nByte);
6852 }
6853 }
6854 return pRet;
6855}
6856
dan42ebb012019-04-27 18:47:03 +00006857/*
6858** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
6859** Otherwise, zFmt is treated as a printf() style string. The result of
6860** formatting it along with any trailing arguments is written into a
6861** buffer obtained from sqlite3_malloc(), and pointer to which is returned.
6862** It is the responsibility of the caller to eventually free this buffer
6863** using a call to sqlite3_free().
6864**
6865** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL
6866** pointer returned.
6867*/
dan68cb86e2019-04-20 20:57:28 +00006868static char *shellMPrintf(int *pRc, const char *zFmt, ...){
6869 char *z = 0;
6870 if( *pRc==SQLITE_OK ){
6871 va_list ap;
6872 va_start(ap, zFmt);
6873 z = sqlite3_vmprintf(zFmt, ap);
6874 va_end(ap);
6875 if( z==0 ){
6876 *pRc = SQLITE_NOMEM;
6877 }
6878 }
6879 return z;
6880}
6881
dan42ebb012019-04-27 18:47:03 +00006882/*
6883** When running the ".recover" command, each output table, and the special
6884** orphaned row table if it is required, is represented by an instance
6885** of the following struct.
6886*/
dan68cb86e2019-04-20 20:57:28 +00006887typedef struct RecoverTable RecoverTable;
6888struct RecoverTable {
dan42ebb012019-04-27 18:47:03 +00006889 char *zQuoted; /* Quoted version of table name */
dan68cb86e2019-04-20 20:57:28 +00006890 int nCol; /* Number of columns in table */
6891 char **azlCol; /* Array of column lists */
dan42ebb012019-04-27 18:47:03 +00006892 int iPk; /* Index of IPK column */
dan68cb86e2019-04-20 20:57:28 +00006893};
6894
6895/*
dan42ebb012019-04-27 18:47:03 +00006896** Free a RecoverTable object allocated by recoverFindTable() or
6897** recoverOrphanTable().
dan68cb86e2019-04-20 20:57:28 +00006898*/
6899static void recoverFreeTable(RecoverTable *pTab){
6900 if( pTab ){
dan68cb86e2019-04-20 20:57:28 +00006901 sqlite3_free(pTab->zQuoted);
dan68cb86e2019-04-20 20:57:28 +00006902 if( pTab->azlCol ){
6903 int i;
dan98c5ad32019-04-26 21:11:37 +00006904 for(i=0; i<=pTab->nCol; i++){
dan68cb86e2019-04-20 20:57:28 +00006905 sqlite3_free(pTab->azlCol[i]);
6906 }
6907 sqlite3_free(pTab->azlCol);
6908 }
6909 sqlite3_free(pTab);
6910 }
6911}
6912
dan42ebb012019-04-27 18:47:03 +00006913/*
6914** This function is a no-op if (*pRc) is not SQLITE_OK when it is called.
6915** Otherwise, it allocates and returns a RecoverTable object based on the
6916** final four arguments passed to this function. It is the responsibility
6917** of the caller to eventually free the returned object using
6918** recoverFreeTable().
6919*/
6920static RecoverTable *recoverNewTable(
danb40af492019-04-22 20:52:12 +00006921 int *pRc, /* IN/OUT: Error code */
danb40af492019-04-22 20:52:12 +00006922 const char *zName, /* Name of table */
6923 const char *zSql, /* CREATE TABLE statement */
6924 int bIntkey,
6925 int nCol
6926){
6927 sqlite3 *dbtmp = 0; /* sqlite3 handle for testing CREATE TABLE */
6928 int rc = *pRc;
dan98c5ad32019-04-26 21:11:37 +00006929 RecoverTable *pTab = 0;
danb40af492019-04-22 20:52:12 +00006930
dan98c5ad32019-04-26 21:11:37 +00006931 pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable));
danb40af492019-04-22 20:52:12 +00006932 if( rc==SQLITE_OK ){
6933 int nSqlCol = 0;
6934 int bSqlIntkey = 0;
6935 sqlite3_stmt *pStmt = 0;
dan98c5ad32019-04-26 21:11:37 +00006936
danb40af492019-04-22 20:52:12 +00006937 rc = sqlite3_open("", &dbtmp);
6938 if( rc==SQLITE_OK ){
drha2de66c2019-08-06 20:26:17 +00006939 sqlite3_create_function(dbtmp, "shell_idquote", 1, SQLITE_UTF8, 0,
6940 shellIdQuote, 0, 0);
6941 }
6942 if( rc==SQLITE_OK ){
dan38f9c712019-04-23 18:03:02 +00006943 rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
6944 }
6945 if( rc==SQLITE_OK ){
danb40af492019-04-22 20:52:12 +00006946 rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0);
6947 if( rc==SQLITE_ERROR ){
6948 rc = SQLITE_OK;
6949 goto finished;
6950 }
6951 }
6952 shellPreparePrintf(dbtmp, &rc, &pStmt,
6953 "SELECT count(*) FROM pragma_table_info(%Q)", zName
6954 );
6955 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
6956 nSqlCol = sqlite3_column_int(pStmt, 0);
6957 }
6958 shellFinalize(&rc, pStmt);
6959
6960 if( rc!=SQLITE_OK || nSqlCol<nCol ){
6961 goto finished;
6962 }
6963
6964 shellPreparePrintf(dbtmp, &rc, &pStmt,
6965 "SELECT ("
6966 " SELECT substr(data,1,1)==X'0D' FROM sqlite_dbpage WHERE pgno=rootpage"
drh067b92b2020-06-19 15:24:12 +00006967 ") FROM sqlite_schema WHERE name = %Q", zName
danb40af492019-04-22 20:52:12 +00006968 );
6969 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
6970 bSqlIntkey = sqlite3_column_int(pStmt, 0);
6971 }
6972 shellFinalize(&rc, pStmt);
6973
6974 if( bIntkey==bSqlIntkey ){
dan98c5ad32019-04-26 21:11:37 +00006975 int i;
danb40af492019-04-22 20:52:12 +00006976 const char *zPk = "_rowid_";
6977 sqlite3_stmt *pPkFinder = 0;
6978
danf57bea32019-04-27 15:35:45 +00006979 /* If this is an intkey table and there is an INTEGER PRIMARY KEY,
6980 ** set zPk to the name of the PK column, and pTab->iPk to the index
6981 ** of the column, where columns are 0-numbered from left to right.
6982 ** Or, if this is a WITHOUT ROWID table or if there is no IPK column,
6983 ** leave zPk as "_rowid_" and pTab->iPk at -2. */
dan98c5ad32019-04-26 21:11:37 +00006984 pTab->iPk = -2;
6985 if( bIntkey ){
6986 shellPreparePrintf(dbtmp, &rc, &pPkFinder,
danb40af492019-04-22 20:52:12 +00006987 "SELECT cid, name FROM pragma_table_info(%Q) "
6988 " WHERE pk=1 AND type='integer' COLLATE nocase"
dan98c5ad32019-04-26 21:11:37 +00006989 " AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
6990 , zName, zName
6991 );
6992 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){
6993 pTab->iPk = sqlite3_column_int(pPkFinder, 0);
6994 zPk = (const char*)sqlite3_column_text(pPkFinder, 1);
6995 }
danb40af492019-04-22 20:52:12 +00006996 }
6997
drha2de66c2019-08-06 20:26:17 +00006998 pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName);
dan98c5ad32019-04-26 21:11:37 +00006999 pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
danb40af492019-04-22 20:52:12 +00007000 pTab->nCol = nSqlCol;
7001
dan98c5ad32019-04-26 21:11:37 +00007002 if( bIntkey ){
drha2de66c2019-08-06 20:26:17 +00007003 pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk);
danb40af492019-04-22 20:52:12 +00007004 }else{
dan98c5ad32019-04-26 21:11:37 +00007005 pTab->azlCol[0] = shellMPrintf(&rc, "");
danb40af492019-04-22 20:52:12 +00007006 }
dan98c5ad32019-04-26 21:11:37 +00007007 i = 1;
7008 shellPreparePrintf(dbtmp, &rc, &pStmt,
drha2de66c2019-08-06 20:26:17 +00007009 "SELECT %Q || group_concat(shell_idquote(name), ', ') "
danf57bea32019-04-27 15:35:45 +00007010 " FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
dan98c5ad32019-04-26 21:11:37 +00007011 "FROM pragma_table_info(%Q)",
danf57bea32019-04-27 15:35:45 +00007012 bIntkey ? ", " : "", pTab->iPk,
7013 bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ",
7014 zName
dan98c5ad32019-04-26 21:11:37 +00007015 );
7016 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7017 const char *zText = (const char*)sqlite3_column_text(pStmt, 0);
7018 pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText);
7019 i++;
7020 }
7021 shellFinalize(&rc, pStmt);
7022
danb40af492019-04-22 20:52:12 +00007023 shellFinalize(&rc, pPkFinder);
7024 }
7025 }
7026
7027 finished:
7028 sqlite3_close(dbtmp);
7029 *pRc = rc;
dan98779652019-05-09 14:15:19 +00007030 if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){
dan98c5ad32019-04-26 21:11:37 +00007031 recoverFreeTable(pTab);
7032 pTab = 0;
7033 }
7034 return pTab;
danb40af492019-04-22 20:52:12 +00007035}
7036
dan0aa01ee2019-04-27 19:36:49 +00007037/*
7038** This function is called to search the schema recovered from the
drh067b92b2020-06-19 15:24:12 +00007039** sqlite_schema table of the (possibly) corrupt database as part
dan0aa01ee2019-04-27 19:36:49 +00007040** of a ".recover" command. Specifically, for a table with root page
7041** iRoot and at least nCol columns. Additionally, if bIntkey is 0, the
7042** table must be a WITHOUT ROWID table, or if non-zero, not one of
7043** those.
7044**
7045** If a table is found, a (RecoverTable*) object is returned. Or, if
7046** no such table is found, but bIntkey is false and iRoot is the
7047** root page of an index in the recovered schema, then (*pbNoop) is
7048** set to true and NULL returned. Or, if there is no such table or
7049** index, NULL is returned and (*pbNoop) set to 0, indicating that
7050** the caller should write data to the orphans table.
7051*/
dan42ebb012019-04-27 18:47:03 +00007052static RecoverTable *recoverFindTable(
dan0aa01ee2019-04-27 19:36:49 +00007053 ShellState *pState, /* Shell state object */
7054 int *pRc, /* IN/OUT: Error code */
7055 int iRoot, /* Root page of table */
7056 int bIntkey, /* True for an intkey table */
7057 int nCol, /* Number of columns in table */
7058 int *pbNoop /* OUT: True if iRoot is root of index */
dan68cb86e2019-04-20 20:57:28 +00007059){
danb40af492019-04-22 20:52:12 +00007060 sqlite3_stmt *pStmt = 0;
dan68cb86e2019-04-20 20:57:28 +00007061 RecoverTable *pRet = 0;
danb40af492019-04-22 20:52:12 +00007062 int bNoop = 0;
7063 const char *zSql = 0;
7064 const char *zName = 0;
dan68cb86e2019-04-20 20:57:28 +00007065
danb40af492019-04-22 20:52:12 +00007066 /* Search the recovered schema for an object with root page iRoot. */
7067 shellPreparePrintf(pState->db, pRc, &pStmt,
7068 "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot
7069 );
7070 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7071 const char *zType = (const char*)sqlite3_column_text(pStmt, 0);
7072 if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){
7073 bNoop = 1;
7074 break;
7075 }
7076 if( sqlite3_stricmp(zType, "table")==0 ){
7077 zName = (const char*)sqlite3_column_text(pStmt, 1);
7078 zSql = (const char*)sqlite3_column_text(pStmt, 2);
dan42ebb012019-04-27 18:47:03 +00007079 pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol);
danb40af492019-04-22 20:52:12 +00007080 break;
7081 }
7082 }
dan98c5ad32019-04-26 21:11:37 +00007083
danb40af492019-04-22 20:52:12 +00007084 shellFinalize(pRc, pStmt);
dan98c5ad32019-04-26 21:11:37 +00007085 *pbNoop = bNoop;
7086 return pRet;
7087}
danb40af492019-04-22 20:52:12 +00007088
dan0aa01ee2019-04-27 19:36:49 +00007089/*
7090** Return a RecoverTable object representing the orphans table.
7091*/
dan98c5ad32019-04-26 21:11:37 +00007092static RecoverTable *recoverOrphanTable(
dan0aa01ee2019-04-27 19:36:49 +00007093 ShellState *pState, /* Shell state object */
7094 int *pRc, /* IN/OUT: Error code */
7095 const char *zLostAndFound, /* Base name for orphans table */
7096 int nCol /* Number of user data columns */
dan98c5ad32019-04-26 21:11:37 +00007097){
7098 RecoverTable *pTab = 0;
7099 if( nCol>=0 && *pRc==SQLITE_OK ){
7100 int i;
dan42ebb012019-04-27 18:47:03 +00007101
7102 /* This block determines the name of the orphan table. The prefered
7103 ** name is zLostAndFound. But if that clashes with another name
7104 ** in the recovered schema, try zLostAndFound_0, zLostAndFound_1
7105 ** and so on until a non-clashing name is found. */
7106 int iTab = 0;
7107 char *zTab = shellMPrintf(pRc, "%s", zLostAndFound);
7108 sqlite3_stmt *pTest = 0;
7109 shellPrepare(pState->db, pRc,
7110 "SELECT 1 FROM recovery.schema WHERE name=?", &pTest
dan68cb86e2019-04-20 20:57:28 +00007111 );
dan42ebb012019-04-27 18:47:03 +00007112 if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
7113 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){
7114 shellReset(pRc, pTest);
7115 sqlite3_free(zTab);
7116 zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++);
7117 sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
dan68cb86e2019-04-20 20:57:28 +00007118 }
dan42ebb012019-04-27 18:47:03 +00007119 shellFinalize(pRc, pTest);
dan68cb86e2019-04-20 20:57:28 +00007120
dan98c5ad32019-04-26 21:11:37 +00007121 pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
7122 if( pTab ){
drha2de66c2019-08-06 20:26:17 +00007123 pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab);
dan98c5ad32019-04-26 21:11:37 +00007124 pTab->nCol = nCol;
7125 pTab->iPk = -2;
7126 if( nCol>0 ){
7127 pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1));
7128 if( pTab->azlCol ){
7129 pTab->azlCol[nCol] = shellMPrintf(pRc, "");
7130 for(i=nCol-1; i>=0; i--){
7131 pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]);
7132 }
7133 }
danb40af492019-04-22 20:52:12 +00007134 }
dan68cb86e2019-04-20 20:57:28 +00007135
dan42ebb012019-04-27 18:47:03 +00007136 if( *pRc!=SQLITE_OK ){
7137 recoverFreeTable(pTab);
7138 pTab = 0;
7139 }else{
7140 raw_printf(pState->out,
7141 "CREATE TABLE %s(rootpgno INTEGER, "
7142 "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted
7143 );
7144 for(i=0; i<nCol; i++){
7145 raw_printf(pState->out, ", c%d", i);
7146 }
7147 raw_printf(pState->out, ");\n");
7148 }
dan98c5ad32019-04-26 21:11:37 +00007149 }
dan42ebb012019-04-27 18:47:03 +00007150 sqlite3_free(zTab);
dan68cb86e2019-04-20 20:57:28 +00007151 }
dan98c5ad32019-04-26 21:11:37 +00007152 return pTab;
dan68cb86e2019-04-20 20:57:28 +00007153}
7154
7155/*
7156** This function is called to recover data from the database. A script
7157** to construct a new database containing all recovered data is output
7158** on stream pState->out.
7159*/
danb9b71db2019-04-25 16:20:40 +00007160static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
dan68cb86e2019-04-20 20:57:28 +00007161 int rc = SQLITE_OK;
7162 sqlite3_stmt *pLoop = 0; /* Loop through all root pages */
danefa363b2019-04-24 20:48:55 +00007163 sqlite3_stmt *pPages = 0; /* Loop through all pages in a group */
7164 sqlite3_stmt *pCells = 0; /* Loop through all cells in a page */
danc0b42432019-04-26 15:14:53 +00007165 const char *zRecoveryDb = ""; /* Name of "recovery" database */
dan42ebb012019-04-27 18:47:03 +00007166 const char *zLostAndFound = "lost_and_found";
dan9c014f82019-04-25 19:23:15 +00007167 int i;
dan98c5ad32019-04-26 21:11:37 +00007168 int nOrphan = -1;
7169 RecoverTable *pOrphan = 0;
dan9c014f82019-04-25 19:23:15 +00007170
7171 int bFreelist = 1; /* 0 if --freelist-corrupt is specified */
dan8cce6b82019-09-14 16:44:51 +00007172 int bRowids = 1; /* 0 if --no-rowids */
dan9c014f82019-04-25 19:23:15 +00007173 for(i=1; i<nArg; i++){
7174 char *z = azArg[i];
7175 int n;
7176 if( z[0]=='-' && z[1]=='-' ) z++;
drh4245e042019-06-13 13:52:46 +00007177 n = strlen30(z);
dan9c014f82019-04-25 19:23:15 +00007178 if( n<=17 && memcmp("-freelist-corrupt", z, n)==0 ){
7179 bFreelist = 0;
dan42ebb012019-04-27 18:47:03 +00007180 }else
danc0b42432019-04-26 15:14:53 +00007181 if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
7182 i++;
7183 zRecoveryDb = azArg[i];
dan42ebb012019-04-27 18:47:03 +00007184 }else
7185 if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
7186 i++;
7187 zLostAndFound = azArg[i];
dan8cce6b82019-09-14 16:44:51 +00007188 }else
7189 if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
7190 bRowids = 0;
danc0b42432019-04-26 15:14:53 +00007191 }
dan9c014f82019-04-25 19:23:15 +00007192 else{
drhe2754c12019-08-26 12:50:01 +00007193 utf8_printf(stderr, "unexpected option: %s\n", azArg[i]);
7194 showHelp(pState->out, azArg[0]);
dan9c014f82019-04-25 19:23:15 +00007195 return 1;
7196 }
7197 }
dan68cb86e2019-04-20 20:57:28 +00007198
danc0b42432019-04-26 15:14:53 +00007199 shellExecPrintf(pState->db, &rc,
dan68cb86e2019-04-20 20:57:28 +00007200 /* Attach an in-memory database named 'recovery'. Create an indexed
7201 ** cache of the sqlite_dbptr virtual table. */
dan01c08bc2019-07-24 19:20:30 +00007202 "PRAGMA writable_schema = on;"
danc0b42432019-04-26 15:14:53 +00007203 "ATTACH %Q AS recovery;"
7204 "DROP TABLE IF EXISTS recovery.dbptr;"
7205 "DROP TABLE IF EXISTS recovery.freelist;"
7206 "DROP TABLE IF EXISTS recovery.map;"
7207 "DROP TABLE IF EXISTS recovery.schema;"
danc0b42432019-04-26 15:14:53 +00007208 "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb
dan9c014f82019-04-25 19:23:15 +00007209 );
7210
7211 if( bFreelist ){
7212 shellExec(pState->db, &rc,
7213 "WITH trunk(pgno) AS ("
7214 " SELECT shell_int32("
7215 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x "
7216 " WHERE x>0"
7217 " UNION"
7218 " SELECT shell_int32("
7219 " (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x "
7220 " FROM trunk WHERE x>0"
7221 "),"
7222 "freelist(data, n, freepgno) AS ("
danf6099e92019-05-09 16:57:39 +00007223 " SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno "
dan9c014f82019-04-25 19:23:15 +00007224 " FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno"
7225 " UNION ALL"
7226 " SELECT data, n-1, shell_int32(data, 2+n) "
7227 " FROM freelist WHERE n>=0"
7228 ")"
7229 "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;"
7230 );
7231 }
7232
dan95063c22019-07-24 08:15:09 +00007233 /* If this is an auto-vacuum database, add all pointer-map pages to
7234 ** the freelist table. Do this regardless of whether or not
7235 ** --freelist-corrupt was specified. */
7236 shellExec(pState->db, &rc,
7237 "WITH ptrmap(pgno) AS ("
7238 " SELECT 2 WHERE shell_int32("
7239 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 13"
7240 " )"
7241 " UNION ALL "
7242 " SELECT pgno+1+(SELECT page_size FROM pragma_page_size)/5 AS pp "
7243 " FROM ptrmap WHERE pp<=(SELECT page_count FROM pragma_page_count)"
7244 ")"
7245 "REPLACE INTO recovery.freelist SELECT pgno FROM ptrmap"
7246 );
7247
dan9c014f82019-04-25 19:23:15 +00007248 shellExec(pState->db, &rc,
danca424382019-04-26 15:40:27 +00007249 "CREATE TABLE recovery.dbptr("
7250 " pgno, child, PRIMARY KEY(child, pgno)"
7251 ") WITHOUT ROWID;"
7252 "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) "
7253 " SELECT * FROM sqlite_dbptr"
7254 " WHERE pgno NOT IN freelist AND child NOT IN freelist;"
7255
7256 /* Delete any pointer to page 1. This ensures that page 1 is considered
7257 ** a root page, regardless of how corrupt the db is. */
7258 "DELETE FROM recovery.dbptr WHERE child = 1;"
7259
7260 /* Delete all pointers to any pages that have more than one pointer
7261 ** to them. Such pages will be treated as root pages when recovering
7262 ** data. */
7263 "DELETE FROM recovery.dbptr WHERE child IN ("
7264 " SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1"
7265 ");"
7266
dan68cb86e2019-04-20 20:57:28 +00007267 /* Create the "map" table that will (eventually) contain instructions
7268 ** for dealing with each page in the db that contains one or more
7269 ** records. */
danb40af492019-04-22 20:52:12 +00007270 "CREATE TABLE recovery.map("
7271 "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT"
7272 ");"
dan68cb86e2019-04-20 20:57:28 +00007273
7274 /* Populate table [map]. If there are circular loops of pages in the
7275 ** database, the following adds all pages in such a loop to the map
7276 ** as individual root pages. This could be handled better. */
7277 "WITH pages(i, maxlen) AS ("
danb9b71db2019-04-25 16:20:40 +00007278 " SELECT page_count, ("
7279 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count"
dan13b87672019-05-09 11:45:21 +00007280 " ) FROM pragma_page_count WHERE page_count>0"
dan68cb86e2019-04-20 20:57:28 +00007281 " UNION ALL"
danb40af492019-04-22 20:52:12 +00007282 " SELECT i-1, ("
7283 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1"
7284 " ) FROM pages WHERE i>=2"
dan68cb86e2019-04-20 20:57:28 +00007285 ")"
danb40af492019-04-22 20:52:12 +00007286 "INSERT INTO recovery.map(pgno, maxlen, intkey, root) "
7287 " SELECT i, maxlen, NULL, ("
dan68cb86e2019-04-20 20:57:28 +00007288 " WITH p(orig, pgno, parent) AS ("
7289 " SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)"
dan39e04f82019-05-09 18:33:32 +00007290 " UNION "
dan68cb86e2019-04-20 20:57:28 +00007291 " SELECT i, p.parent, "
7292 " (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p"
7293 " )"
7294 " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
7295 ") "
dand790c9a2019-08-26 14:57:58 +00007296 "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;"
danb40af492019-04-22 20:52:12 +00007297 "UPDATE recovery.map AS o SET intkey = ("
7298 " SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
7299 ");"
dan68cb86e2019-04-20 20:57:28 +00007300
7301 /* Extract data from page 1 and any linked pages into table
drh067b92b2020-06-19 15:24:12 +00007302 ** recovery.schema. With the same schema as an sqlite_schema table. */
dan68cb86e2019-04-20 20:57:28 +00007303 "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
7304 "INSERT INTO recovery.schema SELECT "
7305 " max(CASE WHEN field=0 THEN value ELSE NULL END),"
7306 " max(CASE WHEN field=1 THEN value ELSE NULL END),"
7307 " max(CASE WHEN field=2 THEN value ELSE NULL END),"
7308 " max(CASE WHEN field=3 THEN value ELSE NULL END),"
7309 " max(CASE WHEN field=4 THEN value ELSE NULL END)"
7310 "FROM sqlite_dbdata WHERE pgno IN ("
7311 " SELECT pgno FROM recovery.map WHERE root=1"
7312 ")"
7313 "GROUP BY pgno, cell;"
dan98c5ad32019-04-26 21:11:37 +00007314 "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);"
dan68cb86e2019-04-20 20:57:28 +00007315 );
7316
danb40af492019-04-22 20:52:12 +00007317 /* Open a transaction, then print out all non-virtual, non-"sqlite_%"
7318 ** CREATE TABLE statements that extracted from the existing schema. */
7319 if( rc==SQLITE_OK ){
7320 sqlite3_stmt *pStmt = 0;
danf3210572019-08-06 18:40:36 +00007321 /* ".recover" might output content in an order which causes immediate
7322 ** foreign key constraints to be violated. So disable foreign-key
7323 ** constraint enforcement to prevent problems when running the output
7324 ** script. */
7325 raw_printf(pState->out, "PRAGMA foreign_keys=OFF;\n");
danb40af492019-04-22 20:52:12 +00007326 raw_printf(pState->out, "BEGIN;\n");
dan38f9c712019-04-23 18:03:02 +00007327 raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
7328 shellPrepare(pState->db, &rc,
danb40af492019-04-22 20:52:12 +00007329 "SELECT sql FROM recovery.schema "
dan38f9c712019-04-23 18:03:02 +00007330 "WHERE type='table' AND sql LIKE 'create table%'", &pStmt
danb40af492019-04-22 20:52:12 +00007331 );
7332 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7333 const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0);
dan38f9c712019-04-23 18:03:02 +00007334 raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n",
7335 &zCreateTable[12]
7336 );
danb40af492019-04-22 20:52:12 +00007337 }
7338 shellFinalize(&rc, pStmt);
7339 }
7340
dan98c5ad32019-04-26 21:11:37 +00007341 /* Figure out if an orphan table will be required. And if so, how many
7342 ** user columns it should contain */
7343 shellPrepare(pState->db, &rc,
dan98779652019-05-09 14:15:19 +00007344 "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1"
dan98c5ad32019-04-26 21:11:37 +00007345 , &pLoop
7346 );
7347 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
7348 nOrphan = sqlite3_column_int(pLoop, 0);
7349 }
7350 shellFinalize(&rc, pLoop);
7351 pLoop = 0;
dan98c5ad32019-04-26 21:11:37 +00007352
danefa363b2019-04-24 20:48:55 +00007353 shellPrepare(pState->db, &rc,
7354 "SELECT pgno FROM recovery.map WHERE root=?", &pPages
7355 );
dan8cce6b82019-09-14 16:44:51 +00007356
danefa363b2019-04-24 20:48:55 +00007357 shellPrepare(pState->db, &rc,
dan8cce6b82019-09-14 16:44:51 +00007358 "SELECT max(field), group_concat(shell_escape_crnl(quote"
7359 "(case when (? AND field<0) then NULL else value end)"
7360 "), ', ')"
dan9443dbc2019-07-24 20:10:27 +00007361 ", min(field) "
danefa363b2019-04-24 20:48:55 +00007362 "FROM sqlite_dbdata WHERE pgno = ? AND field != ?"
7363 "GROUP BY cell", &pCells
7364 );
7365
dan68cb86e2019-04-20 20:57:28 +00007366 /* Loop through each root page. */
danb40af492019-04-22 20:52:12 +00007367 shellPrepare(pState->db, &rc,
7368 "SELECT root, intkey, max(maxlen) FROM recovery.map"
dan38f9c712019-04-23 18:03:02 +00007369 " WHERE root>1 GROUP BY root, intkey ORDER BY root=("
7370 " SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'"
7371 ")", &pLoop
danb40af492019-04-22 20:52:12 +00007372 );
dan68cb86e2019-04-20 20:57:28 +00007373 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
7374 int iRoot = sqlite3_column_int(pLoop, 0);
danb40af492019-04-22 20:52:12 +00007375 int bIntkey = sqlite3_column_int(pLoop, 1);
7376 int nCol = sqlite3_column_int(pLoop, 2);
dan98c5ad32019-04-26 21:11:37 +00007377 int bNoop = 0;
dan68cb86e2019-04-20 20:57:28 +00007378 RecoverTable *pTab;
7379
dan9443dbc2019-07-24 20:10:27 +00007380 assert( bIntkey==0 || bIntkey==1 );
dan42ebb012019-04-27 18:47:03 +00007381 pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);
dan98c5ad32019-04-26 21:11:37 +00007382 if( bNoop || rc ) continue;
dan98779652019-05-09 14:15:19 +00007383 if( pTab==0 ){
7384 if( pOrphan==0 ){
7385 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
7386 }
7387 pTab = pOrphan;
7388 if( pTab==0 ) break;
7389 }
dan98c5ad32019-04-26 21:11:37 +00007390
drha2de66c2019-08-06 20:26:17 +00007391 if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){
dan98c5ad32019-04-26 21:11:37 +00007392 raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
7393 }
7394 sqlite3_bind_int(pPages, 1, iRoot);
dan8cce6b82019-09-14 16:44:51 +00007395 if( bRowids==0 && pTab->iPk<0 ){
7396 sqlite3_bind_int(pCells, 1, 1);
7397 }else{
7398 sqlite3_bind_int(pCells, 1, 0);
7399 }
7400 sqlite3_bind_int(pCells, 3, pTab->iPk);
dan98c5ad32019-04-26 21:11:37 +00007401
7402 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){
7403 int iPgno = sqlite3_column_int(pPages, 0);
dan8cce6b82019-09-14 16:44:51 +00007404 sqlite3_bind_int(pCells, 2, iPgno);
dan98c5ad32019-04-26 21:11:37 +00007405 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){
7406 int nField = sqlite3_column_int(pCells, 0);
dan9443dbc2019-07-24 20:10:27 +00007407 int iMin = sqlite3_column_int(pCells, 2);
dan98c5ad32019-04-26 21:11:37 +00007408 const char *zVal = (const char*)sqlite3_column_text(pCells, 1);
7409
dan9443dbc2019-07-24 20:10:27 +00007410 RecoverTable *pTab2 = pTab;
7411 if( pTab!=pOrphan && (iMin<0)!=bIntkey ){
7412 if( pOrphan==0 ){
7413 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
7414 }
7415 pTab2 = pOrphan;
7416 if( pTab2==0 ) break;
7417 }
7418
dan98c5ad32019-04-26 21:11:37 +00007419 nField = nField+1;
dan9443dbc2019-07-24 20:10:27 +00007420 if( pTab2==pOrphan ){
dan98c5ad32019-04-26 21:11:37 +00007421 raw_printf(pState->out,
7422 "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",
dan9443dbc2019-07-24 20:10:27 +00007423 pTab2->zQuoted, iRoot, iPgno, nField,
7424 iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField]
dan98c5ad32019-04-26 21:11:37 +00007425 );
7426 }else{
danefa363b2019-04-24 20:48:55 +00007427 raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n",
dan9443dbc2019-07-24 20:10:27 +00007428 pTab2->zQuoted, pTab2->azlCol[nField], zVal
danefa363b2019-04-24 20:48:55 +00007429 );
7430 }
dan68cb86e2019-04-20 20:57:28 +00007431 }
dan98c5ad32019-04-26 21:11:37 +00007432 shellReset(&rc, pCells);
dan68cb86e2019-04-20 20:57:28 +00007433 }
dan98c5ad32019-04-26 21:11:37 +00007434 shellReset(&rc, pPages);
7435 if( pTab!=pOrphan ) recoverFreeTable(pTab);
dan68cb86e2019-04-20 20:57:28 +00007436 }
7437 shellFinalize(&rc, pLoop);
danefa363b2019-04-24 20:48:55 +00007438 shellFinalize(&rc, pPages);
7439 shellFinalize(&rc, pCells);
dan98c5ad32019-04-26 21:11:37 +00007440 recoverFreeTable(pOrphan);
dan68cb86e2019-04-20 20:57:28 +00007441
dan38f9c712019-04-23 18:03:02 +00007442 /* The rest of the schema */
danb40af492019-04-22 20:52:12 +00007443 if( rc==SQLITE_OK ){
dan38f9c712019-04-23 18:03:02 +00007444 sqlite3_stmt *pStmt = 0;
7445 shellPrepare(pState->db, &rc,
7446 "SELECT sql, name FROM recovery.schema "
danb1825882019-04-23 20:48:32 +00007447 "WHERE sql NOT LIKE 'create table%'", &pStmt
dan38f9c712019-04-23 18:03:02 +00007448 );
7449 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7450 const char *zSql = (const char*)sqlite3_column_text(pStmt, 0);
7451 if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){
7452 const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
7453 char *zPrint = shellMPrintf(&rc,
drh067b92b2020-06-19 15:24:12 +00007454 "INSERT INTO sqlite_schema VALUES('table', %Q, %Q, 0, %Q)",
dan38f9c712019-04-23 18:03:02 +00007455 zName, zName, zSql
7456 );
7457 raw_printf(pState->out, "%s;\n", zPrint);
7458 sqlite3_free(zPrint);
7459 }else{
7460 raw_printf(pState->out, "%s;\n", zSql);
7461 }
7462 }
7463 shellFinalize(&rc, pStmt);
7464 }
7465
7466 if( rc==SQLITE_OK ){
7467 raw_printf(pState->out, "PRAGMA writable_schema = off;\n");
danb40af492019-04-22 20:52:12 +00007468 raw_printf(pState->out, "COMMIT;\n");
7469 }
dan68cb86e2019-04-20 20:57:28 +00007470 sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
7471 return rc;
7472}
dan1b162162019-04-27 20:15:15 +00007473#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
dan68cb86e2019-04-20 20:57:28 +00007474
drh2ce15c32017-07-11 13:34:40 +00007475/*
7476** If an input line begins with "." then invoke this routine to
7477** process that line.
7478**
7479** Return 1 on error, 2 to exit, and 0 otherwise.
7480*/
7481static int do_meta_command(char *zLine, ShellState *p){
7482 int h = 1;
7483 int nArg = 0;
7484 int n, c;
7485 int rc = 0;
drh5df84282019-08-17 19:45:25 +00007486 char *azArg[52];
drh2ce15c32017-07-11 13:34:40 +00007487
dan6b046be2018-01-09 15:25:55 +00007488#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00007489 if( p->expert.pExpert ){
7490 expertFinish(p, 1, 0);
7491 }
dan6b046be2018-01-09 15:25:55 +00007492#endif
dan43efc182017-12-19 17:42:13 +00007493
drh2ce15c32017-07-11 13:34:40 +00007494 /* Parse the input line into tokens.
7495 */
drh5df84282019-08-17 19:45:25 +00007496 while( zLine[h] && nArg<ArraySize(azArg)-1 ){
drh2ce15c32017-07-11 13:34:40 +00007497 while( IsSpace(zLine[h]) ){ h++; }
7498 if( zLine[h]==0 ) break;
7499 if( zLine[h]=='\'' || zLine[h]=='"' ){
7500 int delim = zLine[h++];
7501 azArg[nArg++] = &zLine[h];
7502 while( zLine[h] && zLine[h]!=delim ){
7503 if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
7504 h++;
7505 }
7506 if( zLine[h]==delim ){
7507 zLine[h++] = 0;
7508 }
7509 if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
7510 }else{
7511 azArg[nArg++] = &zLine[h];
7512 while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
7513 if( zLine[h] ) zLine[h++] = 0;
7514 resolve_backslashes(azArg[nArg-1]);
7515 }
7516 }
drh5df84282019-08-17 19:45:25 +00007517 azArg[nArg] = 0;
drh2ce15c32017-07-11 13:34:40 +00007518
7519 /* Process the input line.
7520 */
7521 if( nArg==0 ) return 0; /* no tokens, no error */
7522 n = strlen30(azArg[0]);
7523 c = azArg[0][0];
drh13c20932018-01-10 21:41:55 +00007524 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +00007525
7526#ifndef SQLITE_OMIT_AUTHORIZATION
7527 if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
7528 if( nArg!=2 ){
7529 raw_printf(stderr, "Usage: .auth ON|OFF\n");
7530 rc = 1;
7531 goto meta_command_exit;
7532 }
7533 open_db(p, 0);
7534 if( booleanValue(azArg[1]) ){
7535 sqlite3_set_authorizer(p->db, shellAuth, p);
drhb97e2ad2021-08-26 18:31:39 +00007536 }else if( p->bSafeModePersist ){
7537 sqlite3_set_authorizer(p->db, safeModeAuth, p);
drh2ce15c32017-07-11 13:34:40 +00007538 }else{
7539 sqlite3_set_authorizer(p->db, 0, 0);
7540 }
7541 }else
7542#endif
7543
drhe37c0e12018-01-06 19:19:50 +00007544#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
7545 if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
danfd0245d2017-12-07 15:44:29 +00007546 open_db(p, 0);
drhb97e2ad2021-08-26 18:31:39 +00007547 failIfSafeMode(p, "cannot run .archive in safe mode");
drhd0f9cdc2018-05-17 14:09:06 +00007548 rc = arDotCommand(p, 0, azArg, nArg);
danfd0245d2017-12-07 15:44:29 +00007549 }else
7550#endif
7551
drh2ce15c32017-07-11 13:34:40 +00007552 if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
7553 || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
7554 ){
7555 const char *zDestFile = 0;
7556 const char *zDb = 0;
7557 sqlite3 *pDest;
7558 sqlite3_backup *pBackup;
7559 int j;
drha50bffb2018-12-08 01:09:14 +00007560 int bAsync = 0;
drh69ed38a2018-05-14 00:23:08 +00007561 const char *zVfs = 0;
drhb97e2ad2021-08-26 18:31:39 +00007562 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00007563 for(j=1; j<nArg; j++){
7564 const char *z = azArg[j];
7565 if( z[0]=='-' ){
drh69ed38a2018-05-14 00:23:08 +00007566 if( z[1]=='-' ) z++;
7567 if( strcmp(z, "-append")==0 ){
7568 zVfs = "apndvfs";
7569 }else
drha50bffb2018-12-08 01:09:14 +00007570 if( strcmp(z, "-async")==0 ){
7571 bAsync = 1;
7572 }else
drh2ce15c32017-07-11 13:34:40 +00007573 {
7574 utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
7575 return 1;
7576 }
7577 }else if( zDestFile==0 ){
7578 zDestFile = azArg[j];
7579 }else if( zDb==0 ){
7580 zDb = zDestFile;
7581 zDestFile = azArg[j];
7582 }else{
drha50bffb2018-12-08 01:09:14 +00007583 raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
drh2ce15c32017-07-11 13:34:40 +00007584 return 1;
7585 }
7586 }
7587 if( zDestFile==0 ){
7588 raw_printf(stderr, "missing FILENAME argument on .backup\n");
7589 return 1;
7590 }
7591 if( zDb==0 ) zDb = "main";
drh69ed38a2018-05-14 00:23:08 +00007592 rc = sqlite3_open_v2(zDestFile, &pDest,
7593 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
drh2ce15c32017-07-11 13:34:40 +00007594 if( rc!=SQLITE_OK ){
7595 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
drh9e804032018-05-18 17:11:50 +00007596 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007597 return 1;
7598 }
drha50bffb2018-12-08 01:09:14 +00007599 if( bAsync ){
7600 sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
7601 0, 0, 0);
7602 }
drh2ce15c32017-07-11 13:34:40 +00007603 open_db(p, 0);
7604 pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
7605 if( pBackup==0 ){
7606 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
drh9e804032018-05-18 17:11:50 +00007607 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007608 return 1;
7609 }
7610 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
7611 sqlite3_backup_finish(pBackup);
7612 if( rc==SQLITE_DONE ){
7613 rc = 0;
7614 }else{
7615 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
7616 rc = 1;
7617 }
drh9e804032018-05-18 17:11:50 +00007618 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007619 }else
7620
7621 if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
7622 if( nArg==2 ){
7623 bail_on_error = booleanValue(azArg[1]);
7624 }else{
7625 raw_printf(stderr, "Usage: .bail on|off\n");
7626 rc = 1;
7627 }
7628 }else
7629
7630 if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
7631 if( nArg==2 ){
7632 if( booleanValue(azArg[1]) ){
7633 setBinaryMode(p->out, 1);
7634 }else{
7635 setTextMode(p->out, 1);
7636 }
7637 }else{
7638 raw_printf(stderr, "Usage: .binary on|off\n");
7639 rc = 1;
7640 }
7641 }else
7642
drh37407122021-07-23 18:43:58 +00007643 /* The undocumented ".breakpoint" command causes a call to the no-op
7644 ** routine named test_breakpoint().
7645 */
7646 if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
7647 test_breakpoint();
7648 }else
7649
drh2ce15c32017-07-11 13:34:40 +00007650 if( c=='c' && strcmp(azArg[0],"cd")==0 ){
drhb97e2ad2021-08-26 18:31:39 +00007651 failIfSafeMode(p, "cannot run .cd in safe mode");
drh2ce15c32017-07-11 13:34:40 +00007652 if( nArg==2 ){
7653#if defined(_WIN32) || defined(WIN32)
7654 wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
7655 rc = !SetCurrentDirectoryW(z);
7656 sqlite3_free(z);
7657#else
7658 rc = chdir(azArg[1]);
7659#endif
7660 if( rc ){
7661 utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
7662 rc = 1;
7663 }
7664 }else{
7665 raw_printf(stderr, "Usage: .cd DIRECTORY\n");
7666 rc = 1;
7667 }
7668 }else
7669
drh2ce15c32017-07-11 13:34:40 +00007670 if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
7671 if( nArg==2 ){
7672 setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
7673 }else{
7674 raw_printf(stderr, "Usage: .changes on|off\n");
7675 rc = 1;
7676 }
7677 }else
7678
7679 /* Cancel output redirection, if it is currently set (by .testcase)
7680 ** Then read the content of the testcase-out.txt file and compare against
7681 ** azArg[1]. If there are differences, report an error and exit.
7682 */
7683 if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
7684 char *zRes = 0;
7685 output_reset(p);
7686 if( nArg!=2 ){
7687 raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
7688 rc = 2;
7689 }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
7690 raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
7691 rc = 2;
7692 }else if( testcase_glob(azArg[1],zRes)==0 ){
7693 utf8_printf(stderr,
7694 "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
7695 p->zTestcase, azArg[1], zRes);
drhf30d3452017-10-17 13:44:46 +00007696 rc = 1;
drh2ce15c32017-07-11 13:34:40 +00007697 }else{
7698 utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
7699 p->nCheck++;
7700 }
7701 sqlite3_free(zRes);
7702 }else
7703
7704 if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
drhb97e2ad2021-08-26 18:31:39 +00007705 failIfSafeMode(p, "cannot run .clone in safe mode");
drh2ce15c32017-07-11 13:34:40 +00007706 if( nArg==2 ){
7707 tryToClone(p, azArg[1]);
7708 }else{
7709 raw_printf(stderr, "Usage: .clone FILENAME\n");
7710 rc = 1;
7711 }
7712 }else
7713
drh37407122021-07-23 18:43:58 +00007714 if( c=='c' && strncmp(azArg[0], "connection", n)==0 ){
7715 if( nArg==1 ){
7716 /* List available connections */
7717 int i;
7718 for(i=0; i<ArraySize(p->aAuxDb); i++){
7719 const char *zFile = p->aAuxDb[i].zDbFilename;
7720 if( p->aAuxDb[i].db==0 && p->pAuxDb!=&p->aAuxDb[i] ){
7721 zFile = "(not open)";
7722 }else if( zFile==0 ){
7723 zFile = "(memory)";
7724 }else if( zFile[0]==0 ){
7725 zFile = "(temporary-file)";
7726 }
7727 if( p->pAuxDb == &p->aAuxDb[i] ){
7728 utf8_printf(stdout, "ACTIVE %d: %s\n", i, zFile);
7729 }else if( p->aAuxDb[i].db!=0 ){
7730 utf8_printf(stdout, " %d: %s\n", i, zFile);
7731 }
7732 }
7733 }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){
7734 int i = azArg[1][0] - '0';
7735 if( p->pAuxDb != &p->aAuxDb[i] && i>=0 && i<ArraySize(p->aAuxDb) ){
7736 p->pAuxDb->db = p->db;
7737 p->pAuxDb = &p->aAuxDb[i];
7738 globalDb = p->db = p->pAuxDb->db;
7739 p->pAuxDb->db = 0;
7740 }
7741 }else if( nArg==3 && strcmp(azArg[1], "close")==0
7742 && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){
7743 int i = azArg[2][0] - '0';
7744 if( i<0 || i>=ArraySize(p->aAuxDb) ){
7745 /* No-op */
7746 }else if( p->pAuxDb == &p->aAuxDb[i] ){
7747 raw_printf(stderr, "cannot close the active database connection\n");
7748 rc = 1;
7749 }else if( p->aAuxDb[i].db ){
7750 session_close_all(p, i);
7751 close_db(p->aAuxDb[i].db);
7752 p->aAuxDb[i].db = 0;
7753 }
7754 }else{
7755 raw_printf(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n");
7756 rc = 1;
7757 }
7758 }else
7759
drh2ce15c32017-07-11 13:34:40 +00007760 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
drh60081a02020-08-26 19:07:18 +00007761 char **azName = 0;
7762 int nName = 0;
7763 sqlite3_stmt *pStmt;
drh60081a02020-08-26 19:07:18 +00007764 int i;
drh2ce15c32017-07-11 13:34:40 +00007765 open_db(p, 0);
drh60081a02020-08-26 19:07:18 +00007766 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
7767 if( rc ){
7768 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh2ce15c32017-07-11 13:34:40 +00007769 rc = 1;
drh60081a02020-08-26 19:07:18 +00007770 }else{
7771 while( sqlite3_step(pStmt)==SQLITE_ROW ){
7772 const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
7773 const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
7774 azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
7775 if( azName==0 ){ shell_out_of_memory(); /* Does not return */ }
7776 azName[nName*2] = strdup(zSchema);
7777 azName[nName*2+1] = strdup(zFile);
7778 nName++;
7779 }
drh2ce15c32017-07-11 13:34:40 +00007780 }
drh60081a02020-08-26 19:07:18 +00007781 sqlite3_finalize(pStmt);
7782 for(i=0; i<nName; i++){
7783 int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
7784 int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
7785 const char *z = azName[i*2+1];
7786 utf8_printf(p->out, "%s: %s %s%s\n",
7787 azName[i*2],
7788 z && z[0] ? z : "\"\"",
7789 bRdonly ? "r/o" : "r/w",
7790 eTxn==SQLITE_TXN_NONE ? "" :
7791 eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
7792 free(azName[i*2]);
7793 free(azName[i*2+1]);
7794 }
7795 sqlite3_free(azName);
drh2ce15c32017-07-11 13:34:40 +00007796 }else
7797
drh7df01192018-04-28 12:43:16 +00007798 if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
drheb7f2a02018-09-26 18:02:32 +00007799 static const struct DbConfigChoices {
7800 const char *zName;
7801 int op;
7802 } aDbConfig[] = {
drhb945bcd2019-12-31 22:52:10 +00007803 { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
7804 { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL },
7805 { "dqs_dml", SQLITE_DBCONFIG_DQS_DML },
drh0a6873b2019-06-14 21:25:25 +00007806 { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
drhb945bcd2019-12-31 22:52:10 +00007807 { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
drh0a6873b2019-06-14 21:25:25 +00007808 { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
drh11d88e62019-08-15 21:27:20 +00007809 { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
drh0a6873b2019-06-14 21:25:25 +00007810 { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
drhb945bcd2019-12-31 22:52:10 +00007811 { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
7812 { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
drh0a6873b2019-06-14 21:25:25 +00007813 { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
7814 { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
drh0a6873b2019-06-14 21:25:25 +00007815 { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
drhb945bcd2019-12-31 22:52:10 +00007816 { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
drhb77da372020-01-07 16:09:11 +00007817 { "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA },
dan07312a62019-06-21 14:05:27 +00007818 { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA },
drh7df01192018-04-28 12:43:16 +00007819 };
7820 int ii, v;
7821 open_db(p, 0);
7822 for(ii=0; ii<ArraySize(aDbConfig); ii++){
7823 if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
7824 if( nArg>=3 ){
7825 sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
7826 }
7827 sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
drhb945bcd2019-12-31 22:52:10 +00007828 utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
drh7df01192018-04-28 12:43:16 +00007829 if( nArg>1 ) break;
7830 }
7831 if( nArg>1 && ii==ArraySize(aDbConfig) ){
7832 utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
7833 utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
7834 }
7835 }else
7836
7837 if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00007838 rc = shell_dbinfo_command(p, nArg, azArg);
7839 }else
7840
dan1b162162019-04-27 20:15:15 +00007841#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00007842 if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){
7843 open_db(p, 0);
danb9b71db2019-04-25 16:20:40 +00007844 rc = recoverDatabaseCmd(p, nArg, azArg);
dan68cb86e2019-04-20 20:57:28 +00007845 }else
dan1b162162019-04-27 20:15:15 +00007846#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
dan68cb86e2019-04-20 20:57:28 +00007847
drh2ce15c32017-07-11 13:34:40 +00007848 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
drh8e9297f2020-03-25 12:50:13 +00007849 char *zLike = 0;
7850 char *zSql;
drh2ce15c32017-07-11 13:34:40 +00007851 int i;
7852 int savedShowHeader = p->showHeader;
drhf213b332018-07-05 17:35:46 +00007853 int savedShellFlags = p->shellFlgs;
drhc1962192020-10-12 16:54:28 +00007854 ShellClearFlag(p,
7855 SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
7856 |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
drh2ce15c32017-07-11 13:34:40 +00007857 for(i=1; i<nArg; i++){
7858 if( azArg[i][0]=='-' ){
7859 const char *z = azArg[i]+1;
7860 if( z[0]=='-' ) z++;
7861 if( strcmp(z,"preserve-rowids")==0 ){
7862#ifdef SQLITE_OMIT_VIRTUALTABLE
7863 raw_printf(stderr, "The --preserve-rowids option is not compatible"
7864 " with SQLITE_OMIT_VIRTUALTABLE\n");
7865 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00007866 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00007867 goto meta_command_exit;
7868#else
7869 ShellSetFlag(p, SHFLG_PreserveRowid);
7870#endif
7871 }else
7872 if( strcmp(z,"newlines")==0 ){
7873 ShellSetFlag(p, SHFLG_Newlines);
7874 }else
drhc1962192020-10-12 16:54:28 +00007875 if( strcmp(z,"data-only")==0 ){
7876 ShellSetFlag(p, SHFLG_DumpDataOnly);
7877 }else
7878 if( strcmp(z,"nosys")==0 ){
7879 ShellSetFlag(p, SHFLG_DumpNoSys);
7880 }else
drh2ce15c32017-07-11 13:34:40 +00007881 {
7882 raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
7883 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00007884 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00007885 goto meta_command_exit;
7886 }
drh2ce15c32017-07-11 13:34:40 +00007887 }else{
dan78a9d752021-05-25 11:39:14 +00007888 /* azArg[i] contains a LIKE pattern. This ".dump" request should
7889 ** only dump data for tables for which either the table name matches
7890 ** the LIKE pattern, or the table appears to be a shadow table of
7891 ** a virtual table for which the name matches the LIKE pattern.
7892 */
7893 char *zExpr = sqlite3_mprintf(
7894 "name LIKE %Q ESCAPE '\\' OR EXISTS ("
7895 " SELECT 1 FROM sqlite_schema WHERE "
7896 " name LIKE %Q ESCAPE '\\' AND"
7897 " sql LIKE 'CREATE VIRTUAL TABLE%%' AND"
7898 " substr(o.name, 1, length(name)+1) == (name||'_')"
7899 ")", azArg[i], azArg[i]
7900 );
7901
7902 if( zLike ){
7903 zLike = sqlite3_mprintf("%z OR %z", zLike, zExpr);
7904 }else{
7905 zLike = zExpr;
7906 }
drh2ce15c32017-07-11 13:34:40 +00007907 }
7908 }
dan68cb86e2019-04-20 20:57:28 +00007909
drh2ce15c32017-07-11 13:34:40 +00007910 open_db(p, 0);
dan68cb86e2019-04-20 20:57:28 +00007911
drhc1962192020-10-12 16:54:28 +00007912 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
7913 /* When playing back a "dump", the content might appear in an order
7914 ** which causes immediate foreign key constraints to be violated.
7915 ** So disable foreign-key constraint enforcement to prevent problems. */
7916 raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
7917 raw_printf(p->out, "BEGIN TRANSACTION;\n");
7918 }
drh2ce15c32017-07-11 13:34:40 +00007919 p->writableSchema = 0;
7920 p->showHeader = 0;
7921 /* Set writable_schema=ON since doing so forces SQLite to initialize
drh067b92b2020-06-19 15:24:12 +00007922 ** as much of the schema as it can even if the sqlite_schema table is
drh2ce15c32017-07-11 13:34:40 +00007923 ** corrupt. */
7924 sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
7925 p->nErr = 0;
drh8e9297f2020-03-25 12:50:13 +00007926 if( zLike==0 ) zLike = sqlite3_mprintf("true");
7927 zSql = sqlite3_mprintf(
dan78a9d752021-05-25 11:39:14 +00007928 "SELECT name, type, sql FROM sqlite_schema AS o "
drh8e9297f2020-03-25 12:50:13 +00007929 "WHERE (%s) AND type=='table'"
7930 " AND sql NOT NULL"
7931 " ORDER BY tbl_name='sqlite_sequence', rowid",
7932 zLike
7933 );
7934 run_schema_dump_query(p,zSql);
7935 sqlite3_free(zSql);
drhc1962192020-10-12 16:54:28 +00007936 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
7937 zSql = sqlite3_mprintf(
dan78a9d752021-05-25 11:39:14 +00007938 "SELECT sql FROM sqlite_schema AS o "
drhc1962192020-10-12 16:54:28 +00007939 "WHERE (%s) AND sql NOT NULL"
7940 " AND type IN ('index','trigger','view')",
7941 zLike
7942 );
7943 run_table_dump_query(p, zSql);
7944 sqlite3_free(zSql);
7945 }
drh8e9297f2020-03-25 12:50:13 +00007946 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00007947 if( p->writableSchema ){
7948 raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
7949 p->writableSchema = 0;
7950 }
7951 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
7952 sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
drhc1962192020-10-12 16:54:28 +00007953 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
7954 raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
7955 }
drh2ce15c32017-07-11 13:34:40 +00007956 p->showHeader = savedShowHeader;
drhf213b332018-07-05 17:35:46 +00007957 p->shellFlgs = savedShellFlags;
drh2ce15c32017-07-11 13:34:40 +00007958 }else
7959
7960 if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
7961 if( nArg==2 ){
7962 setOrClearFlag(p, SHFLG_Echo, azArg[1]);
7963 }else{
7964 raw_printf(stderr, "Usage: .echo on|off\n");
7965 rc = 1;
7966 }
7967 }else
7968
7969 if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
7970 if( nArg==2 ){
drhe2ca99c2018-05-02 00:33:43 +00007971 p->autoEQPtest = 0;
drhb4e50392019-01-26 15:40:04 +00007972 if( p->autoEQPtrace ){
7973 if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
7974 p->autoEQPtrace = 0;
7975 }
drh2ce15c32017-07-11 13:34:40 +00007976 if( strcmp(azArg[1],"full")==0 ){
drhada70452017-12-21 21:02:27 +00007977 p->autoEQP = AUTOEQP_full;
7978 }else if( strcmp(azArg[1],"trigger")==0 ){
7979 p->autoEQP = AUTOEQP_trigger;
drhb4e50392019-01-26 15:40:04 +00007980#ifdef SQLITE_DEBUG
drhe2ca99c2018-05-02 00:33:43 +00007981 }else if( strcmp(azArg[1],"test")==0 ){
7982 p->autoEQP = AUTOEQP_on;
7983 p->autoEQPtest = 1;
drhb4e50392019-01-26 15:40:04 +00007984 }else if( strcmp(azArg[1],"trace")==0 ){
7985 p->autoEQP = AUTOEQP_full;
7986 p->autoEQPtrace = 1;
7987 open_db(p, 0);
drh067b92b2020-06-19 15:24:12 +00007988 sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0);
drhb4e50392019-01-26 15:40:04 +00007989 sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
7990#endif
drh2ce15c32017-07-11 13:34:40 +00007991 }else{
mistachkinb71aa092018-01-23 00:05:18 +00007992 p->autoEQP = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00007993 }
7994 }else{
drhb4e50392019-01-26 15:40:04 +00007995 raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
drh2ce15c32017-07-11 13:34:40 +00007996 rc = 1;
7997 }
7998 }else
7999
8000 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
8001 if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
8002 rc = 2;
8003 }else
8004
8005 /* The ".explain" command is automatic now. It is largely pointless. It
8006 ** retained purely for backwards compatibility */
8007 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
8008 int val = 1;
8009 if( nArg>=2 ){
8010 if( strcmp(azArg[1],"auto")==0 ){
8011 val = 99;
8012 }else{
8013 val = booleanValue(azArg[1]);
8014 }
8015 }
8016 if( val==1 && p->mode!=MODE_Explain ){
8017 p->normalMode = p->mode;
8018 p->mode = MODE_Explain;
8019 p->autoExplain = 0;
8020 }else if( val==0 ){
8021 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
8022 p->autoExplain = 0;
8023 }else if( val==99 ){
8024 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
8025 p->autoExplain = 1;
8026 }
8027 }else
8028
dan6b046be2018-01-09 15:25:55 +00008029#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00008030 if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
8031 open_db(p, 0);
8032 expertDotCommand(p, azArg, nArg);
8033 }else
dan6b046be2018-01-09 15:25:55 +00008034#endif
dan43efc182017-12-19 17:42:13 +00008035
drhd985f722019-06-05 14:29:53 +00008036 if( c=='f' && strncmp(azArg[0], "filectrl", n)==0 ){
8037 static const struct {
8038 const char *zCtrlName; /* Name of a test-control option */
8039 int ctrlCode; /* Integer code for that option */
8040 const char *zUsage; /* Usage notes */
8041 } aCtrl[] = {
drhd985f722019-06-05 14:29:53 +00008042 { "chunk_size", SQLITE_FCNTL_CHUNK_SIZE, "SIZE" },
drh18a4bbd2020-12-17 15:17:42 +00008043 { "data_version", SQLITE_FCNTL_DATA_VERSION, "" },
drhd985f722019-06-05 14:29:53 +00008044 { "has_moved", SQLITE_FCNTL_HAS_MOVED, "" },
8045 { "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" },
drh18a4bbd2020-12-17 15:17:42 +00008046 { "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" },
8047 /* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/
8048 { "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" },
drh541ef2c2020-04-20 16:21:30 +00008049 { "reserve_bytes", SQLITE_FCNTL_RESERVE_BYTES, "[N]" },
drh18a4bbd2020-12-17 15:17:42 +00008050 { "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" },
8051 { "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" },
8052 /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/
drhd985f722019-06-05 14:29:53 +00008053 };
8054 int filectrl = -1;
8055 int iCtrl = -1;
drh4245e042019-06-13 13:52:46 +00008056 sqlite3_int64 iRes = 0; /* Integer result to display if rc2==1 */
8057 int isOk = 0; /* 0: usage 1: %lld 2: no-result */
drhd985f722019-06-05 14:29:53 +00008058 int n2, i;
8059 const char *zCmd = 0;
drh541ef2c2020-04-20 16:21:30 +00008060 const char *zSchema = 0;
drhd985f722019-06-05 14:29:53 +00008061
8062 open_db(p, 0);
8063 zCmd = nArg>=2 ? azArg[1] : "help";
8064
drh541ef2c2020-04-20 16:21:30 +00008065 if( zCmd[0]=='-'
8066 && (strcmp(zCmd,"--schema")==0 || strcmp(zCmd,"-schema")==0)
8067 && nArg>=4
8068 ){
8069 zSchema = azArg[2];
8070 for(i=3; i<nArg; i++) azArg[i-2] = azArg[i];
8071 nArg -= 2;
8072 zCmd = azArg[1];
8073 }
8074
drhd985f722019-06-05 14:29:53 +00008075 /* The argument can optionally begin with "-" or "--" */
8076 if( zCmd[0]=='-' && zCmd[1] ){
8077 zCmd++;
8078 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
8079 }
8080
8081 /* --help lists all file-controls */
8082 if( strcmp(zCmd,"help")==0 ){
8083 utf8_printf(p->out, "Available file-controls:\n");
8084 for(i=0; i<ArraySize(aCtrl); i++){
8085 utf8_printf(p->out, " .filectrl %s %s\n",
8086 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
8087 }
8088 rc = 1;
8089 goto meta_command_exit;
8090 }
8091
8092 /* convert filectrl text option to value. allow any unique prefix
8093 ** of the option name, or a numerical value. */
8094 n2 = strlen30(zCmd);
8095 for(i=0; i<ArraySize(aCtrl); i++){
8096 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
8097 if( filectrl<0 ){
8098 filectrl = aCtrl[i].ctrlCode;
8099 iCtrl = i;
8100 }else{
8101 utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n"
8102 "Use \".filectrl --help\" for help\n", zCmd);
8103 rc = 1;
8104 goto meta_command_exit;
8105 }
8106 }
8107 }
8108 if( filectrl<0 ){
8109 utf8_printf(stderr,"Error: unknown file-control: %s\n"
8110 "Use \".filectrl --help\" for help\n", zCmd);
8111 }else{
8112 switch(filectrl){
8113 case SQLITE_FCNTL_SIZE_LIMIT: {
8114 if( nArg!=2 && nArg!=3 ) break;
8115 iRes = nArg==3 ? integerValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00008116 sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
drhd985f722019-06-05 14:29:53 +00008117 isOk = 1;
8118 break;
8119 }
8120 case SQLITE_FCNTL_LOCK_TIMEOUT:
8121 case SQLITE_FCNTL_CHUNK_SIZE: {
8122 int x;
8123 if( nArg!=3 ) break;
8124 x = (int)integerValue(azArg[2]);
drh541ef2c2020-04-20 16:21:30 +00008125 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008126 isOk = 2;
8127 break;
8128 }
8129 case SQLITE_FCNTL_PERSIST_WAL:
8130 case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
8131 int x;
8132 if( nArg!=2 && nArg!=3 ) break;
8133 x = nArg==3 ? booleanValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00008134 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008135 iRes = x;
8136 isOk = 1;
8137 break;
8138 }
drh18a4bbd2020-12-17 15:17:42 +00008139 case SQLITE_FCNTL_DATA_VERSION:
drhd985f722019-06-05 14:29:53 +00008140 case SQLITE_FCNTL_HAS_MOVED: {
8141 int x;
8142 if( nArg!=2 ) break;
drh541ef2c2020-04-20 16:21:30 +00008143 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008144 iRes = x;
8145 isOk = 1;
8146 break;
8147 }
8148 case SQLITE_FCNTL_TEMPFILENAME: {
8149 char *z = 0;
8150 if( nArg!=2 ) break;
drh541ef2c2020-04-20 16:21:30 +00008151 sqlite3_file_control(p->db, zSchema, filectrl, &z);
drhd985f722019-06-05 14:29:53 +00008152 if( z ){
8153 utf8_printf(p->out, "%s\n", z);
8154 sqlite3_free(z);
8155 }
8156 isOk = 2;
8157 break;
8158 }
drh541ef2c2020-04-20 16:21:30 +00008159 case SQLITE_FCNTL_RESERVE_BYTES: {
8160 int x;
8161 if( nArg>=3 ){
8162 x = atoi(azArg[2]);
8163 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8164 }
8165 x = -1;
8166 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8167 utf8_printf(p->out,"%d\n", x);
8168 isOk = 2;
8169 break;
8170 }
drhd985f722019-06-05 14:29:53 +00008171 }
8172 }
8173 if( isOk==0 && iCtrl>=0 ){
8174 utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
8175 rc = 1;
8176 }else if( isOk==1 ){
drhe2500762019-06-13 14:07:41 +00008177 char zBuf[100];
8178 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
8179 raw_printf(p->out, "%s\n", zBuf);
drhd985f722019-06-05 14:29:53 +00008180 }
8181 }else
8182
drh2ce15c32017-07-11 13:34:40 +00008183 if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
8184 ShellState data;
drh2ce15c32017-07-11 13:34:40 +00008185 int doStats = 0;
8186 memcpy(&data, p, sizeof(data));
8187 data.showHeader = 0;
8188 data.cMode = data.mode = MODE_Semi;
8189 if( nArg==2 && optionMatch(azArg[1], "indent") ){
8190 data.cMode = data.mode = MODE_Pretty;
8191 nArg = 1;
8192 }
8193 if( nArg!=1 ){
8194 raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
8195 rc = 1;
8196 goto meta_command_exit;
8197 }
8198 open_db(p, 0);
8199 rc = sqlite3_exec(p->db,
8200 "SELECT sql FROM"
8201 " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
drh067b92b2020-06-19 15:24:12 +00008202 " FROM sqlite_schema UNION ALL"
8203 " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
drh2ce15c32017-07-11 13:34:40 +00008204 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
drh69935c02021-06-25 11:14:10 +00008205 "ORDER BY x",
drhf83d5012021-05-03 13:35:00 +00008206 callback, &data, 0
drh2ce15c32017-07-11 13:34:40 +00008207 );
8208 if( rc==SQLITE_OK ){
8209 sqlite3_stmt *pStmt;
8210 rc = sqlite3_prepare_v2(p->db,
drh067b92b2020-06-19 15:24:12 +00008211 "SELECT rowid FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00008212 " WHERE name GLOB 'sqlite_stat[134]'",
8213 -1, &pStmt, 0);
8214 doStats = sqlite3_step(pStmt)==SQLITE_ROW;
8215 sqlite3_finalize(pStmt);
8216 }
8217 if( doStats==0 ){
8218 raw_printf(p->out, "/* No STAT tables available */\n");
8219 }else{
drh067b92b2020-06-19 15:24:12 +00008220 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00008221 data.cMode = data.mode = MODE_Insert;
8222 data.zDestTable = "sqlite_stat1";
drhf83d5012021-05-03 13:35:00 +00008223 shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
drh2ce15c32017-07-11 13:34:40 +00008224 data.zDestTable = "sqlite_stat4";
drhf83d5012021-05-03 13:35:00 +00008225 shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
drh067b92b2020-06-19 15:24:12 +00008226 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00008227 }
8228 }else
8229
8230 if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
8231 if( nArg==2 ){
8232 p->showHeader = booleanValue(azArg[1]);
drhc0605082020-06-05 00:54:27 +00008233 p->shellFlgs |= SHFLG_HeaderSet;
drh2ce15c32017-07-11 13:34:40 +00008234 }else{
8235 raw_printf(stderr, "Usage: .headers on|off\n");
8236 rc = 1;
8237 }
8238 }else
8239
8240 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
drh98aa2ab2018-09-26 16:53:51 +00008241 if( nArg>=2 ){
drhe93f8262018-10-11 16:53:37 +00008242 n = showHelp(p->out, azArg[1]);
drh98aa2ab2018-09-26 16:53:51 +00008243 if( n==0 ){
8244 utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
8245 }
8246 }else{
8247 showHelp(p->out, 0);
8248 }
drh2ce15c32017-07-11 13:34:40 +00008249 }else
8250
8251 if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
drhccb37812020-03-09 15:39:39 +00008252 char *zTable = 0; /* Insert data into this table */
8253 char *zFile = 0; /* Name of file to extra content from */
drh2ce15c32017-07-11 13:34:40 +00008254 sqlite3_stmt *pStmt = NULL; /* A statement */
8255 int nCol; /* Number of columns in the table */
8256 int nByte; /* Number of bytes in an SQL string */
8257 int i, j; /* Loop counters */
8258 int needCommit; /* True to COMMIT or ROLLBACK at end */
8259 int nSep; /* Number of bytes in p->colSeparator[] */
8260 char *zSql; /* An SQL statement */
8261 ImportCtx sCtx; /* Reader context */
8262 char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
drhccb37812020-03-09 15:39:39 +00008263 int eVerbose = 0; /* Larger for more console output */
8264 int nSkip = 0; /* Initial lines to skip */
8265 int useOutputMode = 1; /* Use output mode to determine separators */
drh2ce15c32017-07-11 13:34:40 +00008266
drhb97e2ad2021-08-26 18:31:39 +00008267 failIfSafeMode(p, "cannot run .import in safe mode");
drhccb37812020-03-09 15:39:39 +00008268 memset(&sCtx, 0, sizeof(sCtx));
8269 if( p->mode==MODE_Ascii ){
8270 xRead = ascii_read_one_field;
8271 }else{
8272 xRead = csv_read_one_field;
8273 }
8274 for(i=1; i<nArg; i++){
8275 char *z = azArg[i];
8276 if( z[0]=='-' && z[1]=='-' ) z++;
8277 if( z[0]!='-' ){
8278 if( zFile==0 ){
8279 zFile = z;
8280 }else if( zTable==0 ){
8281 zTable = z;
8282 }else{
8283 utf8_printf(p->out, "ERROR: extra argument: \"%s\". Usage:\n", z);
8284 showHelp(p->out, "import");
8285 rc = 1;
8286 goto meta_command_exit;
8287 }
8288 }else if( strcmp(z,"-v")==0 ){
8289 eVerbose++;
8290 }else if( strcmp(z,"-skip")==0 && i<nArg-1 ){
8291 nSkip = integerValue(azArg[++i]);
8292 }else if( strcmp(z,"-ascii")==0 ){
8293 sCtx.cColSep = SEP_Unit[0];
8294 sCtx.cRowSep = SEP_Record[0];
8295 xRead = ascii_read_one_field;
8296 useOutputMode = 0;
8297 }else if( strcmp(z,"-csv")==0 ){
8298 sCtx.cColSep = ',';
8299 sCtx.cRowSep = '\n';
8300 xRead = csv_read_one_field;
8301 useOutputMode = 0;
8302 }else{
8303 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", z);
8304 showHelp(p->out, "import");
8305 rc = 1;
8306 goto meta_command_exit;
8307 }
8308 }
8309 if( zTable==0 ){
8310 utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
8311 zFile==0 ? "FILE" : "TABLE");
8312 showHelp(p->out, "import");
8313 rc = 1;
drh2ce15c32017-07-11 13:34:40 +00008314 goto meta_command_exit;
8315 }
drh2ce15c32017-07-11 13:34:40 +00008316 seenInterrupt = 0;
drh2ce15c32017-07-11 13:34:40 +00008317 open_db(p, 0);
drhccb37812020-03-09 15:39:39 +00008318 if( useOutputMode ){
8319 /* If neither the --csv or --ascii options are specified, then set
8320 ** the column and row separator characters from the output mode. */
8321 nSep = strlen30(p->colSeparator);
8322 if( nSep==0 ){
8323 raw_printf(stderr,
8324 "Error: non-null column separator required for import\n");
8325 rc = 1;
8326 goto meta_command_exit;
8327 }
8328 if( nSep>1 ){
8329 raw_printf(stderr,
8330 "Error: multi-character column separators not allowed"
8331 " for import\n");
8332 rc = 1;
8333 goto meta_command_exit;
8334 }
drh2ce15c32017-07-11 13:34:40 +00008335 nSep = strlen30(p->rowSeparator);
drhccb37812020-03-09 15:39:39 +00008336 if( nSep==0 ){
8337 raw_printf(stderr,
8338 "Error: non-null row separator required for import\n");
8339 rc = 1;
8340 goto meta_command_exit;
8341 }
8342 if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator,SEP_CrLf)==0 ){
8343 /* When importing CSV (only), if the row separator is set to the
8344 ** default output row separator, change it to the default input
8345 ** row separator. This avoids having to maintain different input
8346 ** and output row separators. */
8347 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8348 nSep = strlen30(p->rowSeparator);
8349 }
8350 if( nSep>1 ){
8351 raw_printf(stderr, "Error: multi-character row separators not allowed"
8352 " for import\n");
8353 rc = 1;
8354 goto meta_command_exit;
8355 }
8356 sCtx.cColSep = p->colSeparator[0];
8357 sCtx.cRowSep = p->rowSeparator[0];
drh2ce15c32017-07-11 13:34:40 +00008358 }
8359 sCtx.zFile = zFile;
8360 sCtx.nLine = 1;
8361 if( sCtx.zFile[0]=='|' ){
8362#ifdef SQLITE_OMIT_POPEN
8363 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
drhccb37812020-03-09 15:39:39 +00008364 rc = 1;
8365 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008366#else
8367 sCtx.in = popen(sCtx.zFile+1, "r");
8368 sCtx.zFile = "<pipe>";
drh97767842020-05-29 19:39:35 +00008369 sCtx.xCloser = pclose;
drh2ce15c32017-07-11 13:34:40 +00008370#endif
8371 }else{
8372 sCtx.in = fopen(sCtx.zFile, "rb");
drh97767842020-05-29 19:39:35 +00008373 sCtx.xCloser = fclose;
drh2ce15c32017-07-11 13:34:40 +00008374 }
drh2ce15c32017-07-11 13:34:40 +00008375 if( sCtx.in==0 ){
8376 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
drhccb37812020-03-09 15:39:39 +00008377 rc = 1;
8378 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008379 }
drhccb37812020-03-09 15:39:39 +00008380 if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
8381 char zSep[2];
8382 zSep[1] = 0;
8383 zSep[0] = sCtx.cColSep;
8384 utf8_printf(p->out, "Column separator ");
8385 output_c_string(p->out, zSep);
8386 utf8_printf(p->out, ", row separator ");
8387 zSep[0] = sCtx.cRowSep;
8388 output_c_string(p->out, zSep);
8389 utf8_printf(p->out, "\n");
8390 }
8391 while( (nSkip--)>0 ){
8392 while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
drhccb37812020-03-09 15:39:39 +00008393 }
drhc6712642020-10-12 17:57:29 +00008394 zSql = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
drh2ce15c32017-07-11 13:34:40 +00008395 if( zSql==0 ){
drh97767842020-05-29 19:39:35 +00008396 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00008397 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00008398 }
8399 nByte = strlen30(zSql);
8400 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8401 import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
8402 if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
drhc6712642020-10-12 17:57:29 +00008403 char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"", zTable);
drh2ce15c32017-07-11 13:34:40 +00008404 char cSep = '(';
8405 while( xRead(&sCtx) ){
8406 zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z);
8407 cSep = ',';
8408 if( sCtx.cTerm!=sCtx.cColSep ) break;
8409 }
8410 if( cSep=='(' ){
8411 sqlite3_free(zCreate);
drh97767842020-05-29 19:39:35 +00008412 import_cleanup(&sCtx);
drh2ce15c32017-07-11 13:34:40 +00008413 utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
drhccb37812020-03-09 15:39:39 +00008414 rc = 1;
8415 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008416 }
8417 zCreate = sqlite3_mprintf("%z\n)", zCreate);
drhccb37812020-03-09 15:39:39 +00008418 if( eVerbose>=1 ){
8419 utf8_printf(p->out, "%s\n", zCreate);
8420 }
drh2ce15c32017-07-11 13:34:40 +00008421 rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
8422 sqlite3_free(zCreate);
8423 if( rc ){
drhc6712642020-10-12 17:57:29 +00008424 utf8_printf(stderr, "CREATE TABLE \"%s\"(...) failed: %s\n", zTable,
drh2ce15c32017-07-11 13:34:40 +00008425 sqlite3_errmsg(p->db));
drh97767842020-05-29 19:39:35 +00008426 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008427 rc = 1;
8428 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008429 }
8430 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8431 }
8432 sqlite3_free(zSql);
8433 if( rc ){
8434 if (pStmt) sqlite3_finalize(pStmt);
8435 utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
drh97767842020-05-29 19:39:35 +00008436 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008437 rc = 1;
8438 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008439 }
8440 nCol = sqlite3_column_count(pStmt);
8441 sqlite3_finalize(pStmt);
8442 pStmt = 0;
8443 if( nCol==0 ) return 0; /* no columns, no error */
8444 zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
8445 if( zSql==0 ){
drh97767842020-05-29 19:39:35 +00008446 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00008447 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00008448 }
8449 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
8450 j = strlen30(zSql);
8451 for(i=1; i<nCol; i++){
8452 zSql[j++] = ',';
8453 zSql[j++] = '?';
8454 }
8455 zSql[j++] = ')';
8456 zSql[j] = 0;
drhccb37812020-03-09 15:39:39 +00008457 if( eVerbose>=2 ){
8458 utf8_printf(p->out, "Insert using: %s\n", zSql);
8459 }
drh2ce15c32017-07-11 13:34:40 +00008460 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8461 sqlite3_free(zSql);
8462 if( rc ){
8463 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
8464 if (pStmt) sqlite3_finalize(pStmt);
drh97767842020-05-29 19:39:35 +00008465 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008466 rc = 1;
8467 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008468 }
8469 needCommit = sqlite3_get_autocommit(p->db);
8470 if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
8471 do{
8472 int startLine = sCtx.nLine;
8473 for(i=0; i<nCol; i++){
8474 char *z = xRead(&sCtx);
8475 /*
8476 ** Did we reach end-of-file before finding any columns?
8477 ** If so, stop instead of NULL filling the remaining columns.
8478 */
8479 if( z==0 && i==0 ) break;
8480 /*
8481 ** Did we reach end-of-file OR end-of-line before finding any
8482 ** columns in ASCII mode? If so, stop instead of NULL filling
8483 ** the remaining columns.
8484 */
8485 if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
8486 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
8487 if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
8488 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
8489 "filling the rest with NULL\n",
8490 sCtx.zFile, startLine, nCol, i+1);
8491 i += 2;
8492 while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
8493 }
8494 }
8495 if( sCtx.cTerm==sCtx.cColSep ){
8496 do{
8497 xRead(&sCtx);
8498 i++;
8499 }while( sCtx.cTerm==sCtx.cColSep );
8500 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
8501 "extras ignored\n",
8502 sCtx.zFile, startLine, nCol, i);
8503 }
8504 if( i>=nCol ){
8505 sqlite3_step(pStmt);
8506 rc = sqlite3_reset(pStmt);
8507 if( rc!=SQLITE_OK ){
8508 utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
8509 startLine, sqlite3_errmsg(p->db));
drhccb37812020-03-09 15:39:39 +00008510 sCtx.nErr++;
8511 }else{
8512 sCtx.nRow++;
drh2ce15c32017-07-11 13:34:40 +00008513 }
8514 }
8515 }while( sCtx.cTerm!=EOF );
8516
drh97767842020-05-29 19:39:35 +00008517 import_cleanup(&sCtx);
drh2ce15c32017-07-11 13:34:40 +00008518 sqlite3_finalize(pStmt);
8519 if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
drhccb37812020-03-09 15:39:39 +00008520 if( eVerbose>0 ){
8521 utf8_printf(p->out,
8522 "Added %d rows with %d errors using %d lines of input\n",
8523 sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
8524 }
drh2ce15c32017-07-11 13:34:40 +00008525 }else
8526
8527#ifndef SQLITE_UNTESTABLE
8528 if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
8529 char *zSql;
8530 char *zCollist = 0;
8531 sqlite3_stmt *pStmt;
8532 int tnum = 0;
drh491c5be2019-10-18 15:58:50 +00008533 int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */
8534 int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
drh2ce15c32017-07-11 13:34:40 +00008535 int i;
drh48d219a2018-04-23 18:38:48 +00008536 if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
8537 utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
8538 " .imposter off\n");
drh491c5be2019-10-18 15:58:50 +00008539 /* Also allowed, but not documented:
8540 **
8541 ** .imposter TABLE IMPOSTER
8542 **
8543 ** where TABLE is a WITHOUT ROWID table. In that case, the
8544 ** imposter is another WITHOUT ROWID table with the columns in
8545 ** storage order. */
drh2ce15c32017-07-11 13:34:40 +00008546 rc = 1;
8547 goto meta_command_exit;
8548 }
8549 open_db(p, 0);
drh48d219a2018-04-23 18:38:48 +00008550 if( nArg==2 ){
8551 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
8552 goto meta_command_exit;
8553 }
drh491c5be2019-10-18 15:58:50 +00008554 zSql = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00008555 "SELECT rootpage, 0 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00008556 " WHERE name='%q' AND type='index'"
8557 "UNION ALL "
drh067b92b2020-06-19 15:24:12 +00008558 "SELECT rootpage, 1 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00008559 " WHERE name='%q' AND type='table'"
8560 " AND sql LIKE '%%without%%rowid%%'",
8561 azArg[1], azArg[1]
8562 );
drh2ce15c32017-07-11 13:34:40 +00008563 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8564 sqlite3_free(zSql);
8565 if( sqlite3_step(pStmt)==SQLITE_ROW ){
8566 tnum = sqlite3_column_int(pStmt, 0);
drh491c5be2019-10-18 15:58:50 +00008567 isWO = sqlite3_column_int(pStmt, 1);
drh2ce15c32017-07-11 13:34:40 +00008568 }
8569 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00008570 zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
8571 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8572 sqlite3_free(zSql);
8573 i = 0;
8574 while( sqlite3_step(pStmt)==SQLITE_ROW ){
8575 char zLabel[20];
8576 const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
8577 i++;
8578 if( zCol==0 ){
8579 if( sqlite3_column_int(pStmt,1)==-1 ){
8580 zCol = "_ROWID_";
8581 }else{
8582 sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
8583 zCol = zLabel;
8584 }
8585 }
drh491c5be2019-10-18 15:58:50 +00008586 if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){
8587 lenPK = (int)strlen(zCollist);
8588 }
drh2ce15c32017-07-11 13:34:40 +00008589 if( zCollist==0 ){
8590 zCollist = sqlite3_mprintf("\"%w\"", zCol);
8591 }else{
8592 zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
8593 }
8594 }
8595 sqlite3_finalize(pStmt);
drh491c5be2019-10-18 15:58:50 +00008596 if( i==0 || tnum==0 ){
8597 utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
8598 rc = 1;
8599 sqlite3_free(zCollist);
8600 goto meta_command_exit;
8601 }
8602 if( lenPK==0 ) lenPK = 100000;
drh2ce15c32017-07-11 13:34:40 +00008603 zSql = sqlite3_mprintf(
drh491c5be2019-10-18 15:58:50 +00008604 "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
8605 azArg[2], zCollist, lenPK, zCollist);
drh2ce15c32017-07-11 13:34:40 +00008606 sqlite3_free(zCollist);
8607 rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
8608 if( rc==SQLITE_OK ){
8609 rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
8610 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
8611 if( rc ){
8612 utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
8613 }else{
8614 utf8_printf(stdout, "%s;\n", zSql);
8615 raw_printf(stdout,
drh491c5be2019-10-18 15:58:50 +00008616 "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
8617 azArg[1], isWO ? "table" : "index"
drh2ce15c32017-07-11 13:34:40 +00008618 );
8619 }
8620 }else{
8621 raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
8622 rc = 1;
8623 }
8624 sqlite3_free(zSql);
8625 }else
8626#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
8627
8628#ifdef SQLITE_ENABLE_IOTRACE
8629 if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
8630 SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
8631 if( iotrace && iotrace!=stdout ) fclose(iotrace);
8632 iotrace = 0;
8633 if( nArg<2 ){
8634 sqlite3IoTrace = 0;
8635 }else if( strcmp(azArg[1], "-")==0 ){
8636 sqlite3IoTrace = iotracePrintf;
8637 iotrace = stdout;
8638 }else{
8639 iotrace = fopen(azArg[1], "w");
8640 if( iotrace==0 ){
8641 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
8642 sqlite3IoTrace = 0;
8643 rc = 1;
8644 }else{
8645 sqlite3IoTrace = iotracePrintf;
8646 }
8647 }
8648 }else
8649#endif
8650
8651 if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
8652 static const struct {
8653 const char *zLimitName; /* Name of a limit */
8654 int limitCode; /* Integer code for that limit */
8655 } aLimit[] = {
8656 { "length", SQLITE_LIMIT_LENGTH },
8657 { "sql_length", SQLITE_LIMIT_SQL_LENGTH },
8658 { "column", SQLITE_LIMIT_COLUMN },
8659 { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
8660 { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
8661 { "vdbe_op", SQLITE_LIMIT_VDBE_OP },
8662 { "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
8663 { "attached", SQLITE_LIMIT_ATTACHED },
8664 { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
8665 { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER },
8666 { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
8667 { "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
8668 };
8669 int i, n2;
8670 open_db(p, 0);
8671 if( nArg==1 ){
8672 for(i=0; i<ArraySize(aLimit); i++){
8673 printf("%20s %d\n", aLimit[i].zLimitName,
8674 sqlite3_limit(p->db, aLimit[i].limitCode, -1));
8675 }
8676 }else if( nArg>3 ){
8677 raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
8678 rc = 1;
8679 goto meta_command_exit;
8680 }else{
8681 int iLimit = -1;
8682 n2 = strlen30(azArg[1]);
8683 for(i=0; i<ArraySize(aLimit); i++){
8684 if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
8685 if( iLimit<0 ){
8686 iLimit = i;
8687 }else{
8688 utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
8689 rc = 1;
8690 goto meta_command_exit;
8691 }
8692 }
8693 }
8694 if( iLimit<0 ){
8695 utf8_printf(stderr, "unknown limit: \"%s\"\n"
8696 "enter \".limits\" with no arguments for a list.\n",
8697 azArg[1]);
8698 rc = 1;
8699 goto meta_command_exit;
8700 }
8701 if( nArg==3 ){
8702 sqlite3_limit(p->db, aLimit[iLimit].limitCode,
8703 (int)integerValue(azArg[2]));
8704 }
8705 printf("%20s %d\n", aLimit[iLimit].zLimitName,
8706 sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
8707 }
8708 }else
8709
8710 if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
8711 open_db(p, 0);
8712 lintDotCommand(p, azArg, nArg);
8713 }else
8714
8715#ifndef SQLITE_OMIT_LOAD_EXTENSION
8716 if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
8717 const char *zFile, *zProc;
8718 char *zErrMsg = 0;
drhb97e2ad2021-08-26 18:31:39 +00008719 failIfSafeMode(p, "cannot run .load in safe mode");
drh2ce15c32017-07-11 13:34:40 +00008720 if( nArg<2 ){
8721 raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
8722 rc = 1;
8723 goto meta_command_exit;
8724 }
8725 zFile = azArg[1];
8726 zProc = nArg>=3 ? azArg[2] : 0;
8727 open_db(p, 0);
8728 rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
8729 if( rc!=SQLITE_OK ){
8730 utf8_printf(stderr, "Error: %s\n", zErrMsg);
8731 sqlite3_free(zErrMsg);
8732 rc = 1;
8733 }
8734 }else
8735#endif
8736
8737 if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
drhb97e2ad2021-08-26 18:31:39 +00008738 failIfSafeMode(p, "cannot run .log in safe mode");
drh2ce15c32017-07-11 13:34:40 +00008739 if( nArg!=2 ){
8740 raw_printf(stderr, "Usage: .log FILENAME\n");
8741 rc = 1;
8742 }else{
8743 const char *zFile = azArg[1];
8744 output_file_close(p->pLog);
drha92a01a2018-01-10 22:15:37 +00008745 p->pLog = output_file_open(zFile, 0);
drh2ce15c32017-07-11 13:34:40 +00008746 }
8747 }else
8748
8749 if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
8750 const char *zMode = nArg>=2 ? azArg[1] : "";
drhaf2770f2018-01-05 14:55:43 +00008751 int n2 = strlen30(zMode);
drh2ce15c32017-07-11 13:34:40 +00008752 int c2 = zMode[0];
8753 if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){
8754 p->mode = MODE_Line;
8755 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8756 }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
8757 p->mode = MODE_Column;
drhc0605082020-06-05 00:54:27 +00008758 if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){
8759 p->showHeader = 1;
8760 }
drh2ce15c32017-07-11 13:34:40 +00008761 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8762 }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
8763 p->mode = MODE_List;
8764 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
8765 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8766 }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){
8767 p->mode = MODE_Html;
8768 }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
8769 p->mode = MODE_Tcl;
8770 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
8771 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8772 }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
8773 p->mode = MODE_Csv;
8774 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
8775 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
8776 }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
8777 p->mode = MODE_List;
8778 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
8779 }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
8780 p->mode = MODE_Insert;
8781 set_table_name(p, nArg>=3 ? azArg[2] : "table");
8782 }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
8783 p->mode = MODE_Quote;
drhc6835732020-05-28 20:37:17 +00008784 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
8785 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +00008786 }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
8787 p->mode = MODE_Ascii;
8788 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
8789 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
drh30c54a02020-05-28 23:49:50 +00008790 }else if( c2=='m' && strncmp(azArg[1],"markdown",n2)==0 ){
8791 p->mode = MODE_Markdown;
8792 }else if( c2=='t' && strncmp(azArg[1],"table",n2)==0 ){
8793 p->mode = MODE_Table;
drh0908e382020-06-04 18:05:39 +00008794 }else if( c2=='b' && strncmp(azArg[1],"box",n2)==0 ){
8795 p->mode = MODE_Box;
drh30c54a02020-05-28 23:49:50 +00008796 }else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){
8797 p->mode = MODE_Json;
drh2ce15c32017-07-11 13:34:40 +00008798 }else if( nArg==1 ){
8799 raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
8800 }else{
8801 raw_printf(stderr, "Error: mode should be one of: "
drh0908e382020-06-04 18:05:39 +00008802 "ascii box column csv html insert json line list markdown "
drh30c54a02020-05-28 23:49:50 +00008803 "quote table tabs tcl\n");
drh2ce15c32017-07-11 13:34:40 +00008804 rc = 1;
8805 }
8806 p->cMode = p->mode;
8807 }else
8808
drhb97e2ad2021-08-26 18:31:39 +00008809 if( c=='n' && strcmp(azArg[0], "nonce")==0 ){
8810 if( nArg!=2 ){
8811 raw_printf(stderr, "Usage: .nonce NONCE\n");
8812 rc = 1;
8813 }else if( p->zNonce==0 || strcmp(azArg[1],p->zNonce)!=0 ){
8814 raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n", p->lineno, azArg[1]);
8815 exit(1);
8816 }
8817 p->bSafeMode = 0;
8818 return 0; /* Return immediately to bypass the safe mode reset
8819 ** at the end of this procedure */
8820 }else
8821
drh2ce15c32017-07-11 13:34:40 +00008822 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
8823 if( nArg==2 ){
8824 sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
8825 "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
8826 }else{
8827 raw_printf(stderr, "Usage: .nullvalue STRING\n");
8828 rc = 1;
8829 }
8830 }else
8831
drh4a3a3eb2020-02-29 15:53:48 +00008832#ifdef SQLITE_DEBUG
8833 if( c=='o' && strcmp(azArg[0],"oom")==0 ){
8834 int i;
8835 for(i=1; i<nArg; i++){
8836 const char *z = azArg[i];
8837 if( z[0]=='-' && z[1]=='-' ) z++;
8838 if( strcmp(z,"-repeat")==0 ){
8839 if( i==nArg-1 ){
8840 raw_printf(p->out, "missing argument on \"%s\"\n", azArg[i]);
8841 rc = 1;
8842 }else{
8843 oomRepeat = (int)integerValue(azArg[++i]);
8844 }
8845 }else if( IsDigit(z[0]) ){
8846 oomCounter = (int)integerValue(azArg[i]);
8847 }else{
8848 raw_printf(p->out, "unknown argument: \"%s\"\n", azArg[i]);
8849 raw_printf(p->out, "Usage: .oom [--repeat N] [M]\n");
8850 rc = 1;
8851 }
8852 }
8853 if( rc==0 ){
8854 raw_printf(p->out, "oomCounter = %d\n", oomCounter);
8855 raw_printf(p->out, "oomRepeat = %d\n", oomRepeat);
8856 }
8857 }else
8858#endif /* SQLITE_DEBUG */
8859
drh2ce15c32017-07-11 13:34:40 +00008860 if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
drhf30bbce2020-12-02 18:27:48 +00008861 char *zNewFilename = 0; /* Name of the database file to open */
8862 int iName = 1; /* Index in azArg[] of the filename */
8863 int newFlag = 0; /* True to delete file before opening */
drh2ce15c32017-07-11 13:34:40 +00008864 /* Close the existing database */
drh37407122021-07-23 18:43:58 +00008865 session_close_all(p, -1);
drh9e804032018-05-18 17:11:50 +00008866 close_db(p->db);
drh2ce15c32017-07-11 13:34:40 +00008867 p->db = 0;
drh37407122021-07-23 18:43:58 +00008868 p->pAuxDb->zDbFilename = 0;
8869 sqlite3_free(p->pAuxDb->zFreeOnClose);
8870 p->pAuxDb->zFreeOnClose = 0;
drh1fa6d9f2018-01-06 21:46:01 +00008871 p->openMode = SHELL_OPEN_UNSPEC;
drh0933aad2019-11-18 17:46:38 +00008872 p->openFlags = 0;
drh6ca64482019-01-22 16:06:20 +00008873 p->szMax = 0;
drh2ce15c32017-07-11 13:34:40 +00008874 /* Check for command-line arguments */
drhf30bbce2020-12-02 18:27:48 +00008875 for(iName=1; iName<nArg; iName++){
drh2ce15c32017-07-11 13:34:40 +00008876 const char *z = azArg[iName];
8877 if( optionMatch(z,"new") ){
8878 newFlag = 1;
drh3baed312018-03-08 18:14:41 +00008879#ifdef SQLITE_HAVE_ZLIB
drh1fa6d9f2018-01-06 21:46:01 +00008880 }else if( optionMatch(z, "zip") ){
8881 p->openMode = SHELL_OPEN_ZIPFILE;
8882#endif
8883 }else if( optionMatch(z, "append") ){
8884 p->openMode = SHELL_OPEN_APPENDVFS;
drhee269a62018-02-14 23:27:43 +00008885 }else if( optionMatch(z, "readonly") ){
8886 p->openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +00008887 }else if( optionMatch(z, "nofollow") ){
8888 p->openFlags |= SQLITE_OPEN_NOFOLLOW;
drhdff34ab2021-06-24 18:23:54 +00008889 }else if( optionMatch(z, "excl") ){
8890 p->openFlags |= SQLITE_OPEN_EXCLUSIVE;
drh8d889af2021-05-08 17:18:23 +00008891#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +00008892 }else if( optionMatch(z, "deserialize") ){
8893 p->openMode = SHELL_OPEN_DESERIALIZE;
drh33746482018-12-13 15:06:26 +00008894 }else if( optionMatch(z, "hexdb") ){
8895 p->openMode = SHELL_OPEN_HEXDB;
drh6ca64482019-01-22 16:06:20 +00008896 }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
8897 p->szMax = integerValue(azArg[++iName]);
drh8d889af2021-05-08 17:18:23 +00008898#endif /* SQLITE_OMIT_DESERIALIZE */
drh2ce15c32017-07-11 13:34:40 +00008899 }else if( z[0]=='-' ){
8900 utf8_printf(stderr, "unknown option: %s\n", z);
8901 rc = 1;
8902 goto meta_command_exit;
drhf30bbce2020-12-02 18:27:48 +00008903 }else if( zNewFilename ){
8904 utf8_printf(stderr, "extra argument: \"%s\"\n", z);
8905 rc = 1;
8906 goto meta_command_exit;
8907 }else{
8908 zNewFilename = sqlite3_mprintf("%s", z);
drh2ce15c32017-07-11 13:34:40 +00008909 }
8910 }
8911 /* If a filename is specified, try to open it first */
drh33746482018-12-13 15:06:26 +00008912 if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
drhb97e2ad2021-08-26 18:31:39 +00008913 if( newFlag && !p->bSafeMode ) shellDeleteFile(zNewFilename);
8914 if( p->bSafeMode
8915 && p->openMode!=SHELL_OPEN_HEXDB
8916 && zNewFilename
8917 && strcmp(zNewFilename,":memory:")!=0
8918 ){
8919 failIfSafeMode(p, "cannot open disk-based database files in safe mode");
8920 }
drh37407122021-07-23 18:43:58 +00008921 p->pAuxDb->zDbFilename = zNewFilename;
drhbe4ccb22018-05-17 20:04:24 +00008922 open_db(p, OPEN_DB_KEEPALIVE);
drh2ce15c32017-07-11 13:34:40 +00008923 if( p->db==0 ){
8924 utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
8925 sqlite3_free(zNewFilename);
8926 }else{
drh37407122021-07-23 18:43:58 +00008927 p->pAuxDb->zFreeOnClose = zNewFilename;
drh2ce15c32017-07-11 13:34:40 +00008928 }
8929 }
8930 if( p->db==0 ){
8931 /* As a fall-back open a TEMP database */
drh37407122021-07-23 18:43:58 +00008932 p->pAuxDb->zDbFilename = 0;
drh2ce15c32017-07-11 13:34:40 +00008933 open_db(p, 0);
8934 }
8935 }else
8936
drh13c20932018-01-10 21:41:55 +00008937 if( (c=='o'
8938 && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
8939 || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
drh2ce15c32017-07-11 13:34:40 +00008940 ){
drh4b0229a2021-02-17 13:19:22 +00008941 char *zFile = 0;
drha92a01a2018-01-10 22:15:37 +00008942 int bTxtMode = 0;
drh7a431002020-04-18 14:12:00 +00008943 int i;
8944 int eMode = 0;
8945 int bBOM = 0;
drh5415ab42020-04-23 20:45:46 +00008946 int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */
drh7a431002020-04-18 14:12:00 +00008947
drhb97e2ad2021-08-26 18:31:39 +00008948 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh7a431002020-04-18 14:12:00 +00008949 if( c=='e' ){
8950 eMode = 'x';
8951 bOnce = 2;
8952 }else if( strncmp(azArg[0],"once",n)==0 ){
8953 bOnce = 1;
drh13c20932018-01-10 21:41:55 +00008954 }
drh7a431002020-04-18 14:12:00 +00008955 for(i=1; i<nArg; i++){
8956 char *z = azArg[i];
8957 if( z[0]=='-' ){
8958 if( z[1]=='-' ) z++;
8959 if( strcmp(z,"-bom")==0 ){
8960 bBOM = 1;
8961 }else if( c!='e' && strcmp(z,"-x")==0 ){
8962 eMode = 'x'; /* spreadsheet */
8963 }else if( c!='e' && strcmp(z,"-e")==0 ){
8964 eMode = 'e'; /* text editor */
8965 }else{
8966 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n",
8967 azArg[i]);
8968 showHelp(p->out, azArg[0]);
8969 rc = 1;
8970 goto meta_command_exit;
8971 }
drh4b0229a2021-02-17 13:19:22 +00008972 }else if( zFile==0 && eMode!='e' && eMode!='x' ){
8973 zFile = sqlite3_mprintf("%s", z);
8974 if( zFile[0]=='|' ){
8975 while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]);
8976 break;
8977 }
drh7a431002020-04-18 14:12:00 +00008978 }else{
8979 utf8_printf(p->out,"ERROR: extra parameter: \"%s\". Usage:\n",
8980 azArg[i]);
8981 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00008982 rc = 1;
drh4b0229a2021-02-17 13:19:22 +00008983 sqlite3_free(zFile);
drh2ce15c32017-07-11 13:34:40 +00008984 goto meta_command_exit;
8985 }
drh7a431002020-04-18 14:12:00 +00008986 }
drh4b0229a2021-02-17 13:19:22 +00008987 if( zFile==0 ) zFile = sqlite3_mprintf("stdout");
drh7a431002020-04-18 14:12:00 +00008988 if( bOnce ){
drh2ce15c32017-07-11 13:34:40 +00008989 p->outCount = 2;
8990 }else{
8991 p->outCount = 0;
8992 }
8993 output_reset(p);
drh04a28c32018-01-31 01:38:44 +00008994#ifndef SQLITE_NOHAVE_SYSTEM
drh7a431002020-04-18 14:12:00 +00008995 if( eMode=='e' || eMode=='x' ){
drh3c484e82018-01-10 22:27:21 +00008996 p->doXdgOpen = 1;
8997 outputModePush(p);
drh7a431002020-04-18 14:12:00 +00008998 if( eMode=='x' ){
8999 /* spreadsheet mode. Output as CSV. */
drh13c20932018-01-10 21:41:55 +00009000 newTempFile(p, "csv");
drh7a431002020-04-18 14:12:00 +00009001 ShellClearFlag(p, SHFLG_Echo);
drh13c20932018-01-10 21:41:55 +00009002 p->mode = MODE_Csv;
9003 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
9004 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
9005 }else{
drh7a431002020-04-18 14:12:00 +00009006 /* text editor mode */
drh13c20932018-01-10 21:41:55 +00009007 newTempFile(p, "txt");
drha92a01a2018-01-10 22:15:37 +00009008 bTxtMode = 1;
drh13c20932018-01-10 21:41:55 +00009009 }
drh4b0229a2021-02-17 13:19:22 +00009010 sqlite3_free(zFile);
9011 zFile = sqlite3_mprintf("%s", p->zTempFile);
drh13c20932018-01-10 21:41:55 +00009012 }
drh04a28c32018-01-31 01:38:44 +00009013#endif /* SQLITE_NOHAVE_SYSTEM */
drh2ce15c32017-07-11 13:34:40 +00009014 if( zFile[0]=='|' ){
9015#ifdef SQLITE_OMIT_POPEN
9016 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
9017 rc = 1;
9018 p->out = stdout;
9019#else
9020 p->out = popen(zFile + 1, "w");
9021 if( p->out==0 ){
9022 utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
9023 p->out = stdout;
9024 rc = 1;
9025 }else{
drh7a431002020-04-18 14:12:00 +00009026 if( bBOM ) fprintf(p->out,"\357\273\277");
drh2ce15c32017-07-11 13:34:40 +00009027 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
9028 }
9029#endif
9030 }else{
drha92a01a2018-01-10 22:15:37 +00009031 p->out = output_file_open(zFile, bTxtMode);
drh2ce15c32017-07-11 13:34:40 +00009032 if( p->out==0 ){
9033 if( strcmp(zFile,"off")!=0 ){
9034 utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
9035 }
9036 p->out = stdout;
9037 rc = 1;
9038 } else {
drh7a431002020-04-18 14:12:00 +00009039 if( bBOM ) fprintf(p->out,"\357\273\277");
drh2ce15c32017-07-11 13:34:40 +00009040 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
9041 }
9042 }
drh4b0229a2021-02-17 13:19:22 +00009043 sqlite3_free(zFile);
drh2ce15c32017-07-11 13:34:40 +00009044 }else
9045
drh9cb02642019-02-28 20:10:52 +00009046 if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
9047 open_db(p,0);
9048 if( nArg<=1 ) goto parameter_syntax_error;
9049
9050 /* .parameter clear
9051 ** Clear all bind parameters by dropping the TEMP table that holds them.
9052 */
9053 if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
drh65c29fd2019-03-25 21:56:26 +00009054 sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
drh9cb02642019-02-28 20:10:52 +00009055 0, 0, 0);
9056 }else
9057
9058 /* .parameter list
9059 ** List all bind parameters.
9060 */
9061 if( nArg==2 && strcmp(azArg[1],"list")==0 ){
9062 sqlite3_stmt *pStmt = 0;
9063 int rx;
9064 int len = 0;
9065 rx = sqlite3_prepare_v2(p->db,
9066 "SELECT max(length(key)) "
drh65c29fd2019-03-25 21:56:26 +00009067 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drh9cb02642019-02-28 20:10:52 +00009068 if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
9069 len = sqlite3_column_int(pStmt, 0);
9070 if( len>40 ) len = 40;
9071 }
9072 sqlite3_finalize(pStmt);
9073 pStmt = 0;
9074 if( len ){
9075 rx = sqlite3_prepare_v2(p->db,
9076 "SELECT key, quote(value) "
drh65c29fd2019-03-25 21:56:26 +00009077 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drh9cb02642019-02-28 20:10:52 +00009078 while( sqlite3_step(pStmt)==SQLITE_ROW ){
9079 utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
9080 sqlite3_column_text(pStmt,1));
9081 }
9082 sqlite3_finalize(pStmt);
9083 }
9084 }else
9085
9086 /* .parameter init
9087 ** Make sure the TEMP table used to hold bind parameters exists.
9088 ** Create it if necessary.
9089 */
9090 if( nArg==2 && strcmp(azArg[1],"init")==0 ){
9091 bind_table_init(p);
9092 }else
9093
9094 /* .parameter set NAME VALUE
9095 ** Set or reset a bind parameter. NAME should be the full parameter
9096 ** name exactly as it appears in the query. (ex: $abc, @def). The
9097 ** VALUE can be in either SQL literal notation, or if not it will be
9098 ** understood to be a text string.
9099 */
9100 if( nArg==4 && strcmp(azArg[1],"set")==0 ){
9101 int rx;
9102 char *zSql;
9103 sqlite3_stmt *pStmt;
9104 const char *zKey = azArg[2];
9105 const char *zValue = azArg[3];
9106 bind_table_init(p);
9107 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009108 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00009109 "VALUES(%Q,%s);", zKey, zValue);
9110 if( zSql==0 ) shell_out_of_memory();
9111 pStmt = 0;
9112 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9113 sqlite3_free(zSql);
9114 if( rx!=SQLITE_OK ){
9115 sqlite3_finalize(pStmt);
9116 pStmt = 0;
9117 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009118 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00009119 "VALUES(%Q,%Q);", zKey, zValue);
9120 if( zSql==0 ) shell_out_of_memory();
9121 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9122 sqlite3_free(zSql);
9123 if( rx!=SQLITE_OK ){
9124 utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
9125 sqlite3_finalize(pStmt);
9126 pStmt = 0;
9127 rc = 1;
9128 }
9129 }
9130 sqlite3_step(pStmt);
9131 sqlite3_finalize(pStmt);
9132 }else
9133
9134 /* .parameter unset NAME
9135 ** Remove the NAME binding from the parameter binding table, if it
9136 ** exists.
9137 */
9138 if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
9139 char *zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009140 "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
drh9cb02642019-02-28 20:10:52 +00009141 if( zSql==0 ) shell_out_of_memory();
9142 sqlite3_exec(p->db, zSql, 0, 0, 0);
9143 sqlite3_free(zSql);
9144 }else
9145 /* If no command name matches, show a syntax error */
9146 parameter_syntax_error:
9147 showHelp(p->out, "parameter");
9148 }else
9149
drh2ce15c32017-07-11 13:34:40 +00009150 if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
9151 int i;
9152 for(i=1; i<nArg; i++){
9153 if( i>1 ) raw_printf(p->out, " ");
9154 utf8_printf(p->out, "%s", azArg[i]);
9155 }
9156 raw_printf(p->out, "\n");
9157 }else
9158
drh569b1d92019-02-05 20:51:41 +00009159#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh3f83f592019-02-04 14:53:18 +00009160 if( c=='p' && n>=3 && strncmp(azArg[0], "progress", n)==0 ){
9161 int i;
drhfc4eeef2019-02-05 19:48:46 +00009162 int nn = 0;
drh3f83f592019-02-04 14:53:18 +00009163 p->flgProgress = 0;
9164 p->mxProgress = 0;
9165 p->nProgress = 0;
9166 for(i=1; i<nArg; i++){
9167 const char *z = azArg[i];
9168 if( z[0]=='-' ){
9169 z++;
9170 if( z[0]=='-' ) z++;
9171 if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009172 p->flgProgress |= SHELL_PROGRESS_QUIET;
drh3f83f592019-02-04 14:53:18 +00009173 continue;
9174 }
9175 if( strcmp(z,"reset")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009176 p->flgProgress |= SHELL_PROGRESS_RESET;
drh3f83f592019-02-04 14:53:18 +00009177 continue;
9178 }
9179 if( strcmp(z,"once")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009180 p->flgProgress |= SHELL_PROGRESS_ONCE;
drh3f83f592019-02-04 14:53:18 +00009181 continue;
9182 }
9183 if( strcmp(z,"limit")==0 ){
9184 if( i+1>=nArg ){
9185 utf8_printf(stderr, "Error: missing argument on --limit\n");
9186 rc = 1;
9187 goto meta_command_exit;
9188 }else{
9189 p->mxProgress = (int)integerValue(azArg[++i]);
9190 }
9191 continue;
9192 }
9193 utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
9194 rc = 1;
9195 goto meta_command_exit;
9196 }else{
drhfc4eeef2019-02-05 19:48:46 +00009197 nn = (int)integerValue(z);
drh3f83f592019-02-04 14:53:18 +00009198 }
9199 }
9200 open_db(p, 0);
drhfc4eeef2019-02-05 19:48:46 +00009201 sqlite3_progress_handler(p->db, nn, progress_handler, p);
drh3f83f592019-02-04 14:53:18 +00009202 }else
drh569b1d92019-02-05 20:51:41 +00009203#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
drh3f83f592019-02-04 14:53:18 +00009204
drh2ce15c32017-07-11 13:34:40 +00009205 if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
9206 if( nArg >= 2) {
9207 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
9208 }
9209 if( nArg >= 3) {
9210 strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
9211 }
9212 }else
9213
9214 if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
9215 rc = 2;
9216 }else
9217
9218 if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
drh60379d42018-12-13 18:30:01 +00009219 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +00009220 int savedLineno = p->lineno;
drhb97e2ad2021-08-26 18:31:39 +00009221 failIfSafeMode(p, "cannot run .read in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009222 if( nArg!=2 ){
9223 raw_printf(stderr, "Usage: .read FILE\n");
9224 rc = 1;
9225 goto meta_command_exit;
9226 }
drh30497f42020-08-26 10:50:48 +00009227 if( azArg[1][0]=='|' ){
drh9d59e3b2021-03-12 01:49:08 +00009228#ifdef SQLITE_OMIT_POPEN
9229 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
9230 rc = 1;
9231 p->out = stdout;
9232#else
drh30497f42020-08-26 10:50:48 +00009233 p->in = popen(azArg[1]+1, "r");
9234 if( p->in==0 ){
9235 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
9236 rc = 1;
9237 }else{
9238 rc = process_input(p);
9239 pclose(p->in);
9240 }
drh9d59e3b2021-03-12 01:49:08 +00009241#endif
drh30497f42020-08-26 10:50:48 +00009242 }else if( notNormalFile(azArg[1]) || (p->in = fopen(azArg[1], "rb"))==0 ){
drh2ce15c32017-07-11 13:34:40 +00009243 utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
9244 rc = 1;
9245 }else{
drh60379d42018-12-13 18:30:01 +00009246 rc = process_input(p);
9247 fclose(p->in);
drh2ce15c32017-07-11 13:34:40 +00009248 }
drh60379d42018-12-13 18:30:01 +00009249 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +00009250 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +00009251 }else
9252
9253 if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
9254 const char *zSrcFile;
9255 const char *zDb;
9256 sqlite3 *pSrc;
9257 sqlite3_backup *pBackup;
9258 int nTimeout = 0;
9259
drhb97e2ad2021-08-26 18:31:39 +00009260 failIfSafeMode(p, "cannot run .restore in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009261 if( nArg==2 ){
9262 zSrcFile = azArg[1];
9263 zDb = "main";
9264 }else if( nArg==3 ){
9265 zSrcFile = azArg[2];
9266 zDb = azArg[1];
9267 }else{
9268 raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
9269 rc = 1;
9270 goto meta_command_exit;
9271 }
9272 rc = sqlite3_open(zSrcFile, &pSrc);
9273 if( rc!=SQLITE_OK ){
9274 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
drh9e804032018-05-18 17:11:50 +00009275 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009276 return 1;
9277 }
9278 open_db(p, 0);
9279 pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
9280 if( pBackup==0 ){
9281 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh9e804032018-05-18 17:11:50 +00009282 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009283 return 1;
9284 }
9285 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
9286 || rc==SQLITE_BUSY ){
9287 if( rc==SQLITE_BUSY ){
9288 if( nTimeout++ >= 3 ) break;
9289 sqlite3_sleep(100);
9290 }
9291 }
9292 sqlite3_backup_finish(pBackup);
9293 if( rc==SQLITE_DONE ){
9294 rc = 0;
9295 }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
9296 raw_printf(stderr, "Error: source database is busy\n");
9297 rc = 1;
9298 }else{
9299 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9300 rc = 1;
9301 }
drh9e804032018-05-18 17:11:50 +00009302 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009303 }else
9304
drh2ce15c32017-07-11 13:34:40 +00009305 if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
9306 if( nArg==2 ){
mistachkinb71aa092018-01-23 00:05:18 +00009307 p->scanstatsOn = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00009308#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
9309 raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
9310#endif
9311 }else{
9312 raw_printf(stderr, "Usage: .scanstats on|off\n");
9313 rc = 1;
9314 }
9315 }else
9316
9317 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
9318 ShellText sSelect;
9319 ShellState data;
9320 char *zErrMsg = 0;
drh667a2a22018-01-02 00:04:37 +00009321 const char *zDiv = "(";
drhceba7922018-01-01 21:28:25 +00009322 const char *zName = 0;
drh2ce15c32017-07-11 13:34:40 +00009323 int iSchema = 0;
drhceba7922018-01-01 21:28:25 +00009324 int bDebug = 0;
drhbbb29ec2020-10-12 14:56:47 +00009325 int bNoSystemTabs = 0;
drhceba7922018-01-01 21:28:25 +00009326 int ii;
drh2ce15c32017-07-11 13:34:40 +00009327
9328 open_db(p, 0);
9329 memcpy(&data, p, sizeof(data));
9330 data.showHeader = 0;
9331 data.cMode = data.mode = MODE_Semi;
9332 initText(&sSelect);
drhceba7922018-01-01 21:28:25 +00009333 for(ii=1; ii<nArg; ii++){
9334 if( optionMatch(azArg[ii],"indent") ){
9335 data.cMode = data.mode = MODE_Pretty;
9336 }else if( optionMatch(azArg[ii],"debug") ){
9337 bDebug = 1;
drhbbb29ec2020-10-12 14:56:47 +00009338 }else if( optionMatch(azArg[ii],"nosys") ){
9339 bNoSystemTabs = 1;
9340 }else if( azArg[ii][0]=='-' ){
9341 utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
9342 rc = 1;
9343 goto meta_command_exit;
drhceba7922018-01-01 21:28:25 +00009344 }else if( zName==0 ){
9345 zName = azArg[ii];
drh2ce15c32017-07-11 13:34:40 +00009346 }else{
drhbbb29ec2020-10-12 14:56:47 +00009347 raw_printf(stderr, "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
drhceba7922018-01-01 21:28:25 +00009348 rc = 1;
9349 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00009350 }
drh2ce15c32017-07-11 13:34:40 +00009351 }
drhceba7922018-01-01 21:28:25 +00009352 if( zName!=0 ){
drh067b92b2020-06-19 15:24:12 +00009353 int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0
drh346a70c2020-06-15 20:27:35 +00009354 || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
9355 || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
9356 || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
drh067b92b2020-06-19 15:24:12 +00009357 if( isSchema ){
drh2ce15c32017-07-11 13:34:40 +00009358 char *new_argv[2], *new_colv[2];
drhc22b7162018-01-01 20:11:23 +00009359 new_argv[0] = sqlite3_mprintf(
9360 "CREATE TABLE %s (\n"
drh2ce15c32017-07-11 13:34:40 +00009361 " type text,\n"
9362 " name text,\n"
9363 " tbl_name text,\n"
9364 " rootpage integer,\n"
9365 " sql text\n"
drh346a70c2020-06-15 20:27:35 +00009366 ")", zName);
drh2ce15c32017-07-11 13:34:40 +00009367 new_argv[1] = 0;
9368 new_colv[0] = "sql";
9369 new_colv[1] = 0;
9370 callback(&data, 1, new_argv, new_colv);
drhc22b7162018-01-01 20:11:23 +00009371 sqlite3_free(new_argv[0]);
drh2ce15c32017-07-11 13:34:40 +00009372 }
drh2ce15c32017-07-11 13:34:40 +00009373 }
9374 if( zDiv ){
9375 sqlite3_stmt *pStmt = 0;
9376 rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
9377 -1, &pStmt, 0);
9378 if( rc ){
9379 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9380 sqlite3_finalize(pStmt);
9381 rc = 1;
9382 goto meta_command_exit;
9383 }
9384 appendText(&sSelect, "SELECT sql FROM", 0);
9385 iSchema = 0;
9386 while( sqlite3_step(pStmt)==SQLITE_ROW ){
9387 const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
9388 char zScNum[30];
9389 sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
9390 appendText(&sSelect, zDiv, 0);
9391 zDiv = " UNION ALL ";
drhceba7922018-01-01 21:28:25 +00009392 appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
9393 if( sqlite3_stricmp(zDb, "main")!=0 ){
drhea38f4f2019-07-13 17:21:47 +00009394 appendText(&sSelect, zDb, '\'');
drh2ce15c32017-07-11 13:34:40 +00009395 }else{
drhceba7922018-01-01 21:28:25 +00009396 appendText(&sSelect, "NULL", 0);
drh2ce15c32017-07-11 13:34:40 +00009397 }
drhceba7922018-01-01 21:28:25 +00009398 appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0);
9399 appendText(&sSelect, zScNum, 0);
9400 appendText(&sSelect, " AS snum, ", 0);
9401 appendText(&sSelect, zDb, '\'');
9402 appendText(&sSelect, " AS sname FROM ", 0);
drhea38f4f2019-07-13 17:21:47 +00009403 appendText(&sSelect, zDb, quoteChar(zDb));
drh067b92b2020-06-19 15:24:12 +00009404 appendText(&sSelect, ".sqlite_schema", 0);
drh2ce15c32017-07-11 13:34:40 +00009405 }
9406 sqlite3_finalize(pStmt);
drhcc3f3d12019-08-17 15:27:58 +00009407#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
drh667a2a22018-01-02 00:04:37 +00009408 if( zName ){
9409 appendText(&sSelect,
9410 " UNION ALL SELECT shell_module_schema(name),"
drhe2754c12019-08-26 12:50:01 +00009411 " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
9412 0);
drh667a2a22018-01-02 00:04:37 +00009413 }
drhcde7b772018-01-02 12:50:40 +00009414#endif
drh2ce15c32017-07-11 13:34:40 +00009415 appendText(&sSelect, ") WHERE ", 0);
drhceba7922018-01-01 21:28:25 +00009416 if( zName ){
9417 char *zQarg = sqlite3_mprintf("%Q", zName);
mistachkin9d107262018-03-23 14:24:34 +00009418 int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
9419 strchr(zName, '[') != 0;
drhceba7922018-01-01 21:28:25 +00009420 if( strchr(zName, '.') ){
drh2ce15c32017-07-11 13:34:40 +00009421 appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
9422 }else{
9423 appendText(&sSelect, "lower(tbl_name)", 0);
9424 }
mistachkin9d107262018-03-23 14:24:34 +00009425 appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0);
drh2ce15c32017-07-11 13:34:40 +00009426 appendText(&sSelect, zQarg, 0);
mistachkin9d107262018-03-23 14:24:34 +00009427 if( !bGlob ){
9428 appendText(&sSelect, " ESCAPE '\\' ", 0);
9429 }
drh2ce15c32017-07-11 13:34:40 +00009430 appendText(&sSelect, " AND ", 0);
9431 sqlite3_free(zQarg);
9432 }
drhbbb29ec2020-10-12 14:56:47 +00009433 if( bNoSystemTabs ){
9434 appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
9435 }
9436 appendText(&sSelect, "sql IS NOT NULL"
drh2ce15c32017-07-11 13:34:40 +00009437 " ORDER BY snum, rowid", 0);
drhceba7922018-01-01 21:28:25 +00009438 if( bDebug ){
9439 utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
9440 }else{
9441 rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
9442 }
drh2ce15c32017-07-11 13:34:40 +00009443 freeText(&sSelect);
9444 }
9445 if( zErrMsg ){
9446 utf8_printf(stderr,"Error: %s\n", zErrMsg);
9447 sqlite3_free(zErrMsg);
9448 rc = 1;
9449 }else if( rc != SQLITE_OK ){
9450 raw_printf(stderr,"Error: querying schema information\n");
9451 rc = 1;
9452 }else{
9453 rc = 0;
9454 }
9455 }else
9456
drh2ce15c32017-07-11 13:34:40 +00009457 if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
drhfda8e492020-12-04 16:04:45 +00009458 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
drhc0622a42020-12-04 01:17:57 +00009459 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
drh2ce15c32017-07-11 13:34:40 +00009460 }else
drh2ce15c32017-07-11 13:34:40 +00009461
9462#if defined(SQLITE_ENABLE_SESSION)
9463 if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
drh37407122021-07-23 18:43:58 +00009464 struct AuxDb *pAuxDb = p->pAuxDb;
9465 OpenSession *pSession = &pAuxDb->aSession[0];
drh2ce15c32017-07-11 13:34:40 +00009466 char **azCmd = &azArg[1];
9467 int iSes = 0;
9468 int nCmd = nArg - 1;
9469 int i;
9470 if( nArg<=1 ) goto session_syntax_error;
9471 open_db(p, 0);
9472 if( nArg>=3 ){
drh37407122021-07-23 18:43:58 +00009473 for(iSes=0; iSes<pAuxDb->nSession; iSes++){
9474 if( strcmp(pAuxDb->aSession[iSes].zName, azArg[1])==0 ) break;
drh2ce15c32017-07-11 13:34:40 +00009475 }
drh37407122021-07-23 18:43:58 +00009476 if( iSes<pAuxDb->nSession ){
9477 pSession = &pAuxDb->aSession[iSes];
drh2ce15c32017-07-11 13:34:40 +00009478 azCmd++;
9479 nCmd--;
9480 }else{
drh37407122021-07-23 18:43:58 +00009481 pSession = &pAuxDb->aSession[0];
drh2ce15c32017-07-11 13:34:40 +00009482 iSes = 0;
9483 }
9484 }
9485
9486 /* .session attach TABLE
9487 ** Invoke the sqlite3session_attach() interface to attach a particular
9488 ** table so that it is never filtered.
9489 */
9490 if( strcmp(azCmd[0],"attach")==0 ){
9491 if( nCmd!=2 ) goto session_syntax_error;
9492 if( pSession->p==0 ){
9493 session_not_open:
9494 raw_printf(stderr, "ERROR: No sessions are open\n");
9495 }else{
9496 rc = sqlite3session_attach(pSession->p, azCmd[1]);
9497 if( rc ){
9498 raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
9499 rc = 0;
9500 }
9501 }
9502 }else
9503
9504 /* .session changeset FILE
9505 ** .session patchset FILE
9506 ** Write a changeset or patchset into a file. The file is overwritten.
9507 */
9508 if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
9509 FILE *out = 0;
drhb97e2ad2021-08-26 18:31:39 +00009510 failIfSafeMode(p, "cannot run \".session %s\" in safe mode", azCmd[0]);
drh2ce15c32017-07-11 13:34:40 +00009511 if( nCmd!=2 ) goto session_syntax_error;
9512 if( pSession->p==0 ) goto session_not_open;
9513 out = fopen(azCmd[1], "wb");
9514 if( out==0 ){
drhe2754c12019-08-26 12:50:01 +00009515 utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
9516 azCmd[1]);
drh2ce15c32017-07-11 13:34:40 +00009517 }else{
9518 int szChng;
9519 void *pChng;
9520 if( azCmd[0][0]=='c' ){
9521 rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
9522 }else{
9523 rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
9524 }
9525 if( rc ){
9526 printf("Error: error code %d\n", rc);
9527 rc = 0;
9528 }
9529 if( pChng
9530 && fwrite(pChng, szChng, 1, out)!=1 ){
9531 raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
9532 szChng);
9533 }
9534 sqlite3_free(pChng);
9535 fclose(out);
9536 }
9537 }else
9538
9539 /* .session close
9540 ** Close the identified session
9541 */
9542 if( strcmp(azCmd[0], "close")==0 ){
9543 if( nCmd!=1 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009544 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009545 session_close(pSession);
drh37407122021-07-23 18:43:58 +00009546 pAuxDb->aSession[iSes] = pAuxDb->aSession[--pAuxDb->nSession];
drh2ce15c32017-07-11 13:34:40 +00009547 }
9548 }else
9549
9550 /* .session enable ?BOOLEAN?
9551 ** Query or set the enable flag
9552 */
9553 if( strcmp(azCmd[0], "enable")==0 ){
9554 int ii;
9555 if( nCmd>2 ) goto session_syntax_error;
9556 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
drh37407122021-07-23 18:43:58 +00009557 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009558 ii = sqlite3session_enable(pSession->p, ii);
9559 utf8_printf(p->out, "session %s enable flag = %d\n",
9560 pSession->zName, ii);
9561 }
9562 }else
9563
9564 /* .session filter GLOB ....
9565 ** Set a list of GLOB patterns of table names to be excluded.
9566 */
9567 if( strcmp(azCmd[0], "filter")==0 ){
9568 int ii, nByte;
9569 if( nCmd<2 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009570 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009571 for(ii=0; ii<pSession->nFilter; ii++){
9572 sqlite3_free(pSession->azFilter[ii]);
9573 }
9574 sqlite3_free(pSession->azFilter);
9575 nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
9576 pSession->azFilter = sqlite3_malloc( nByte );
9577 if( pSession->azFilter==0 ){
9578 raw_printf(stderr, "Error: out or memory\n");
9579 exit(1);
9580 }
9581 for(ii=1; ii<nCmd; ii++){
9582 pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
9583 }
9584 pSession->nFilter = ii-1;
9585 }
9586 }else
9587
9588 /* .session indirect ?BOOLEAN?
9589 ** Query or set the indirect flag
9590 */
9591 if( strcmp(azCmd[0], "indirect")==0 ){
9592 int ii;
9593 if( nCmd>2 ) goto session_syntax_error;
9594 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
drh37407122021-07-23 18:43:58 +00009595 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009596 ii = sqlite3session_indirect(pSession->p, ii);
9597 utf8_printf(p->out, "session %s indirect flag = %d\n",
9598 pSession->zName, ii);
9599 }
9600 }else
9601
9602 /* .session isempty
9603 ** Determine if the session is empty
9604 */
9605 if( strcmp(azCmd[0], "isempty")==0 ){
9606 int ii;
9607 if( nCmd!=1 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009608 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009609 ii = sqlite3session_isempty(pSession->p);
9610 utf8_printf(p->out, "session %s isempty flag = %d\n",
9611 pSession->zName, ii);
9612 }
9613 }else
9614
9615 /* .session list
9616 ** List all currently open sessions
9617 */
9618 if( strcmp(azCmd[0],"list")==0 ){
drh37407122021-07-23 18:43:58 +00009619 for(i=0; i<pAuxDb->nSession; i++){
9620 utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName);
drh2ce15c32017-07-11 13:34:40 +00009621 }
9622 }else
9623
9624 /* .session open DB NAME
9625 ** Open a new session called NAME on the attached database DB.
9626 ** DB is normally "main".
9627 */
9628 if( strcmp(azCmd[0],"open")==0 ){
9629 char *zName;
9630 if( nCmd!=3 ) goto session_syntax_error;
9631 zName = azCmd[2];
9632 if( zName[0]==0 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009633 for(i=0; i<pAuxDb->nSession; i++){
9634 if( strcmp(pAuxDb->aSession[i].zName,zName)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009635 utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
9636 goto meta_command_exit;
9637 }
9638 }
drh37407122021-07-23 18:43:58 +00009639 if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){
9640 raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession));
drh2ce15c32017-07-11 13:34:40 +00009641 goto meta_command_exit;
9642 }
drh37407122021-07-23 18:43:58 +00009643 pSession = &pAuxDb->aSession[pAuxDb->nSession];
drh2ce15c32017-07-11 13:34:40 +00009644 rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
9645 if( rc ){
9646 raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
9647 rc = 0;
9648 goto meta_command_exit;
9649 }
9650 pSession->nFilter = 0;
9651 sqlite3session_table_filter(pSession->p, session_filter, pSession);
drh37407122021-07-23 18:43:58 +00009652 pAuxDb->nSession++;
drh2ce15c32017-07-11 13:34:40 +00009653 pSession->zName = sqlite3_mprintf("%s", zName);
9654 }else
9655 /* If no command name matches, show a syntax error */
9656 session_syntax_error:
drheb7f2a02018-09-26 18:02:32 +00009657 showHelp(p->out, "session");
drh2ce15c32017-07-11 13:34:40 +00009658 }else
9659#endif
9660
9661#ifdef SQLITE_DEBUG
9662 /* Undocumented commands for internal testing. Subject to change
9663 ** without notice. */
9664 if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
9665 if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
9666 int i, v;
9667 for(i=1; i<nArg; i++){
9668 v = booleanValue(azArg[i]);
9669 utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
9670 }
9671 }
9672 if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
9673 int i; sqlite3_int64 v;
9674 for(i=1; i<nArg; i++){
9675 char zBuf[200];
9676 v = integerValue(azArg[i]);
9677 sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
9678 utf8_printf(p->out, "%s", zBuf);
9679 }
9680 }
9681 }else
9682#endif
9683
9684 if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){
9685 int bIsInit = 0; /* True to initialize the SELFTEST table */
9686 int bVerbose = 0; /* Verbose output */
9687 int bSelftestExists; /* True if SELFTEST already exists */
9688 int i, k; /* Loop counters */
9689 int nTest = 0; /* Number of tests runs */
9690 int nErr = 0; /* Number of errors seen */
9691 ShellText str; /* Answer for a query */
9692 sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
9693
9694 open_db(p,0);
9695 for(i=1; i<nArg; i++){
9696 const char *z = azArg[i];
9697 if( z[0]=='-' && z[1]=='-' ) z++;
9698 if( strcmp(z,"-init")==0 ){
9699 bIsInit = 1;
9700 }else
9701 if( strcmp(z,"-v")==0 ){
9702 bVerbose++;
9703 }else
9704 {
9705 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
9706 azArg[i], azArg[0]);
9707 raw_printf(stderr, "Should be one of: --init -v\n");
9708 rc = 1;
9709 goto meta_command_exit;
9710 }
9711 }
9712 if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
9713 != SQLITE_OK ){
9714 bSelftestExists = 0;
9715 }else{
9716 bSelftestExists = 1;
9717 }
9718 if( bIsInit ){
9719 createSelftestTable(p);
9720 bSelftestExists = 1;
9721 }
9722 initText(&str);
9723 appendText(&str, "x", 0);
9724 for(k=bSelftestExists; k>=0; k--){
9725 if( k==1 ){
9726 rc = sqlite3_prepare_v2(p->db,
9727 "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
9728 -1, &pStmt, 0);
9729 }else{
9730 rc = sqlite3_prepare_v2(p->db,
9731 "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
9732 " (1,'run','PRAGMA integrity_check','ok')",
9733 -1, &pStmt, 0);
9734 }
9735 if( rc ){
9736 raw_printf(stderr, "Error querying the selftest table\n");
9737 rc = 1;
9738 sqlite3_finalize(pStmt);
9739 goto meta_command_exit;
9740 }
9741 for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
9742 int tno = sqlite3_column_int(pStmt, 0);
9743 const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
9744 const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
9745 const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
9746
9747 k = 0;
9748 if( bVerbose>0 ){
9749 char *zQuote = sqlite3_mprintf("%q", zSql);
9750 printf("%d: %s %s\n", tno, zOp, zSql);
9751 sqlite3_free(zQuote);
9752 }
9753 if( strcmp(zOp,"memo")==0 ){
9754 utf8_printf(p->out, "%s\n", zSql);
9755 }else
9756 if( strcmp(zOp,"run")==0 ){
9757 char *zErrMsg = 0;
9758 str.n = 0;
9759 str.z[0] = 0;
9760 rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
9761 nTest++;
9762 if( bVerbose ){
9763 utf8_printf(p->out, "Result: %s\n", str.z);
9764 }
9765 if( rc || zErrMsg ){
9766 nErr++;
9767 rc = 1;
9768 utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
9769 sqlite3_free(zErrMsg);
9770 }else if( strcmp(zAns,str.z)!=0 ){
9771 nErr++;
9772 rc = 1;
9773 utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
9774 utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z);
9775 }
9776 }else
9777 {
9778 utf8_printf(stderr,
9779 "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
9780 rc = 1;
9781 break;
9782 }
9783 } /* End loop over rows of content from SELFTEST */
9784 sqlite3_finalize(pStmt);
9785 } /* End loop over k */
9786 freeText(&str);
9787 utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
9788 }else
9789
9790 if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
9791 if( nArg<2 || nArg>3 ){
9792 raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
9793 rc = 1;
9794 }
9795 if( nArg>=2 ){
9796 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
9797 "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
9798 }
9799 if( nArg>=3 ){
9800 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator,
9801 "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]);
9802 }
9803 }else
9804
9805 if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){
9806 const char *zLike = 0; /* Which table to checksum. 0 means everything */
9807 int i; /* Loop counter */
9808 int bSchema = 0; /* Also hash the schema */
9809 int bSeparate = 0; /* Hash each table separately */
9810 int iSize = 224; /* Hash algorithm to use */
9811 int bDebug = 0; /* Only show the query that would have run */
9812 sqlite3_stmt *pStmt; /* For querying tables names */
9813 char *zSql; /* SQL to be run */
9814 char *zSep; /* Separator */
9815 ShellText sSql; /* Complete SQL for the query to run the hash */
9816 ShellText sQuery; /* Set of queries used to read all content */
9817 open_db(p, 0);
9818 for(i=1; i<nArg; i++){
9819 const char *z = azArg[i];
9820 if( z[0]=='-' ){
9821 z++;
9822 if( z[0]=='-' ) z++;
9823 if( strcmp(z,"schema")==0 ){
9824 bSchema = 1;
9825 }else
9826 if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
9827 || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
9828 ){
9829 iSize = atoi(&z[5]);
9830 }else
9831 if( strcmp(z,"debug")==0 ){
9832 bDebug = 1;
9833 }else
9834 {
9835 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
9836 azArg[i], azArg[0]);
drhe2754c12019-08-26 12:50:01 +00009837 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00009838 rc = 1;
9839 goto meta_command_exit;
9840 }
9841 }else if( zLike ){
9842 raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
9843 rc = 1;
9844 goto meta_command_exit;
9845 }else{
9846 zLike = z;
9847 bSeparate = 1;
drhcedfecf2018-03-23 12:59:10 +00009848 if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1;
drh2ce15c32017-07-11 13:34:40 +00009849 }
9850 }
9851 if( bSchema ){
drh067b92b2020-06-19 15:24:12 +00009852 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00009853 " WHERE type='table' AND coalesce(rootpage,0)>1"
drh067b92b2020-06-19 15:24:12 +00009854 " UNION ALL SELECT 'sqlite_schema'"
drh2ce15c32017-07-11 13:34:40 +00009855 " ORDER BY 1 collate nocase";
9856 }else{
drh067b92b2020-06-19 15:24:12 +00009857 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00009858 " WHERE type='table' AND coalesce(rootpage,0)>1"
9859 " AND name NOT LIKE 'sqlite_%'"
9860 " ORDER BY 1 collate nocase";
9861 }
9862 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9863 initText(&sQuery);
9864 initText(&sSql);
9865 appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
9866 zSep = "VALUES(";
9867 while( SQLITE_ROW==sqlite3_step(pStmt) ){
9868 const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
9869 if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
9870 if( strncmp(zTab, "sqlite_",7)!=0 ){
9871 appendText(&sQuery,"SELECT * FROM ", 0);
9872 appendText(&sQuery,zTab,'"');
9873 appendText(&sQuery," NOT INDEXED;", 0);
drh067b92b2020-06-19 15:24:12 +00009874 }else if( strcmp(zTab, "sqlite_schema")==0 ){
9875 appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00009876 " ORDER BY name;", 0);
9877 }else if( strcmp(zTab, "sqlite_sequence")==0 ){
9878 appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
9879 " ORDER BY name;", 0);
9880 }else if( strcmp(zTab, "sqlite_stat1")==0 ){
9881 appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
9882 " ORDER BY tbl,idx;", 0);
drh175b8f02019-08-08 15:24:17 +00009883 }else if( strcmp(zTab, "sqlite_stat4")==0 ){
drh2ce15c32017-07-11 13:34:40 +00009884 appendText(&sQuery, "SELECT * FROM ", 0);
9885 appendText(&sQuery, zTab, 0);
9886 appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
9887 }
9888 appendText(&sSql, zSep, 0);
9889 appendText(&sSql, sQuery.z, '\'');
9890 sQuery.n = 0;
9891 appendText(&sSql, ",", 0);
9892 appendText(&sSql, zTab, '\'');
9893 zSep = "),(";
9894 }
9895 sqlite3_finalize(pStmt);
9896 if( bSeparate ){
9897 zSql = sqlite3_mprintf(
9898 "%s))"
9899 " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
9900 " FROM [sha3sum$query]",
9901 sSql.z, iSize);
9902 }else{
9903 zSql = sqlite3_mprintf(
9904 "%s))"
9905 " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
9906 " FROM [sha3sum$query]",
9907 sSql.z, iSize);
9908 }
9909 freeText(&sQuery);
9910 freeText(&sSql);
9911 if( bDebug ){
9912 utf8_printf(p->out, "%s\n", zSql);
9913 }else{
drha10b9992018-03-09 15:24:33 +00009914 shell_exec(p, zSql, 0);
drh2ce15c32017-07-11 13:34:40 +00009915 }
9916 sqlite3_free(zSql);
9917 }else
9918
drh04a28c32018-01-31 01:38:44 +00009919#ifndef SQLITE_NOHAVE_SYSTEM
drh2ce15c32017-07-11 13:34:40 +00009920 if( c=='s'
9921 && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
9922 ){
9923 char *zCmd;
9924 int i, x;
drhb97e2ad2021-08-26 18:31:39 +00009925 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00009926 if( nArg<2 ){
9927 raw_printf(stderr, "Usage: .system COMMAND\n");
9928 rc = 1;
9929 goto meta_command_exit;
9930 }
9931 zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
9932 for(i=2; i<nArg; i++){
9933 zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
9934 zCmd, azArg[i]);
9935 }
9936 x = system(zCmd);
9937 sqlite3_free(zCmd);
9938 if( x ) raw_printf(stderr, "System command returns %d\n", x);
9939 }else
drh04a28c32018-01-31 01:38:44 +00009940#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
drh2ce15c32017-07-11 13:34:40 +00009941
9942 if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
drhada70452017-12-21 21:02:27 +00009943 static const char *azBool[] = { "off", "on", "trigger", "full"};
drha6e6cf22021-01-09 19:10:04 +00009944 const char *zOut;
drh2ce15c32017-07-11 13:34:40 +00009945 int i;
9946 if( nArg!=1 ){
9947 raw_printf(stderr, "Usage: .show\n");
9948 rc = 1;
9949 goto meta_command_exit;
9950 }
9951 utf8_printf(p->out, "%12.12s: %s\n","echo",
9952 azBool[ShellHasFlag(p, SHFLG_Echo)]);
9953 utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
9954 utf8_printf(p->out, "%12.12s: %s\n","explain",
9955 p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
9956 utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
9957 utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
9958 utf8_printf(p->out, "%12.12s: ", "nullvalue");
9959 output_c_string(p->out, p->nullValue);
9960 raw_printf(p->out, "\n");
9961 utf8_printf(p->out,"%12.12s: %s\n","output",
9962 strlen30(p->outfile) ? p->outfile : "stdout");
9963 utf8_printf(p->out,"%12.12s: ", "colseparator");
9964 output_c_string(p->out, p->colSeparator);
9965 raw_printf(p->out, "\n");
9966 utf8_printf(p->out,"%12.12s: ", "rowseparator");
9967 output_c_string(p->out, p->rowSeparator);
9968 raw_printf(p->out, "\n");
drha6e6cf22021-01-09 19:10:04 +00009969 switch( p->statsOn ){
9970 case 0: zOut = "off"; break;
9971 default: zOut = "on"; break;
9972 case 2: zOut = "stmt"; break;
9973 case 3: zOut = "vmstep"; break;
9974 }
9975 utf8_printf(p->out, "%12.12s: %s\n","stats", zOut);
drh2ce15c32017-07-11 13:34:40 +00009976 utf8_printf(p->out, "%12.12s: ", "width");
drh0285d982020-05-29 14:38:43 +00009977 for (i=0;i<p->nWidth;i++) {
drh2ce15c32017-07-11 13:34:40 +00009978 raw_printf(p->out, "%d ", p->colWidth[i]);
9979 }
9980 raw_printf(p->out, "\n");
9981 utf8_printf(p->out, "%12.12s: %s\n", "filename",
drh37407122021-07-23 18:43:58 +00009982 p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : "");
drh2ce15c32017-07-11 13:34:40 +00009983 }else
9984
9985 if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
9986 if( nArg==2 ){
drha6e6cf22021-01-09 19:10:04 +00009987 if( strcmp(azArg[1],"stmt")==0 ){
9988 p->statsOn = 2;
9989 }else if( strcmp(azArg[1],"vmstep")==0 ){
9990 p->statsOn = 3;
9991 }else{
9992 p->statsOn = (u8)booleanValue(azArg[1]);
9993 }
drh2ce15c32017-07-11 13:34:40 +00009994 }else if( nArg==1 ){
9995 display_stats(p->db, p, 0);
9996 }else{
drha6e6cf22021-01-09 19:10:04 +00009997 raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n");
drh2ce15c32017-07-11 13:34:40 +00009998 rc = 1;
9999 }
10000 }else
10001
10002 if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0)
10003 || (c=='i' && (strncmp(azArg[0], "indices", n)==0
10004 || strncmp(azArg[0], "indexes", n)==0) )
10005 ){
10006 sqlite3_stmt *pStmt;
10007 char **azResult;
10008 int nRow, nAlloc;
10009 int ii;
10010 ShellText s;
10011 initText(&s);
10012 open_db(p, 0);
10013 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
drh9e804032018-05-18 17:11:50 +000010014 if( rc ){
10015 sqlite3_finalize(pStmt);
10016 return shellDatabaseError(p->db);
10017 }
drh2ce15c32017-07-11 13:34:40 +000010018
10019 if( nArg>2 && c=='i' ){
10020 /* It is an historical accident that the .indexes command shows an error
10021 ** when called with the wrong number of arguments whereas the .tables
10022 ** command does not. */
10023 raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
10024 rc = 1;
drh9e804032018-05-18 17:11:50 +000010025 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +000010026 goto meta_command_exit;
10027 }
10028 for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
10029 const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
10030 if( zDbName==0 ) continue;
10031 if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0);
10032 if( sqlite3_stricmp(zDbName, "main")==0 ){
10033 appendText(&s, "SELECT name FROM ", 0);
10034 }else{
10035 appendText(&s, "SELECT ", 0);
10036 appendText(&s, zDbName, '\'');
10037 appendText(&s, "||'.'||name FROM ", 0);
10038 }
10039 appendText(&s, zDbName, '"');
drh067b92b2020-06-19 15:24:12 +000010040 appendText(&s, ".sqlite_schema ", 0);
drh2ce15c32017-07-11 13:34:40 +000010041 if( c=='t' ){
10042 appendText(&s," WHERE type IN ('table','view')"
10043 " AND name NOT LIKE 'sqlite_%'"
10044 " AND name LIKE ?1", 0);
10045 }else{
10046 appendText(&s," WHERE type='index'"
10047 " AND tbl_name LIKE ?1", 0);
10048 }
10049 }
10050 rc = sqlite3_finalize(pStmt);
10051 appendText(&s, " ORDER BY 1", 0);
10052 rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
10053 freeText(&s);
10054 if( rc ) return shellDatabaseError(p->db);
10055
10056 /* Run the SQL statement prepared by the above block. Store the results
10057 ** as an array of nul-terminated strings in azResult[]. */
10058 nRow = nAlloc = 0;
10059 azResult = 0;
10060 if( nArg>1 ){
10061 sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
10062 }else{
10063 sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
10064 }
10065 while( sqlite3_step(pStmt)==SQLITE_ROW ){
10066 if( nRow>=nAlloc ){
10067 char **azNew;
10068 int n2 = nAlloc*2 + 10;
10069 azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
drh4b5345c2018-04-24 13:07:40 +000010070 if( azNew==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +000010071 nAlloc = n2;
10072 azResult = azNew;
10073 }
10074 azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
drh4b5345c2018-04-24 13:07:40 +000010075 if( 0==azResult[nRow] ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +000010076 nRow++;
10077 }
10078 if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
10079 rc = shellDatabaseError(p->db);
10080 }
10081
10082 /* Pretty-print the contents of array azResult[] to the output */
10083 if( rc==0 && nRow>0 ){
10084 int len, maxlen = 0;
10085 int i, j;
10086 int nPrintCol, nPrintRow;
10087 for(i=0; i<nRow; i++){
10088 len = strlen30(azResult[i]);
10089 if( len>maxlen ) maxlen = len;
10090 }
10091 nPrintCol = 80/(maxlen+2);
10092 if( nPrintCol<1 ) nPrintCol = 1;
10093 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
10094 for(i=0; i<nPrintRow; i++){
10095 for(j=i; j<nRow; j+=nPrintRow){
10096 char *zSp = j<nPrintRow ? "" : " ";
10097 utf8_printf(p->out, "%s%-*s", zSp, maxlen,
10098 azResult[j] ? azResult[j]:"");
10099 }
10100 raw_printf(p->out, "\n");
10101 }
10102 }
10103
10104 for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
10105 sqlite3_free(azResult);
10106 }else
10107
10108 /* Begin redirecting output to the file "testcase-out.txt" */
10109 if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
10110 output_reset(p);
drha92a01a2018-01-10 22:15:37 +000010111 p->out = output_file_open("testcase-out.txt", 0);
drh2ce15c32017-07-11 13:34:40 +000010112 if( p->out==0 ){
10113 raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
10114 }
10115 if( nArg>=2 ){
10116 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
10117 }else{
10118 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
10119 }
10120 }else
10121
10122#ifndef SQLITE_UNTESTABLE
drh35f51a42017-11-15 17:07:22 +000010123 if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010124 static const struct {
10125 const char *zCtrlName; /* Name of a test-control option */
10126 int ctrlCode; /* Integer code for that option */
drhef302e82017-11-15 19:14:08 +000010127 const char *zUsage; /* Usage notes */
drh2ce15c32017-07-11 13:34:40 +000010128 } aCtrl[] = {
drhe2754c12019-08-26 12:50:01 +000010129 { "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" },
10130 { "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" },
10131 /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/
10132 /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/
10133 { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" },
10134 { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN" },
10135 /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" },*/
10136 { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
drh171c50e2020-01-01 15:43:30 +000010137 { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "" },
drhe2754c12019-08-26 12:50:01 +000010138 { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" },
10139 { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" },
10140 { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" },
drh0d9de992017-12-26 18:04:23 +000010141#ifdef YYCOVERAGE
drhe2754c12019-08-26 12:50:01 +000010142 { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" },
drh0d9de992017-12-26 18:04:23 +000010143#endif
drhe2754c12019-08-26 12:50:01 +000010144 { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " },
10145 { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
10146 { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
10147 { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
drh37ccfcf2020-08-31 18:49:04 +000010148 { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, "" },
dan779e9902021-07-28 18:13:28 +000010149 { "sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, "NMAX" },
drhf3c12562021-06-04 13:16:46 +000010150 { "tune", SQLITE_TESTCTRL_TUNE, "ID VALUE" },
drh2ce15c32017-07-11 13:34:40 +000010151 };
10152 int testctrl = -1;
drhef302e82017-11-15 19:14:08 +000010153 int iCtrl = -1;
10154 int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */
10155 int isOk = 0;
drh2ce15c32017-07-11 13:34:40 +000010156 int i, n2;
mistachkinc6bc15a2017-11-21 21:14:32 +000010157 const char *zCmd = 0;
10158
drh2ce15c32017-07-11 13:34:40 +000010159 open_db(p, 0);
mistachkinc6bc15a2017-11-21 21:14:32 +000010160 zCmd = nArg>=2 ? azArg[1] : "help";
drh35f51a42017-11-15 17:07:22 +000010161
10162 /* The argument can optionally begin with "-" or "--" */
10163 if( zCmd[0]=='-' && zCmd[1] ){
10164 zCmd++;
10165 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
10166 }
10167
10168 /* --help lists all test-controls */
10169 if( strcmp(zCmd,"help")==0 ){
10170 utf8_printf(p->out, "Available test-controls:\n");
10171 for(i=0; i<ArraySize(aCtrl); i++){
drhef302e82017-11-15 19:14:08 +000010172 utf8_printf(p->out, " .testctrl %s %s\n",
10173 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
drh35f51a42017-11-15 17:07:22 +000010174 }
10175 rc = 1;
10176 goto meta_command_exit;
10177 }
drh2ce15c32017-07-11 13:34:40 +000010178
10179 /* convert testctrl text option to value. allow any unique prefix
10180 ** of the option name, or a numerical value. */
drh35f51a42017-11-15 17:07:22 +000010181 n2 = strlen30(zCmd);
drh2ce15c32017-07-11 13:34:40 +000010182 for(i=0; i<ArraySize(aCtrl); i++){
drh35f51a42017-11-15 17:07:22 +000010183 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010184 if( testctrl<0 ){
10185 testctrl = aCtrl[i].ctrlCode;
drhef302e82017-11-15 19:14:08 +000010186 iCtrl = i;
drh2ce15c32017-07-11 13:34:40 +000010187 }else{
drh35f51a42017-11-15 17:07:22 +000010188 utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
10189 "Use \".testctrl --help\" for help\n", zCmd);
10190 rc = 1;
10191 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +000010192 }
10193 }
10194 }
drhef302e82017-11-15 19:14:08 +000010195 if( testctrl<0 ){
drh35f51a42017-11-15 17:07:22 +000010196 utf8_printf(stderr,"Error: unknown test-control: %s\n"
10197 "Use \".testctrl --help\" for help\n", zCmd);
drh2ce15c32017-07-11 13:34:40 +000010198 }else{
10199 switch(testctrl){
10200
10201 /* sqlite3_test_control(int, db, int) */
10202 case SQLITE_TESTCTRL_OPTIMIZATIONS:
drh2ce15c32017-07-11 13:34:40 +000010203 if( nArg==3 ){
drhaf7b7652021-01-13 19:28:17 +000010204 unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
drh2ce15c32017-07-11 13:34:40 +000010205 rc2 = sqlite3_test_control(testctrl, p->db, opt);
drhef302e82017-11-15 19:14:08 +000010206 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010207 }
10208 break;
10209
10210 /* sqlite3_test_control(int) */
10211 case SQLITE_TESTCTRL_PRNG_SAVE:
10212 case SQLITE_TESTCTRL_PRNG_RESTORE:
drh2ce15c32017-07-11 13:34:40 +000010213 case SQLITE_TESTCTRL_BYTEORDER:
10214 if( nArg==2 ){
10215 rc2 = sqlite3_test_control(testctrl);
drhef302e82017-11-15 19:14:08 +000010216 isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
drh2ce15c32017-07-11 13:34:40 +000010217 }
10218 break;
10219
10220 /* sqlite3_test_control(int, uint) */
10221 case SQLITE_TESTCTRL_PENDING_BYTE:
10222 if( nArg==3 ){
10223 unsigned int opt = (unsigned int)integerValue(azArg[2]);
10224 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010225 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010226 }
10227 break;
10228
drh2e6d83b2019-08-03 01:39:20 +000010229 /* sqlite3_test_control(int, int, sqlite3*) */
10230 case SQLITE_TESTCTRL_PRNG_SEED:
10231 if( nArg==3 || nArg==4 ){
drh51755a72019-08-08 19:40:29 +000010232 int ii = (int)integerValue(azArg[2]);
drh2e6d83b2019-08-03 01:39:20 +000010233 sqlite3 *db;
drh41428a92019-08-12 16:25:11 +000010234 if( ii==0 && strcmp(azArg[2],"random")==0 ){
10235 sqlite3_randomness(sizeof(ii),&ii);
10236 printf("-- random seed: %d\n", ii);
10237 }
drh2e6d83b2019-08-03 01:39:20 +000010238 if( nArg==3 ){
10239 db = 0;
10240 }else{
10241 db = p->db;
10242 /* Make sure the schema has been loaded */
10243 sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);
10244 }
drh51755a72019-08-08 19:40:29 +000010245 rc2 = sqlite3_test_control(testctrl, ii, db);
drh2e6d83b2019-08-03 01:39:20 +000010246 isOk = 3;
10247 }
10248 break;
10249
drh2ce15c32017-07-11 13:34:40 +000010250 /* sqlite3_test_control(int, int) */
10251 case SQLITE_TESTCTRL_ASSERT:
10252 case SQLITE_TESTCTRL_ALWAYS:
drhef302e82017-11-15 19:14:08 +000010253 if( nArg==3 ){
10254 int opt = booleanValue(azArg[2]);
10255 rc2 = sqlite3_test_control(testctrl, opt);
10256 isOk = 1;
10257 }
10258 break;
10259
10260 /* sqlite3_test_control(int, int) */
10261 case SQLITE_TESTCTRL_LOCALTIME_FAULT:
drh2ce15c32017-07-11 13:34:40 +000010262 case SQLITE_TESTCTRL_NEVER_CORRUPT:
10263 if( nArg==3 ){
10264 int opt = booleanValue(azArg[2]);
10265 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010266 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010267 }
10268 break;
10269
drh171c50e2020-01-01 15:43:30 +000010270 /* sqlite3_test_control(sqlite3*) */
10271 case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
10272 rc2 = sqlite3_test_control(testctrl, p->db);
drh2a83c102020-01-01 23:02:35 +000010273 isOk = 3;
drh171c50e2020-01-01 15:43:30 +000010274 break;
10275
drh2ce15c32017-07-11 13:34:40 +000010276 case SQLITE_TESTCTRL_IMPOSTER:
10277 if( nArg==5 ){
10278 rc2 = sqlite3_test_control(testctrl, p->db,
10279 azArg[2],
10280 integerValue(azArg[3]),
10281 integerValue(azArg[4]));
drhef302e82017-11-15 19:14:08 +000010282 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010283 }
10284 break;
drh0d9de992017-12-26 18:04:23 +000010285
drh37ccfcf2020-08-31 18:49:04 +000010286 case SQLITE_TESTCTRL_SEEK_COUNT: {
10287 u64 x = 0;
10288 rc2 = sqlite3_test_control(testctrl, p->db, &x);
10289 utf8_printf(p->out, "%llu\n", x);
10290 isOk = 3;
10291 break;
10292 }
10293
drh0d9de992017-12-26 18:04:23 +000010294#ifdef YYCOVERAGE
drhf3c12562021-06-04 13:16:46 +000010295 case SQLITE_TESTCTRL_PARSER_COVERAGE: {
drh0d9de992017-12-26 18:04:23 +000010296 if( nArg==2 ){
10297 sqlite3_test_control(testctrl, p->out);
10298 isOk = 3;
10299 }
drhf3c12562021-06-04 13:16:46 +000010300 break;
10301 }
10302#endif
10303#ifdef SQLITE_DEBUG
10304 case SQLITE_TESTCTRL_TUNE: {
10305 if( nArg==4 ){
10306 int id = (int)integerValue(azArg[2]);
drh2d26cfc2021-06-04 13:40:26 +000010307 int val = (int)integerValue(azArg[3]);
10308 sqlite3_test_control(testctrl, id, &val);
10309 isOk = 3;
10310 }else if( nArg==3 ){
10311 int id = (int)integerValue(azArg[2]);
10312 sqlite3_test_control(testctrl, -id, &rc2);
10313 isOk = 1;
10314 }else if( nArg==2 ){
10315 int id = 1;
10316 while(1){
10317 int val = 0;
10318 rc2 = sqlite3_test_control(testctrl, -id, &val);
10319 if( rc2!=SQLITE_OK ) break;
10320 if( id>1 ) utf8_printf(p->out, " ");
10321 utf8_printf(p->out, "%d: %d", id, val);
10322 id++;
10323 }
10324 if( id>1 ) utf8_printf(p->out, "\n");
drhf3c12562021-06-04 13:16:46 +000010325 isOk = 3;
10326 }
10327 break;
10328 }
drh0d9de992017-12-26 18:04:23 +000010329#endif
dan779e9902021-07-28 18:13:28 +000010330 case SQLITE_TESTCTRL_SORTER_MMAP:
10331 if( nArg==3 ){
10332 int opt = (unsigned int)integerValue(azArg[2]);
10333 rc2 = sqlite3_test_control(testctrl, p->db, opt);
10334 isOk = 3;
10335 }
10336 break;
drh2ce15c32017-07-11 13:34:40 +000010337 }
10338 }
drhef302e82017-11-15 19:14:08 +000010339 if( isOk==0 && iCtrl>=0 ){
drhe2754c12019-08-26 12:50:01 +000010340 utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
drhef302e82017-11-15 19:14:08 +000010341 rc = 1;
10342 }else if( isOk==1 ){
10343 raw_printf(p->out, "%d\n", rc2);
10344 }else if( isOk==2 ){
10345 raw_printf(p->out, "0x%08x\n", rc2);
10346 }
drh2ce15c32017-07-11 13:34:40 +000010347 }else
10348#endif /* !defined(SQLITE_UNTESTABLE) */
10349
10350 if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
10351 open_db(p, 0);
10352 sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
10353 }else
10354
10355 if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
10356 if( nArg==2 ){
10357 enableTimer = booleanValue(azArg[1]);
10358 if( enableTimer && !HAS_TIMER ){
10359 raw_printf(stderr, "Error: timer not available on this system.\n");
10360 enableTimer = 0;
10361 }
10362 }else{
10363 raw_printf(stderr, "Usage: .timer on|off\n");
10364 rc = 1;
10365 }
10366 }else
10367
drh707821f2018-12-05 13:39:06 +000010368#ifndef SQLITE_OMIT_TRACE
drh2ce15c32017-07-11 13:34:40 +000010369 if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
drh707821f2018-12-05 13:39:06 +000010370 int mType = 0;
10371 int jj;
drh2ce15c32017-07-11 13:34:40 +000010372 open_db(p, 0);
drh707821f2018-12-05 13:39:06 +000010373 for(jj=1; jj<nArg; jj++){
10374 const char *z = azArg[jj];
10375 if( z[0]=='-' ){
10376 if( optionMatch(z, "expanded") ){
10377 p->eTraceType = SHELL_TRACE_EXPANDED;
10378 }
10379#ifdef SQLITE_ENABLE_NORMALIZE
10380 else if( optionMatch(z, "normalized") ){
10381 p->eTraceType = SHELL_TRACE_NORMALIZED;
10382 }
10383#endif
10384 else if( optionMatch(z, "plain") ){
10385 p->eTraceType = SHELL_TRACE_PLAIN;
10386 }
10387 else if( optionMatch(z, "profile") ){
10388 mType |= SQLITE_TRACE_PROFILE;
10389 }
10390 else if( optionMatch(z, "row") ){
10391 mType |= SQLITE_TRACE_ROW;
10392 }
10393 else if( optionMatch(z, "stmt") ){
10394 mType |= SQLITE_TRACE_STMT;
10395 }
10396 else if( optionMatch(z, "close") ){
10397 mType |= SQLITE_TRACE_CLOSE;
10398 }
10399 else {
10400 raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
10401 rc = 1;
10402 goto meta_command_exit;
10403 }
10404 }else{
10405 output_file_close(p->traceOut);
10406 p->traceOut = output_file_open(azArg[1], 0);
10407 }
drh2ce15c32017-07-11 13:34:40 +000010408 }
drh2ce15c32017-07-11 13:34:40 +000010409 if( p->traceOut==0 ){
10410 sqlite3_trace_v2(p->db, 0, 0, 0);
10411 }else{
drh707821f2018-12-05 13:39:06 +000010412 if( mType==0 ) mType = SQLITE_TRACE_STMT;
10413 sqlite3_trace_v2(p->db, mType, sql_trace_callback, p);
drh2ce15c32017-07-11 13:34:40 +000010414 }
drh2ce15c32017-07-11 13:34:40 +000010415 }else
drh707821f2018-12-05 13:39:06 +000010416#endif /* !defined(SQLITE_OMIT_TRACE) */
drh2ce15c32017-07-11 13:34:40 +000010417
drhe2b7a762019-10-02 00:25:08 +000010418#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhcc5979d2019-08-16 22:58:29 +000010419 if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){
10420 int ii;
drh8c754a32019-08-19 20:35:30 +000010421 int lenOpt;
drh5df84282019-08-17 19:45:25 +000010422 char *zOpt;
drhcc5979d2019-08-16 22:58:29 +000010423 if( nArg<2 ){
drh5df84282019-08-17 19:45:25 +000010424 raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
drhcc5979d2019-08-16 22:58:29 +000010425 rc = 1;
10426 goto meta_command_exit;
10427 }
10428 open_db(p, 0);
drh5df84282019-08-17 19:45:25 +000010429 zOpt = azArg[1];
10430 if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
drh8c754a32019-08-19 20:35:30 +000010431 lenOpt = (int)strlen(zOpt);
10432 if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){
drh5df84282019-08-17 19:45:25 +000010433 assert( azArg[nArg]==0 );
drh8c754a32019-08-19 20:35:30 +000010434 sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0);
drh5df84282019-08-17 19:45:25 +000010435 }else{
10436 for(ii=1; ii<nArg; ii++){
10437 sqlite3_create_module(p->db, azArg[ii], 0, 0);
10438 }
drhcc5979d2019-08-16 22:58:29 +000010439 }
10440 }else
10441#endif
10442
drh2ce15c32017-07-11 13:34:40 +000010443#if SQLITE_USER_AUTHENTICATION
10444 if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
10445 if( nArg<2 ){
10446 raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
10447 rc = 1;
10448 goto meta_command_exit;
10449 }
10450 open_db(p, 0);
10451 if( strcmp(azArg[1],"login")==0 ){
10452 if( nArg!=4 ){
10453 raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
10454 rc = 1;
10455 goto meta_command_exit;
10456 }
drhe2754c12019-08-26 12:50:01 +000010457 rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
10458 strlen30(azArg[3]));
drh2ce15c32017-07-11 13:34:40 +000010459 if( rc ){
10460 utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
10461 rc = 1;
10462 }
10463 }else if( strcmp(azArg[1],"add")==0 ){
10464 if( nArg!=5 ){
10465 raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
10466 rc = 1;
10467 goto meta_command_exit;
10468 }
drhaf2770f2018-01-05 14:55:43 +000010469 rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000010470 booleanValue(azArg[4]));
10471 if( rc ){
10472 raw_printf(stderr, "User-Add failed: %d\n", rc);
10473 rc = 1;
10474 }
10475 }else if( strcmp(azArg[1],"edit")==0 ){
10476 if( nArg!=5 ){
10477 raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
10478 rc = 1;
10479 goto meta_command_exit;
10480 }
drhaf2770f2018-01-05 14:55:43 +000010481 rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000010482 booleanValue(azArg[4]));
10483 if( rc ){
10484 raw_printf(stderr, "User-Edit failed: %d\n", rc);
10485 rc = 1;
10486 }
10487 }else if( strcmp(azArg[1],"delete")==0 ){
10488 if( nArg!=3 ){
10489 raw_printf(stderr, "Usage: .user delete USER\n");
10490 rc = 1;
10491 goto meta_command_exit;
10492 }
10493 rc = sqlite3_user_delete(p->db, azArg[2]);
10494 if( rc ){
10495 raw_printf(stderr, "User-Delete failed: %d\n", rc);
10496 rc = 1;
10497 }
10498 }else{
10499 raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
10500 rc = 1;
10501 goto meta_command_exit;
10502 }
10503 }else
10504#endif /* SQLITE_USER_AUTHENTICATION */
10505
10506 if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
10507 utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
10508 sqlite3_libversion(), sqlite3_sourceid());
drh0ed2fd82018-01-16 20:05:27 +000010509#if SQLITE_HAVE_ZLIB
10510 utf8_printf(p->out, "zlib version %s\n", zlibVersion());
10511#endif
10512#define CTIMEOPT_VAL_(opt) #opt
10513#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
10514#if defined(__clang__) && defined(__clang_major__)
10515 utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
10516 CTIMEOPT_VAL(__clang_minor__) "."
10517 CTIMEOPT_VAL(__clang_patchlevel__) "\n");
10518#elif defined(_MSC_VER)
10519 utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n");
10520#elif defined(__GNUC__) && defined(__VERSION__)
10521 utf8_printf(p->out, "gcc-" __VERSION__ "\n");
10522#endif
drh2ce15c32017-07-11 13:34:40 +000010523 }else
10524
10525 if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
10526 const char *zDbName = nArg==2 ? azArg[1] : "main";
10527 sqlite3_vfs *pVfs = 0;
10528 if( p->db ){
10529 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
10530 if( pVfs ){
10531 utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
10532 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
10533 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
10534 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
10535 }
10536 }
10537 }else
10538
10539 if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){
10540 sqlite3_vfs *pVfs;
10541 sqlite3_vfs *pCurrent = 0;
10542 if( p->db ){
10543 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
10544 }
10545 for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
10546 utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName,
10547 pVfs==pCurrent ? " <--- CURRENT" : "");
10548 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
10549 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
10550 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
10551 if( pVfs->pNext ){
10552 raw_printf(p->out, "-----------------------------------\n");
10553 }
10554 }
10555 }else
10556
10557 if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
10558 const char *zDbName = nArg==2 ? azArg[1] : "main";
10559 char *zVfsName = 0;
10560 if( p->db ){
10561 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
10562 if( zVfsName ){
10563 utf8_printf(p->out, "%s\n", zVfsName);
10564 sqlite3_free(zVfsName);
10565 }
10566 }
10567 }else
10568
drh2ce15c32017-07-11 13:34:40 +000010569 if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
drhc0622a42020-12-04 01:17:57 +000010570 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
10571 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x);
drh2ce15c32017-07-11 13:34:40 +000010572 }else
drh2ce15c32017-07-11 13:34:40 +000010573
10574 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
10575 int j;
10576 assert( nArg<=ArraySize(azArg) );
drh0285d982020-05-29 14:38:43 +000010577 p->nWidth = nArg-1;
10578 p->colWidth = realloc(p->colWidth, p->nWidth*sizeof(int)*2);
10579 if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory();
10580 if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
10581 for(j=1; j<nArg; j++){
drh2ce15c32017-07-11 13:34:40 +000010582 p->colWidth[j-1] = (int)integerValue(azArg[j]);
10583 }
10584 }else
10585
10586 {
10587 utf8_printf(stderr, "Error: unknown command or invalid arguments: "
10588 " \"%s\". Enter \".help\" for help\n", azArg[0]);
10589 rc = 1;
10590 }
10591
10592meta_command_exit:
10593 if( p->outCount ){
10594 p->outCount--;
10595 if( p->outCount==0 ) output_reset(p);
10596 }
drhb97e2ad2021-08-26 18:31:39 +000010597 p->bSafeMode = p->bSafeModePersist;
drh2ce15c32017-07-11 13:34:40 +000010598 return rc;
10599}
10600
larrybr8bc4cbc2021-09-10 00:58:46 +000010601/* Line scan result and intermediate states (supporting scan resumption)
drh2ce15c32017-07-11 13:34:40 +000010602*/
larrybr8bc4cbc2021-09-10 00:58:46 +000010603typedef enum {
10604 QSS_InPlain = 0, QSS_InString, QSS_InDquote,
10605 QSS_InBlockComment, QSS_EndingSemi,
10606 QSS_NoDark = 0, QSS_HasDark = 1<<3,
10607 QSS_ScanMask = 0x7, QSS_DarkMask = 1<<3
10608} QuickScanState;
10609#define QSS_STATE(qss) ((qss) & QSS_ScanMask)
10610#define QSS_SETV(qss, newst) (newst | ((qss) & QSS_DarkMask))
10611#define QSS_PLAINWHITE(qss) ((qss)==QSS_NoDark)
10612#define QSS_PLAINDARK(qss) ((qss)==QSS_HasDark)
drh2ce15c32017-07-11 13:34:40 +000010613
10614/*
larrybr8bc4cbc2021-09-10 00:58:46 +000010615** Scan line for classification to guide shell's handling.
10616** The scan is resumable for subsequent lines when prior
10617** return values are passed as the 2nd argument.
drh2ce15c32017-07-11 13:34:40 +000010618*/
larrybr8bc4cbc2021-09-10 00:58:46 +000010619static QuickScanState quickscan(char *zLine, QuickScanState qss){
10620 char cin;
10621 switch( QSS_STATE(qss) ){
10622 case QSS_InPlain:
10623 InPlainSet:
10624 qss = QSS_SETV(qss, QSS_InPlain);
10625 InPlain:
10626 while (cin = *zLine++){
10627 if( IsSpace(cin) )
10628 continue;
10629 switch (cin){
10630 case '-':
10631 if( *zLine=='-' ){
10632 while(*++zLine!=0)
10633 ;
10634 return qss;
10635 }
10636 break;
10637 case ';':
10638 qss = QSS_SETV(qss, QSS_EndingSemi);
10639 goto EndingSemi;
10640 case '/':
10641 if( *zLine=='*' ){
10642 ++zLine;
10643 qss = QSS_SETV(qss, QSS_InBlockComment);
10644 goto InBlockComment;
10645 }
10646 break;
10647 case '\'':
10648 qss = QSS_SETV(qss, QSS_InString);
10649 goto InString;
10650 case '"':
10651 qss = QSS_SETV(qss, QSS_InDquote);
10652 goto InDquote;
10653 default:
10654 break;
10655 }
10656 qss |= QSS_HasDark;
drh2ce15c32017-07-11 13:34:40 +000010657 }
larrybr8bc4cbc2021-09-10 00:58:46 +000010658 break;
10659 case QSS_InString:
10660 InString:
10661 while (cin = *zLine++){
10662 if( cin=='\'' ){
10663 if( *zLine!='\'' ){
10664 goto InPlainSet;
10665 }else{
10666 ++zLine;
10667 }
10668 }
drh2ce15c32017-07-11 13:34:40 +000010669 }
larrybr8bc4cbc2021-09-10 00:58:46 +000010670 break;
10671 case QSS_InDquote:
10672 InDquote:
10673 while (cin = *zLine++){
10674 if( cin=='"' ){
10675 if( *zLine!='"' ){
10676 goto InPlainSet;
10677 }else{
10678 ++zLine;
10679 }
10680 }
10681 }
10682 break;
10683 case QSS_InBlockComment:
10684 InBlockComment:
10685 while (cin = *zLine++){
10686 if( cin=='*' && *zLine=='/' ){
10687 ++zLine;
10688 goto InPlainSet;
10689 }
10690 }
10691 break;
10692 case QSS_EndingSemi:
10693 EndingSemi:
10694 while (cin = *zLine++){
10695 if( !IsSpace(cin) && cin!=';' ){
10696 --zLine;
10697 goto InPlain;
10698 }
10699 }
10700 break;
10701 default: assert(0);
drh2ce15c32017-07-11 13:34:40 +000010702 }
larrybr8bc4cbc2021-09-10 00:58:46 +000010703 return qss;
drh2ce15c32017-07-11 13:34:40 +000010704}
10705
10706/*
10707** Return TRUE if the line typed in is an SQL command terminator other
10708** than a semi-colon. The SQL Server style "go" command is understood
10709** as is the Oracle "/".
10710*/
larrybr8bc4cbc2021-09-10 00:58:46 +000010711static int line_is_command_terminator(char *zLine){
drh2ce15c32017-07-11 13:34:40 +000010712 while( IsSpace(zLine[0]) ){ zLine++; };
larrybr8bc4cbc2021-09-10 00:58:46 +000010713 if( zLine[0]=='/' )
10714 zLine += 1; /* Oracle */
10715 else if ( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o' )
10716 zLine += 2; /* SQL Server */
10717 else
10718 return 0;
10719 return quickscan(zLine,QSS_NoDark)==QSS_NoDark;
drh2ce15c32017-07-11 13:34:40 +000010720}
10721
10722/*
drh56f17742018-01-24 01:58:49 +000010723** We need a default sqlite3_complete() implementation to use in case
10724** the shell is compiled with SQLITE_OMIT_COMPLETE. The default assumes
10725** any arbitrary text is a complete SQL statement. This is not very
10726** user-friendly, but it does seem to work.
10727*/
10728#ifdef SQLITE_OMIT_COMPLETE
danc86b23b2018-11-16 14:36:42 +000010729#define sqlite3_complete(x) 1
drh56f17742018-01-24 01:58:49 +000010730#endif
10731
10732/*
drh2ce15c32017-07-11 13:34:40 +000010733** Return true if zSql is a complete SQL statement. Return false if it
10734** ends in the middle of a string literal or C-style comment.
10735*/
10736static int line_is_complete(char *zSql, int nSql){
10737 int rc;
10738 if( zSql==0 ) return 1;
10739 zSql[nSql] = ';';
10740 zSql[nSql+1] = 0;
10741 rc = sqlite3_complete(zSql);
10742 zSql[nSql] = 0;
10743 return rc;
10744}
10745
10746/*
drhfc29a862018-05-11 19:11:18 +000010747** Run a single line of SQL. Return the number of errors.
drh2ce15c32017-07-11 13:34:40 +000010748*/
10749static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
10750 int rc;
10751 char *zErrMsg = 0;
10752
10753 open_db(p, 0);
10754 if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
drhfc4eeef2019-02-05 19:48:46 +000010755 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
drh2ce15c32017-07-11 13:34:40 +000010756 BEGIN_TIMER;
drha10b9992018-03-09 15:24:33 +000010757 rc = shell_exec(p, zSql, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000010758 END_TIMER;
10759 if( rc || zErrMsg ){
10760 char zPrefix[100];
10761 if( in!=0 || !stdin_is_interactive ){
10762 sqlite3_snprintf(sizeof(zPrefix), zPrefix,
10763 "Error: near line %d:", startline);
10764 }else{
10765 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
10766 }
10767 if( zErrMsg!=0 ){
10768 utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
10769 sqlite3_free(zErrMsg);
10770 zErrMsg = 0;
10771 }else{
10772 utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
10773 }
10774 return 1;
10775 }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
larrybr10496f72021-06-23 16:07:20 +000010776 raw_printf(p->out, "changes: %3lld total_changes: %lld\n",
10777 sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
drh2ce15c32017-07-11 13:34:40 +000010778 }
10779 return 0;
10780}
10781
10782
10783/*
10784** Read input from *in and process it. If *in==0 then input
10785** is interactive - the user is typing it it. Otherwise, input
10786** is coming from a file or device. A prompt is issued and history
10787** is saved only if input is interactive. An interrupt signal will
10788** cause this routine to exit immediately, unless input is interactive.
10789**
10790** Return the number of errors.
10791*/
drh60379d42018-12-13 18:30:01 +000010792static int process_input(ShellState *p){
drh2ce15c32017-07-11 13:34:40 +000010793 char *zLine = 0; /* A single input line */
10794 char *zSql = 0; /* Accumulated SQL text */
10795 int nLine; /* Length of current line */
10796 int nSql = 0; /* Bytes of zSql[] used */
10797 int nAlloc = 0; /* Allocated zSql[] space */
10798 int nSqlPrior = 0; /* Bytes of zSql[] used by prior line */
10799 int rc; /* Error code */
10800 int errCnt = 0; /* Number of errors seen */
drh2ce15c32017-07-11 13:34:40 +000010801 int startline = 0; /* Line number for start of current input */
larrybr8bc4cbc2021-09-10 00:58:46 +000010802 QuickScanState qss = QSS_InPlain; /* Accumulated line status (so far) */
drh2ce15c32017-07-11 13:34:40 +000010803
drh2c8ee022018-12-13 18:59:30 +000010804 p->lineno = 0;
drh60379d42018-12-13 18:30:01 +000010805 while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
drh2ce15c32017-07-11 13:34:40 +000010806 fflush(p->out);
drh60379d42018-12-13 18:30:01 +000010807 zLine = one_input_line(p->in, zLine, nSql>0);
drh2ce15c32017-07-11 13:34:40 +000010808 if( zLine==0 ){
10809 /* End of input */
drh60379d42018-12-13 18:30:01 +000010810 if( p->in==0 && stdin_is_interactive ) printf("\n");
drh2ce15c32017-07-11 13:34:40 +000010811 break;
10812 }
10813 if( seenInterrupt ){
drh60379d42018-12-13 18:30:01 +000010814 if( p->in!=0 ) break;
drh2ce15c32017-07-11 13:34:40 +000010815 seenInterrupt = 0;
10816 }
drh2c8ee022018-12-13 18:59:30 +000010817 p->lineno++;
larrybr8bc4cbc2021-09-10 00:58:46 +000010818 if( QSS_STATE(qss)==QSS_InPlain
10819 && line_is_command_terminator(zLine)
10820 && line_is_complete(zSql, nSql) ){
10821 memcpy(zLine,";",2);
10822 }
10823 qss = quickscan(zLine, qss);
10824 if( QSS_PLAINWHITE(qss) && nSql==0 ){
10825 if( ShellHasFlag(p, SHFLG_Echo) )
10826 printf("%s\n", zLine);
10827 /* Just swallow leading whitespace */
10828 continue;
drh2ce15c32017-07-11 13:34:40 +000010829 }
drh1615c372018-05-12 23:56:22 +000010830 if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
drh2ce15c32017-07-11 13:34:40 +000010831 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
drh1615c372018-05-12 23:56:22 +000010832 if( zLine[0]=='.' ){
10833 rc = do_meta_command(zLine, p);
10834 if( rc==2 ){ /* exit requested */
10835 break;
10836 }else if( rc ){
10837 errCnt++;
10838 }
drh2ce15c32017-07-11 13:34:40 +000010839 }
10840 continue;
10841 }
drh2ce15c32017-07-11 13:34:40 +000010842 nLine = strlen30(zLine);
10843 if( nSql+nLine+2>=nAlloc ){
larrybr31bffb42021-09-08 21:49:03 +000010844 /* Grow buffer by half-again increments when big. */
10845 nAlloc = nSql+(nSql>>1)+nLine+100;
drh2ce15c32017-07-11 13:34:40 +000010846 zSql = realloc(zSql, nAlloc);
drh4b5345c2018-04-24 13:07:40 +000010847 if( zSql==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +000010848 }
10849 nSqlPrior = nSql;
10850 if( nSql==0 ){
10851 int i;
10852 for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
10853 assert( nAlloc>0 && zSql!=0 );
10854 memcpy(zSql, zLine+i, nLine+1-i);
drh2c8ee022018-12-13 18:59:30 +000010855 startline = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000010856 nSql = nLine-i;
10857 }else{
10858 zSql[nSql++] = '\n';
10859 memcpy(zSql+nSql, zLine, nLine+1);
10860 nSql += nLine;
10861 }
larrybr8bc4cbc2021-09-10 00:58:46 +000010862 if( nSql && QSS_STATE(qss)==QSS_EndingSemi && sqlite3_complete(zSql) ){
drh60379d42018-12-13 18:30:01 +000010863 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000010864 nSql = 0;
10865 if( p->outCount ){
10866 output_reset(p);
10867 p->outCount = 0;
drh13c20932018-01-10 21:41:55 +000010868 }else{
10869 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +000010870 }
drhb97e2ad2021-08-26 18:31:39 +000010871 p->bSafeMode = p->bSafeModePersist;
larrybr8bc4cbc2021-09-10 00:58:46 +000010872 }else if( nSql && QSS_PLAINWHITE(qss) ){
drh2ce15c32017-07-11 13:34:40 +000010873 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
10874 nSql = 0;
10875 }
10876 }
larrybr8bc4cbc2021-09-10 00:58:46 +000010877 if( nSql && QSS_PLAINDARK(qss) ){
drh60379d42018-12-13 18:30:01 +000010878 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000010879 }
10880 free(zSql);
10881 free(zLine);
10882 return errCnt>0;
10883}
10884
10885/*
10886** Return a pathname which is the user's home directory. A
10887** 0 return indicates an error of some kind.
10888*/
10889static char *find_home_dir(int clearFlag){
10890 static char *home_dir = NULL;
10891 if( clearFlag ){
10892 free(home_dir);
10893 home_dir = 0;
10894 return 0;
10895 }
10896 if( home_dir ) return home_dir;
10897
10898#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
10899 && !defined(__RTP__) && !defined(_WRS_KERNEL)
10900 {
10901 struct passwd *pwent;
10902 uid_t uid = getuid();
10903 if( (pwent=getpwuid(uid)) != NULL) {
10904 home_dir = pwent->pw_dir;
10905 }
10906 }
10907#endif
10908
10909#if defined(_WIN32_WCE)
10910 /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
10911 */
10912 home_dir = "/";
10913#else
10914
10915#if defined(_WIN32) || defined(WIN32)
10916 if (!home_dir) {
10917 home_dir = getenv("USERPROFILE");
10918 }
10919#endif
10920
10921 if (!home_dir) {
10922 home_dir = getenv("HOME");
10923 }
10924
10925#if defined(_WIN32) || defined(WIN32)
10926 if (!home_dir) {
10927 char *zDrive, *zPath;
10928 int n;
10929 zDrive = getenv("HOMEDRIVE");
10930 zPath = getenv("HOMEPATH");
10931 if( zDrive && zPath ){
10932 n = strlen30(zDrive) + strlen30(zPath) + 1;
10933 home_dir = malloc( n );
10934 if( home_dir==0 ) return 0;
10935 sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
10936 return home_dir;
10937 }
10938 home_dir = "c:\\";
10939 }
10940#endif
10941
10942#endif /* !_WIN32_WCE */
10943
10944 if( home_dir ){
10945 int n = strlen30(home_dir) + 1;
10946 char *z = malloc( n );
10947 if( z ) memcpy(z, home_dir, n);
10948 home_dir = z;
10949 }
10950
10951 return home_dir;
10952}
10953
10954/*
10955** Read input from the file given by sqliterc_override. Or if that
10956** parameter is NULL, take input from ~/.sqliterc
10957**
10958** Returns the number of errors.
10959*/
10960static void process_sqliterc(
10961 ShellState *p, /* Configuration data */
10962 const char *sqliterc_override /* Name of config file. NULL to use default */
10963){
10964 char *home_dir = NULL;
10965 const char *sqliterc = sqliterc_override;
10966 char *zBuf = 0;
drh60379d42018-12-13 18:30:01 +000010967 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +000010968 int savedLineno = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000010969
10970 if (sqliterc == NULL) {
10971 home_dir = find_home_dir(0);
10972 if( home_dir==0 ){
10973 raw_printf(stderr, "-- warning: cannot find home directory;"
10974 " cannot read ~/.sqliterc\n");
10975 return;
10976 }
drh2ce15c32017-07-11 13:34:40 +000010977 zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
10978 sqliterc = zBuf;
10979 }
drh60379d42018-12-13 18:30:01 +000010980 p->in = fopen(sqliterc,"rb");
10981 if( p->in ){
drh2ce15c32017-07-11 13:34:40 +000010982 if( stdin_is_interactive ){
10983 utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
10984 }
drhb7c46aa2020-11-25 13:59:47 +000010985 if( process_input(p) && bail_on_error ) exit(1);
drh60379d42018-12-13 18:30:01 +000010986 fclose(p->in);
drhb7c46aa2020-11-25 13:59:47 +000010987 }else if( sqliterc_override!=0 ){
10988 utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
10989 if( bail_on_error ) exit(1);
drh2ce15c32017-07-11 13:34:40 +000010990 }
drh60379d42018-12-13 18:30:01 +000010991 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +000010992 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +000010993 sqlite3_free(zBuf);
10994}
10995
10996/*
10997** Show available command line options
10998*/
10999static const char zOptions[] =
drhda57d962018-03-05 19:34:05 +000011000#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhad7fd5d2018-03-05 20:21:50 +000011001 " -A ARGS... run \".archive ARGS\" and exit\n"
drhda57d962018-03-05 19:34:05 +000011002#endif
drh3baed312018-03-08 18:14:41 +000011003 " -append append the database to the end of the file\n"
drh2ce15c32017-07-11 13:34:40 +000011004 " -ascii set output mode to 'ascii'\n"
11005 " -bail stop after hitting an error\n"
11006 " -batch force batch I/O\n"
drh0908e382020-06-04 18:05:39 +000011007 " -box set output mode to 'box'\n"
drh2ce15c32017-07-11 13:34:40 +000011008 " -column set output mode to 'column'\n"
11009 " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
11010 " -csv set output mode to 'csv'\n"
drh8d889af2021-05-08 17:18:23 +000011011#if !defined(SQLITE_OMIT_DESERIALIZE)
drh6ca64482019-01-22 16:06:20 +000011012 " -deserialize open the database using sqlite3_deserialize()\n"
11013#endif
drh2ce15c32017-07-11 13:34:40 +000011014 " -echo print commands before execution\n"
11015 " -init FILENAME read/process named file\n"
11016 " -[no]header turn headers on or off\n"
11017#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
11018 " -heap SIZE Size of heap for memsys3 or memsys5\n"
11019#endif
11020 " -help show this message\n"
11021 " -html set output mode to HTML\n"
11022 " -interactive force interactive I/O\n"
drh30c54a02020-05-28 23:49:50 +000011023 " -json set output mode to 'json'\n"
drh2ce15c32017-07-11 13:34:40 +000011024 " -line set output mode to 'line'\n"
11025 " -list set output mode to 'list'\n"
11026 " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
drh30c54a02020-05-28 23:49:50 +000011027 " -markdown set output mode to 'markdown'\n"
drh8d889af2021-05-08 17:18:23 +000011028#if !defined(SQLITE_OMIT_DESERIALIZE)
drh6ca64482019-01-22 16:06:20 +000011029 " -maxsize N maximum size for a --deserialize database\n"
11030#endif
drhaf482572019-02-04 19:52:39 +000011031 " -memtrace trace all memory allocations and deallocations\n"
drh2ce15c32017-07-11 13:34:40 +000011032 " -mmap N default mmap size set to N\n"
11033#ifdef SQLITE_ENABLE_MULTIPLEX
11034 " -multiplex enable the multiplexor VFS\n"
11035#endif
11036 " -newline SEP set output row separator. Default: '\\n'\n"
drh0933aad2019-11-18 17:46:38 +000011037 " -nofollow refuse to open symbolic links to database files\n"
drhb97e2ad2021-08-26 18:31:39 +000011038 " -nonce STRING set the safe-mode escape nonce\n"
drh2ce15c32017-07-11 13:34:40 +000011039 " -nullvalue TEXT set text string for NULL values. Default ''\n"
11040 " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
11041 " -quote set output mode to 'quote'\n"
drhee269a62018-02-14 23:27:43 +000011042 " -readonly open the database read-only\n"
drhb97e2ad2021-08-26 18:31:39 +000011043 " -safe enable safe-mode\n"
drh2ce15c32017-07-11 13:34:40 +000011044 " -separator SEP set output column separator. Default: '|'\n"
drha90d84f2018-04-18 15:21:13 +000011045#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11046 " -sorterref SIZE sorter references threshold size\n"
11047#endif
drh2ce15c32017-07-11 13:34:40 +000011048 " -stats print memory stats before each finalize\n"
drh30c54a02020-05-28 23:49:50 +000011049 " -table set output mode to 'table'\n"
drh2fa78182020-10-31 18:58:37 +000011050 " -tabs set output mode to 'tabs'\n"
drh2ce15c32017-07-11 13:34:40 +000011051 " -version show SQLite version\n"
11052 " -vfs NAME use NAME as the default VFS\n"
11053#ifdef SQLITE_ENABLE_VFSTRACE
11054 " -vfstrace enable tracing of all VFS calls\n"
11055#endif
drh3baed312018-03-08 18:14:41 +000011056#ifdef SQLITE_HAVE_ZLIB
11057 " -zip open the file as a ZIP Archive\n"
11058#endif
drh2ce15c32017-07-11 13:34:40 +000011059;
11060static void usage(int showDetail){
11061 utf8_printf(stderr,
11062 "Usage: %s [OPTIONS] FILENAME [SQL]\n"
11063 "FILENAME is the name of an SQLite database. A new database is created\n"
11064 "if the file does not previously exist.\n", Argv0);
11065 if( showDetail ){
11066 utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
11067 }else{
11068 raw_printf(stderr, "Use the -help option for additional information\n");
11069 }
11070 exit(1);
11071}
11072
11073/*
drhe7df8922018-04-18 10:44:58 +000011074** Internal check: Verify that the SQLite is uninitialized. Print a
11075** error message if it is initialized.
11076*/
11077static void verify_uninitialized(void){
11078 if( sqlite3_config(-1)==SQLITE_MISUSE ){
drh8e02a182018-05-30 07:24:41 +000011079 utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
drhe7df8922018-04-18 10:44:58 +000011080 " initialization.\n");
11081 }
11082}
11083
11084/*
drh2ce15c32017-07-11 13:34:40 +000011085** Initialize the state information in data
11086*/
11087static void main_init(ShellState *data) {
11088 memset(data, 0, sizeof(*data));
11089 data->normalMode = data->cMode = data->mode = MODE_List;
11090 data->autoExplain = 1;
drh37407122021-07-23 18:43:58 +000011091 data->pAuxDb = &data->aAuxDb[0];
drh2ce15c32017-07-11 13:34:40 +000011092 memcpy(data->colSeparator,SEP_Column, 2);
11093 memcpy(data->rowSeparator,SEP_Row, 2);
11094 data->showHeader = 0;
11095 data->shellFlgs = SHFLG_Lookaside;
drhe7df8922018-04-18 10:44:58 +000011096 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000011097 sqlite3_config(SQLITE_CONFIG_URI, 1);
11098 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
11099 sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
11100 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
11101 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
11102}
11103
11104/*
11105** Output text to the console in a font that attracts extra attention.
11106*/
11107#ifdef _WIN32
11108static void printBold(const char *zText){
mistachkin43e86272020-04-09 15:31:22 +000011109#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000011110 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
11111 CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
11112 GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
11113 SetConsoleTextAttribute(out,
11114 FOREGROUND_RED|FOREGROUND_INTENSITY
11115 );
mistachkin43e86272020-04-09 15:31:22 +000011116#endif
drh2ce15c32017-07-11 13:34:40 +000011117 printf("%s", zText);
mistachkin43e86272020-04-09 15:31:22 +000011118#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000011119 SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
mistachkin43e86272020-04-09 15:31:22 +000011120#endif
drh2ce15c32017-07-11 13:34:40 +000011121}
11122#else
11123static void printBold(const char *zText){
11124 printf("\033[1m%s\033[0m", zText);
11125}
11126#endif
11127
11128/*
11129** Get the argument to an --option. Throw an error and die if no argument
11130** is available.
11131*/
11132static char *cmdline_option_value(int argc, char **argv, int i){
11133 if( i==argc ){
11134 utf8_printf(stderr, "%s: Error: missing argument to %s\n",
11135 argv[0], argv[argc-1]);
11136 exit(1);
11137 }
11138 return argv[i];
11139}
11140
11141#ifndef SQLITE_SHELL_IS_UTF8
dan39b6bd52021-03-04 18:31:07 +000011142# if (defined(_WIN32) || defined(WIN32)) \
11143 && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
drh2ce15c32017-07-11 13:34:40 +000011144# define SQLITE_SHELL_IS_UTF8 (0)
11145# else
11146# define SQLITE_SHELL_IS_UTF8 (1)
11147# endif
11148#endif
11149
11150#if SQLITE_SHELL_IS_UTF8
11151int SQLITE_CDECL main(int argc, char **argv){
11152#else
11153int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
11154 char **argv;
11155#endif
11156 char *zErrMsg = 0;
11157 ShellState data;
11158 const char *zInitFile = 0;
11159 int i;
11160 int rc = 0;
11161 int warnInmemoryDb = 0;
11162 int readStdin = 1;
11163 int nCmd = 0;
11164 char **azCmd = 0;
dan16a47422018-04-18 09:16:11 +000011165 const char *zVfs = 0; /* Value of -vfs command-line option */
drh1f22f622018-05-17 13:29:14 +000011166#if !SQLITE_SHELL_IS_UTF8
11167 char **argvToFree = 0;
11168 int argcToFree = 0;
11169#endif
drh2ce15c32017-07-11 13:34:40 +000011170
11171 setBinaryMode(stdin, 0);
11172 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
11173 stdin_is_interactive = isatty(0);
11174 stdout_is_console = isatty(1);
11175
drh4a3a3eb2020-02-29 15:53:48 +000011176#ifdef SQLITE_DEBUG
11177 registerOomSimulator();
11178#endif
11179
mistachkin1e8487d2018-07-22 06:25:35 +000011180#if !defined(_WIN32_WCE)
11181 if( getenv("SQLITE_DEBUG_BREAK") ){
11182 if( isatty(0) && isatty(2) ){
11183 fprintf(stderr,
11184 "attach debugger to process %d and press any key to continue.\n",
11185 GETPID());
11186 fgetc(stdin);
11187 }else{
11188#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +000011189#if SQLITE_OS_WINRT
11190 __debugbreak();
11191#else
mistachkin1e8487d2018-07-22 06:25:35 +000011192 DebugBreak();
mistachkin43e86272020-04-09 15:31:22 +000011193#endif
mistachkin1e8487d2018-07-22 06:25:35 +000011194#elif defined(SIGTRAP)
11195 raise(SIGTRAP);
11196#endif
11197 }
11198 }
11199#endif
11200
drh2ce15c32017-07-11 13:34:40 +000011201#if USE_SYSTEM_SQLITE+0!=1
drhb3c45232017-08-28 14:33:27 +000011202 if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
drh2ce15c32017-07-11 13:34:40 +000011203 utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
11204 sqlite3_sourceid(), SQLITE_SOURCE_ID);
11205 exit(1);
11206 }
11207#endif
11208 main_init(&data);
drh501ea052018-02-15 01:03:37 +000011209
11210 /* On Windows, we must translate command-line arguments into UTF-8.
11211 ** The SQLite memory allocator subsystem has to be enabled in order to
11212 ** do this. But we want to run an sqlite3_shutdown() afterwards so that
11213 ** subsequent sqlite3_config() calls will work. So copy all results into
11214 ** memory that does not come from the SQLite memory allocator.
11215 */
drh4b18c1d2018-02-04 20:33:13 +000011216#if !SQLITE_SHELL_IS_UTF8
drh501ea052018-02-15 01:03:37 +000011217 sqlite3_initialize();
drh1f22f622018-05-17 13:29:14 +000011218 argvToFree = malloc(sizeof(argv[0])*argc*2);
11219 argcToFree = argc;
11220 argv = argvToFree + argc;
drh4b5345c2018-04-24 13:07:40 +000011221 if( argv==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +000011222 for(i=0; i<argc; i++){
drh501ea052018-02-15 01:03:37 +000011223 char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
11224 int n;
drh4b5345c2018-04-24 13:07:40 +000011225 if( z==0 ) shell_out_of_memory();
drh501ea052018-02-15 01:03:37 +000011226 n = (int)strlen(z);
11227 argv[i] = malloc( n+1 );
drh4b5345c2018-04-24 13:07:40 +000011228 if( argv[i]==0 ) shell_out_of_memory();
drh501ea052018-02-15 01:03:37 +000011229 memcpy(argv[i], z, n+1);
drh1f22f622018-05-17 13:29:14 +000011230 argvToFree[i] = argv[i];
drh501ea052018-02-15 01:03:37 +000011231 sqlite3_free(z);
drh2ce15c32017-07-11 13:34:40 +000011232 }
drh501ea052018-02-15 01:03:37 +000011233 sqlite3_shutdown();
drh2ce15c32017-07-11 13:34:40 +000011234#endif
drh501ea052018-02-15 01:03:37 +000011235
drh2ce15c32017-07-11 13:34:40 +000011236 assert( argc>=1 && argv && argv[0] );
11237 Argv0 = argv[0];
11238
11239 /* Make sure we have a valid signal handler early, before anything
11240 ** else is done.
11241 */
11242#ifdef SIGINT
11243 signal(SIGINT, interrupt_handler);
mistachkinb4bab902017-10-27 17:09:44 +000011244#elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
11245 SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
drh2ce15c32017-07-11 13:34:40 +000011246#endif
11247
11248#ifdef SQLITE_SHELL_DBNAME_PROC
11249 {
11250 /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
11251 ** of a C-function that will provide the name of the database file. Use
11252 ** this compile-time option to embed this shell program in larger
11253 ** applications. */
11254 extern void SQLITE_SHELL_DBNAME_PROC(const char**);
drh37407122021-07-23 18:43:58 +000011255 SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename);
drh2ce15c32017-07-11 13:34:40 +000011256 warnInmemoryDb = 0;
11257 }
11258#endif
11259
11260 /* Do an initial pass through the command-line argument to locate
11261 ** the name of the database file, the name of the initialization file,
11262 ** the size of the alternative malloc heap,
11263 ** and the first command to execute.
11264 */
drhe7df8922018-04-18 10:44:58 +000011265 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000011266 for(i=1; i<argc; i++){
11267 char *z;
11268 z = argv[i];
11269 if( z[0]!='-' ){
drh37407122021-07-23 18:43:58 +000011270 if( data.aAuxDb->zDbFilename==0 ){
11271 data.aAuxDb->zDbFilename = z;
drh2ce15c32017-07-11 13:34:40 +000011272 }else{
11273 /* Excesss arguments are interpreted as SQL (or dot-commands) and
11274 ** mean that nothing is read from stdin */
11275 readStdin = 0;
11276 nCmd++;
11277 azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
drh4b5345c2018-04-24 13:07:40 +000011278 if( azCmd==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +000011279 azCmd[nCmd-1] = z;
11280 }
11281 }
11282 if( z[1]=='-' ) z++;
11283 if( strcmp(z,"-separator")==0
11284 || strcmp(z,"-nullvalue")==0
11285 || strcmp(z,"-newline")==0
11286 || strcmp(z,"-cmd")==0
11287 ){
11288 (void)cmdline_option_value(argc, argv, ++i);
11289 }else if( strcmp(z,"-init")==0 ){
11290 zInitFile = cmdline_option_value(argc, argv, ++i);
11291 }else if( strcmp(z,"-batch")==0 ){
11292 /* Need to check for batch mode here to so we can avoid printing
11293 ** informational messages (like from process_sqliterc) before
11294 ** we do the actual processing of arguments later in a second pass.
11295 */
11296 stdin_is_interactive = 0;
11297 }else if( strcmp(z,"-heap")==0 ){
11298#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
11299 const char *zSize;
11300 sqlite3_int64 szHeap;
11301
11302 zSize = cmdline_option_value(argc, argv, ++i);
11303 szHeap = integerValue(zSize);
11304 if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
11305 sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
11306#else
11307 (void)cmdline_option_value(argc, argv, ++i);
11308#endif
drh2ce15c32017-07-11 13:34:40 +000011309 }else if( strcmp(z,"-pagecache")==0 ){
drhf573b4f2020-09-28 13:34:05 +000011310 sqlite3_int64 n, sz;
11311 sz = integerValue(cmdline_option_value(argc,argv,++i));
drh2ce15c32017-07-11 13:34:40 +000011312 if( sz>70000 ) sz = 70000;
11313 if( sz<0 ) sz = 0;
drhf573b4f2020-09-28 13:34:05 +000011314 n = integerValue(cmdline_option_value(argc,argv,++i));
11315 if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
11316 n = 0xffffffffffffLL/sz;
11317 }
drh2ce15c32017-07-11 13:34:40 +000011318 sqlite3_config(SQLITE_CONFIG_PAGECACHE,
11319 (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
11320 data.shellFlgs |= SHFLG_Pagecache;
11321 }else if( strcmp(z,"-lookaside")==0 ){
11322 int n, sz;
11323 sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
11324 if( sz<0 ) sz = 0;
11325 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
11326 if( n<0 ) n = 0;
11327 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
11328 if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
drhaf6d1af2021-08-09 17:37:58 +000011329 }else if( strcmp(z,"-threadsafe")==0 ){
drh9d16fb12021-08-09 17:45:00 +000011330 int n;
11331 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
11332 switch( n ){
drhaf6d1af2021-08-09 17:37:58 +000011333 case 0: sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); break;
11334 case 2: sqlite3_config(SQLITE_CONFIG_MULTITHREAD); break;
11335 default: sqlite3_config(SQLITE_CONFIG_SERIALIZED); break;
11336 }
drh2ce15c32017-07-11 13:34:40 +000011337#ifdef SQLITE_ENABLE_VFSTRACE
11338 }else if( strcmp(z,"-vfstrace")==0 ){
11339 extern int vfstrace_register(
11340 const char *zTraceName,
11341 const char *zOldVfsName,
11342 int (*xOut)(const char*,void*),
11343 void *pOutArg,
11344 int makeDefault
11345 );
11346 vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
11347#endif
11348#ifdef SQLITE_ENABLE_MULTIPLEX
11349 }else if( strcmp(z,"-multiplex")==0 ){
11350 extern int sqlite3_multiple_initialize(const char*,int);
11351 sqlite3_multiplex_initialize(0, 1);
11352#endif
11353 }else if( strcmp(z,"-mmap")==0 ){
11354 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
11355 sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
drha90d84f2018-04-18 15:21:13 +000011356#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11357 }else if( strcmp(z,"-sorterref")==0 ){
11358 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
11359 sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz);
11360#endif
drh2ce15c32017-07-11 13:34:40 +000011361 }else if( strcmp(z,"-vfs")==0 ){
dan16a47422018-04-18 09:16:11 +000011362 zVfs = cmdline_option_value(argc, argv, ++i);
drh3baed312018-03-08 18:14:41 +000011363#ifdef SQLITE_HAVE_ZLIB
drh8682e122018-01-07 20:38:10 +000011364 }else if( strcmp(z,"-zip")==0 ){
11365 data.openMode = SHELL_OPEN_ZIPFILE;
11366#endif
11367 }else if( strcmp(z,"-append")==0 ){
11368 data.openMode = SHELL_OPEN_APPENDVFS;
drh8d889af2021-05-08 17:18:23 +000011369#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +000011370 }else if( strcmp(z,"-deserialize")==0 ){
11371 data.openMode = SHELL_OPEN_DESERIALIZE;
drh6ca64482019-01-22 16:06:20 +000011372 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
11373 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000011374#endif
drhee269a62018-02-14 23:27:43 +000011375 }else if( strcmp(z,"-readonly")==0 ){
11376 data.openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +000011377 }else if( strcmp(z,"-nofollow")==0 ){
11378 data.openFlags = SQLITE_OPEN_NOFOLLOW;
drhda57d962018-03-05 19:34:05 +000011379#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drh93b77312018-03-05 20:20:22 +000011380 }else if( strncmp(z, "-A",2)==0 ){
drhda57d962018-03-05 19:34:05 +000011381 /* All remaining command-line arguments are passed to the ".archive"
11382 ** command, so ignore them */
11383 break;
11384#endif
drh50b910a2019-01-21 14:55:03 +000011385 }else if( strcmp(z, "-memtrace")==0 ){
11386 sqlite3MemTraceActivate(stderr);
drhb7c46aa2020-11-25 13:59:47 +000011387 }else if( strcmp(z,"-bail")==0 ){
11388 bail_on_error = 1;
drhb97e2ad2021-08-26 18:31:39 +000011389 }else if( strcmp(z,"-nonce")==0 ){
11390 free(data.zNonce);
11391 data.zNonce = strdup(argv[++i]);
11392 }else if( strcmp(z,"-safe")==0 ){
11393 /* no-op - catch this on the second pass */
drh2ce15c32017-07-11 13:34:40 +000011394 }
11395 }
drhe7df8922018-04-18 10:44:58 +000011396 verify_uninitialized();
11397
dan16a47422018-04-18 09:16:11 +000011398
drhd11b8f62018-04-25 13:27:07 +000011399#ifdef SQLITE_SHELL_INIT_PROC
11400 {
11401 /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name
11402 ** of a C-function that will perform initialization actions on SQLite that
11403 ** occur just before or after sqlite3_initialize(). Use this compile-time
11404 ** option to embed this shell program in larger applications. */
11405 extern void SQLITE_SHELL_INIT_PROC(void);
11406 SQLITE_SHELL_INIT_PROC();
11407 }
11408#else
dan16a47422018-04-18 09:16:11 +000011409 /* All the sqlite3_config() calls have now been made. So it is safe
11410 ** to call sqlite3_initialize() and process any command line -vfs option. */
11411 sqlite3_initialize();
drhd11b8f62018-04-25 13:27:07 +000011412#endif
11413
dan16a47422018-04-18 09:16:11 +000011414 if( zVfs ){
11415 sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
11416 if( pVfs ){
11417 sqlite3_vfs_register(pVfs, 1);
11418 }else{
11419 utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
11420 exit(1);
11421 }
11422 }
11423
drh37407122021-07-23 18:43:58 +000011424 if( data.pAuxDb->zDbFilename==0 ){
drh2ce15c32017-07-11 13:34:40 +000011425#ifndef SQLITE_OMIT_MEMORYDB
drh37407122021-07-23 18:43:58 +000011426 data.pAuxDb->zDbFilename = ":memory:";
drh2ce15c32017-07-11 13:34:40 +000011427 warnInmemoryDb = argc==1;
11428#else
11429 utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
11430 return 1;
11431#endif
11432 }
11433 data.out = stdout;
drh8682e122018-01-07 20:38:10 +000011434 sqlite3_appendvfs_init(0,0,0);
drh2ce15c32017-07-11 13:34:40 +000011435
11436 /* Go ahead and open the database file if it already exists. If the
11437 ** file does not exist, delay opening it. This prevents empty database
11438 ** files from being created if a user mistypes the database name argument
11439 ** to the sqlite command-line tool.
11440 */
drh37407122021-07-23 18:43:58 +000011441 if( access(data.pAuxDb->zDbFilename, 0)==0 ){
drh2ce15c32017-07-11 13:34:40 +000011442 open_db(&data, 0);
11443 }
11444
11445 /* Process the initialization file if there is one. If no -init option
11446 ** is given on the command line, look for a file named ~/.sqliterc and
11447 ** try to process it.
11448 */
11449 process_sqliterc(&data,zInitFile);
11450
11451 /* Make a second pass through the command-line argument and set
11452 ** options. This second pass is delayed until after the initialization
11453 ** file is processed so that the command-line arguments will override
11454 ** settings in the initialization file.
11455 */
11456 for(i=1; i<argc; i++){
11457 char *z = argv[i];
11458 if( z[0]!='-' ) continue;
11459 if( z[1]=='-' ){ z++; }
11460 if( strcmp(z,"-init")==0 ){
11461 i++;
11462 }else if( strcmp(z,"-html")==0 ){
11463 data.mode = MODE_Html;
11464 }else if( strcmp(z,"-list")==0 ){
11465 data.mode = MODE_List;
11466 }else if( strcmp(z,"-quote")==0 ){
11467 data.mode = MODE_Quote;
drh9191c702020-08-17 09:11:21 +000011468 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma);
11469 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +000011470 }else if( strcmp(z,"-line")==0 ){
11471 data.mode = MODE_Line;
11472 }else if( strcmp(z,"-column")==0 ){
11473 data.mode = MODE_Column;
drh30c54a02020-05-28 23:49:50 +000011474 }else if( strcmp(z,"-json")==0 ){
11475 data.mode = MODE_Json;
11476 }else if( strcmp(z,"-markdown")==0 ){
11477 data.mode = MODE_Markdown;
11478 }else if( strcmp(z,"-table")==0 ){
11479 data.mode = MODE_Table;
drh0908e382020-06-04 18:05:39 +000011480 }else if( strcmp(z,"-box")==0 ){
11481 data.mode = MODE_Box;
drh2ce15c32017-07-11 13:34:40 +000011482 }else if( strcmp(z,"-csv")==0 ){
11483 data.mode = MODE_Csv;
11484 memcpy(data.colSeparator,",",2);
drh3baed312018-03-08 18:14:41 +000011485#ifdef SQLITE_HAVE_ZLIB
drh1fa6d9f2018-01-06 21:46:01 +000011486 }else if( strcmp(z,"-zip")==0 ){
11487 data.openMode = SHELL_OPEN_ZIPFILE;
11488#endif
11489 }else if( strcmp(z,"-append")==0 ){
11490 data.openMode = SHELL_OPEN_APPENDVFS;
drh8d889af2021-05-08 17:18:23 +000011491#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +000011492 }else if( strcmp(z,"-deserialize")==0 ){
11493 data.openMode = SHELL_OPEN_DESERIALIZE;
drh6ca64482019-01-22 16:06:20 +000011494 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
11495 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000011496#endif
drh4aafe592018-03-23 16:08:30 +000011497 }else if( strcmp(z,"-readonly")==0 ){
11498 data.openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +000011499 }else if( strcmp(z,"-nofollow")==0 ){
11500 data.openFlags |= SQLITE_OPEN_NOFOLLOW;
drh2ce15c32017-07-11 13:34:40 +000011501 }else if( strcmp(z,"-ascii")==0 ){
11502 data.mode = MODE_Ascii;
drh2fa78182020-10-31 18:58:37 +000011503 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit);
11504 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record);
11505 }else if( strcmp(z,"-tabs")==0 ){
11506 data.mode = MODE_List;
11507 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Tab);
11508 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +000011509 }else if( strcmp(z,"-separator")==0 ){
11510 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
11511 "%s",cmdline_option_value(argc,argv,++i));
11512 }else if( strcmp(z,"-newline")==0 ){
11513 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
11514 "%s",cmdline_option_value(argc,argv,++i));
11515 }else if( strcmp(z,"-nullvalue")==0 ){
11516 sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
11517 "%s",cmdline_option_value(argc,argv,++i));
11518 }else if( strcmp(z,"-header")==0 ){
11519 data.showHeader = 1;
11520 }else if( strcmp(z,"-noheader")==0 ){
11521 data.showHeader = 0;
11522 }else if( strcmp(z,"-echo")==0 ){
11523 ShellSetFlag(&data, SHFLG_Echo);
11524 }else if( strcmp(z,"-eqp")==0 ){
drhada70452017-12-21 21:02:27 +000011525 data.autoEQP = AUTOEQP_on;
drh2ce15c32017-07-11 13:34:40 +000011526 }else if( strcmp(z,"-eqpfull")==0 ){
drhada70452017-12-21 21:02:27 +000011527 data.autoEQP = AUTOEQP_full;
drh2ce15c32017-07-11 13:34:40 +000011528 }else if( strcmp(z,"-stats")==0 ){
11529 data.statsOn = 1;
11530 }else if( strcmp(z,"-scanstats")==0 ){
11531 data.scanstatsOn = 1;
11532 }else if( strcmp(z,"-backslash")==0 ){
11533 /* Undocumented command-line option: -backslash
11534 ** Causes C-style backslash escapes to be evaluated in SQL statements
11535 ** prior to sending the SQL into SQLite. Useful for injecting
11536 ** crazy bytes in the middle of SQL statements for testing and debugging.
11537 */
11538 ShellSetFlag(&data, SHFLG_Backslash);
11539 }else if( strcmp(z,"-bail")==0 ){
drhb7c46aa2020-11-25 13:59:47 +000011540 /* No-op. The bail_on_error flag should already be set. */
drh2ce15c32017-07-11 13:34:40 +000011541 }else if( strcmp(z,"-version")==0 ){
11542 printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
11543 return 0;
11544 }else if( strcmp(z,"-interactive")==0 ){
11545 stdin_is_interactive = 1;
11546 }else if( strcmp(z,"-batch")==0 ){
11547 stdin_is_interactive = 0;
11548 }else if( strcmp(z,"-heap")==0 ){
11549 i++;
drh2ce15c32017-07-11 13:34:40 +000011550 }else if( strcmp(z,"-pagecache")==0 ){
11551 i+=2;
11552 }else if( strcmp(z,"-lookaside")==0 ){
11553 i+=2;
drhaf6d1af2021-08-09 17:37:58 +000011554 }else if( strcmp(z,"-threadsafe")==0 ){
11555 i+=2;
drhb97e2ad2021-08-26 18:31:39 +000011556 }else if( strcmp(z,"-nonce")==0 ){
11557 i += 2;
drh2ce15c32017-07-11 13:34:40 +000011558 }else if( strcmp(z,"-mmap")==0 ){
11559 i++;
drh50b910a2019-01-21 14:55:03 +000011560 }else if( strcmp(z,"-memtrace")==0 ){
11561 i++;
drha90d84f2018-04-18 15:21:13 +000011562#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11563 }else if( strcmp(z,"-sorterref")==0 ){
11564 i++;
11565#endif
drh2ce15c32017-07-11 13:34:40 +000011566 }else if( strcmp(z,"-vfs")==0 ){
11567 i++;
11568#ifdef SQLITE_ENABLE_VFSTRACE
11569 }else if( strcmp(z,"-vfstrace")==0 ){
11570 i++;
11571#endif
11572#ifdef SQLITE_ENABLE_MULTIPLEX
11573 }else if( strcmp(z,"-multiplex")==0 ){
11574 i++;
11575#endif
11576 }else if( strcmp(z,"-help")==0 ){
11577 usage(1);
11578 }else if( strcmp(z,"-cmd")==0 ){
11579 /* Run commands that follow -cmd first and separately from commands
11580 ** that simply appear on the command-line. This seems goofy. It would
11581 ** be better if all commands ran in the order that they appear. But
11582 ** we retain the goofy behavior for historical compatibility. */
11583 if( i==argc-1 ) break;
11584 z = cmdline_option_value(argc,argv,++i);
11585 if( z[0]=='.' ){
11586 rc = do_meta_command(z, &data);
11587 if( rc && bail_on_error ) return rc==2 ? 0 : rc;
11588 }else{
11589 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000011590 rc = shell_exec(&data, z, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000011591 if( zErrMsg!=0 ){
11592 utf8_printf(stderr,"Error: %s\n", zErrMsg);
11593 if( bail_on_error ) return rc!=0 ? rc : 1;
11594 }else if( rc!=0 ){
11595 utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
11596 if( bail_on_error ) return rc;
11597 }
11598 }
drhda57d962018-03-05 19:34:05 +000011599#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drh93b77312018-03-05 20:20:22 +000011600 }else if( strncmp(z, "-A", 2)==0 ){
drhda57d962018-03-05 19:34:05 +000011601 if( nCmd>0 ){
11602 utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
11603 " with \"%s\"\n", z);
11604 return 1;
11605 }
drhbe4ccb22018-05-17 20:04:24 +000011606 open_db(&data, OPEN_DB_ZIPFILE);
drh93b77312018-03-05 20:20:22 +000011607 if( z[2] ){
11608 argv[i] = &z[2];
drhd0f9cdc2018-05-17 14:09:06 +000011609 arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
drh93b77312018-03-05 20:20:22 +000011610 }else{
drhd0f9cdc2018-05-17 14:09:06 +000011611 arDotCommand(&data, 1, argv+i, argc-i);
drh93b77312018-03-05 20:20:22 +000011612 }
drhda57d962018-03-05 19:34:05 +000011613 readStdin = 0;
11614 break;
11615#endif
drhb97e2ad2021-08-26 18:31:39 +000011616 }else if( strcmp(z,"-safe")==0 ){
11617 data.bSafeMode = data.bSafeModePersist = 1;
drh2ce15c32017-07-11 13:34:40 +000011618 }else{
11619 utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
11620 raw_printf(stderr,"Use -help for a list of options.\n");
11621 return 1;
11622 }
11623 data.cMode = data.mode;
11624 }
11625
11626 if( !readStdin ){
11627 /* Run all arguments that do not begin with '-' as if they were separate
11628 ** command-line inputs, except for the argToSkip argument which contains
11629 ** the database filename.
11630 */
11631 for(i=0; i<nCmd; i++){
11632 if( azCmd[i][0]=='.' ){
11633 rc = do_meta_command(azCmd[i], &data);
danaff1a572020-11-17 21:09:56 +000011634 if( rc ){
11635 free(azCmd);
11636 return rc==2 ? 0 : rc;
11637 }
drh2ce15c32017-07-11 13:34:40 +000011638 }else{
11639 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000011640 rc = shell_exec(&data, azCmd[i], &zErrMsg);
danaff1a572020-11-17 21:09:56 +000011641 if( zErrMsg || rc ){
11642 if( zErrMsg!=0 ){
11643 utf8_printf(stderr,"Error: %s\n", zErrMsg);
11644 }else{
11645 utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
11646 }
11647 sqlite3_free(zErrMsg);
11648 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000011649 return rc!=0 ? rc : 1;
drh2ce15c32017-07-11 13:34:40 +000011650 }
11651 }
11652 }
drh2ce15c32017-07-11 13:34:40 +000011653 }else{
11654 /* Run commands received from standard input
11655 */
11656 if( stdin_is_interactive ){
11657 char *zHome;
drha9e4be32018-10-10 18:56:40 +000011658 char *zHistory;
drh2ce15c32017-07-11 13:34:40 +000011659 int nHistory;
11660 printf(
11661 "SQLite version %s %.19s\n" /*extra-version-info*/
11662 "Enter \".help\" for usage hints.\n",
11663 sqlite3_libversion(), sqlite3_sourceid()
11664 );
11665 if( warnInmemoryDb ){
11666 printf("Connected to a ");
11667 printBold("transient in-memory database");
11668 printf(".\nUse \".open FILENAME\" to reopen on a "
11669 "persistent database.\n");
11670 }
drha9e4be32018-10-10 18:56:40 +000011671 zHistory = getenv("SQLITE_HISTORY");
11672 if( zHistory ){
11673 zHistory = strdup(zHistory);
11674 }else if( (zHome = find_home_dir(0))!=0 ){
drh2ce15c32017-07-11 13:34:40 +000011675 nHistory = strlen30(zHome) + 20;
11676 if( (zHistory = malloc(nHistory))!=0 ){
11677 sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
11678 }
11679 }
11680 if( zHistory ){ shell_read_history(zHistory); }
drh56eb09b2017-07-11 13:59:07 +000011681#if HAVE_READLINE || HAVE_EDITLINE
11682 rl_attempted_completion_function = readline_completion;
11683#elif HAVE_LINENOISE
11684 linenoiseSetCompletionCallback(linenoise_completion);
11685#endif
drh60379d42018-12-13 18:30:01 +000011686 data.in = 0;
11687 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000011688 if( zHistory ){
drh5a75dd82017-07-18 20:59:40 +000011689 shell_stifle_history(2000);
drh2ce15c32017-07-11 13:34:40 +000011690 shell_write_history(zHistory);
11691 free(zHistory);
11692 }
11693 }else{
drh60379d42018-12-13 18:30:01 +000011694 data.in = stdin;
11695 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000011696 }
11697 }
danaff1a572020-11-17 21:09:56 +000011698 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000011699 set_table_name(&data, 0);
11700 if( data.db ){
drh37407122021-07-23 18:43:58 +000011701 session_close_all(&data, -1);
drh9e804032018-05-18 17:11:50 +000011702 close_db(data.db);
drh2ce15c32017-07-11 13:34:40 +000011703 }
drh37407122021-07-23 18:43:58 +000011704 for(i=0; i<ArraySize(data.aAuxDb); i++){
11705 sqlite3_free(data.aAuxDb[i].zFreeOnClose);
11706 if( data.aAuxDb[i].db ){
11707 session_close_all(&data, i);
11708 close_db(data.aAuxDb[i].db);
11709 }
11710 }
drh2ce15c32017-07-11 13:34:40 +000011711 find_home_dir(1);
drh536c3452018-01-11 00:38:39 +000011712 output_reset(&data);
11713 data.doXdgOpen = 0;
drh13c20932018-01-10 21:41:55 +000011714 clearTempFile(&data);
drh2ce15c32017-07-11 13:34:40 +000011715#if !SQLITE_SHELL_IS_UTF8
drh1f22f622018-05-17 13:29:14 +000011716 for(i=0; i<argcToFree; i++) free(argvToFree[i]);
11717 free(argvToFree);
drh2ce15c32017-07-11 13:34:40 +000011718#endif
drh0285d982020-05-29 14:38:43 +000011719 free(data.colWidth);
drhb97e2ad2021-08-26 18:31:39 +000011720 free(data.zNonce);
drh9e804032018-05-18 17:11:50 +000011721 /* Clear the global data structure so that valgrind will detect memory
11722 ** leaks */
11723 memset(&data, 0, sizeof(data));
drh2ce15c32017-07-11 13:34:40 +000011724 return rc;
11725}