blob: 3d8f9537dd3b6aba58f698f41fa89a16bead596c [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/*
larrybrd96bcc72021-09-17 21:12:47 +0000638** Return open FILE * if zFile exists, can be opened for read
639** and is an ordinary file or a character stream source.
640** Otherwise return 0.
drhbbd620e2020-07-20 23:33:11 +0000641*/
larrybrd96bcc72021-09-17 21:12:47 +0000642static FILE * openChrSource(const char *zFile){
drhbbd620e2020-07-20 23:33:11 +0000643#ifdef _WIN32
larrybrd0007852021-09-13 23:11:46 +0000644 struct _stat x = {0};
larrybrd0007852021-09-13 23:11:46 +0000645# define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0)
larrybrd96bcc72021-09-17 21:12:47 +0000646 /* On Windows, open first, then check the stream nature. This order
647 ** is necessary because _stat() and sibs, when checking a named pipe,
648 ** effectively break the pipe as its supplier sees it. */
649 FILE *rv = fopen(zFile, "rb");
650 if( rv==0 ) return 0;
651 if( _fstat(_fileno(rv), &x) != 0
652 || !STAT_CHR_SRC(x.st_mode)){
653 fclose(rv);
654 rv = 0;
655 }
656 return rv;
drhbbd620e2020-07-20 23:33:11 +0000657#else
larrybrd0007852021-09-13 23:11:46 +0000658 struct stat x = {0};
659 int rc = stat(zFile, &x);
660# define STAT_CHR_SRC(mode) (S_ISREG(mode)||S_ISFIFO(mode)||S_ISCHR(mode))
larrybrd96bcc72021-09-17 21:12:47 +0000661 if( rc!=0 ) return 0;
662 if( STAT_CHR_SRC(x.st_mode) ){
663 return fopen(zFile, "rb");
664 }else{
665 return 0;
666 }
drhbbd620e2020-07-20 23:33:11 +0000667#endif
larrybrd0007852021-09-13 23:11:46 +0000668#undef STAT_CHR_SRC
669}
drhbbd620e2020-07-20 23:33:11 +0000670
671/*
drh2ce15c32017-07-11 13:34:40 +0000672** This routine reads a line of text from FILE in, stores
673** the text in memory obtained from malloc() and returns a pointer
674** to the text. NULL is returned at end of file, or if malloc()
675** fails.
676**
677** If zLine is not NULL then it is a malloced buffer returned from
678** a previous call to this routine that may be reused.
679*/
680static char *local_getline(char *zLine, FILE *in){
681 int nLine = zLine==0 ? 0 : 100;
682 int n = 0;
683
684 while( 1 ){
685 if( n+100>nLine ){
686 nLine = nLine*2 + 100;
687 zLine = realloc(zLine, nLine);
drh884406b2018-07-29 18:56:35 +0000688 if( zLine==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +0000689 }
690 if( fgets(&zLine[n], nLine - n, in)==0 ){
691 if( n==0 ){
692 free(zLine);
693 return 0;
694 }
695 zLine[n] = 0;
696 break;
697 }
698 while( zLine[n] ) n++;
699 if( n>0 && zLine[n-1]=='\n' ){
700 n--;
701 if( n>0 && zLine[n-1]=='\r' ) n--;
702 zLine[n] = 0;
703 break;
704 }
705 }
706#if defined(_WIN32) || defined(WIN32)
707 /* For interactive input on Windows systems, translate the
708 ** multi-byte characterset characters into UTF-8. */
709 if( stdin_is_interactive && in==stdin ){
710 char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
711 if( zTrans ){
712 int nTrans = strlen30(zTrans)+1;
713 if( nTrans>nLine ){
714 zLine = realloc(zLine, nTrans);
drh884406b2018-07-29 18:56:35 +0000715 if( zLine==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +0000716 }
717 memcpy(zLine, zTrans, nTrans);
718 sqlite3_free(zTrans);
719 }
720 }
721#endif /* defined(_WIN32) || defined(WIN32) */
722 return zLine;
723}
724
725/*
726** Retrieve a single line of input text.
727**
728** If in==0 then read from standard input and prompt before each line.
729** If isContinuation is true, then a continuation prompt is appropriate.
730** If isContinuation is zero, then the main prompt should be used.
731**
732** If zPrior is not NULL then it is a buffer from a prior call to this
733** routine that can be reused.
734**
735** The result is stored in space obtained from malloc() and must either
736** be freed by the caller or else passed back into this routine via the
737** zPrior argument for reuse.
738*/
739static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
740 char *zPrompt;
741 char *zResult;
742 if( in!=0 ){
743 zResult = local_getline(zPrior, in);
744 }else{
745 zPrompt = isContinuation ? continuePrompt : mainPrompt;
746#if SHELL_USE_LOCAL_GETLINE
747 printf("%s", zPrompt);
748 fflush(stdout);
749 zResult = local_getline(zPrior, stdin);
750#else
751 free(zPrior);
752 zResult = shell_readline(zPrompt);
753 if( zResult && *zResult ) shell_add_history(zResult);
754#endif
755 }
756 return zResult;
757}
drh5af06982018-01-10 00:53:55 +0000758
759
760/*
761** Return the value of a hexadecimal digit. Return -1 if the input
762** is not a hex digit.
763*/
764static int hexDigitValue(char c){
765 if( c>='0' && c<='9' ) return c - '0';
766 if( c>='a' && c<='f' ) return c - 'a' + 10;
767 if( c>='A' && c<='F' ) return c - 'A' + 10;
768 return -1;
769}
770
771/*
772** Interpret zArg as an integer value, possibly with suffixes.
773*/
774static sqlite3_int64 integerValue(const char *zArg){
775 sqlite3_int64 v = 0;
776 static const struct { char *zSuffix; int iMult; } aMult[] = {
777 { "KiB", 1024 },
778 { "MiB", 1024*1024 },
779 { "GiB", 1024*1024*1024 },
780 { "KB", 1000 },
781 { "MB", 1000000 },
782 { "GB", 1000000000 },
783 { "K", 1000 },
784 { "M", 1000000 },
785 { "G", 1000000000 },
786 };
787 int i;
788 int isNeg = 0;
789 if( zArg[0]=='-' ){
790 isNeg = 1;
791 zArg++;
792 }else if( zArg[0]=='+' ){
793 zArg++;
794 }
795 if( zArg[0]=='0' && zArg[1]=='x' ){
796 int x;
797 zArg += 2;
798 while( (x = hexDigitValue(zArg[0]))>=0 ){
799 v = (v<<4) + x;
800 zArg++;
801 }
802 }else{
803 while( IsDigit(zArg[0]) ){
804 v = v*10 + zArg[0] - '0';
805 zArg++;
806 }
807 }
808 for(i=0; i<ArraySize(aMult); i++){
809 if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
810 v *= aMult[i].iMult;
811 break;
812 }
813 }
814 return isNeg? -v : v;
815}
816
drh2ce15c32017-07-11 13:34:40 +0000817/*
818** A variable length string to which one can append text.
819*/
820typedef struct ShellText ShellText;
821struct ShellText {
822 char *z;
823 int n;
824 int nAlloc;
825};
826
827/*
828** Initialize and destroy a ShellText object
829*/
830static void initText(ShellText *p){
831 memset(p, 0, sizeof(*p));
832}
833static void freeText(ShellText *p){
834 free(p->z);
835 initText(p);
836}
837
838/* zIn is either a pointer to a NULL-terminated string in memory obtained
839** from malloc(), or a NULL pointer. The string pointed to by zAppend is
840** added to zIn, and the result returned in memory obtained from malloc().
841** zIn, if it was not NULL, is freed.
842**
843** If the third argument, quote, is not '\0', then it is used as a
844** quote character for zAppend.
845*/
846static void appendText(ShellText *p, char const *zAppend, char quote){
847 int len;
848 int i;
849 int nAppend = strlen30(zAppend);
850
851 len = nAppend+p->n+1;
852 if( quote ){
853 len += 2;
854 for(i=0; i<nAppend; i++){
855 if( zAppend[i]==quote ) len++;
856 }
857 }
858
859 if( p->n+len>=p->nAlloc ){
860 p->nAlloc = p->nAlloc*2 + len + 20;
861 p->z = realloc(p->z, p->nAlloc);
drh884406b2018-07-29 18:56:35 +0000862 if( p->z==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +0000863 }
864
865 if( quote ){
866 char *zCsr = p->z+p->n;
867 *zCsr++ = quote;
868 for(i=0; i<nAppend; i++){
869 *zCsr++ = zAppend[i];
870 if( zAppend[i]==quote ) *zCsr++ = quote;
871 }
872 *zCsr++ = quote;
873 p->n = (int)(zCsr - p->z);
874 *zCsr = '\0';
875 }else{
876 memcpy(p->z+p->n, zAppend, nAppend);
877 p->n += nAppend;
878 p->z[p->n] = '\0';
879 }
880}
881
882/*
883** Attempt to determine if identifier zName needs to be quoted, either
884** because it contains non-alphanumeric characters, or because it is an
885** SQLite keyword. Be conservative in this estimate: When in doubt assume
886** that quoting is required.
887**
888** Return '"' if quoting is required. Return 0 if no quoting is required.
889*/
890static char quoteChar(const char *zName){
drhfc0ec3e2018-04-25 19:02:48 +0000891 int i;
drh2ce15c32017-07-11 13:34:40 +0000892 if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
893 for(i=0; zName[i]; i++){
894 if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
895 }
drhfc0ec3e2018-04-25 19:02:48 +0000896 return sqlite3_keyword_check(zName, i) ? '"' : 0;
drh2ce15c32017-07-11 13:34:40 +0000897}
898
899/*
drh667a2a22018-01-02 00:04:37 +0000900** Construct a fake object name and column list to describe the structure
901** of the view, virtual table, or table valued function zSchema.zName.
drhceba7922018-01-01 21:28:25 +0000902*/
drh667a2a22018-01-02 00:04:37 +0000903static char *shellFakeSchema(
drhceba7922018-01-01 21:28:25 +0000904 sqlite3 *db, /* The database connection containing the vtab */
905 const char *zSchema, /* Schema of the database holding the vtab */
906 const char *zName /* The name of the virtual table */
907){
908 sqlite3_stmt *pStmt = 0;
909 char *zSql;
drh1d315cf2018-01-01 21:49:43 +0000910 ShellText s;
911 char cQuote;
912 char *zDiv = "(";
drh667a2a22018-01-02 00:04:37 +0000913 int nRow = 0;
drhceba7922018-01-01 21:28:25 +0000914
drh1d315cf2018-01-01 21:49:43 +0000915 zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
916 zSchema ? zSchema : "main", zName);
drhceba7922018-01-01 21:28:25 +0000917 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
918 sqlite3_free(zSql);
drh1d315cf2018-01-01 21:49:43 +0000919 initText(&s);
920 if( zSchema ){
921 cQuote = quoteChar(zSchema);
922 if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0;
923 appendText(&s, zSchema, cQuote);
924 appendText(&s, ".", 0);
drhceba7922018-01-01 21:28:25 +0000925 }
drh1d315cf2018-01-01 21:49:43 +0000926 cQuote = quoteChar(zName);
927 appendText(&s, zName, cQuote);
928 while( sqlite3_step(pStmt)==SQLITE_ROW ){
929 const char *zCol = (const char*)sqlite3_column_text(pStmt, 1);
drh667a2a22018-01-02 00:04:37 +0000930 nRow++;
drh1d315cf2018-01-01 21:49:43 +0000931 appendText(&s, zDiv, 0);
932 zDiv = ",";
933 cQuote = quoteChar(zCol);
934 appendText(&s, zCol, cQuote);
935 }
936 appendText(&s, ")", 0);
drhceba7922018-01-01 21:28:25 +0000937 sqlite3_finalize(pStmt);
drh667a2a22018-01-02 00:04:37 +0000938 if( nRow==0 ){
939 freeText(&s);
940 s.z = 0;
941 }
drh1d315cf2018-01-01 21:49:43 +0000942 return s.z;
drhceba7922018-01-01 21:28:25 +0000943}
944
945/*
drh667a2a22018-01-02 00:04:37 +0000946** SQL function: shell_module_schema(X)
947**
948** Return a fake schema for the table-valued function or eponymous virtual
949** table X.
950*/
951static void shellModuleSchema(
952 sqlite3_context *pCtx,
953 int nVal,
954 sqlite3_value **apVal
955){
956 const char *zName = (const char*)sqlite3_value_text(apVal[0]);
957 char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName);
drhb9685182018-01-17 13:15:23 +0000958 UNUSED_PARAMETER(nVal);
drh667a2a22018-01-02 00:04:37 +0000959 if( zFake ){
dandcfbff92018-01-08 17:05:32 +0000960 sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
drh667a2a22018-01-02 00:04:37 +0000961 -1, sqlite3_free);
dandcfbff92018-01-08 17:05:32 +0000962 free(zFake);
drh667a2a22018-01-02 00:04:37 +0000963 }
964}
965
966/*
drh2ce15c32017-07-11 13:34:40 +0000967** SQL function: shell_add_schema(S,X)
968**
969** Add the schema name X to the CREATE statement in S and return the result.
970** Examples:
971**
972** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x);
973**
974** Also works on
975**
976** CREATE INDEX
977** CREATE UNIQUE INDEX
978** CREATE VIEW
979** CREATE TRIGGER
980** CREATE VIRTUAL TABLE
981**
982** This UDF is used by the .schema command to insert the schema name of
drh067b92b2020-06-19 15:24:12 +0000983** attached databases into the middle of the sqlite_schema.sql field.
drh2ce15c32017-07-11 13:34:40 +0000984*/
985static void shellAddSchemaName(
986 sqlite3_context *pCtx,
987 int nVal,
988 sqlite3_value **apVal
989){
990 static const char *aPrefix[] = {
991 "TABLE",
992 "INDEX",
993 "UNIQUE INDEX",
994 "VIEW",
995 "TRIGGER",
996 "VIRTUAL TABLE"
997 };
998 int i = 0;
999 const char *zIn = (const char*)sqlite3_value_text(apVal[0]);
1000 const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
drh667a2a22018-01-02 00:04:37 +00001001 const char *zName = (const char*)sqlite3_value_text(apVal[2]);
drhceba7922018-01-01 21:28:25 +00001002 sqlite3 *db = sqlite3_context_db_handle(pCtx);
drhb9685182018-01-17 13:15:23 +00001003 UNUSED_PARAMETER(nVal);
drh2ce15c32017-07-11 13:34:40 +00001004 if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
drh37407122021-07-23 18:43:58 +00001005 for(i=0; i<ArraySize(aPrefix); i++){
drh2ce15c32017-07-11 13:34:40 +00001006 int n = strlen30(aPrefix[i]);
1007 if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
drhceba7922018-01-01 21:28:25 +00001008 char *z = 0;
drh667a2a22018-01-02 00:04:37 +00001009 char *zFake = 0;
drhceba7922018-01-01 21:28:25 +00001010 if( zSchema ){
1011 char cQuote = quoteChar(zSchema);
1012 if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){
1013 z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8);
1014 }else{
1015 z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8);
1016 }
drh2ce15c32017-07-11 13:34:40 +00001017 }
drh667a2a22018-01-02 00:04:37 +00001018 if( zName
1019 && aPrefix[i][0]=='V'
1020 && (zFake = shellFakeSchema(db, zSchema, zName))!=0
1021 ){
1022 if( z==0 ){
dandcfbff92018-01-08 17:05:32 +00001023 z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake);
drh667a2a22018-01-02 00:04:37 +00001024 }else{
dandcfbff92018-01-08 17:05:32 +00001025 z = sqlite3_mprintf("%z\n/* %s */", z, zFake);
drh667a2a22018-01-02 00:04:37 +00001026 }
dandcfbff92018-01-08 17:05:32 +00001027 free(zFake);
drhceba7922018-01-01 21:28:25 +00001028 }
1029 if( z ){
1030 sqlite3_result_text(pCtx, z, -1, sqlite3_free);
1031 return;
1032 }
drh2ce15c32017-07-11 13:34:40 +00001033 }
1034 }
1035 }
1036 sqlite3_result_value(pCtx, apVal[0]);
1037}
1038
1039/*
1040** The source code for several run-time loadable extensions is inserted
1041** below by the ../tool/mkshellc.tcl script. Before processing that included
1042** code, we need to override some macros to make the included program code
1043** work here in the middle of this regular program.
1044*/
1045#define SQLITE_EXTENSION_INIT1
drh89997982017-07-11 18:11:33 +00001046#define SQLITE_EXTENSION_INIT2(X) (void)(X)
drh2ce15c32017-07-11 13:34:40 +00001047
mistachkinacae8c32018-01-05 20:08:46 +00001048#if defined(_WIN32) && defined(_MSC_VER)
drh03491a12018-01-07 21:58:17 +00001049INCLUDE test_windirent.h
mistachkindfdfd8c2018-01-04 22:46:08 +00001050INCLUDE test_windirent.c
1051#define dirent DIRENT
mistachkindfdfd8c2018-01-04 22:46:08 +00001052#endif
drh2ce15c32017-07-11 13:34:40 +00001053INCLUDE ../ext/misc/shathree.c
1054INCLUDE ../ext/misc/fileio.c
drh56eb09b2017-07-11 13:59:07 +00001055INCLUDE ../ext/misc/completion.c
drh8682e122018-01-07 20:38:10 +00001056INCLUDE ../ext/misc/appendvfs.c
drh50b910a2019-01-21 14:55:03 +00001057INCLUDE ../ext/misc/memtrace.c
drhf05dd032020-04-14 15:53:58 +00001058INCLUDE ../ext/misc/uint.c
drhbeb9def2020-06-22 19:12:23 +00001059INCLUDE ../ext/misc/decimal.c
drh8cda77d2020-06-24 15:06:29 +00001060INCLUDE ../ext/misc/ieee754.c
mistachkin72c38d82020-08-28 18:47:39 +00001061INCLUDE ../ext/misc/series.c
drh64689902021-06-03 13:51:31 +00001062INCLUDE ../ext/misc/regexp.c
dan72afc3c2017-12-05 18:32:40 +00001063#ifdef SQLITE_HAVE_ZLIB
dan9ebfaad2017-12-26 20:39:58 +00001064INCLUDE ../ext/misc/zipfile.c
dand1b51d42017-12-16 19:11:26 +00001065INCLUDE ../ext/misc/sqlar.c
dan72afc3c2017-12-05 18:32:40 +00001066#endif
dan43efc182017-12-19 17:42:13 +00001067INCLUDE ../ext/expert/sqlite3expert.h
1068INCLUDE ../ext/expert/sqlite3expert.c
drh2ce15c32017-07-11 13:34:40 +00001069
dan1b162162019-04-27 20:15:15 +00001070#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00001071INCLUDE ../ext/misc/dbdata.c
dan1b162162019-04-27 20:15:15 +00001072#endif
dan68cb86e2019-04-20 20:57:28 +00001073
drh2ce15c32017-07-11 13:34:40 +00001074#if defined(SQLITE_ENABLE_SESSION)
1075/*
1076** State information for a single open session
1077*/
1078typedef struct OpenSession OpenSession;
1079struct OpenSession {
1080 char *zName; /* Symbolic name for this session */
1081 int nFilter; /* Number of xFilter rejection GLOB patterns */
1082 char **azFilter; /* Array of xFilter rejection GLOB patterns */
1083 sqlite3_session *p; /* The open session */
1084};
1085#endif
1086
dan43efc182017-12-19 17:42:13 +00001087typedef struct ExpertInfo ExpertInfo;
1088struct ExpertInfo {
1089 sqlite3expert *pExpert;
1090 int bVerbose;
1091};
1092
drh4b5345c2018-04-24 13:07:40 +00001093/* A single line in the EQP output */
1094typedef struct EQPGraphRow EQPGraphRow;
1095struct EQPGraphRow {
drhe2ca99c2018-05-02 00:33:43 +00001096 int iEqpId; /* ID for this row */
1097 int iParentId; /* ID of the parent row */
drh4b5345c2018-04-24 13:07:40 +00001098 EQPGraphRow *pNext; /* Next row in sequence */
1099 char zText[1]; /* Text to display for this row */
1100};
1101
1102/* All EQP output is collected into an instance of the following */
1103typedef struct EQPGraph EQPGraph;
1104struct EQPGraph {
1105 EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */
1106 EQPGraphRow *pLast; /* Last element of the pRow list */
1107 char zPrefix[100]; /* Graph prefix */
1108};
1109
drh2ce15c32017-07-11 13:34:40 +00001110/*
1111** State information about the database connection is contained in an
1112** instance of the following structure.
1113*/
1114typedef struct ShellState ShellState;
1115struct ShellState {
1116 sqlite3 *db; /* The database */
drh1fa6d9f2018-01-06 21:46:01 +00001117 u8 autoExplain; /* Automatically turn on .explain mode */
1118 u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
drhe2ca99c2018-05-02 00:33:43 +00001119 u8 autoEQPtest; /* autoEQP is in test mode */
drhb4e50392019-01-26 15:40:04 +00001120 u8 autoEQPtrace; /* autoEQP is in trace mode */
drh1fa6d9f2018-01-06 21:46:01 +00001121 u8 scanstatsOn; /* True to display scan stats before each finalize */
1122 u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
drh13c20932018-01-10 21:41:55 +00001123 u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
drh4b5345c2018-04-24 13:07:40 +00001124 u8 nEqpLevel; /* Depth of the EQP output graph */
drh707821f2018-12-05 13:39:06 +00001125 u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
drhb97e2ad2021-08-26 18:31:39 +00001126 u8 bSafeMode; /* True to prohibit unsafe operations */
1127 u8 bSafeModePersist; /* The long-term value of bSafeMode */
drha6e6cf22021-01-09 19:10:04 +00001128 unsigned statsOn; /* True to display memory stats before each finalize */
drh4b5345c2018-04-24 13:07:40 +00001129 unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */
drh2ce15c32017-07-11 13:34:40 +00001130 int outCount; /* Revert to stdout when reaching zero */
1131 int cnt; /* Number of records displayed so far */
drh2c8ee022018-12-13 18:59:30 +00001132 int lineno; /* Line number of last line read from in */
drh0933aad2019-11-18 17:46:38 +00001133 int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */
drh60379d42018-12-13 18:30:01 +00001134 FILE *in; /* Read commands from this stream */
drh2ce15c32017-07-11 13:34:40 +00001135 FILE *out; /* Write results here */
1136 FILE *traceOut; /* Output for sqlite3_trace() */
1137 int nErr; /* Number of errors seen */
1138 int mode; /* An output mode setting */
drh3c484e82018-01-10 22:27:21 +00001139 int modePrior; /* Saved mode */
drh2ce15c32017-07-11 13:34:40 +00001140 int cMode; /* temporary output mode for the current query */
1141 int normalMode; /* Output mode before ".explain on" */
1142 int writableSchema; /* True if PRAGMA writable_schema=ON */
1143 int showHeader; /* True to show column names in List or Column mode */
1144 int nCheck; /* Number of ".check" commands run */
drh3f83f592019-02-04 14:53:18 +00001145 unsigned nProgress; /* Number of progress callbacks encountered */
1146 unsigned mxProgress; /* Maximum progress callbacks before failing */
1147 unsigned flgProgress; /* Flags for the progress callback */
drh2ce15c32017-07-11 13:34:40 +00001148 unsigned shellFlgs; /* Various flags */
drh7a431002020-04-18 14:12:00 +00001149 unsigned priorShFlgs; /* Saved copy of flags */
drh6ca64482019-01-22 16:06:20 +00001150 sqlite3_int64 szMax; /* --maxsize argument to .open */
drh2ce15c32017-07-11 13:34:40 +00001151 char *zDestTable; /* Name of destination table when MODE_Insert */
drh13c20932018-01-10 21:41:55 +00001152 char *zTempFile; /* Temporary file that might need deleting */
drh2ce15c32017-07-11 13:34:40 +00001153 char zTestcase[30]; /* Name of current test case */
1154 char colSeparator[20]; /* Column separator character for several modes */
1155 char rowSeparator[20]; /* Row separator character for MODE_Ascii */
drh3c484e82018-01-10 22:27:21 +00001156 char colSepPrior[20]; /* Saved column separator */
1157 char rowSepPrior[20]; /* Saved row separator */
drh0285d982020-05-29 14:38:43 +00001158 int *colWidth; /* Requested width of each column in columnar modes */
1159 int *actualWidth; /* Actual width of each column */
1160 int nWidth; /* Number of slots in colWidth[] and actualWidth[] */
drh2ce15c32017-07-11 13:34:40 +00001161 char nullValue[20]; /* The text to print when a NULL comes back from
1162 ** the database */
1163 char outfile[FILENAME_MAX]; /* Filename for *out */
drh2ce15c32017-07-11 13:34:40 +00001164 sqlite3_stmt *pStmt; /* Current statement if any. */
1165 FILE *pLog; /* Write log output here */
drh37407122021-07-23 18:43:58 +00001166 struct AuxDb { /* Storage space for auxiliary database connections */
1167 sqlite3 *db; /* Connection pointer */
1168 const char *zDbFilename; /* Filename used to open the connection */
1169 char *zFreeOnClose; /* Free this memory allocation on close */
1170#if defined(SQLITE_ENABLE_SESSION)
1171 int nSession; /* Number of active sessions */
1172 OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */
1173#endif
1174 } aAuxDb[5], /* Array of all database connections */
1175 *pAuxDb; /* Currently active database connection */
drh2ce15c32017-07-11 13:34:40 +00001176 int *aiIndent; /* Array of indents used in MODE_Explain */
1177 int nIndent; /* Size of array aiIndent[] */
1178 int iIndent; /* Index of current op in aiIndent[] */
drhb97e2ad2021-08-26 18:31:39 +00001179 char *zNonce; /* Nonce for temporary safe-mode excapes */
drh4b5345c2018-04-24 13:07:40 +00001180 EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */
drhb97e2ad2021-08-26 18:31:39 +00001181 ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
drh2ce15c32017-07-11 13:34:40 +00001182};
1183
drh1fa6d9f2018-01-06 21:46:01 +00001184
drhada70452017-12-21 21:02:27 +00001185/* Allowed values for ShellState.autoEQP
1186*/
drhe2ca99c2018-05-02 00:33:43 +00001187#define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */
1188#define AUTOEQP_on 1 /* Automatic EQP is on */
1189#define AUTOEQP_trigger 2 /* On and also show plans for triggers */
1190#define AUTOEQP_full 3 /* Show full EXPLAIN */
drhada70452017-12-21 21:02:27 +00001191
drh1fa6d9f2018-01-06 21:46:01 +00001192/* Allowed values for ShellState.openMode
1193*/
drh60f34ae2018-10-30 13:19:49 +00001194#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
1195#define SHELL_OPEN_NORMAL 1 /* Normal database file */
1196#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
1197#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
1198#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
1199#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
drh33746482018-12-13 15:06:26 +00001200#define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */
drh1fa6d9f2018-01-06 21:46:01 +00001201
drh707821f2018-12-05 13:39:06 +00001202/* Allowed values for ShellState.eTraceType
1203*/
1204#define SHELL_TRACE_PLAIN 0 /* Show input SQL text */
1205#define SHELL_TRACE_EXPANDED 1 /* Show expanded SQL text */
1206#define SHELL_TRACE_NORMALIZED 2 /* Show normalized SQL text */
1207
drh3f83f592019-02-04 14:53:18 +00001208/* Bits in the ShellState.flgProgress variable */
drhfc4eeef2019-02-05 19:48:46 +00001209#define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */
1210#define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progres
1211 ** callback limit is reached, and for each
1212 ** top-level SQL statement */
1213#define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */
drh3f83f592019-02-04 14:53:18 +00001214
drh2ce15c32017-07-11 13:34:40 +00001215/*
1216** These are the allowed shellFlgs values
1217*/
drhb2a0f752017-08-28 15:51:35 +00001218#define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */
1219#define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */
1220#define SHFLG_Backslash 0x00000004 /* The --backslash option is used */
1221#define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */
1222#define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
1223#define SHFLG_CountChanges 0x00000020 /* .changes setting */
1224#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
larrybrae509122021-09-10 01:45:20 +00001225#define SHFLG_HeaderSet 0x00000080 /* showHeader has been specified */
drhc1962192020-10-12 16:54:28 +00001226#define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */
1227#define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */
drh2ce15c32017-07-11 13:34:40 +00001228
1229/*
1230** Macros for testing and setting shellFlgs
1231*/
1232#define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0)
1233#define ShellSetFlag(P,X) ((P)->shellFlgs|=(X))
1234#define ShellClearFlag(P,X) ((P)->shellFlgs&=(~(X)))
1235
1236/*
1237** These are the allowed modes.
1238*/
1239#define MODE_Line 0 /* One column per line. Blank line between records */
1240#define MODE_Column 1 /* One record per line in neat columns */
1241#define MODE_List 2 /* One record per line with a separator */
1242#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
1243#define MODE_Html 4 /* Generate an XHTML table */
1244#define MODE_Insert 5 /* Generate SQL "insert" statements */
1245#define MODE_Quote 6 /* Quote values as for SQL */
1246#define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */
1247#define MODE_Csv 8 /* Quote strings, numbers are plain */
1248#define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */
1249#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
1250#define MODE_Pretty 11 /* Pretty-print schemas */
drh4b5345c2018-04-24 13:07:40 +00001251#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
drh30c54a02020-05-28 23:49:50 +00001252#define MODE_Json 13 /* Output JSON */
1253#define MODE_Markdown 14 /* Markdown formatting */
1254#define MODE_Table 15 /* MySQL-style table formatting */
drh0908e382020-06-04 18:05:39 +00001255#define MODE_Box 16 /* Unicode box-drawing characters */
drh2ce15c32017-07-11 13:34:40 +00001256
1257static const char *modeDescr[] = {
1258 "line",
1259 "column",
1260 "list",
1261 "semi",
1262 "html",
1263 "insert",
1264 "quote",
1265 "tcl",
1266 "csv",
1267 "explain",
1268 "ascii",
1269 "prettyprint",
drh30c54a02020-05-28 23:49:50 +00001270 "eqp",
1271 "json",
1272 "markdown",
drh0908e382020-06-04 18:05:39 +00001273 "table",
1274 "box"
drh2ce15c32017-07-11 13:34:40 +00001275};
1276
1277/*
1278** These are the column/row/line separators used by the various
1279** import/export modes.
1280*/
1281#define SEP_Column "|"
1282#define SEP_Row "\n"
1283#define SEP_Tab "\t"
1284#define SEP_Space " "
1285#define SEP_Comma ","
1286#define SEP_CrLf "\r\n"
1287#define SEP_Unit "\x1F"
1288#define SEP_Record "\x1E"
1289
1290/*
drh2ce15c32017-07-11 13:34:40 +00001291** A callback for the sqlite3_log() interface.
1292*/
1293static void shellLog(void *pArg, int iErrCode, const char *zMsg){
1294 ShellState *p = (ShellState*)pArg;
1295 if( p->pLog==0 ) return;
1296 utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
1297 fflush(p->pLog);
1298}
1299
1300/*
drh634c70f2018-01-10 16:50:18 +00001301** SQL function: shell_putsnl(X)
1302**
1303** Write the text X to the screen (or whatever output is being directed)
1304** adding a newline at the end, and then return X.
1305*/
1306static void shellPutsFunc(
1307 sqlite3_context *pCtx,
1308 int nVal,
1309 sqlite3_value **apVal
1310){
1311 ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
drhb9685182018-01-17 13:15:23 +00001312 (void)nVal;
drh634c70f2018-01-10 16:50:18 +00001313 utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
1314 sqlite3_result_value(pCtx, apVal[0]);
1315}
1316
1317/*
drhb97e2ad2021-08-26 18:31:39 +00001318** If in safe mode, print an error message described by the arguments
1319** and exit immediately.
1320*/
1321static void failIfSafeMode(
1322 ShellState *p,
1323 const char *zErrMsg,
1324 ...
1325){
1326 if( p->bSafeMode ){
1327 va_list ap;
1328 char *zMsg;
1329 va_start(ap, zErrMsg);
1330 zMsg = sqlite3_vmprintf(zErrMsg, ap);
1331 va_end(ap);
1332 raw_printf(stderr, "line %d: ", p->lineno);
1333 utf8_printf(stderr, "%s\n", zMsg);
1334 exit(1);
1335 }
1336}
1337
1338/*
drh97913132018-01-11 00:04:00 +00001339** SQL function: edit(VALUE)
1340** edit(VALUE,EDITOR)
1341**
1342** These steps:
1343**
1344** (1) Write VALUE into a temporary file.
1345** (2) Run program EDITOR on that temporary file.
1346** (3) Read the temporary file back and return its content as the result.
1347** (4) Delete the temporary file
1348**
1349** If the EDITOR argument is omitted, use the value in the VISUAL
1350** environment variable. If still there is no EDITOR, through an error.
1351**
1352** Also throw an error if the EDITOR program returns a non-zero exit code.
1353*/
drh04a28c32018-01-31 01:38:44 +00001354#ifndef SQLITE_NOHAVE_SYSTEM
drh97913132018-01-11 00:04:00 +00001355static void editFunc(
1356 sqlite3_context *context,
1357 int argc,
1358 sqlite3_value **argv
1359){
1360 const char *zEditor;
1361 char *zTempFile = 0;
1362 sqlite3 *db;
1363 char *zCmd = 0;
1364 int bBin;
1365 int rc;
drhf018fd52018-08-06 02:08:53 +00001366 int hasCRNL = 0;
drh97913132018-01-11 00:04:00 +00001367 FILE *f = 0;
1368 sqlite3_int64 sz;
1369 sqlite3_int64 x;
1370 unsigned char *p = 0;
1371
1372 if( argc==2 ){
1373 zEditor = (const char*)sqlite3_value_text(argv[1]);
1374 }else{
1375 zEditor = getenv("VISUAL");
1376 }
1377 if( zEditor==0 ){
1378 sqlite3_result_error(context, "no editor for edit()", -1);
1379 return;
1380 }
1381 if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
1382 sqlite3_result_error(context, "NULL input to edit()", -1);
1383 return;
1384 }
1385 db = sqlite3_context_db_handle(context);
1386 zTempFile = 0;
1387 sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile);
1388 if( zTempFile==0 ){
1389 sqlite3_uint64 r = 0;
1390 sqlite3_randomness(sizeof(r), &r);
1391 zTempFile = sqlite3_mprintf("temp%llx", r);
1392 if( zTempFile==0 ){
1393 sqlite3_result_error_nomem(context);
1394 return;
1395 }
1396 }
1397 bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB;
drhf018fd52018-08-06 02:08:53 +00001398 /* When writing the file to be edited, do \n to \r\n conversions on systems
1399 ** that want \r\n line endings */
drh97913132018-01-11 00:04:00 +00001400 f = fopen(zTempFile, bBin ? "wb" : "w");
1401 if( f==0 ){
1402 sqlite3_result_error(context, "edit() cannot open temp file", -1);
1403 goto edit_func_end;
1404 }
1405 sz = sqlite3_value_bytes(argv[0]);
1406 if( bBin ){
dan4d02b5f2019-07-17 07:23:06 +00001407 x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001408 }else{
drhf018fd52018-08-06 02:08:53 +00001409 const char *z = (const char*)sqlite3_value_text(argv[0]);
1410 /* Remember whether or not the value originally contained \r\n */
1411 if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
dan4d02b5f2019-07-17 07:23:06 +00001412 x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001413 }
1414 fclose(f);
1415 f = 0;
1416 if( x!=sz ){
1417 sqlite3_result_error(context, "edit() could not write the whole file", -1);
1418 goto edit_func_end;
1419 }
1420 zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile);
1421 if( zCmd==0 ){
1422 sqlite3_result_error_nomem(context);
1423 goto edit_func_end;
1424 }
1425 rc = system(zCmd);
1426 sqlite3_free(zCmd);
1427 if( rc ){
1428 sqlite3_result_error(context, "EDITOR returned non-zero", -1);
1429 goto edit_func_end;
1430 }
drhf018fd52018-08-06 02:08:53 +00001431 f = fopen(zTempFile, "rb");
drh97913132018-01-11 00:04:00 +00001432 if( f==0 ){
1433 sqlite3_result_error(context,
1434 "edit() cannot reopen temp file after edit", -1);
1435 goto edit_func_end;
1436 }
1437 fseek(f, 0, SEEK_END);
1438 sz = ftell(f);
1439 rewind(f);
drhee37f8b2019-08-23 23:05:32 +00001440 p = sqlite3_malloc64( sz+1 );
drh97913132018-01-11 00:04:00 +00001441 if( p==0 ){
1442 sqlite3_result_error_nomem(context);
1443 goto edit_func_end;
1444 }
dan4d02b5f2019-07-17 07:23:06 +00001445 x = fread(p, 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001446 fclose(f);
1447 f = 0;
1448 if( x!=sz ){
1449 sqlite3_result_error(context, "could not read back the whole file", -1);
1450 goto edit_func_end;
1451 }
1452 if( bBin ){
mistachkinb71aa092018-01-23 00:05:18 +00001453 sqlite3_result_blob64(context, p, sz, sqlite3_free);
drh97913132018-01-11 00:04:00 +00001454 }else{
dan60bdcf52018-10-03 11:13:30 +00001455 sqlite3_int64 i, j;
drhf018fd52018-08-06 02:08:53 +00001456 if( hasCRNL ){
1457 /* If the original contains \r\n then do no conversions back to \n */
1458 j = sz;
1459 }else{
1460 /* If the file did not originally contain \r\n then convert any new
1461 ** \r\n back into \n */
1462 for(i=j=0; i<sz; i++){
1463 if( p[i]=='\r' && p[i+1]=='\n' ) i++;
1464 p[j++] = p[i];
1465 }
1466 sz = j;
1467 p[sz] = 0;
1468 }
mistachkinb71aa092018-01-23 00:05:18 +00001469 sqlite3_result_text64(context, (const char*)p, sz,
1470 sqlite3_free, SQLITE_UTF8);
drh97913132018-01-11 00:04:00 +00001471 }
1472 p = 0;
1473
1474edit_func_end:
1475 if( f ) fclose(f);
1476 unlink(zTempFile);
1477 sqlite3_free(zTempFile);
1478 sqlite3_free(p);
1479}
drh04a28c32018-01-31 01:38:44 +00001480#endif /* SQLITE_NOHAVE_SYSTEM */
drh97913132018-01-11 00:04:00 +00001481
1482/*
drh3c484e82018-01-10 22:27:21 +00001483** Save or restore the current output mode
1484*/
1485static void outputModePush(ShellState *p){
1486 p->modePrior = p->mode;
drh7a431002020-04-18 14:12:00 +00001487 p->priorShFlgs = p->shellFlgs;
drh3c484e82018-01-10 22:27:21 +00001488 memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));
1489 memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));
1490}
1491static void outputModePop(ShellState *p){
1492 p->mode = p->modePrior;
drh7a431002020-04-18 14:12:00 +00001493 p->shellFlgs = p->priorShFlgs;
drh3c484e82018-01-10 22:27:21 +00001494 memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
1495 memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
1496}
1497
1498/*
drh2ce15c32017-07-11 13:34:40 +00001499** Output the given string as a hex-encoded blob (eg. X'1234' )
1500*/
1501static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
1502 int i;
1503 char *zBlob = (char *)pBlob;
1504 raw_printf(out,"X'");
1505 for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); }
1506 raw_printf(out,"'");
1507}
1508
1509/*
1510** Find a string that is not found anywhere in z[]. Return a pointer
1511** to that string.
1512**
1513** Try to use zA and zB first. If both of those are already found in z[]
1514** then make up some string and store it in the buffer zBuf.
1515*/
1516static const char *unused_string(
1517 const char *z, /* Result must not appear anywhere in z */
1518 const char *zA, const char *zB, /* Try these first */
1519 char *zBuf /* Space to store a generated string */
1520){
1521 unsigned i = 0;
1522 if( strstr(z, zA)==0 ) return zA;
1523 if( strstr(z, zB)==0 ) return zB;
1524 do{
1525 sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
1526 }while( strstr(z,zBuf)!=0 );
1527 return zBuf;
1528}
1529
1530/*
1531** Output the given string as a quoted string using SQL quoting conventions.
1532**
1533** See also: output_quoted_escaped_string()
1534*/
1535static void output_quoted_string(FILE *out, const char *z){
1536 int i;
1537 char c;
1538 setBinaryMode(out, 1);
1539 for(i=0; (c = z[i])!=0 && c!='\''; i++){}
1540 if( c==0 ){
1541 utf8_printf(out,"'%s'",z);
1542 }else{
1543 raw_printf(out, "'");
1544 while( *z ){
1545 for(i=0; (c = z[i])!=0 && c!='\''; i++){}
1546 if( c=='\'' ) i++;
1547 if( i ){
1548 utf8_printf(out, "%.*s", i, z);
1549 z += i;
1550 }
1551 if( c=='\'' ){
1552 raw_printf(out, "'");
1553 continue;
1554 }
1555 if( c==0 ){
1556 break;
1557 }
1558 z++;
1559 }
1560 raw_printf(out, "'");
1561 }
1562 setTextMode(out, 1);
1563}
1564
1565/*
1566** Output the given string as a quoted string using SQL quoting conventions.
1567** Additionallly , escape the "\n" and "\r" characters so that they do not
1568** get corrupted by end-of-line translation facilities in some operating
1569** systems.
1570**
1571** This is like output_quoted_string() but with the addition of the \r\n
1572** escape mechanism.
1573*/
1574static void output_quoted_escaped_string(FILE *out, const char *z){
1575 int i;
1576 char c;
1577 setBinaryMode(out, 1);
1578 for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
1579 if( c==0 ){
1580 utf8_printf(out,"'%s'",z);
1581 }else{
1582 const char *zNL = 0;
1583 const char *zCR = 0;
1584 int nNL = 0;
1585 int nCR = 0;
1586 char zBuf1[20], zBuf2[20];
1587 for(i=0; z[i]; i++){
1588 if( z[i]=='\n' ) nNL++;
1589 if( z[i]=='\r' ) nCR++;
1590 }
1591 if( nNL ){
1592 raw_printf(out, "replace(");
1593 zNL = unused_string(z, "\\n", "\\012", zBuf1);
1594 }
1595 if( nCR ){
1596 raw_printf(out, "replace(");
1597 zCR = unused_string(z, "\\r", "\\015", zBuf2);
1598 }
1599 raw_printf(out, "'");
1600 while( *z ){
1601 for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
1602 if( c=='\'' ) i++;
1603 if( i ){
1604 utf8_printf(out, "%.*s", i, z);
1605 z += i;
1606 }
1607 if( c=='\'' ){
1608 raw_printf(out, "'");
1609 continue;
1610 }
1611 if( c==0 ){
1612 break;
1613 }
1614 z++;
1615 if( c=='\n' ){
1616 raw_printf(out, "%s", zNL);
1617 continue;
1618 }
1619 raw_printf(out, "%s", zCR);
1620 }
1621 raw_printf(out, "'");
1622 if( nCR ){
1623 raw_printf(out, ",'%s',char(13))", zCR);
1624 }
1625 if( nNL ){
1626 raw_printf(out, ",'%s',char(10))", zNL);
1627 }
1628 }
1629 setTextMode(out, 1);
1630}
1631
1632/*
1633** Output the given string as a quoted according to C or TCL quoting rules.
1634*/
1635static void output_c_string(FILE *out, const char *z){
1636 unsigned int c;
1637 fputc('"', out);
1638 while( (c = *(z++))!=0 ){
1639 if( c=='\\' ){
1640 fputc(c, out);
1641 fputc(c, out);
1642 }else if( c=='"' ){
1643 fputc('\\', out);
1644 fputc('"', out);
1645 }else if( c=='\t' ){
1646 fputc('\\', out);
1647 fputc('t', out);
1648 }else if( c=='\n' ){
1649 fputc('\\', out);
1650 fputc('n', out);
1651 }else if( c=='\r' ){
1652 fputc('\\', out);
1653 fputc('r', out);
1654 }else if( !isprint(c&0xff) ){
1655 raw_printf(out, "\\%03o", c&0xff);
1656 }else{
1657 fputc(c, out);
1658 }
1659 }
1660 fputc('"', out);
1661}
1662
1663/*
drh69c093d2020-05-29 00:21:43 +00001664** Output the given string as a quoted according to JSON quoting rules.
1665*/
1666static void output_json_string(FILE *out, const char *z, int n){
1667 unsigned int c;
1668 if( n<0 ) n = (int)strlen(z);
1669 fputc('"', out);
1670 while( n-- ){
1671 c = *(z++);
1672 if( c=='\\' || c=='"' ){
1673 fputc('\\', out);
1674 fputc(c, out);
1675 }else if( c<=0x1f ){
1676 fputc('\\', out);
1677 if( c=='\b' ){
1678 fputc('b', out);
1679 }else if( c=='\f' ){
1680 fputc('f', out);
1681 }else if( c=='\n' ){
1682 fputc('n', out);
1683 }else if( c=='\r' ){
1684 fputc('r', out);
1685 }else if( c=='\t' ){
1686 fputc('t', out);
1687 }else{
1688 raw_printf(out, "u%04x",c);
1689 }
1690 }else{
1691 fputc(c, out);
1692 }
1693 }
1694 fputc('"', out);
1695}
1696
1697/*
drh2ce15c32017-07-11 13:34:40 +00001698** Output the given string with characters that are special to
1699** HTML escaped.
1700*/
1701static void output_html_string(FILE *out, const char *z){
1702 int i;
1703 if( z==0 ) z = "";
1704 while( *z ){
1705 for(i=0; z[i]
1706 && z[i]!='<'
1707 && z[i]!='&'
1708 && z[i]!='>'
1709 && z[i]!='\"'
1710 && z[i]!='\'';
1711 i++){}
1712 if( i>0 ){
1713 utf8_printf(out,"%.*s",i,z);
1714 }
1715 if( z[i]=='<' ){
1716 raw_printf(out,"&lt;");
1717 }else if( z[i]=='&' ){
1718 raw_printf(out,"&amp;");
1719 }else if( z[i]=='>' ){
1720 raw_printf(out,"&gt;");
1721 }else if( z[i]=='\"' ){
1722 raw_printf(out,"&quot;");
1723 }else if( z[i]=='\'' ){
1724 raw_printf(out,"&#39;");
1725 }else{
1726 break;
1727 }
1728 z += i + 1;
1729 }
1730}
1731
1732/*
1733** If a field contains any character identified by a 1 in the following
1734** array, then the string must be quoted for CSV.
1735*/
1736static const char needCsvQuote[] = {
1737 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1738 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1739 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1740 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1741 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1742 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1743 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1744 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1745 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1746 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1747 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1748 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1749 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1750 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1751 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1752 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1753};
1754
1755/*
1756** Output a single term of CSV. Actually, p->colSeparator is used for
1757** the separator, which may or may not be a comma. p->nullValue is
1758** the null value. Strings are quoted if necessary. The separator
1759** is only issued if bSep is true.
1760*/
1761static void output_csv(ShellState *p, const char *z, int bSep){
1762 FILE *out = p->out;
1763 if( z==0 ){
1764 utf8_printf(out,"%s",p->nullValue);
1765 }else{
1766 int i;
1767 int nSep = strlen30(p->colSeparator);
1768 for(i=0; z[i]; i++){
1769 if( needCsvQuote[((unsigned char*)z)[i]]
1770 || (z[i]==p->colSeparator[0] &&
1771 (nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){
1772 i = 0;
1773 break;
1774 }
1775 }
1776 if( i==0 ){
drh9b7affc2017-11-26 02:14:18 +00001777 char *zQuoted = sqlite3_mprintf("\"%w\"", z);
1778 utf8_printf(out, "%s", zQuoted);
1779 sqlite3_free(zQuoted);
drh2ce15c32017-07-11 13:34:40 +00001780 }else{
1781 utf8_printf(out, "%s", z);
1782 }
1783 }
1784 if( bSep ){
1785 utf8_printf(p->out, "%s", p->colSeparator);
1786 }
1787}
1788
drh2ce15c32017-07-11 13:34:40 +00001789/*
1790** This routine runs when the user presses Ctrl-C
1791*/
1792static void interrupt_handler(int NotUsed){
1793 UNUSED_PARAMETER(NotUsed);
1794 seenInterrupt++;
1795 if( seenInterrupt>2 ) exit(1);
1796 if( globalDb ) sqlite3_interrupt(globalDb);
1797}
mistachkinb4bab902017-10-27 17:09:44 +00001798
1799#if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
1800/*
1801** This routine runs for console events (e.g. Ctrl-C) on Win32
1802*/
1803static BOOL WINAPI ConsoleCtrlHandler(
1804 DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */
1805){
1806 if( dwCtrlType==CTRL_C_EVENT ){
1807 interrupt_handler(0);
1808 return TRUE;
1809 }
1810 return FALSE;
1811}
drh2ce15c32017-07-11 13:34:40 +00001812#endif
1813
1814#ifndef SQLITE_OMIT_AUTHORIZATION
1815/*
drhb97e2ad2021-08-26 18:31:39 +00001816** This authorizer runs in safe mode.
1817*/
1818static int safeModeAuth(
1819 void *pClientData,
1820 int op,
1821 const char *zA1,
1822 const char *zA2,
1823 const char *zA3,
1824 const char *zA4
1825){
1826 ShellState *p = (ShellState*)pClientData;
1827 static const char *azProhibitedFunctions[] = {
1828 "edit",
1829 "fts3_tokenizer",
1830 "load_extension",
1831 "readfile",
1832 "writefile",
1833 "zipfile",
1834 "zipfile_cds",
1835 };
1836 UNUSED_PARAMETER(zA2);
1837 UNUSED_PARAMETER(zA3);
1838 UNUSED_PARAMETER(zA4);
1839 switch( op ){
1840 case SQLITE_ATTACH: {
1841 failIfSafeMode(p, "cannot run ATTACH in safe mode");
1842 break;
1843 }
1844 case SQLITE_FUNCTION: {
1845 int i;
1846 for(i=0; i<ArraySize(azProhibitedFunctions); i++){
1847 if( sqlite3_stricmp(zA1, azProhibitedFunctions[i])==0 ){
1848 failIfSafeMode(p, "cannot use the %s() function in safe mode",
1849 azProhibitedFunctions[i]);
1850 }
1851 }
1852 break;
1853 }
1854 }
1855 return SQLITE_OK;
1856}
1857
1858/*
drh2ce15c32017-07-11 13:34:40 +00001859** When the ".auth ON" is set, the following authorizer callback is
1860** invoked. It always returns SQLITE_OK.
1861*/
1862static int shellAuth(
1863 void *pClientData,
1864 int op,
1865 const char *zA1,
1866 const char *zA2,
1867 const char *zA3,
1868 const char *zA4
1869){
1870 ShellState *p = (ShellState*)pClientData;
1871 static const char *azAction[] = { 0,
1872 "CREATE_INDEX", "CREATE_TABLE", "CREATE_TEMP_INDEX",
1873 "CREATE_TEMP_TABLE", "CREATE_TEMP_TRIGGER", "CREATE_TEMP_VIEW",
1874 "CREATE_TRIGGER", "CREATE_VIEW", "DELETE",
1875 "DROP_INDEX", "DROP_TABLE", "DROP_TEMP_INDEX",
1876 "DROP_TEMP_TABLE", "DROP_TEMP_TRIGGER", "DROP_TEMP_VIEW",
1877 "DROP_TRIGGER", "DROP_VIEW", "INSERT",
1878 "PRAGMA", "READ", "SELECT",
1879 "TRANSACTION", "UPDATE", "ATTACH",
1880 "DETACH", "ALTER_TABLE", "REINDEX",
1881 "ANALYZE", "CREATE_VTABLE", "DROP_VTABLE",
1882 "FUNCTION", "SAVEPOINT", "RECURSIVE"
1883 };
1884 int i;
1885 const char *az[4];
1886 az[0] = zA1;
1887 az[1] = zA2;
1888 az[2] = zA3;
1889 az[3] = zA4;
1890 utf8_printf(p->out, "authorizer: %s", azAction[op]);
1891 for(i=0; i<4; i++){
1892 raw_printf(p->out, " ");
1893 if( az[i] ){
1894 output_c_string(p->out, az[i]);
1895 }else{
1896 raw_printf(p->out, "NULL");
1897 }
1898 }
1899 raw_printf(p->out, "\n");
drhb97e2ad2021-08-26 18:31:39 +00001900 if( p->bSafeMode ) (void)safeModeAuth(pClientData, op, zA1, zA2, zA3, zA4);
drh2ce15c32017-07-11 13:34:40 +00001901 return SQLITE_OK;
1902}
1903#endif
1904
1905/*
1906** Print a schema statement. Part of MODE_Semi and MODE_Pretty output.
1907**
1908** This routine converts some CREATE TABLE statements for shadow tables
1909** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
1910*/
1911static void printSchemaLine(FILE *out, const char *z, const char *zTail){
drh0a0536a2019-05-09 18:13:30 +00001912 if( z==0 ) return;
1913 if( zTail==0 ) return;
drh2ce15c32017-07-11 13:34:40 +00001914 if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
1915 utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
1916 }else{
1917 utf8_printf(out, "%s%s", z, zTail);
1918 }
1919}
1920static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
1921 char c = z[n];
1922 z[n] = 0;
1923 printSchemaLine(out, z, zTail);
1924 z[n] = c;
1925}
1926
1927/*
drh11be81d2018-01-06 15:46:20 +00001928** Return true if string z[] has nothing but whitespace and comments to the
1929** end of the first line.
1930*/
1931static int wsToEol(const char *z){
1932 int i;
1933 for(i=0; z[i]; i++){
1934 if( z[i]=='\n' ) return 1;
1935 if( IsSpace(z[i]) ) continue;
1936 if( z[i]=='-' && z[i+1]=='-' ) return 1;
1937 return 0;
1938 }
1939 return 1;
1940}
drh4b5345c2018-04-24 13:07:40 +00001941
1942/*
1943** Add a new entry to the EXPLAIN QUERY PLAN data
1944*/
drhe2ca99c2018-05-02 00:33:43 +00001945static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
drh4b5345c2018-04-24 13:07:40 +00001946 EQPGraphRow *pNew;
1947 int nText = strlen30(zText);
drhe2ca99c2018-05-02 00:33:43 +00001948 if( p->autoEQPtest ){
1949 utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
1950 }
drh4b5345c2018-04-24 13:07:40 +00001951 pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
1952 if( pNew==0 ) shell_out_of_memory();
drhe2ca99c2018-05-02 00:33:43 +00001953 pNew->iEqpId = iEqpId;
1954 pNew->iParentId = p2;
drh4b5345c2018-04-24 13:07:40 +00001955 memcpy(pNew->zText, zText, nText+1);
1956 pNew->pNext = 0;
1957 if( p->sGraph.pLast ){
1958 p->sGraph.pLast->pNext = pNew;
1959 }else{
1960 p->sGraph.pRow = pNew;
1961 }
1962 p->sGraph.pLast = pNew;
1963}
1964
1965/*
1966** Free and reset the EXPLAIN QUERY PLAN data that has been collected
1967** in p->sGraph.
1968*/
1969static void eqp_reset(ShellState *p){
1970 EQPGraphRow *pRow, *pNext;
1971 for(pRow = p->sGraph.pRow; pRow; pRow = pNext){
1972 pNext = pRow->pNext;
1973 sqlite3_free(pRow);
1974 }
1975 memset(&p->sGraph, 0, sizeof(p->sGraph));
1976}
1977
drhe2ca99c2018-05-02 00:33:43 +00001978/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after
drh4b5345c2018-04-24 13:07:40 +00001979** pOld, or return the first such line if pOld is NULL
1980*/
drhe2ca99c2018-05-02 00:33:43 +00001981static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){
drh4b5345c2018-04-24 13:07:40 +00001982 EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow;
drhe2ca99c2018-05-02 00:33:43 +00001983 while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext;
drh4b5345c2018-04-24 13:07:40 +00001984 return pRow;
1985}
1986
drhe2ca99c2018-05-02 00:33:43 +00001987/* Render a single level of the graph that has iEqpId as its parent. Called
drh4b5345c2018-04-24 13:07:40 +00001988** recursively to render sublevels.
1989*/
drhe2ca99c2018-05-02 00:33:43 +00001990static void eqp_render_level(ShellState *p, int iEqpId){
drh4b5345c2018-04-24 13:07:40 +00001991 EQPGraphRow *pRow, *pNext;
drh4b5345c2018-04-24 13:07:40 +00001992 int n = strlen30(p->sGraph.zPrefix);
1993 char *z;
drhe2ca99c2018-05-02 00:33:43 +00001994 for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
1995 pNext = eqp_next_row(p, iEqpId, pRow);
drh4b5345c2018-04-24 13:07:40 +00001996 z = pRow->zText;
drhe2754c12019-08-26 12:50:01 +00001997 utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
1998 pNext ? "|--" : "`--", z);
drhe2188f02018-05-07 11:37:34 +00001999 if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){
drh4b5345c2018-04-24 13:07:40 +00002000 memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4);
drhe2ca99c2018-05-02 00:33:43 +00002001 eqp_render_level(p, pRow->iEqpId);
drh4b5345c2018-04-24 13:07:40 +00002002 p->sGraph.zPrefix[n] = 0;
2003 }
2004 }
2005}
2006
2007/*
2008** Display and reset the EXPLAIN QUERY PLAN data
2009*/
2010static void eqp_render(ShellState *p){
2011 EQPGraphRow *pRow = p->sGraph.pRow;
2012 if( pRow ){
2013 if( pRow->zText[0]=='-' ){
2014 if( pRow->pNext==0 ){
2015 eqp_reset(p);
2016 return;
2017 }
2018 utf8_printf(p->out, "%s\n", pRow->zText+3);
2019 p->sGraph.pRow = pRow->pNext;
2020 sqlite3_free(pRow);
2021 }else{
2022 utf8_printf(p->out, "QUERY PLAN\n");
2023 }
2024 p->sGraph.zPrefix[0] = 0;
2025 eqp_render_level(p, 0);
2026 eqp_reset(p);
2027 }
2028}
drh11be81d2018-01-06 15:46:20 +00002029
drh569b1d92019-02-05 20:51:41 +00002030#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh11be81d2018-01-06 15:46:20 +00002031/*
drh3f83f592019-02-04 14:53:18 +00002032** Progress handler callback.
2033*/
2034static int progress_handler(void *pClientData) {
2035 ShellState *p = (ShellState*)pClientData;
2036 p->nProgress++;
2037 if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
2038 raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
drhfc4eeef2019-02-05 19:48:46 +00002039 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
2040 if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
drh3f83f592019-02-04 14:53:18 +00002041 return 1;
2042 }
drhfc4eeef2019-02-05 19:48:46 +00002043 if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
drh3f83f592019-02-04 14:53:18 +00002044 raw_printf(p->out, "Progress %u\n", p->nProgress);
2045 }
2046 return 0;
2047}
drh569b1d92019-02-05 20:51:41 +00002048#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
drh3f83f592019-02-04 14:53:18 +00002049
2050/*
drh30c54a02020-05-28 23:49:50 +00002051** Print N dashes
2052*/
2053static void print_dashes(FILE *out, int N){
2054 const char zDash[] = "--------------------------------------------------";
2055 const int nDash = sizeof(zDash) - 1;
2056 while( N>nDash ){
2057 fputs(zDash, out);
2058 N -= nDash;
2059 }
2060 raw_printf(out, "%.*s", N, zDash);
2061}
2062
2063/*
drh0908e382020-06-04 18:05:39 +00002064** Print a markdown or table-style row separator using ascii-art
drh30c54a02020-05-28 23:49:50 +00002065*/
2066static void print_row_separator(
2067 ShellState *p,
2068 int nArg,
2069 const char *zSep
2070){
2071 int i;
drh0908e382020-06-04 18:05:39 +00002072 if( nArg>0 ){
drh30c54a02020-05-28 23:49:50 +00002073 fputs(zSep, p->out);
drh0908e382020-06-04 18:05:39 +00002074 print_dashes(p->out, p->actualWidth[0]+2);
2075 for(i=1; i<nArg; i++){
2076 fputs(zSep, p->out);
2077 print_dashes(p->out, p->actualWidth[i]+2);
2078 }
2079 fputs(zSep, p->out);
drh30c54a02020-05-28 23:49:50 +00002080 }
drh30c54a02020-05-28 23:49:50 +00002081 fputs("\n", p->out);
2082}
2083
2084/*
drh2ce15c32017-07-11 13:34:40 +00002085** This is the callback routine that the shell
2086** invokes for each row of a query result.
2087*/
2088static int shell_callback(
2089 void *pArg,
2090 int nArg, /* Number of result columns */
2091 char **azArg, /* Text of each result column */
2092 char **azCol, /* Column names */
drhd6f25242020-05-29 12:31:53 +00002093 int *aiType /* Column types. Might be NULL */
drh2ce15c32017-07-11 13:34:40 +00002094){
2095 int i;
2096 ShellState *p = (ShellState*)pArg;
2097
drhb3c45232017-08-28 14:33:27 +00002098 if( azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00002099 switch( p->cMode ){
2100 case MODE_Line: {
2101 int w = 5;
2102 if( azArg==0 ) break;
2103 for(i=0; i<nArg; i++){
2104 int len = strlen30(azCol[i] ? azCol[i] : "");
2105 if( len>w ) w = len;
2106 }
2107 if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
2108 for(i=0; i<nArg; i++){
2109 utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
2110 azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
2111 }
2112 break;
2113 }
drh8c748632020-05-29 16:15:58 +00002114 case MODE_Explain: {
2115 static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
2116 if( nArg>ArraySize(aExplainWidth) ){
2117 nArg = ArraySize(aExplainWidth);
drh2ce15c32017-07-11 13:34:40 +00002118 }
2119 if( p->cnt++==0 ){
2120 for(i=0; i<nArg; i++){
drh8c748632020-05-29 16:15:58 +00002121 int w = aExplainWidth[i];
2122 utf8_width_print(p->out, w, azCol[i]);
2123 fputs(i==nArg-1 ? "\n" : " ", p->out);
drh2ce15c32017-07-11 13:34:40 +00002124 }
drhe566ceb2020-05-30 15:34:49 +00002125 for(i=0; i<nArg; i++){
2126 int w = aExplainWidth[i];
2127 print_dashes(p->out, w);
2128 fputs(i==nArg-1 ? "\n" : " ", p->out);
2129 }
drh2ce15c32017-07-11 13:34:40 +00002130 }
2131 if( azArg==0 ) break;
2132 for(i=0; i<nArg; i++){
drh8c748632020-05-29 16:15:58 +00002133 int w = aExplainWidth[i];
drhaa556b02021-01-13 12:59:20 +00002134 if( i==nArg-1 ) w = 0;
drh8c748632020-05-29 16:15:58 +00002135 if( azArg[i] && strlenChar(azArg[i])>w ){
2136 w = strlenChar(azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00002137 }
drh8c748632020-05-29 16:15:58 +00002138 if( i==1 && p->aiIndent && p->pStmt ){
2139 if( p->iIndent<p->nIndent ){
2140 utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
drh2ce15c32017-07-11 13:34:40 +00002141 }
drh8c748632020-05-29 16:15:58 +00002142 p->iIndent++;
drh2ce15c32017-07-11 13:34:40 +00002143 }
2144 utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
drh8c748632020-05-29 16:15:58 +00002145 fputs(i==nArg-1 ? "\n" : " ", p->out);
drh2ce15c32017-07-11 13:34:40 +00002146 }
2147 break;
2148 }
2149 case MODE_Semi: { /* .schema and .fullschema output */
2150 printSchemaLine(p->out, azArg[0], ";\n");
2151 break;
2152 }
2153 case MODE_Pretty: { /* .schema and .fullschema with --indent */
2154 char *z;
2155 int j;
2156 int nParen = 0;
2157 char cEnd = 0;
2158 char c;
2159 int nLine = 0;
2160 assert( nArg==1 );
2161 if( azArg[0]==0 ) break;
2162 if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
2163 || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
2164 ){
2165 utf8_printf(p->out, "%s;\n", azArg[0]);
2166 break;
2167 }
2168 z = sqlite3_mprintf("%s", azArg[0]);
2169 j = 0;
2170 for(i=0; IsSpace(z[i]); i++){}
2171 for(; (c = z[i])!=0; i++){
2172 if( IsSpace(c) ){
drhc3cbd672017-10-05 19:12:10 +00002173 if( z[j-1]=='\r' ) z[j-1] = '\n';
drh2ce15c32017-07-11 13:34:40 +00002174 if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
2175 }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
2176 j--;
2177 }
2178 z[j++] = c;
2179 }
2180 while( j>0 && IsSpace(z[j-1]) ){ j--; }
2181 z[j] = 0;
2182 if( strlen30(z)>=79 ){
drhe2754c12019-08-26 12:50:01 +00002183 for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */
drh2ce15c32017-07-11 13:34:40 +00002184 if( c==cEnd ){
2185 cEnd = 0;
2186 }else if( c=='"' || c=='\'' || c=='`' ){
2187 cEnd = c;
2188 }else if( c=='[' ){
2189 cEnd = ']';
drh11be81d2018-01-06 15:46:20 +00002190 }else if( c=='-' && z[i+1]=='-' ){
2191 cEnd = '\n';
drh2ce15c32017-07-11 13:34:40 +00002192 }else if( c=='(' ){
2193 nParen++;
2194 }else if( c==')' ){
2195 nParen--;
2196 if( nLine>0 && nParen==0 && j>0 ){
2197 printSchemaLineN(p->out, z, j, "\n");
2198 j = 0;
2199 }
2200 }
2201 z[j++] = c;
drh11be81d2018-01-06 15:46:20 +00002202 if( nParen==1 && cEnd==0
2203 && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
2204 ){
drh2ce15c32017-07-11 13:34:40 +00002205 if( c=='\n' ) j--;
2206 printSchemaLineN(p->out, z, j, "\n ");
2207 j = 0;
2208 nLine++;
2209 while( IsSpace(z[i+1]) ){ i++; }
2210 }
2211 }
2212 z[j] = 0;
2213 }
2214 printSchemaLine(p->out, z, ";\n");
2215 sqlite3_free(z);
2216 break;
2217 }
2218 case MODE_List: {
2219 if( p->cnt++==0 && p->showHeader ){
2220 for(i=0; i<nArg; i++){
2221 utf8_printf(p->out,"%s%s",azCol[i],
2222 i==nArg-1 ? p->rowSeparator : p->colSeparator);
2223 }
2224 }
2225 if( azArg==0 ) break;
2226 for(i=0; i<nArg; i++){
2227 char *z = azArg[i];
2228 if( z==0 ) z = p->nullValue;
2229 utf8_printf(p->out, "%s", z);
2230 if( i<nArg-1 ){
2231 utf8_printf(p->out, "%s", p->colSeparator);
2232 }else{
2233 utf8_printf(p->out, "%s", p->rowSeparator);
2234 }
2235 }
2236 break;
2237 }
2238 case MODE_Html: {
2239 if( p->cnt++==0 && p->showHeader ){
2240 raw_printf(p->out,"<TR>");
2241 for(i=0; i<nArg; i++){
2242 raw_printf(p->out,"<TH>");
2243 output_html_string(p->out, azCol[i]);
2244 raw_printf(p->out,"</TH>\n");
2245 }
2246 raw_printf(p->out,"</TR>\n");
2247 }
2248 if( azArg==0 ) break;
2249 raw_printf(p->out,"<TR>");
2250 for(i=0; i<nArg; i++){
2251 raw_printf(p->out,"<TD>");
2252 output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
2253 raw_printf(p->out,"</TD>\n");
2254 }
2255 raw_printf(p->out,"</TR>\n");
2256 break;
2257 }
2258 case MODE_Tcl: {
2259 if( p->cnt++==0 && p->showHeader ){
2260 for(i=0; i<nArg; i++){
2261 output_c_string(p->out,azCol[i] ? azCol[i] : "");
2262 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
2263 }
2264 utf8_printf(p->out, "%s", p->rowSeparator);
2265 }
2266 if( azArg==0 ) break;
2267 for(i=0; i<nArg; i++){
2268 output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
2269 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
2270 }
2271 utf8_printf(p->out, "%s", p->rowSeparator);
2272 break;
2273 }
2274 case MODE_Csv: {
2275 setBinaryMode(p->out, 1);
2276 if( p->cnt++==0 && p->showHeader ){
2277 for(i=0; i<nArg; i++){
2278 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
2279 }
2280 utf8_printf(p->out, "%s", p->rowSeparator);
2281 }
2282 if( nArg>0 ){
2283 for(i=0; i<nArg; i++){
2284 output_csv(p, azArg[i], i<nArg-1);
2285 }
2286 utf8_printf(p->out, "%s", p->rowSeparator);
2287 }
2288 setTextMode(p->out, 1);
2289 break;
2290 }
2291 case MODE_Insert: {
2292 if( azArg==0 ) break;
2293 utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
2294 if( p->showHeader ){
2295 raw_printf(p->out,"(");
2296 for(i=0; i<nArg; i++){
2297 if( i>0 ) raw_printf(p->out, ",");
2298 if( quoteChar(azCol[i]) ){
2299 char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
2300 utf8_printf(p->out, "%s", z);
2301 sqlite3_free(z);
2302 }else{
2303 raw_printf(p->out, "%s", azCol[i]);
2304 }
2305 }
2306 raw_printf(p->out,")");
2307 }
2308 p->cnt++;
2309 for(i=0; i<nArg; i++){
2310 raw_printf(p->out, i>0 ? "," : " VALUES(");
2311 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2312 utf8_printf(p->out,"NULL");
2313 }else if( aiType && aiType[i]==SQLITE_TEXT ){
2314 if( ShellHasFlag(p, SHFLG_Newlines) ){
2315 output_quoted_string(p->out, azArg[i]);
2316 }else{
2317 output_quoted_escaped_string(p->out, azArg[i]);
2318 }
2319 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
2320 utf8_printf(p->out,"%s", azArg[i]);
2321 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2322 char z[50];
2323 double r = sqlite3_column_double(p->pStmt, i);
drh2f1f8802018-06-13 17:19:20 +00002324 sqlite3_uint64 ur;
2325 memcpy(&ur,&r,sizeof(r));
2326 if( ur==0x7ff0000000000000LL ){
2327 raw_printf(p->out, "1e999");
2328 }else if( ur==0xfff0000000000000LL ){
2329 raw_printf(p->out, "-1e999");
2330 }else{
2331 sqlite3_snprintf(50,z,"%!.20g", r);
2332 raw_printf(p->out, "%s", z);
2333 }
drh2ce15c32017-07-11 13:34:40 +00002334 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2335 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2336 int nBlob = sqlite3_column_bytes(p->pStmt, i);
2337 output_hex_blob(p->out, pBlob, nBlob);
2338 }else if( isNumber(azArg[i], 0) ){
2339 utf8_printf(p->out,"%s", azArg[i]);
2340 }else if( ShellHasFlag(p, SHFLG_Newlines) ){
2341 output_quoted_string(p->out, azArg[i]);
2342 }else{
2343 output_quoted_escaped_string(p->out, azArg[i]);
2344 }
2345 }
2346 raw_printf(p->out,");\n");
2347 break;
2348 }
drh30c54a02020-05-28 23:49:50 +00002349 case MODE_Json: {
2350 if( azArg==0 ) break;
2351 if( p->cnt==0 ){
2352 fputs("[{", p->out);
2353 }else{
2354 fputs(",\n{", p->out);
2355 }
2356 p->cnt++;
2357 for(i=0; i<nArg; i++){
drh69c093d2020-05-29 00:21:43 +00002358 output_json_string(p->out, azCol[i], -1);
drh30c54a02020-05-28 23:49:50 +00002359 putc(':', p->out);
2360 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2361 fputs("null",p->out);
2362 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2363 char z[50];
2364 double r = sqlite3_column_double(p->pStmt, i);
2365 sqlite3_uint64 ur;
2366 memcpy(&ur,&r,sizeof(r));
2367 if( ur==0x7ff0000000000000LL ){
2368 raw_printf(p->out, "1e999");
2369 }else if( ur==0xfff0000000000000LL ){
2370 raw_printf(p->out, "-1e999");
2371 }else{
2372 sqlite3_snprintf(50,z,"%!.20g", r);
2373 raw_printf(p->out, "%s", z);
2374 }
2375 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2376 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2377 int nBlob = sqlite3_column_bytes(p->pStmt, i);
drh69c093d2020-05-29 00:21:43 +00002378 output_json_string(p->out, pBlob, nBlob);
drh30c54a02020-05-28 23:49:50 +00002379 }else if( aiType && aiType[i]==SQLITE_TEXT ){
drh69c093d2020-05-29 00:21:43 +00002380 output_json_string(p->out, azArg[i], -1);
drh30c54a02020-05-28 23:49:50 +00002381 }else{
2382 utf8_printf(p->out,"%s", azArg[i]);
2383 }
2384 if( i<nArg-1 ){
2385 putc(',', p->out);
2386 }
2387 }
2388 putc('}', p->out);
2389 break;
2390 }
drh2ce15c32017-07-11 13:34:40 +00002391 case MODE_Quote: {
2392 if( azArg==0 ) break;
2393 if( p->cnt==0 && p->showHeader ){
2394 for(i=0; i<nArg; i++){
drhc6835732020-05-28 20:37:17 +00002395 if( i>0 ) fputs(p->colSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002396 output_quoted_string(p->out, azCol[i]);
2397 }
drhc6835732020-05-28 20:37:17 +00002398 fputs(p->rowSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002399 }
2400 p->cnt++;
2401 for(i=0; i<nArg; i++){
drhc6835732020-05-28 20:37:17 +00002402 if( i>0 ) fputs(p->colSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002403 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2404 utf8_printf(p->out,"NULL");
2405 }else if( aiType && aiType[i]==SQLITE_TEXT ){
2406 output_quoted_string(p->out, azArg[i]);
2407 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
2408 utf8_printf(p->out,"%s", azArg[i]);
2409 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2410 char z[50];
2411 double r = sqlite3_column_double(p->pStmt, i);
2412 sqlite3_snprintf(50,z,"%!.20g", r);
2413 raw_printf(p->out, "%s", z);
2414 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2415 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2416 int nBlob = sqlite3_column_bytes(p->pStmt, i);
2417 output_hex_blob(p->out, pBlob, nBlob);
2418 }else if( isNumber(azArg[i], 0) ){
2419 utf8_printf(p->out,"%s", azArg[i]);
2420 }else{
2421 output_quoted_string(p->out, azArg[i]);
2422 }
2423 }
drhc6835732020-05-28 20:37:17 +00002424 fputs(p->rowSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002425 break;
2426 }
2427 case MODE_Ascii: {
2428 if( p->cnt++==0 && p->showHeader ){
2429 for(i=0; i<nArg; i++){
2430 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
2431 utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
2432 }
2433 utf8_printf(p->out, "%s", p->rowSeparator);
2434 }
2435 if( azArg==0 ) break;
2436 for(i=0; i<nArg; i++){
2437 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
2438 utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
2439 }
2440 utf8_printf(p->out, "%s", p->rowSeparator);
2441 break;
2442 }
drh4b5345c2018-04-24 13:07:40 +00002443 case MODE_EQP: {
drhe2ca99c2018-05-02 00:33:43 +00002444 eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]);
drh4b5345c2018-04-24 13:07:40 +00002445 break;
2446 }
drh2ce15c32017-07-11 13:34:40 +00002447 }
2448 return 0;
2449}
2450
2451/*
2452** This is the callback routine that the SQLite library
2453** invokes for each row of a query result.
2454*/
2455static int callback(void *pArg, int nArg, char **azArg, char **azCol){
2456 /* since we don't have type info, call the shell_callback with a NULL value */
2457 return shell_callback(pArg, nArg, azArg, azCol, NULL);
2458}
2459
2460/*
2461** This is the callback routine from sqlite3_exec() that appends all
2462** output onto the end of a ShellText object.
2463*/
2464static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
2465 ShellText *p = (ShellText*)pArg;
2466 int i;
2467 UNUSED_PARAMETER(az);
drhb3c45232017-08-28 14:33:27 +00002468 if( azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00002469 if( p->n ) appendText(p, "|", 0);
2470 for(i=0; i<nArg; i++){
2471 if( i ) appendText(p, ",", 0);
2472 if( azArg[i] ) appendText(p, azArg[i], 0);
2473 }
2474 return 0;
2475}
2476
2477/*
2478** Generate an appropriate SELFTEST table in the main database.
2479*/
2480static void createSelftestTable(ShellState *p){
2481 char *zErrMsg = 0;
2482 sqlite3_exec(p->db,
2483 "SAVEPOINT selftest_init;\n"
2484 "CREATE TABLE IF NOT EXISTS selftest(\n"
2485 " tno INTEGER PRIMARY KEY,\n" /* Test number */
2486 " op TEXT,\n" /* Operator: memo run */
2487 " cmd TEXT,\n" /* Command text */
2488 " ans TEXT\n" /* Desired answer */
2489 ");"
2490 "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n"
2491 "INSERT INTO [_shell$self](rowid,op,cmd)\n"
2492 " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n"
2493 " 'memo','Tests generated by --init');\n"
2494 "INSERT INTO [_shell$self]\n"
2495 " SELECT 'run',\n"
2496 " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql "
drh067b92b2020-06-19 15:24:12 +00002497 "FROM sqlite_schema ORDER BY 2'',224))',\n"
drh2ce15c32017-07-11 13:34:40 +00002498 " hex(sha3_query('SELECT type,name,tbl_name,sql "
drh067b92b2020-06-19 15:24:12 +00002499 "FROM sqlite_schema ORDER BY 2',224));\n"
drh2ce15c32017-07-11 13:34:40 +00002500 "INSERT INTO [_shell$self]\n"
2501 " SELECT 'run',"
2502 " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||"
2503 " printf('%w',name) || '\" NOT INDEXED'',224))',\n"
2504 " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"
2505 " FROM (\n"
drh067b92b2020-06-19 15:24:12 +00002506 " SELECT name FROM sqlite_schema\n"
drh2ce15c32017-07-11 13:34:40 +00002507 " WHERE type='table'\n"
2508 " AND name<>'selftest'\n"
2509 " AND coalesce(rootpage,0)>0\n"
2510 " )\n"
2511 " ORDER BY name;\n"
2512 "INSERT INTO [_shell$self]\n"
2513 " VALUES('run','PRAGMA integrity_check','ok');\n"
2514 "INSERT INTO selftest(tno,op,cmd,ans)"
2515 " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n"
2516 "DROP TABLE [_shell$self];"
2517 ,0,0,&zErrMsg);
2518 if( zErrMsg ){
2519 utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
2520 sqlite3_free(zErrMsg);
2521 }
2522 sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
2523}
2524
2525
2526/*
2527** Set the destination table field of the ShellState structure to
2528** the name of the table given. Escape any quote characters in the
2529** table name.
2530*/
2531static void set_table_name(ShellState *p, const char *zName){
2532 int i, n;
mistachkin2158a0c2017-09-09 00:51:36 +00002533 char cQuote;
drh2ce15c32017-07-11 13:34:40 +00002534 char *z;
2535
2536 if( p->zDestTable ){
2537 free(p->zDestTable);
2538 p->zDestTable = 0;
2539 }
2540 if( zName==0 ) return;
2541 cQuote = quoteChar(zName);
2542 n = strlen30(zName);
2543 if( cQuote ) n += n+2;
2544 z = p->zDestTable = malloc( n+1 );
drh4b5345c2018-04-24 13:07:40 +00002545 if( z==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00002546 n = 0;
2547 if( cQuote ) z[n++] = cQuote;
2548 for(i=0; zName[i]; i++){
2549 z[n++] = zName[i];
2550 if( zName[i]==cQuote ) z[n++] = cQuote;
2551 }
2552 if( cQuote ) z[n++] = cQuote;
2553 z[n] = 0;
2554}
2555
2556
2557/*
2558** Execute a query statement that will generate SQL output. Print
2559** the result columns, comma-separated, on a line and then add a
2560** semicolon terminator to the end of that line.
2561**
2562** If the number of columns is 1 and that column contains text "--"
2563** then write the semicolon on a separate line. That way, if a
2564** "--" comment occurs at the end of the statement, the comment
2565** won't consume the semicolon terminator.
2566*/
2567static int run_table_dump_query(
2568 ShellState *p, /* Query context */
drh8e9297f2020-03-25 12:50:13 +00002569 const char *zSelect /* SELECT statement to extract content */
drh2ce15c32017-07-11 13:34:40 +00002570){
2571 sqlite3_stmt *pSelect;
2572 int rc;
2573 int nResult;
2574 int i;
2575 const char *z;
2576 rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
2577 if( rc!=SQLITE_OK || !pSelect ){
2578 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
2579 sqlite3_errmsg(p->db));
2580 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
2581 return rc;
2582 }
2583 rc = sqlite3_step(pSelect);
2584 nResult = sqlite3_column_count(pSelect);
2585 while( rc==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00002586 z = (const char*)sqlite3_column_text(pSelect, 0);
2587 utf8_printf(p->out, "%s", z);
2588 for(i=1; i<nResult; i++){
2589 utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
2590 }
2591 if( z==0 ) z = "";
2592 while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
2593 if( z[0] ){
2594 raw_printf(p->out, "\n;\n");
2595 }else{
2596 raw_printf(p->out, ";\n");
2597 }
2598 rc = sqlite3_step(pSelect);
2599 }
2600 rc = sqlite3_finalize(pSelect);
2601 if( rc!=SQLITE_OK ){
2602 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
2603 sqlite3_errmsg(p->db));
2604 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
2605 }
2606 return rc;
2607}
2608
2609/*
2610** Allocate space and save off current error string.
2611*/
2612static char *save_err_msg(
2613 sqlite3 *db /* Database to query */
2614){
2615 int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
2616 char *zErrMsg = sqlite3_malloc64(nErrMsg);
2617 if( zErrMsg ){
2618 memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
2619 }
2620 return zErrMsg;
2621}
2622
2623#ifdef __linux__
2624/*
2625** Attempt to display I/O stats on Linux using /proc/PID/io
2626*/
2627static void displayLinuxIoStats(FILE *out){
2628 FILE *in;
2629 char z[200];
2630 sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
2631 in = fopen(z, "rb");
2632 if( in==0 ) return;
2633 while( fgets(z, sizeof(z), in)!=0 ){
2634 static const struct {
2635 const char *zPattern;
2636 const char *zDesc;
2637 } aTrans[] = {
2638 { "rchar: ", "Bytes received by read():" },
2639 { "wchar: ", "Bytes sent to write():" },
2640 { "syscr: ", "Read() system calls:" },
2641 { "syscw: ", "Write() system calls:" },
2642 { "read_bytes: ", "Bytes read from storage:" },
2643 { "write_bytes: ", "Bytes written to storage:" },
2644 { "cancelled_write_bytes: ", "Cancelled write bytes:" },
2645 };
2646 int i;
2647 for(i=0; i<ArraySize(aTrans); i++){
drhaf2770f2018-01-05 14:55:43 +00002648 int n = strlen30(aTrans[i].zPattern);
drh2ce15c32017-07-11 13:34:40 +00002649 if( strncmp(aTrans[i].zPattern, z, n)==0 ){
2650 utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
2651 break;
2652 }
2653 }
2654 }
2655 fclose(in);
2656}
2657#endif
2658
2659/*
2660** Display a single line of status using 64-bit values.
2661*/
2662static void displayStatLine(
2663 ShellState *p, /* The shell context */
2664 char *zLabel, /* Label for this one line */
2665 char *zFormat, /* Format for the result */
2666 int iStatusCtrl, /* Which status to display */
2667 int bReset /* True to reset the stats */
2668){
2669 sqlite3_int64 iCur = -1;
2670 sqlite3_int64 iHiwtr = -1;
2671 int i, nPercent;
2672 char zLine[200];
2673 sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset);
2674 for(i=0, nPercent=0; zFormat[i]; i++){
2675 if( zFormat[i]=='%' ) nPercent++;
2676 }
2677 if( nPercent>1 ){
2678 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr);
2679 }else{
2680 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
2681 }
2682 raw_printf(p->out, "%-36s %s\n", zLabel, zLine);
2683}
2684
2685/*
2686** Display memory stats.
2687*/
2688static int display_stats(
2689 sqlite3 *db, /* Database to query */
2690 ShellState *pArg, /* Pointer to ShellState */
2691 int bReset /* True to reset the stats */
2692){
2693 int iCur;
2694 int iHiwtr;
drh393344f2018-03-09 16:37:05 +00002695 FILE *out;
2696 if( pArg==0 || pArg->out==0 ) return 0;
2697 out = pArg->out;
drh2ce15c32017-07-11 13:34:40 +00002698
drha6e6cf22021-01-09 19:10:04 +00002699 if( pArg->pStmt && pArg->statsOn==2 ){
drh393344f2018-03-09 16:37:05 +00002700 int nCol, i, x;
2701 sqlite3_stmt *pStmt = pArg->pStmt;
2702 char z[100];
2703 nCol = sqlite3_column_count(pStmt);
2704 raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
2705 for(i=0; i<nCol; i++){
2706 sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
2707 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
drh929cce82018-03-17 16:26:36 +00002708#ifndef SQLITE_OMIT_DECLTYPE
drh393344f2018-03-09 16:37:05 +00002709 sqlite3_snprintf(30, z+x, "declared type:");
2710 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
drh929cce82018-03-17 16:26:36 +00002711#endif
2712#ifdef SQLITE_ENABLE_COLUMN_METADATA
drh393344f2018-03-09 16:37:05 +00002713 sqlite3_snprintf(30, z+x, "database name:");
2714 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
2715 sqlite3_snprintf(30, z+x, "table name:");
2716 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
2717 sqlite3_snprintf(30, z+x, "origin name:");
2718 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
drh929cce82018-03-17 16:26:36 +00002719#endif
drh2ce15c32017-07-11 13:34:40 +00002720 }
drh929cce82018-03-17 16:26:36 +00002721 }
drh2ce15c32017-07-11 13:34:40 +00002722
drha6e6cf22021-01-09 19:10:04 +00002723 if( pArg->statsOn==3 ){
2724 if( pArg->pStmt ){
2725 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
2726 raw_printf(pArg->out, "VM-steps: %d\n", iCur);
2727 }
2728 return 0;
2729 }
2730
drh393344f2018-03-09 16:37:05 +00002731 displayStatLine(pArg, "Memory Used:",
2732 "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
2733 displayStatLine(pArg, "Number of Outstanding Allocations:",
2734 "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
2735 if( pArg->shellFlgs & SHFLG_Pagecache ){
2736 displayStatLine(pArg, "Number of Pcache Pages Used:",
2737 "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
2738 }
2739 displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
2740 "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
2741 displayStatLine(pArg, "Largest Allocation:",
2742 "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
2743 displayStatLine(pArg, "Largest Pcache Allocation:",
2744 "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
2745#ifdef YYTRACKMAXSTACKDEPTH
2746 displayStatLine(pArg, "Deepest Parser Stack:",
2747 "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
2748#endif
2749
2750 if( db ){
drh2ce15c32017-07-11 13:34:40 +00002751 if( pArg->shellFlgs & SHFLG_Lookaside ){
2752 iHiwtr = iCur = -1;
2753 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
2754 &iCur, &iHiwtr, bReset);
2755 raw_printf(pArg->out,
2756 "Lookaside Slots Used: %d (max %d)\n",
2757 iCur, iHiwtr);
2758 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
2759 &iCur, &iHiwtr, bReset);
2760 raw_printf(pArg->out, "Successful lookaside attempts: %d\n",
2761 iHiwtr);
2762 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
2763 &iCur, &iHiwtr, bReset);
2764 raw_printf(pArg->out, "Lookaside failures due to size: %d\n",
2765 iHiwtr);
2766 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
2767 &iCur, &iHiwtr, bReset);
2768 raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n",
2769 iHiwtr);
2770 }
2771 iHiwtr = iCur = -1;
2772 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
2773 raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n",
2774 iCur);
2775 iHiwtr = iCur = -1;
2776 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
2777 raw_printf(pArg->out, "Page cache hits: %d\n", iCur);
2778 iHiwtr = iCur = -1;
2779 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
2780 raw_printf(pArg->out, "Page cache misses: %d\n", iCur);
2781 iHiwtr = iCur = -1;
2782 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
2783 raw_printf(pArg->out, "Page cache writes: %d\n", iCur);
2784 iHiwtr = iCur = -1;
drhffc78a42018-03-14 14:53:50 +00002785 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
2786 raw_printf(pArg->out, "Page cache spills: %d\n", iCur);
2787 iHiwtr = iCur = -1;
drh2ce15c32017-07-11 13:34:40 +00002788 sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
2789 raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n",
2790 iCur);
2791 iHiwtr = iCur = -1;
2792 sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
2793 raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
2794 iCur);
2795 }
2796
drh393344f2018-03-09 16:37:05 +00002797 if( pArg->pStmt ){
drh2ce15c32017-07-11 13:34:40 +00002798 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
2799 bReset);
2800 raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
2801 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
2802 raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
2803 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
2804 raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
2805 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
2806 raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
drhe2754c12019-08-26 12:50:01 +00002807 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
drh393344f2018-03-09 16:37:05 +00002808 raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
2809 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
2810 raw_printf(pArg->out, "Number of times run: %d\n", iCur);
2811 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
2812 raw_printf(pArg->out, "Memory used by prepared stmt: %d\n", iCur);
drh2ce15c32017-07-11 13:34:40 +00002813 }
2814
2815#ifdef __linux__
2816 displayLinuxIoStats(pArg->out);
2817#endif
2818
2819 /* Do not remove this machine readable comment: extra-stats-output-here */
2820
2821 return 0;
2822}
2823
2824/*
2825** Display scan stats.
2826*/
2827static void display_scanstats(
2828 sqlite3 *db, /* Database to query */
2829 ShellState *pArg /* Pointer to ShellState */
2830){
2831#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
2832 UNUSED_PARAMETER(db);
2833 UNUSED_PARAMETER(pArg);
2834#else
2835 int i, k, n, mx;
2836 raw_printf(pArg->out, "-------- scanstats --------\n");
2837 mx = 0;
2838 for(k=0; k<=mx; k++){
2839 double rEstLoop = 1.0;
2840 for(i=n=0; 1; i++){
2841 sqlite3_stmt *p = pArg->pStmt;
2842 sqlite3_int64 nLoop, nVisit;
2843 double rEst;
2844 int iSid;
2845 const char *zExplain;
2846 if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){
2847 break;
2848 }
2849 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
2850 if( iSid>mx ) mx = iSid;
2851 if( iSid!=k ) continue;
2852 if( n==0 ){
2853 rEstLoop = (double)nLoop;
2854 if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k);
2855 }
2856 n++;
2857 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
2858 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
2859 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
2860 utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
2861 rEstLoop *= rEst;
2862 raw_printf(pArg->out,
2863 " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
2864 nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
2865 );
2866 }
2867 }
2868 raw_printf(pArg->out, "---------------------------\n");
2869#endif
2870}
2871
2872/*
2873** Parameter azArray points to a zero-terminated array of strings. zStr
2874** points to a single nul-terminated string. Return non-zero if zStr
2875** is equal, according to strcmp(), to any of the strings in the array.
2876** Otherwise, return zero.
2877*/
2878static int str_in_array(const char *zStr, const char **azArray){
2879 int i;
2880 for(i=0; azArray[i]; i++){
2881 if( 0==strcmp(zStr, azArray[i]) ) return 1;
2882 }
2883 return 0;
2884}
2885
2886/*
2887** If compiled statement pSql appears to be an EXPLAIN statement, allocate
2888** and populate the ShellState.aiIndent[] array with the number of
2889** spaces each opcode should be indented before it is output.
2890**
2891** The indenting rules are:
2892**
2893** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
2894** all opcodes that occur between the p2 jump destination and the opcode
2895** itself by 2 spaces.
2896**
2897** * For each "Goto", if the jump destination is earlier in the program
2898** and ends on one of:
2899** Yield SeekGt SeekLt RowSetRead Rewind
2900** or if the P1 parameter is one instead of zero,
2901** then indent all opcodes between the earlier instruction
2902** and "Goto" by 2 spaces.
2903*/
2904static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
2905 const char *zSql; /* The text of the SQL statement */
2906 const char *z; /* Used to check if this is an EXPLAIN */
2907 int *abYield = 0; /* True if op is an OP_Yield */
2908 int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
2909 int iOp; /* Index of operation in p->aiIndent[] */
2910
drhf1949b62018-06-07 17:32:59 +00002911 const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
drh2ce15c32017-07-11 13:34:40 +00002912 const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
2913 "Rewind", 0 };
2914 const char *azGoto[] = { "Goto", 0 };
2915
2916 /* Try to figure out if this is really an EXPLAIN statement. If this
2917 ** cannot be verified, return early. */
2918 if( sqlite3_column_count(pSql)!=8 ){
2919 p->cMode = p->mode;
2920 return;
2921 }
2922 zSql = sqlite3_sql(pSql);
2923 if( zSql==0 ) return;
2924 for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
2925 if( sqlite3_strnicmp(z, "explain", 7) ){
2926 p->cMode = p->mode;
2927 return;
2928 }
2929
2930 for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
2931 int i;
2932 int iAddr = sqlite3_column_int(pSql, 0);
2933 const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
2934
2935 /* Set p2 to the P2 field of the current opcode. Then, assuming that
2936 ** p2 is an instruction address, set variable p2op to the index of that
2937 ** instruction in the aiIndent[] array. p2 and p2op may be different if
2938 ** the current instruction is part of a sub-program generated by an
2939 ** SQL trigger or foreign key. */
2940 int p2 = sqlite3_column_int(pSql, 3);
2941 int p2op = (p2 + (iOp-iAddr));
2942
2943 /* Grow the p->aiIndent array as required */
2944 if( iOp>=nAlloc ){
2945 if( iOp==0 ){
2946 /* Do further verfication that this is explain output. Abort if
2947 ** it is not */
2948 static const char *explainCols[] = {
2949 "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" };
2950 int jj;
2951 for(jj=0; jj<ArraySize(explainCols); jj++){
2952 if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
2953 p->cMode = p->mode;
2954 sqlite3_reset(pSql);
2955 return;
2956 }
2957 }
2958 }
2959 nAlloc += 100;
2960 p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
drh884406b2018-07-29 18:56:35 +00002961 if( p->aiIndent==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00002962 abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
drh884406b2018-07-29 18:56:35 +00002963 if( abYield==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00002964 }
2965 abYield[iOp] = str_in_array(zOp, azYield);
2966 p->aiIndent[iOp] = 0;
2967 p->nIndent = iOp+1;
2968
2969 if( str_in_array(zOp, azNext) ){
2970 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
2971 }
2972 if( str_in_array(zOp, azGoto) && p2op<p->nIndent
2973 && (abYield[p2op] || sqlite3_column_int(pSql, 2))
2974 ){
2975 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
2976 }
2977 }
2978
2979 p->iIndent = 0;
2980 sqlite3_free(abYield);
2981 sqlite3_reset(pSql);
2982}
2983
2984/*
2985** Free the array allocated by explain_data_prepare().
2986*/
2987static void explain_data_delete(ShellState *p){
2988 sqlite3_free(p->aiIndent);
2989 p->aiIndent = 0;
2990 p->nIndent = 0;
2991 p->iIndent = 0;
2992}
2993
2994/*
2995** Disable and restore .wheretrace and .selecttrace settings.
2996*/
drhc0622a42020-12-04 01:17:57 +00002997static unsigned int savedSelectTrace;
2998static unsigned int savedWhereTrace;
drh2ce15c32017-07-11 13:34:40 +00002999static void disable_debug_trace_modes(void){
drh0a2fb792020-12-04 16:58:20 +00003000 unsigned int zero = 0;
drhc0622a42020-12-04 01:17:57 +00003001 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace);
drh0a2fb792020-12-04 16:58:20 +00003002 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero);
drhc0622a42020-12-04 01:17:57 +00003003 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace);
drh0a2fb792020-12-04 16:58:20 +00003004 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero);
drh2ce15c32017-07-11 13:34:40 +00003005}
3006static void restore_debug_trace_modes(void){
drhc0622a42020-12-04 01:17:57 +00003007 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &savedSelectTrace);
3008 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &savedWhereTrace);
drh2ce15c32017-07-11 13:34:40 +00003009}
3010
drh9cb02642019-02-28 20:10:52 +00003011/* Create the TEMP table used to store parameter bindings */
3012static void bind_table_init(ShellState *p){
drh346f4e22019-03-25 21:35:41 +00003013 int wrSchema = 0;
drh4b86e202020-01-19 20:37:26 +00003014 int defensiveMode = 0;
3015 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
3016 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
drh346f4e22019-03-25 21:35:41 +00003017 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
3018 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
drh9cb02642019-02-28 20:10:52 +00003019 sqlite3_exec(p->db,
drh65c29fd2019-03-25 21:56:26 +00003020 "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
drh9cb02642019-02-28 20:10:52 +00003021 " key TEXT PRIMARY KEY,\n"
larrybrdabada62021-04-04 12:52:58 +00003022 " value\n"
drh9cb02642019-02-28 20:10:52 +00003023 ") WITHOUT ROWID;",
3024 0, 0, 0);
drh346f4e22019-03-25 21:35:41 +00003025 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
drh4b86e202020-01-19 20:37:26 +00003026 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0);
drh9cb02642019-02-28 20:10:52 +00003027}
3028
drh8b738d02019-02-25 18:43:54 +00003029/*
3030** Bind parameters on a prepared statement.
3031**
3032** Parameter bindings are taken from a TEMP table of the form:
3033**
drh1cb02632019-03-25 22:05:22 +00003034** CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
drh8b738d02019-02-25 18:43:54 +00003035** WITHOUT ROWID;
3036**
drh91654b22020-04-02 13:21:10 +00003037** No bindings occur if this table does not exist. The name of the table
3038** begins with "sqlite_" so that it will not collide with ordinary application
3039** tables. The table must be in the TEMP schema.
drh8b738d02019-02-25 18:43:54 +00003040*/
3041static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
3042 int nVar;
3043 int i;
3044 int rc;
3045 sqlite3_stmt *pQ = 0;
3046
3047 nVar = sqlite3_bind_parameter_count(pStmt);
3048 if( nVar==0 ) return; /* Nothing to do */
drh65c29fd2019-03-25 21:56:26 +00003049 if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters",
drh8b738d02019-02-25 18:43:54 +00003050 "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
3051 return; /* Parameter table does not exist */
3052 }
3053 rc = sqlite3_prepare_v2(pArg->db,
drh65c29fd2019-03-25 21:56:26 +00003054 "SELECT value FROM temp.sqlite_parameters"
drh8b738d02019-02-25 18:43:54 +00003055 " WHERE key=?1", -1, &pQ, 0);
3056 if( rc || pQ==0 ) return;
3057 for(i=1; i<=nVar; i++){
3058 char zNum[30];
3059 const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
3060 if( zVar==0 ){
3061 sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
3062 zVar = zNum;
3063 }
3064 sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
3065 if( sqlite3_step(pQ)==SQLITE_ROW ){
3066 sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
3067 }else{
3068 sqlite3_bind_null(pStmt, i);
3069 }
3070 sqlite3_reset(pQ);
3071 }
3072 sqlite3_finalize(pQ);
3073}
3074
drh30c54a02020-05-28 23:49:50 +00003075/*
drh0908e382020-06-04 18:05:39 +00003076** UTF8 box-drawing characters. Imagine box lines like this:
3077**
3078** 1
3079** |
3080** 4 --+-- 2
3081** |
3082** 3
3083**
3084** Each box characters has between 2 and 4 of the lines leading from
3085** the center. The characters are here identified by the numbers of
3086** their corresponding lines.
3087*/
3088#define BOX_24 "\342\224\200" /* U+2500 --- */
3089#define BOX_13 "\342\224\202" /* U+2502 | */
3090#define BOX_23 "\342\224\214" /* U+250c ,- */
3091#define BOX_34 "\342\224\220" /* U+2510 -, */
3092#define BOX_12 "\342\224\224" /* U+2514 '- */
3093#define BOX_14 "\342\224\230" /* U+2518 -' */
3094#define BOX_123 "\342\224\234" /* U+251c |- */
3095#define BOX_134 "\342\224\244" /* U+2524 -| */
3096#define BOX_234 "\342\224\254" /* U+252c -,- */
3097#define BOX_124 "\342\224\264" /* U+2534 -'- */
3098#define BOX_1234 "\342\224\274" /* U+253c -|- */
3099
3100/* Draw horizontal line N characters long using unicode box
3101** characters
3102*/
3103static void print_box_line(FILE *out, int N){
3104 const char zDash[] =
3105 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
3106 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
3107 const int nDash = sizeof(zDash) - 1;
3108 N *= 3;
3109 while( N>nDash ){
3110 utf8_printf(out, zDash);
3111 N -= nDash;
3112 }
3113 utf8_printf(out, "%.*s", N, zDash);
3114}
3115
3116/*
3117** Draw a horizontal separator for a MODE_Box table.
3118*/
3119static void print_box_row_separator(
3120 ShellState *p,
3121 int nArg,
3122 const char *zSep1,
3123 const char *zSep2,
3124 const char *zSep3
3125){
3126 int i;
3127 if( nArg>0 ){
3128 utf8_printf(p->out, "%s", zSep1);
3129 print_box_line(p->out, p->actualWidth[0]+2);
3130 for(i=1; i<nArg; i++){
3131 utf8_printf(p->out, "%s", zSep2);
3132 print_box_line(p->out, p->actualWidth[i]+2);
3133 }
3134 utf8_printf(p->out, "%s", zSep3);
3135 }
3136 fputs("\n", p->out);
3137}
3138
3139
3140
3141/*
drh30c54a02020-05-28 23:49:50 +00003142** Run a prepared statement and output the result in one of the
drh0908e382020-06-04 18:05:39 +00003143** table-oriented formats: MODE_Column, MODE_Markdown, MODE_Table,
3144** or MODE_Box.
drh30c54a02020-05-28 23:49:50 +00003145**
3146** This is different from ordinary exec_prepared_stmt() in that
3147** it has to run the entire query and gather the results into memory
3148** first, in order to determine column widths, before providing
3149** any output.
3150*/
drh8c748632020-05-29 16:15:58 +00003151static void exec_prepared_stmt_columnar(
3152 ShellState *p, /* Pointer to ShellState */
3153 sqlite3_stmt *pStmt /* Statment to run */
drh30c54a02020-05-28 23:49:50 +00003154){
drhf82ce382020-08-06 16:45:22 +00003155 sqlite3_int64 nRow = 0;
drh8c748632020-05-29 16:15:58 +00003156 int nColumn = 0;
3157 char **azData = 0;
drhf82ce382020-08-06 16:45:22 +00003158 sqlite3_int64 nAlloc = 0;
drh8c748632020-05-29 16:15:58 +00003159 const char *z;
3160 int rc;
drhf82ce382020-08-06 16:45:22 +00003161 sqlite3_int64 i, nData;
3162 int j, nTotal, w, n;
drh0908e382020-06-04 18:05:39 +00003163 const char *colSep = 0;
3164 const char *rowSep = 0;
drh30c54a02020-05-28 23:49:50 +00003165
drhf82ce382020-08-06 16:45:22 +00003166 rc = sqlite3_step(pStmt);
3167 if( rc!=SQLITE_ROW ) return;
3168 nColumn = sqlite3_column_count(pStmt);
3169 nAlloc = nColumn*4;
drh01a8ad22021-03-20 23:15:52 +00003170 if( nAlloc<=0 ) nAlloc = 1;
drhf82ce382020-08-06 16:45:22 +00003171 azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
3172 if( azData==0 ) shell_out_of_memory();
3173 for(i=0; i<nColumn; i++){
3174 azData[i] = strdup(sqlite3_column_name(pStmt,i));
drh8c748632020-05-29 16:15:58 +00003175 }
drhf82ce382020-08-06 16:45:22 +00003176 do{
3177 if( (nRow+2)*nColumn >= nAlloc ){
3178 nAlloc *= 2;
3179 azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*));
3180 if( azData==0 ) shell_out_of_memory();
3181 }
3182 nRow++;
3183 for(i=0; i<nColumn; i++){
3184 z = (const char*)sqlite3_column_text(pStmt,i);
3185 azData[nRow*nColumn + i] = z ? strdup(z) : 0;
3186 }
3187 }while( (rc = sqlite3_step(pStmt))==SQLITE_ROW );
drh8c748632020-05-29 16:15:58 +00003188 if( nColumn>p->nWidth ){
3189 p->colWidth = realloc(p->colWidth, nColumn*2*sizeof(int));
3190 if( p->colWidth==0 ) shell_out_of_memory();
3191 for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0;
3192 p->nWidth = nColumn;
3193 p->actualWidth = &p->colWidth[nColumn];
3194 }
3195 memset(p->actualWidth, 0, nColumn*sizeof(int));
3196 for(i=0; i<nColumn; i++){
3197 w = p->colWidth[i];
3198 if( w<0 ) w = -w;
3199 p->actualWidth[i] = w;
3200 }
3201 nTotal = nColumn*(nRow+1);
3202 for(i=0; i<nTotal; i++){
3203 z = azData[i];
3204 if( z==0 ) z = p->nullValue;
3205 n = strlenChar(z);
3206 j = i%nColumn;
3207 if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
3208 }
drh99942982020-06-15 20:05:37 +00003209 if( seenInterrupt ) goto columnar_end;
drh01a8ad22021-03-20 23:15:52 +00003210 if( nColumn==0 ) goto columnar_end;
drh0908e382020-06-04 18:05:39 +00003211 switch( p->cMode ){
3212 case MODE_Column: {
3213 colSep = " ";
3214 rowSep = "\n";
3215 if( p->showHeader ){
3216 for(i=0; i<nColumn; i++){
3217 w = p->actualWidth[i];
3218 if( p->colWidth[i]<0 ) w = -w;
3219 utf8_width_print(p->out, w, azData[i]);
3220 fputs(i==nColumn-1?"\n":" ", p->out);
3221 }
3222 for(i=0; i<nColumn; i++){
3223 print_dashes(p->out, p->actualWidth[i]);
3224 fputs(i==nColumn-1?"\n":" ", p->out);
3225 }
3226 }
3227 break;
3228 }
3229 case MODE_Table: {
3230 colSep = " | ";
3231 rowSep = " |\n";
3232 print_row_separator(p, nColumn, "+");
3233 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003234 for(i=0; i<nColumn; i++){
3235 w = p->actualWidth[i];
drh0908e382020-06-04 18:05:39 +00003236 n = strlenChar(azData[i]);
3237 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
3238 fputs(i==nColumn-1?" |\n":" | ", p->out);
drh8c748632020-05-29 16:15:58 +00003239 }
drh0908e382020-06-04 18:05:39 +00003240 print_row_separator(p, nColumn, "+");
3241 break;
3242 }
3243 case MODE_Markdown: {
3244 colSep = " | ";
3245 rowSep = " |\n";
3246 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003247 for(i=0; i<nColumn; i++){
drh0908e382020-06-04 18:05:39 +00003248 w = p->actualWidth[i];
3249 n = strlenChar(azData[i]);
3250 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
3251 fputs(i==nColumn-1?" |\n":" | ", p->out);
drh8c748632020-05-29 16:15:58 +00003252 }
drh0908e382020-06-04 18:05:39 +00003253 print_row_separator(p, nColumn, "|");
3254 break;
drh8c748632020-05-29 16:15:58 +00003255 }
drh0908e382020-06-04 18:05:39 +00003256 case MODE_Box: {
3257 colSep = " " BOX_13 " ";
3258 rowSep = " " BOX_13 "\n";
3259 print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34);
3260 utf8_printf(p->out, BOX_13 " ");
3261 for(i=0; i<nColumn; i++){
3262 w = p->actualWidth[i];
3263 n = strlenChar(azData[i]);
3264 utf8_printf(p->out, "%*s%s%*s%s",
3265 (w-n)/2, "", azData[i], (w-n+1)/2, "",
3266 i==nColumn-1?" "BOX_13"\n":" "BOX_13" ");
3267 }
3268 print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
3269 break;
drh8c748632020-05-29 16:15:58 +00003270 }
drh8c748632020-05-29 16:15:58 +00003271 }
3272 for(i=nColumn, j=0; i<nTotal; i++, j++){
drh0908e382020-06-04 18:05:39 +00003273 if( j==0 && p->cMode!=MODE_Column ){
3274 utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| ");
3275 }
drh8c748632020-05-29 16:15:58 +00003276 z = azData[i];
3277 if( z==0 ) z = p->nullValue;
3278 w = p->actualWidth[j];
3279 if( p->colWidth[j]<0 ) w = -w;
3280 utf8_width_print(p->out, w, z);
3281 if( j==nColumn-1 ){
drh0908e382020-06-04 18:05:39 +00003282 utf8_printf(p->out, "%s", rowSep);
drh8c748632020-05-29 16:15:58 +00003283 j = -1;
drhdd853c32020-06-16 17:34:40 +00003284 if( seenInterrupt ) goto columnar_end;
drh8c748632020-05-29 16:15:58 +00003285 }else{
drh0908e382020-06-04 18:05:39 +00003286 utf8_printf(p->out, "%s", colSep);
drh8c748632020-05-29 16:15:58 +00003287 }
3288 }
3289 if( p->cMode==MODE_Table ){
3290 print_row_separator(p, nColumn, "+");
drh0908e382020-06-04 18:05:39 +00003291 }else if( p->cMode==MODE_Box ){
3292 print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14);
drh8c748632020-05-29 16:15:58 +00003293 }
drh99942982020-06-15 20:05:37 +00003294columnar_end:
drhdd853c32020-06-16 17:34:40 +00003295 if( seenInterrupt ){
3296 utf8_printf(p->out, "Interrupt\n");
3297 }
drhf82ce382020-08-06 16:45:22 +00003298 nData = (nRow+1)*nColumn;
3299 for(i=0; i<nData; i++) free(azData[i]);
3300 sqlite3_free(azData);
drh30c54a02020-05-28 23:49:50 +00003301}
drh30c54a02020-05-28 23:49:50 +00003302
drh2ce15c32017-07-11 13:34:40 +00003303/*
3304** Run a prepared statement
3305*/
3306static void exec_prepared_stmt(
3307 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003308 sqlite3_stmt *pStmt /* Statment to run */
drh2ce15c32017-07-11 13:34:40 +00003309){
3310 int rc;
3311
drh8c748632020-05-29 16:15:58 +00003312 if( pArg->cMode==MODE_Column
3313 || pArg->cMode==MODE_Table
drh0908e382020-06-04 18:05:39 +00003314 || pArg->cMode==MODE_Box
drh8c748632020-05-29 16:15:58 +00003315 || pArg->cMode==MODE_Markdown
3316 ){
3317 exec_prepared_stmt_columnar(pArg, pStmt);
3318 return;
3319 }
3320
drh2ce15c32017-07-11 13:34:40 +00003321 /* perform the first step. this will tell us if we
3322 ** have a result set or not and how wide it is.
3323 */
3324 rc = sqlite3_step(pStmt);
3325 /* if we have a result set... */
3326 if( SQLITE_ROW == rc ){
drha10b9992018-03-09 15:24:33 +00003327 /* allocate space for col name ptr, value ptr, and type */
3328 int nCol = sqlite3_column_count(pStmt);
3329 void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
3330 if( !pData ){
3331 rc = SQLITE_NOMEM;
drh2ce15c32017-07-11 13:34:40 +00003332 }else{
drha10b9992018-03-09 15:24:33 +00003333 char **azCols = (char **)pData; /* Names of result columns */
3334 char **azVals = &azCols[nCol]; /* Results */
3335 int *aiTypes = (int *)&azVals[nCol]; /* Result types */
3336 int i, x;
3337 assert(sizeof(int) <= sizeof(char *));
3338 /* save off ptrs to column names */
3339 for(i=0; i<nCol; i++){
3340 azCols[i] = (char *)sqlite3_column_name(pStmt, i);
3341 }
drh2ce15c32017-07-11 13:34:40 +00003342 do{
drha10b9992018-03-09 15:24:33 +00003343 /* extract the data and data types */
3344 for(i=0; i<nCol; i++){
3345 aiTypes[i] = x = sqlite3_column_type(pStmt, i);
3346 if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
3347 azVals[i] = "";
3348 }else{
3349 azVals[i] = (char*)sqlite3_column_text(pStmt, i);
3350 }
3351 if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
3352 rc = SQLITE_NOMEM;
3353 break; /* from for */
3354 }
3355 } /* end for */
3356
3357 /* if data and types extracted successfully... */
3358 if( SQLITE_ROW == rc ){
3359 /* call the supplied callback with the result row data */
3360 if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){
3361 rc = SQLITE_ABORT;
3362 }else{
3363 rc = sqlite3_step(pStmt);
3364 }
3365 }
3366 } while( SQLITE_ROW == rc );
3367 sqlite3_free(pData);
drh0908e382020-06-04 18:05:39 +00003368 if( pArg->cMode==MODE_Json ){
drh30c54a02020-05-28 23:49:50 +00003369 fputs("]\n", pArg->out);
3370 }
drh2ce15c32017-07-11 13:34:40 +00003371 }
3372 }
3373}
3374
dan6b046be2018-01-09 15:25:55 +00003375#ifndef SQLITE_OMIT_VIRTUALTABLE
drh2ce15c32017-07-11 13:34:40 +00003376/*
dan43efc182017-12-19 17:42:13 +00003377** This function is called to process SQL if the previous shell command
3378** was ".expert". It passes the SQL in the second argument directly to
3379** the sqlite3expert object.
3380**
3381** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3382** code. In this case, (*pzErr) may be set to point to a buffer containing
3383** an English language error message. It is the responsibility of the
3384** caller to eventually free this buffer using sqlite3_free().
3385*/
3386static int expertHandleSQL(
3387 ShellState *pState,
3388 const char *zSql,
3389 char **pzErr
3390){
3391 assert( pState->expert.pExpert );
3392 assert( pzErr==0 || *pzErr==0 );
3393 return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr);
3394}
3395
3396/*
3397** This function is called either to silently clean up the object
3398** created by the ".expert" command (if bCancel==1), or to generate a
3399** report from it and then clean it up (if bCancel==0).
3400**
3401** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3402** code. In this case, (*pzErr) may be set to point to a buffer containing
3403** an English language error message. It is the responsibility of the
3404** caller to eventually free this buffer using sqlite3_free().
3405*/
3406static int expertFinish(
3407 ShellState *pState,
3408 int bCancel,
3409 char **pzErr
3410){
3411 int rc = SQLITE_OK;
3412 sqlite3expert *p = pState->expert.pExpert;
3413 assert( p );
3414 assert( bCancel || pzErr==0 || *pzErr==0 );
3415 if( bCancel==0 ){
3416 FILE *out = pState->out;
3417 int bVerbose = pState->expert.bVerbose;
3418
3419 rc = sqlite3_expert_analyze(p, pzErr);
3420 if( rc==SQLITE_OK ){
3421 int nQuery = sqlite3_expert_count(p);
3422 int i;
3423
3424 if( bVerbose ){
3425 const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
3426 raw_printf(out, "-- Candidates -----------------------------\n");
3427 raw_printf(out, "%s\n", zCand);
3428 }
3429 for(i=0; i<nQuery; i++){
3430 const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
3431 const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
3432 const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
3433 if( zIdx==0 ) zIdx = "(no new indexes)\n";
3434 if( bVerbose ){
3435 raw_printf(out, "-- Query %d --------------------------------\n",i+1);
3436 raw_printf(out, "%s\n\n", zSql);
3437 }
3438 raw_printf(out, "%s\n", zIdx);
3439 raw_printf(out, "%s\n", zEQP);
3440 }
3441 }
3442 }
3443 sqlite3_expert_destroy(p);
3444 pState->expert.pExpert = 0;
3445 return rc;
3446}
3447
dan6b046be2018-01-09 15:25:55 +00003448/*
3449** Implementation of ".expert" dot command.
3450*/
3451static int expertDotCommand(
3452 ShellState *pState, /* Current shell tool state */
3453 char **azArg, /* Array of arguments passed to dot command */
3454 int nArg /* Number of entries in azArg[] */
3455){
3456 int rc = SQLITE_OK;
3457 char *zErr = 0;
3458 int i;
3459 int iSample = 0;
3460
3461 assert( pState->expert.pExpert==0 );
3462 memset(&pState->expert, 0, sizeof(ExpertInfo));
3463
3464 for(i=1; rc==SQLITE_OK && i<nArg; i++){
3465 char *z = azArg[i];
3466 int n;
3467 if( z[0]=='-' && z[1]=='-' ) z++;
3468 n = strlen30(z);
3469 if( n>=2 && 0==strncmp(z, "-verbose", n) ){
3470 pState->expert.bVerbose = 1;
3471 }
3472 else if( n>=2 && 0==strncmp(z, "-sample", n) ){
3473 if( i==(nArg-1) ){
3474 raw_printf(stderr, "option requires an argument: %s\n", z);
3475 rc = SQLITE_ERROR;
3476 }else{
3477 iSample = (int)integerValue(azArg[++i]);
3478 if( iSample<0 || iSample>100 ){
3479 raw_printf(stderr, "value out of range: %s\n", azArg[i]);
3480 rc = SQLITE_ERROR;
3481 }
3482 }
3483 }
3484 else{
3485 raw_printf(stderr, "unknown option: %s\n", z);
3486 rc = SQLITE_ERROR;
3487 }
3488 }
3489
3490 if( rc==SQLITE_OK ){
3491 pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
3492 if( pState->expert.pExpert==0 ){
3493 raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr);
3494 rc = SQLITE_ERROR;
3495 }else{
3496 sqlite3_expert_config(
3497 pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
3498 );
3499 }
3500 }
3501
3502 return rc;
3503}
3504#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
dan43efc182017-12-19 17:42:13 +00003505
3506/*
drh2ce15c32017-07-11 13:34:40 +00003507** Execute a statement or set of statements. Print
3508** any result rows/columns depending on the current mode
3509** set via the supplied callback.
3510**
3511** This is very similar to SQLite's built-in sqlite3_exec()
3512** function except it takes a slightly different callback
3513** and callback data argument.
3514*/
3515static int shell_exec(
drh2ce15c32017-07-11 13:34:40 +00003516 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003517 const char *zSql, /* SQL to be evaluated */
drh2ce15c32017-07-11 13:34:40 +00003518 char **pzErrMsg /* Error msg written here */
3519){
3520 sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
3521 int rc = SQLITE_OK; /* Return Code */
3522 int rc2;
3523 const char *zLeftover; /* Tail of unprocessed SQL */
drha10b9992018-03-09 15:24:33 +00003524 sqlite3 *db = pArg->db;
drh2ce15c32017-07-11 13:34:40 +00003525
3526 if( pzErrMsg ){
3527 *pzErrMsg = NULL;
3528 }
3529
dan6b046be2018-01-09 15:25:55 +00003530#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00003531 if( pArg->expert.pExpert ){
3532 rc = expertHandleSQL(pArg, zSql, pzErrMsg);
3533 return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
3534 }
dan6b046be2018-01-09 15:25:55 +00003535#endif
dan43efc182017-12-19 17:42:13 +00003536
drh2ce15c32017-07-11 13:34:40 +00003537 while( zSql[0] && (SQLITE_OK == rc) ){
3538 static const char *zStmtSql;
3539 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
3540 if( SQLITE_OK != rc ){
3541 if( pzErrMsg ){
3542 *pzErrMsg = save_err_msg(db);
3543 }
3544 }else{
3545 if( !pStmt ){
3546 /* this happens for a comment or white-space */
3547 zSql = zLeftover;
3548 while( IsSpace(zSql[0]) ) zSql++;
3549 continue;
3550 }
3551 zStmtSql = sqlite3_sql(pStmt);
3552 if( zStmtSql==0 ) zStmtSql = "";
3553 while( IsSpace(zStmtSql[0]) ) zStmtSql++;
3554
3555 /* save off the prepared statment handle and reset row count */
3556 if( pArg ){
3557 pArg->pStmt = pStmt;
3558 pArg->cnt = 0;
3559 }
3560
3561 /* echo the sql statement if echo on */
3562 if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
3563 utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
3564 }
3565
3566 /* Show the EXPLAIN QUERY PLAN if .eqp is on */
drh39c5c4a2019-03-06 14:53:27 +00003567 if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
drh2ce15c32017-07-11 13:34:40 +00003568 sqlite3_stmt *pExplain;
3569 char *zEQP;
drhada70452017-12-21 21:02:27 +00003570 int triggerEQP = 0;
drh2ce15c32017-07-11 13:34:40 +00003571 disable_debug_trace_modes();
drhada70452017-12-21 21:02:27 +00003572 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
3573 if( pArg->autoEQP>=AUTOEQP_trigger ){
3574 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
3575 }
drh2ce15c32017-07-11 13:34:40 +00003576 zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
3577 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3578 if( rc==SQLITE_OK ){
3579 while( sqlite3_step(pExplain)==SQLITE_ROW ){
drh4b5345c2018-04-24 13:07:40 +00003580 const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
drhe2ca99c2018-05-02 00:33:43 +00003581 int iEqpId = sqlite3_column_int(pExplain, 0);
3582 int iParentId = sqlite3_column_int(pExplain, 1);
drh7e088a62020-05-02 00:01:39 +00003583 if( zEQPLine==0 ) zEQPLine = "";
drh4b5345c2018-04-24 13:07:40 +00003584 if( zEQPLine[0]=='-' ) eqp_render(pArg);
drhe2ca99c2018-05-02 00:33:43 +00003585 eqp_append(pArg, iEqpId, iParentId, zEQPLine);
drh2ce15c32017-07-11 13:34:40 +00003586 }
drh4b5345c2018-04-24 13:07:40 +00003587 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003588 }
3589 sqlite3_finalize(pExplain);
3590 sqlite3_free(zEQP);
drhada70452017-12-21 21:02:27 +00003591 if( pArg->autoEQP>=AUTOEQP_full ){
drh2ce15c32017-07-11 13:34:40 +00003592 /* Also do an EXPLAIN for ".eqp full" mode */
3593 zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
3594 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3595 if( rc==SQLITE_OK ){
3596 pArg->cMode = MODE_Explain;
3597 explain_data_prepare(pArg, pExplain);
drha10b9992018-03-09 15:24:33 +00003598 exec_prepared_stmt(pArg, pExplain);
drh2ce15c32017-07-11 13:34:40 +00003599 explain_data_delete(pArg);
3600 }
3601 sqlite3_finalize(pExplain);
3602 sqlite3_free(zEQP);
3603 }
drh51efe092018-03-20 12:04:38 +00003604 if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
3605 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
3606 /* Reprepare pStmt before reactiving trace modes */
3607 sqlite3_finalize(pStmt);
3608 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
drh3c49eaf2018-06-07 15:23:43 +00003609 if( pArg ) pArg->pStmt = pStmt;
drh51efe092018-03-20 12:04:38 +00003610 }
drh2ce15c32017-07-11 13:34:40 +00003611 restore_debug_trace_modes();
3612 }
3613
3614 if( pArg ){
3615 pArg->cMode = pArg->mode;
drh4b5345c2018-04-24 13:07:40 +00003616 if( pArg->autoExplain ){
drh39c5c4a2019-03-06 14:53:27 +00003617 if( sqlite3_stmt_isexplain(pStmt)==1 ){
drh4b5345c2018-04-24 13:07:40 +00003618 pArg->cMode = MODE_Explain;
3619 }
drh39c5c4a2019-03-06 14:53:27 +00003620 if( sqlite3_stmt_isexplain(pStmt)==2 ){
drh4b5345c2018-04-24 13:07:40 +00003621 pArg->cMode = MODE_EQP;
3622 }
drh2ce15c32017-07-11 13:34:40 +00003623 }
3624
3625 /* If the shell is currently in ".explain" mode, gather the extra
3626 ** data required to add indents to the output.*/
3627 if( pArg->cMode==MODE_Explain ){
3628 explain_data_prepare(pArg, pStmt);
3629 }
3630 }
3631
drh8b738d02019-02-25 18:43:54 +00003632 bind_prepared_stmt(pArg, pStmt);
drha10b9992018-03-09 15:24:33 +00003633 exec_prepared_stmt(pArg, pStmt);
drh2ce15c32017-07-11 13:34:40 +00003634 explain_data_delete(pArg);
drh4b5345c2018-04-24 13:07:40 +00003635 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003636
3637 /* print usage stats if stats on */
3638 if( pArg && pArg->statsOn ){
3639 display_stats(db, pArg, 0);
3640 }
3641
3642 /* print loop-counters if required */
3643 if( pArg && pArg->scanstatsOn ){
3644 display_scanstats(db, pArg);
3645 }
3646
3647 /* Finalize the statement just executed. If this fails, save a
3648 ** copy of the error message. Otherwise, set zSql to point to the
3649 ** next statement to execute. */
3650 rc2 = sqlite3_finalize(pStmt);
3651 if( rc!=SQLITE_NOMEM ) rc = rc2;
3652 if( rc==SQLITE_OK ){
3653 zSql = zLeftover;
3654 while( IsSpace(zSql[0]) ) zSql++;
3655 }else if( pzErrMsg ){
3656 *pzErrMsg = save_err_msg(db);
3657 }
3658
3659 /* clear saved stmt handle */
3660 if( pArg ){
3661 pArg->pStmt = NULL;
3662 }
3663 }
3664 } /* end while */
3665
3666 return rc;
3667}
3668
3669/*
3670** Release memory previously allocated by tableColumnList().
3671*/
3672static void freeColumnList(char **azCol){
3673 int i;
3674 for(i=1; azCol[i]; i++){
3675 sqlite3_free(azCol[i]);
3676 }
3677 /* azCol[0] is a static string */
3678 sqlite3_free(azCol);
3679}
3680
3681/*
3682** Return a list of pointers to strings which are the names of all
3683** columns in table zTab. The memory to hold the names is dynamically
3684** allocated and must be released by the caller using a subsequent call
3685** to freeColumnList().
3686**
3687** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
3688** value that needs to be preserved, then azCol[0] is filled in with the
3689** name of the rowid column.
3690**
3691** The first regular column in the table is azCol[1]. The list is terminated
3692** by an entry with azCol[i]==0.
3693*/
3694static char **tableColumnList(ShellState *p, const char *zTab){
3695 char **azCol = 0;
3696 sqlite3_stmt *pStmt;
3697 char *zSql;
3698 int nCol = 0;
3699 int nAlloc = 0;
3700 int nPK = 0; /* Number of PRIMARY KEY columns seen */
3701 int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
3702 int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
3703 int rc;
3704
3705 zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
3706 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3707 sqlite3_free(zSql);
3708 if( rc ) return 0;
3709 while( sqlite3_step(pStmt)==SQLITE_ROW ){
3710 if( nCol>=nAlloc-2 ){
3711 nAlloc = nAlloc*2 + nCol + 10;
3712 azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
drh4b5345c2018-04-24 13:07:40 +00003713 if( azCol==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00003714 }
3715 azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
3716 if( sqlite3_column_int(pStmt, 5) ){
3717 nPK++;
3718 if( nPK==1
3719 && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
3720 "INTEGER")==0
3721 ){
3722 isIPK = 1;
3723 }else{
3724 isIPK = 0;
3725 }
3726 }
3727 }
3728 sqlite3_finalize(pStmt);
drh4c6cddc2017-10-12 10:28:30 +00003729 if( azCol==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00003730 azCol[0] = 0;
3731 azCol[nCol+1] = 0;
3732
3733 /* The decision of whether or not a rowid really needs to be preserved
3734 ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
3735 ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
3736 ** rowids on tables where the rowid is inaccessible because there are other
3737 ** columns in the table named "rowid", "_rowid_", and "oid".
3738 */
3739 if( preserveRowid && isIPK ){
3740 /* If a single PRIMARY KEY column with type INTEGER was seen, then it
3741 ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID
3742 ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
3743 ** ROWID aliases. To distinguish these cases, check to see if
3744 ** there is a "pk" entry in "PRAGMA index_list". There will be
3745 ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
3746 */
3747 zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
3748 " WHERE origin='pk'", zTab);
3749 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3750 sqlite3_free(zSql);
3751 if( rc ){
3752 freeColumnList(azCol);
3753 return 0;
3754 }
3755 rc = sqlite3_step(pStmt);
3756 sqlite3_finalize(pStmt);
3757 preserveRowid = rc==SQLITE_ROW;
3758 }
3759 if( preserveRowid ){
3760 /* Only preserve the rowid if we can find a name to use for the
3761 ** rowid */
3762 static char *azRowid[] = { "rowid", "_rowid_", "oid" };
3763 int i, j;
3764 for(j=0; j<3; j++){
3765 for(i=1; i<=nCol; i++){
3766 if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
3767 }
3768 if( i>nCol ){
3769 /* At this point, we know that azRowid[j] is not the name of any
3770 ** ordinary column in the table. Verify that azRowid[j] is a valid
3771 ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
3772 ** tables will fail this last check */
3773 rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
3774 if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
3775 break;
3776 }
3777 }
3778 }
3779 return azCol;
3780}
3781
3782/*
3783** Toggle the reverse_unordered_selects setting.
3784*/
3785static void toggleSelectOrder(sqlite3 *db){
3786 sqlite3_stmt *pStmt = 0;
3787 int iSetting = 0;
3788 char zStmt[100];
3789 sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0);
3790 if( sqlite3_step(pStmt)==SQLITE_ROW ){
3791 iSetting = sqlite3_column_int(pStmt, 0);
3792 }
3793 sqlite3_finalize(pStmt);
3794 sqlite3_snprintf(sizeof(zStmt), zStmt,
3795 "PRAGMA reverse_unordered_selects(%d)", !iSetting);
3796 sqlite3_exec(db, zStmt, 0, 0, 0);
3797}
3798
3799/*
3800** This is a different callback routine used for dumping the database.
3801** Each row received by this callback consists of a table name,
3802** the table type ("index" or "table") and SQL to create the table.
3803** This routine should print text sufficient to recreate the table.
3804*/
3805static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
3806 int rc;
3807 const char *zTable;
3808 const char *zType;
3809 const char *zSql;
3810 ShellState *p = (ShellState *)pArg;
mistachkina00a0162020-10-18 18:35:34 +00003811 int dataOnly;
3812 int noSys;
drh2ce15c32017-07-11 13:34:40 +00003813
3814 UNUSED_PARAMETER(azNotUsed);
drhb3c45232017-08-28 14:33:27 +00003815 if( nArg!=3 || azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00003816 zTable = azArg[0];
3817 zType = azArg[1];
3818 zSql = azArg[2];
mistachkina00a0162020-10-18 18:35:34 +00003819 dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
3820 noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
drh2ce15c32017-07-11 13:34:40 +00003821
drhc1962192020-10-12 16:54:28 +00003822 if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
3823 if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
3824 }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
3825 if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00003826 }else if( strncmp(zTable, "sqlite_", 7)==0 ){
3827 return 0;
drhc1962192020-10-12 16:54:28 +00003828 }else if( dataOnly ){
3829 /* no-op */
drh2ce15c32017-07-11 13:34:40 +00003830 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
3831 char *zIns;
3832 if( !p->writableSchema ){
3833 raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
3834 p->writableSchema = 1;
3835 }
3836 zIns = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00003837 "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
drh2ce15c32017-07-11 13:34:40 +00003838 "VALUES('table','%q','%q',0,'%q');",
3839 zTable, zTable, zSql);
3840 utf8_printf(p->out, "%s\n", zIns);
3841 sqlite3_free(zIns);
3842 return 0;
3843 }else{
3844 printSchemaLine(p->out, zSql, ";\n");
3845 }
3846
3847 if( strcmp(zType, "table")==0 ){
3848 ShellText sSelect;
3849 ShellText sTable;
3850 char **azCol;
3851 int i;
3852 char *savedDestTable;
3853 int savedMode;
3854
3855 azCol = tableColumnList(p, zTable);
3856 if( azCol==0 ){
3857 p->nErr++;
3858 return 0;
3859 }
3860
3861 /* Always quote the table name, even if it appears to be pure ascii,
3862 ** in case it is a keyword. Ex: INSERT INTO "table" ... */
3863 initText(&sTable);
3864 appendText(&sTable, zTable, quoteChar(zTable));
3865 /* If preserving the rowid, add a column list after the table name.
3866 ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
3867 ** instead of the usual "INSERT INTO tab VALUES(...)".
3868 */
3869 if( azCol[0] ){
3870 appendText(&sTable, "(", 0);
3871 appendText(&sTable, azCol[0], 0);
3872 for(i=1; azCol[i]; i++){
3873 appendText(&sTable, ",", 0);
3874 appendText(&sTable, azCol[i], quoteChar(azCol[i]));
3875 }
3876 appendText(&sTable, ")", 0);
3877 }
3878
3879 /* Build an appropriate SELECT statement */
3880 initText(&sSelect);
3881 appendText(&sSelect, "SELECT ", 0);
3882 if( azCol[0] ){
3883 appendText(&sSelect, azCol[0], 0);
3884 appendText(&sSelect, ",", 0);
3885 }
3886 for(i=1; azCol[i]; i++){
3887 appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
3888 if( azCol[i+1] ){
3889 appendText(&sSelect, ",", 0);
3890 }
3891 }
3892 freeColumnList(azCol);
3893 appendText(&sSelect, " FROM ", 0);
3894 appendText(&sSelect, zTable, quoteChar(zTable));
3895
3896 savedDestTable = p->zDestTable;
3897 savedMode = p->mode;
3898 p->zDestTable = sTable.z;
3899 p->mode = p->cMode = MODE_Insert;
drha10b9992018-03-09 15:24:33 +00003900 rc = shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00003901 if( (rc&0xff)==SQLITE_CORRUPT ){
3902 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
3903 toggleSelectOrder(p->db);
drha10b9992018-03-09 15:24:33 +00003904 shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00003905 toggleSelectOrder(p->db);
3906 }
3907 p->zDestTable = savedDestTable;
3908 p->mode = savedMode;
3909 freeText(&sTable);
3910 freeText(&sSelect);
3911 if( rc ) p->nErr++;
3912 }
3913 return 0;
3914}
3915
3916/*
3917** Run zQuery. Use dump_callback() as the callback routine so that
3918** the contents of the query are output as SQL statements.
3919**
3920** If we get a SQLITE_CORRUPT error, rerun the query after appending
3921** "ORDER BY rowid DESC" to the end.
3922*/
3923static int run_schema_dump_query(
3924 ShellState *p,
3925 const char *zQuery
3926){
3927 int rc;
3928 char *zErr = 0;
3929 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
3930 if( rc==SQLITE_CORRUPT ){
3931 char *zQ2;
3932 int len = strlen30(zQuery);
3933 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
3934 if( zErr ){
3935 utf8_printf(p->out, "/****** %s ******/\n", zErr);
3936 sqlite3_free(zErr);
3937 zErr = 0;
3938 }
3939 zQ2 = malloc( len+100 );
3940 if( zQ2==0 ) return rc;
3941 sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
3942 rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
3943 if( rc ){
3944 utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
3945 }else{
3946 rc = SQLITE_CORRUPT;
3947 }
3948 sqlite3_free(zErr);
3949 free(zQ2);
3950 }
3951 return rc;
3952}
3953
3954/*
drh98aa2ab2018-09-26 16:53:51 +00003955** Text of help messages.
3956**
3957** The help text for each individual command begins with a line that starts
3958** with ".". Subsequent lines are supplimental information.
3959**
3960** There must be two or more spaces between the end of the command and the
3961** start of the description of what that command does.
drh2ce15c32017-07-11 13:34:40 +00003962*/
drh98aa2ab2018-09-26 16:53:51 +00003963static const char *(azHelp[]) = {
drhe37c0e12018-01-06 19:19:50 +00003964#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drh98aa2ab2018-09-26 16:53:51 +00003965 ".archive ... Manage SQL archives",
3966 " Each command must have exactly one of the following options:",
3967 " -c, --create Create a new archive",
drhe2754c12019-08-26 12:50:01 +00003968 " -u, --update Add or update files with changed mtime",
3969 " -i, --insert Like -u but always add even if unchanged",
drh98aa2ab2018-09-26 16:53:51 +00003970 " -t, --list List contents of archive",
3971 " -x, --extract Extract files from archive",
3972 " Optional arguments:",
3973 " -v, --verbose Print each filename as it is processed",
drhe2754c12019-08-26 12:50:01 +00003974 " -f FILE, --file FILE Use archive FILE (default is current db)",
3975 " -a FILE, --append FILE Open FILE using the apndvfs VFS",
3976 " -C DIR, --directory DIR Read/extract files from directory DIR",
drh98aa2ab2018-09-26 16:53:51 +00003977 " -n, --dryrun Show the SQL that would have occurred",
3978 " Examples:",
drhe2754c12019-08-26 12:50:01 +00003979 " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
3980 " .ar -tf ARCHIVE # List members of ARCHIVE",
3981 " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE",
drh98aa2ab2018-09-26 16:53:51 +00003982 " See also:",
larrybrbd0d62c2021-06-13 08:23:28 +00003983 " http://sqlite.org/cli.html#sqlite_archive_support",
drhe37c0e12018-01-06 19:19:50 +00003984#endif
drh2ce15c32017-07-11 13:34:40 +00003985#ifndef SQLITE_OMIT_AUTHORIZATION
drh98aa2ab2018-09-26 16:53:51 +00003986 ".auth ON|OFF Show authorizer callbacks",
drh2ce15c32017-07-11 13:34:40 +00003987#endif
drh98aa2ab2018-09-26 16:53:51 +00003988 ".backup ?DB? FILE Backup DB (default \"main\") to FILE",
3989 " --append Use the appendvfs",
drhe2754c12019-08-26 12:50:01 +00003990 " --async Write to FILE without journal and fsync()",
drh98aa2ab2018-09-26 16:53:51 +00003991 ".bail on|off Stop after hitting an error. Default OFF",
3992 ".binary on|off Turn binary output on or off. Default OFF",
3993 ".cd DIRECTORY Change the working directory to DIRECTORY",
3994 ".changes on|off Show number of rows changed by SQL",
3995 ".check GLOB Fail if output since .testcase does not match",
3996 ".clone NEWDB Clone data into NEWDB from the existing database",
drh37407122021-07-23 18:43:58 +00003997 ".connection [close] [#] Open or close an auxiliary database connection",
drh98aa2ab2018-09-26 16:53:51 +00003998 ".databases List names and files of attached databases",
3999 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
4000 ".dbinfo ?DB? Show status information about the database",
larrybr7bdbe592021-03-15 12:56:00 +00004001 ".dump ?OBJECTS? Render database content as SQL",
drheb7f2a02018-09-26 18:02:32 +00004002 " Options:",
drhc1962192020-10-12 16:54:28 +00004003 " --data-only Output only INSERT statements",
drheb7f2a02018-09-26 18:02:32 +00004004 " --newlines Allow unescaped newline characters in output",
drhc1962192020-10-12 16:54:28 +00004005 " --nosys Omit system tables (ex: \"sqlite_stat1\")",
4006 " --preserve-rowids Include ROWID values in the output",
larrybr7bdbe592021-03-15 12:56:00 +00004007 " OBJECTS is a LIKE pattern for tables, indexes, triggers or views to dump",
drh8e9297f2020-03-25 12:50:13 +00004008 " Additional LIKE patterns can be given in subsequent arguments",
drh98aa2ab2018-09-26 16:53:51 +00004009 ".echo on|off Turn command echo on or off",
drhb4e50392019-01-26 15:40:04 +00004010 ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
4011 " Other Modes:",
4012#ifdef SQLITE_DEBUG
4013 " test Show raw EXPLAIN QUERY PLAN output",
drhe2754c12019-08-26 12:50:01 +00004014 " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"",
drhb4e50392019-01-26 15:40:04 +00004015#endif
4016 " trigger Like \"full\" but also show trigger bytecode",
drhe2754c12019-08-26 12:50:01 +00004017 ".excel Display the output of next command in spreadsheet",
drh7a431002020-04-18 14:12:00 +00004018 " --bom Put a UTF8 byte-order mark on intermediate file",
drheb7f2a02018-09-26 18:02:32 +00004019 ".exit ?CODE? Exit this program with return-code CODE",
drhe2754c12019-08-26 12:50:01 +00004020 ".expert EXPERIMENTAL. Suggest indexes for queries",
drh978256f2019-11-02 00:00:14 +00004021 ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto",
drhd985f722019-06-05 14:29:53 +00004022 ".filectrl CMD ... Run various sqlite3_file_control() operations",
drh541ef2c2020-04-20 16:21:30 +00004023 " --schema SCHEMA Use SCHEMA instead of \"main\"",
4024 " --help Show CMD details",
drh98aa2ab2018-09-26 16:53:51 +00004025 ".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
4026 ".headers on|off Turn display of headers on or off",
4027 ".help ?-all? ?PATTERN? Show help text for PATTERN",
4028 ".import FILE TABLE Import data from FILE into TABLE",
drhccb37812020-03-09 15:39:39 +00004029 " Options:",
4030 " --ascii Use \\037 and \\036 as column and row separators",
4031 " --csv Use , and \\n as column and row separators",
4032 " --skip N Skip the first N rows of input",
4033 " -v \"Verbose\" - increase auxiliary output",
4034 " Notes:",
4035 " * If TABLE does not exist, it is created. The first row of input",
4036 " determines the column names.",
4037 " * If neither --csv or --ascii are used, the input mode is derived",
4038 " from the \".mode\" output mode",
4039 " * If FILE begins with \"|\" then it is a command that generates the",
4040 " input text.",
drh2ce15c32017-07-11 13:34:40 +00004041#ifndef SQLITE_OMIT_TEST_CONTROL
drh98aa2ab2018-09-26 16:53:51 +00004042 ".imposter INDEX TABLE Create imposter table TABLE on index INDEX",
drh2ce15c32017-07-11 13:34:40 +00004043#endif
drh98aa2ab2018-09-26 16:53:51 +00004044 ".indexes ?TABLE? Show names of indexes",
4045 " If TABLE is specified, only show indexes for",
4046 " tables matching TABLE using the LIKE operator.",
drh2ce15c32017-07-11 13:34:40 +00004047#ifdef SQLITE_ENABLE_IOTRACE
drh98aa2ab2018-09-26 16:53:51 +00004048 ".iotrace FILE Enable I/O diagnostic logging to FILE",
drh2ce15c32017-07-11 13:34:40 +00004049#endif
drh98aa2ab2018-09-26 16:53:51 +00004050 ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
4051 ".lint OPTIONS Report potential schema issues.",
4052 " Options:",
4053 " fkey-indexes Find missing foreign key indexes",
drh2ce15c32017-07-11 13:34:40 +00004054#ifndef SQLITE_OMIT_LOAD_EXTENSION
drh98aa2ab2018-09-26 16:53:51 +00004055 ".load FILE ?ENTRY? Load an extension library",
drh2ce15c32017-07-11 13:34:40 +00004056#endif
drh98aa2ab2018-09-26 16:53:51 +00004057 ".log FILE|off Turn logging on or off. FILE can be stderr/stdout",
4058 ".mode MODE ?TABLE? Set output mode",
4059 " MODE is one of:",
drh7da29a32020-05-29 19:17:20 +00004060 " ascii Columns/rows delimited by 0x1F and 0x1E",
drh0908e382020-06-04 18:05:39 +00004061 " box Tables using unicode box-drawing characters",
drh7da29a32020-05-29 19:17:20 +00004062 " csv Comma-separated values",
4063 " column Output in columns. (See .width)",
4064 " html HTML <table> code",
4065 " insert SQL insert statements for TABLE",
4066 " json Results in a JSON array",
4067 " line One value per line",
4068 " list Values delimited by \"|\"",
4069 " markdown Markdown table format",
4070 " quote Escape answers as for SQL",
4071 " table ASCII-art table",
4072 " tabs Tab-separated values",
4073 " tcl TCL list elements",
drhb97e2ad2021-08-26 18:31:39 +00004074 ".nonce STRING Disable safe mode for one command if the nonce matches",
drh98aa2ab2018-09-26 16:53:51 +00004075 ".nullvalue STRING Use STRING in place of NULL values",
drh7a431002020-04-18 14:12:00 +00004076 ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE",
drh98aa2ab2018-09-26 16:53:51 +00004077 " If FILE begins with '|' then open as a pipe",
drh7a431002020-04-18 14:12:00 +00004078 " --bom Put a UTF8 byte-order mark at the beginning",
4079 " -e Send output to the system text editor",
4080 " -x Send output as CSV to a spreadsheet (same as \".excel\")",
drh4a3a3eb2020-02-29 15:53:48 +00004081#ifdef SQLITE_DEBUG
drhc0605082020-06-05 00:54:27 +00004082 ".oom ?--repeat M? ?N? Simulate an OOM error on the N-th allocation",
drh4a3a3eb2020-02-29 15:53:48 +00004083#endif
drh98aa2ab2018-09-26 16:53:51 +00004084 ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
4085 " Options:",
drh60f34ae2018-10-30 13:19:49 +00004086 " --append Use appendvfs to append database to the end of FILE",
drh8d889af2021-05-08 17:18:23 +00004087#ifndef SQLITE_OMIT_DESERIALIZE
drhd10c3ca2021-05-08 11:57:35 +00004088 " --deserialize Load into memory using sqlite3_deserialize()",
drhe2754c12019-08-26 12:50:01 +00004089 " --hexdb Load the output of \"dbtotxt\" as an in-memory db",
drh6ca64482019-01-22 16:06:20 +00004090 " --maxsize N Maximum size for --hexdb or --deserialized database",
drha751f392018-10-30 15:31:22 +00004091#endif
drh60f34ae2018-10-30 13:19:49 +00004092 " --new Initialize FILE to an empty database",
drh0933aad2019-11-18 17:46:38 +00004093 " --nofollow Do not follow symbolic links",
drh60f34ae2018-10-30 13:19:49 +00004094 " --readonly Open FILE readonly",
4095 " --zip FILE is a ZIP archive",
drh98aa2ab2018-09-26 16:53:51 +00004096 ".output ?FILE? Send output to FILE or stdout if FILE is omitted",
drh7a431002020-04-18 14:12:00 +00004097 " If FILE begins with '|' then open it as a pipe.",
4098 " Options:",
4099 " --bom Prefix output with a UTF8 byte-order mark",
4100 " -e Send output to the system text editor",
4101 " -x Send output as CSV to a spreadsheet",
drh9cb02642019-02-28 20:10:52 +00004102 ".parameter CMD ... Manage SQL parameter bindings",
4103 " clear Erase all bindings",
4104 " init Initialize the TEMP table that holds bindings",
4105 " list List the current parameter bindings",
4106 " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE",
drhe2754c12019-08-26 12:50:01 +00004107 " PARAMETER should start with one of: $ : @ ?",
drh9cb02642019-02-28 20:10:52 +00004108 " unset PARAMETER Remove PARAMETER from the binding table",
drh98aa2ab2018-09-26 16:53:51 +00004109 ".print STRING... Print literal STRING",
drh569b1d92019-02-05 20:51:41 +00004110#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh3f83f592019-02-04 14:53:18 +00004111 ".progress N Invoke progress handler after every N opcodes",
4112 " --limit N Interrupt after N progress callbacks",
4113 " --once Do no more than one progress interrupt",
4114 " --quiet|-q No output except at interrupts",
4115 " --reset Reset the count for each input and interrupt",
drh569b1d92019-02-05 20:51:41 +00004116#endif
drh98aa2ab2018-09-26 16:53:51 +00004117 ".prompt MAIN CONTINUE Replace the standard prompts",
4118 ".quit Exit this program",
4119 ".read FILE Read input from FILE",
dan1b162162019-04-27 20:15:15 +00004120#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan42ebb012019-04-27 18:47:03 +00004121 ".recover Recover as much data as possible from corrupt db.",
drhe2754c12019-08-26 12:50:01 +00004122 " --freelist-corrupt Assume the freelist is corrupt",
4123 " --recovery-db NAME Store recovery metadata in database file NAME",
4124 " --lost-and-found TABLE Alternative name for the lost-and-found table",
dan8cce6b82019-09-14 16:44:51 +00004125 " --no-rowids Do not attempt to recover rowid values",
4126 " that are not also INTEGER PRIMARY KEYs",
dan1b162162019-04-27 20:15:15 +00004127#endif
drh98aa2ab2018-09-26 16:53:51 +00004128 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
4129 ".save FILE Write in-memory database into FILE",
4130 ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
4131 ".schema ?PATTERN? Show the CREATE statements matching PATTERN",
drhbbb29ec2020-10-12 14:56:47 +00004132 " Options:",
4133 " --indent Try to pretty-print the schema",
4134 " --nosys Omit objects whose names start with \"sqlite_\"",
drheb7f2a02018-09-26 18:02:32 +00004135 ".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
4136 " Options:",
4137 " --init Create a new SELFTEST table",
4138 " -v Verbose output",
drh98aa2ab2018-09-26 16:53:51 +00004139 ".separator COL ?ROW? Change the column and row separators",
drh2ce15c32017-07-11 13:34:40 +00004140#if defined(SQLITE_ENABLE_SESSION)
drheb7f2a02018-09-26 18:02:32 +00004141 ".session ?NAME? CMD ... Create or control sessions",
4142 " Subcommands:",
4143 " attach TABLE Attach TABLE",
4144 " changeset FILE Write a changeset into FILE",
4145 " close Close one session",
4146 " enable ?BOOLEAN? Set or query the enable bit",
4147 " filter GLOB... Reject tables matching GLOBs",
4148 " indirect ?BOOLEAN? Mark or query the indirect status",
4149 " isempty Query whether the session is empty",
4150 " list List currently open session names",
4151 " open DB NAME Open a new session on DB",
4152 " patchset FILE Write a patchset into FILE",
4153 " If ?NAME? is omitted, the first defined session is used.",
drh2ce15c32017-07-11 13:34:40 +00004154#endif
drheb7f2a02018-09-26 18:02:32 +00004155 ".sha3sum ... Compute a SHA3 hash of database content",
4156 " Options:",
drh067b92b2020-06-19 15:24:12 +00004157 " --schema Also hash the sqlite_schema table",
drheb7f2a02018-09-26 18:02:32 +00004158 " --sha3-224 Use the sha3-224 algorithm",
drhe2754c12019-08-26 12:50:01 +00004159 " --sha3-256 Use the sha3-256 algorithm (default)",
drheb7f2a02018-09-26 18:02:32 +00004160 " --sha3-384 Use the sha3-384 algorithm",
4161 " --sha3-512 Use the sha3-512 algorithm",
4162 " Any other argument is a LIKE pattern for tables to hash",
drh04a28c32018-01-31 01:38:44 +00004163#ifndef SQLITE_NOHAVE_SYSTEM
drh98aa2ab2018-09-26 16:53:51 +00004164 ".shell CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004165#endif
drh98aa2ab2018-09-26 16:53:51 +00004166 ".show Show the current values for various settings",
drha6e6cf22021-01-09 19:10:04 +00004167 ".stats ?ARG? Show stats or turn stats on or off",
4168 " off Turn off automatic stat display",
4169 " on Turn on automatic stat display",
4170 " stmt Show statement stats",
4171 " vmstep Show the virtual machine step count only",
drh04a28c32018-01-31 01:38:44 +00004172#ifndef SQLITE_NOHAVE_SYSTEM
drh98aa2ab2018-09-26 16:53:51 +00004173 ".system CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004174#endif
drh98aa2ab2018-09-26 16:53:51 +00004175 ".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
4176 ".testcase NAME Begin redirecting output to 'testcase-out.txt'",
drhd985f722019-06-05 14:29:53 +00004177 ".testctrl CMD ... Run various sqlite3_test_control() operations",
4178 " Run \".testctrl\" with no arguments for details",
drh98aa2ab2018-09-26 16:53:51 +00004179 ".timeout MS Try opening locked tables for MS milliseconds",
4180 ".timer on|off Turn SQL timer on or off",
drh707821f2018-12-05 13:39:06 +00004181#ifndef SQLITE_OMIT_TRACE
4182 ".trace ?OPTIONS? Output each SQL statement as it is run",
4183 " FILE Send output to FILE",
4184 " stdout Send output to stdout",
4185 " stderr Send output to stderr",
4186 " off Disable tracing",
4187 " --expanded Expand query parameters",
4188#ifdef SQLITE_ENABLE_NORMALIZE
4189 " --normalized Normal the SQL statements",
4190#endif
4191 " --plain Show SQL as it is input",
4192 " --stmt Trace statement execution (SQLITE_TRACE_STMT)",
4193 " --profile Profile statements (SQLITE_TRACE_PROFILE)",
4194 " --row Trace each row (SQLITE_TRACE_ROW)",
4195 " --close Trace connection close (SQLITE_TRACE_CLOSE)",
4196#endif /* SQLITE_OMIT_TRACE */
drhcc5979d2019-08-16 22:58:29 +00004197#ifdef SQLITE_DEBUG
4198 ".unmodule NAME ... Unregister virtual table modules",
drh5df84282019-08-17 19:45:25 +00004199 " --allexcept Unregister everything except those named",
drhcc5979d2019-08-16 22:58:29 +00004200#endif
drh98aa2ab2018-09-26 16:53:51 +00004201 ".vfsinfo ?AUX? Information about the top-level VFS",
4202 ".vfslist List all available VFSes",
4203 ".vfsname ?AUX? Print the name of the VFS stack",
drh7da29a32020-05-29 19:17:20 +00004204 ".width NUM1 NUM2 ... Set minimum column widths for columnar output",
drh98aa2ab2018-09-26 16:53:51 +00004205 " Negative values right-justify",
4206};
4207
4208/*
4209** Output help text.
4210**
4211** zPattern describes the set of commands for which help text is provided.
4212** If zPattern is NULL, then show all commands, but only give a one-line
4213** description of each.
4214**
4215** Return the number of matches.
4216*/
4217static int showHelp(FILE *out, const char *zPattern){
drhe93f8262018-10-11 16:53:37 +00004218 int i = 0;
4219 int j = 0;
drh98aa2ab2018-09-26 16:53:51 +00004220 int n = 0;
4221 char *zPat;
drh488cddf2018-10-06 14:38:17 +00004222 if( zPattern==0
4223 || zPattern[0]=='0'
4224 || strcmp(zPattern,"-a")==0
4225 || strcmp(zPattern,"-all")==0
drh7a431002020-04-18 14:12:00 +00004226 || strcmp(zPattern,"--all")==0
drh488cddf2018-10-06 14:38:17 +00004227 ){
drh98aa2ab2018-09-26 16:53:51 +00004228 /* Show all commands, but only one line per command */
drh488cddf2018-10-06 14:38:17 +00004229 if( zPattern==0 ) zPattern = "";
drh98aa2ab2018-09-26 16:53:51 +00004230 for(i=0; i<ArraySize(azHelp); i++){
drh488cddf2018-10-06 14:38:17 +00004231 if( azHelp[i][0]=='.' || zPattern[0] ){
drh98aa2ab2018-09-26 16:53:51 +00004232 utf8_printf(out, "%s\n", azHelp[i]);
4233 n++;
4234 }
4235 }
4236 }else{
4237 /* Look for commands that for which zPattern is an exact prefix */
4238 zPat = sqlite3_mprintf(".%s*", zPattern);
4239 for(i=0; i<ArraySize(azHelp); i++){
4240 if( sqlite3_strglob(zPat, azHelp[i])==0 ){
4241 utf8_printf(out, "%s\n", azHelp[i]);
drheb7f2a02018-09-26 18:02:32 +00004242 j = i+1;
drh98aa2ab2018-09-26 16:53:51 +00004243 n++;
4244 }
4245 }
4246 sqlite3_free(zPat);
drheb7f2a02018-09-26 18:02:32 +00004247 if( n ){
4248 if( n==1 ){
4249 /* when zPattern is a prefix of exactly one command, then include the
4250 ** details of that command, which should begin at offset j */
4251 while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){
4252 utf8_printf(out, "%s\n", azHelp[j]);
4253 j++;
4254 }
4255 }
4256 return n;
4257 }
4258 /* Look for commands that contain zPattern anywhere. Show the complete
4259 ** text of all commands that match. */
drh98aa2ab2018-09-26 16:53:51 +00004260 zPat = sqlite3_mprintf("%%%s%%", zPattern);
4261 for(i=0; i<ArraySize(azHelp); i++){
4262 if( azHelp[i][0]=='.' ) j = i;
4263 if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
4264 utf8_printf(out, "%s\n", azHelp[j]);
4265 while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
4266 j++;
4267 utf8_printf(out, "%s\n", azHelp[j]);
4268 }
4269 i = j;
4270 n++;
4271 }
4272 }
4273 sqlite3_free(zPat);
4274 }
4275 return n;
4276}
drh2ce15c32017-07-11 13:34:40 +00004277
drh2ce15c32017-07-11 13:34:40 +00004278/* Forward reference */
drh60379d42018-12-13 18:30:01 +00004279static int process_input(ShellState *p);
drh2ce15c32017-07-11 13:34:40 +00004280
4281/*
4282** Read the content of file zName into memory obtained from sqlite3_malloc64()
4283** and return a pointer to the buffer. The caller is responsible for freeing
4284** the memory.
4285**
4286** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
4287** read.
4288**
4289** For convenience, a nul-terminator byte is always appended to the data read
4290** from the file before the buffer is returned. This byte is not included in
4291** the final value of (*pnByte), if applicable.
4292**
4293** NULL is returned if any error is encountered. The final value of *pnByte
4294** is undefined in this case.
4295*/
4296static char *readFile(const char *zName, int *pnByte){
4297 FILE *in = fopen(zName, "rb");
4298 long nIn;
4299 size_t nRead;
4300 char *pBuf;
4301 if( in==0 ) return 0;
4302 fseek(in, 0, SEEK_END);
4303 nIn = ftell(in);
4304 rewind(in);
4305 pBuf = sqlite3_malloc64( nIn+1 );
drh1dbb1472018-10-11 10:37:24 +00004306 if( pBuf==0 ){ fclose(in); return 0; }
drh2ce15c32017-07-11 13:34:40 +00004307 nRead = fread(pBuf, nIn, 1, in);
4308 fclose(in);
4309 if( nRead!=1 ){
4310 sqlite3_free(pBuf);
4311 return 0;
4312 }
4313 pBuf[nIn] = 0;
4314 if( pnByte ) *pnByte = nIn;
4315 return pBuf;
4316}
4317
4318#if defined(SQLITE_ENABLE_SESSION)
4319/*
4320** Close a single OpenSession object and release all of its associated
4321** resources.
4322*/
4323static void session_close(OpenSession *pSession){
4324 int i;
4325 sqlite3session_delete(pSession->p);
4326 sqlite3_free(pSession->zName);
4327 for(i=0; i<pSession->nFilter; i++){
4328 sqlite3_free(pSession->azFilter[i]);
4329 }
4330 sqlite3_free(pSession->azFilter);
4331 memset(pSession, 0, sizeof(OpenSession));
4332}
4333#endif
4334
4335/*
4336** Close all OpenSession objects and release all associated resources.
4337*/
4338#if defined(SQLITE_ENABLE_SESSION)
drh37407122021-07-23 18:43:58 +00004339static void session_close_all(ShellState *p, int i){
4340 int j;
4341 struct AuxDb *pAuxDb = i<0 ? p->pAuxDb : &p->aAuxDb[i];
4342 for(j=0; j<pAuxDb->nSession; j++){
4343 session_close(&pAuxDb->aSession[j]);
drh2ce15c32017-07-11 13:34:40 +00004344 }
drh37407122021-07-23 18:43:58 +00004345 pAuxDb->nSession = 0;
drh2ce15c32017-07-11 13:34:40 +00004346}
4347#else
drh37407122021-07-23 18:43:58 +00004348# define session_close_all(X,Y)
drh2ce15c32017-07-11 13:34:40 +00004349#endif
4350
4351/*
4352** Implementation of the xFilter function for an open session. Omit
4353** any tables named by ".session filter" but let all other table through.
4354*/
4355#if defined(SQLITE_ENABLE_SESSION)
4356static int session_filter(void *pCtx, const char *zTab){
4357 OpenSession *pSession = (OpenSession*)pCtx;
4358 int i;
4359 for(i=0; i<pSession->nFilter; i++){
4360 if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
4361 }
4362 return 1;
4363}
4364#endif
4365
4366/*
drh1fa6d9f2018-01-06 21:46:01 +00004367** Try to deduce the type of file for zName based on its content. Return
4368** one of the SHELL_OPEN_* constants.
drh1bf208c2018-03-09 21:54:01 +00004369**
4370** If the file does not exist or is empty but its name looks like a ZIP
4371** archive and the dfltZip flag is true, then assume it is a ZIP archive.
4372** Otherwise, assume an ordinary database regardless of the filename if
4373** the type cannot be determined from content.
drh1fa6d9f2018-01-06 21:46:01 +00004374*/
drhfc97c1c2018-05-14 00:41:12 +00004375int deduceDatabaseType(const char *zName, int dfltZip){
drh1fa6d9f2018-01-06 21:46:01 +00004376 FILE *f = fopen(zName, "rb");
4377 size_t n;
4378 int rc = SHELL_OPEN_UNSPEC;
4379 char zBuf[100];
drh1bf208c2018-03-09 21:54:01 +00004380 if( f==0 ){
drhbe4ccb22018-05-17 20:04:24 +00004381 if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
4382 return SHELL_OPEN_ZIPFILE;
4383 }else{
4384 return SHELL_OPEN_NORMAL;
4385 }
drh1bf208c2018-03-09 21:54:01 +00004386 }
drh2b3c4af2018-10-30 14:36:21 +00004387 n = fread(zBuf, 16, 1, f);
4388 if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
4389 fclose(f);
4390 return SHELL_OPEN_NORMAL;
4391 }
drh1fa6d9f2018-01-06 21:46:01 +00004392 fseek(f, -25, SEEK_END);
4393 n = fread(zBuf, 25, 1, f);
4394 if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
4395 rc = SHELL_OPEN_APPENDVFS;
4396 }else{
4397 fseek(f, -22, SEEK_END);
4398 n = fread(zBuf, 22, 1, f);
4399 if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
4400 && zBuf[3]==0x06 ){
4401 rc = SHELL_OPEN_ZIPFILE;
drh1bf208c2018-03-09 21:54:01 +00004402 }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
mistachkina3926f42018-05-14 12:23:04 +00004403 rc = SHELL_OPEN_ZIPFILE;
drh1fa6d9f2018-01-06 21:46:01 +00004404 }
4405 }
4406 fclose(f);
4407 return rc;
4408}
4409
drh8d889af2021-05-08 17:18:23 +00004410#ifndef SQLITE_OMIT_DESERIALIZE
drh33746482018-12-13 15:06:26 +00004411/*
4412** Reconstruct an in-memory database using the output from the "dbtotxt"
drh37407122021-07-23 18:43:58 +00004413** program. Read content from the file in p->aAuxDb[].zDbFilename.
4414** If p->aAuxDb[].zDbFilename is 0, then read from standard input.
drh33746482018-12-13 15:06:26 +00004415*/
4416static unsigned char *readHexDb(ShellState *p, int *pnData){
4417 unsigned char *a = 0;
drh2c8ee022018-12-13 18:59:30 +00004418 int nLine;
drh33746482018-12-13 15:06:26 +00004419 int n = 0;
4420 int pgsz = 0;
4421 int iOffset = 0;
4422 int j, k;
4423 int rc;
4424 FILE *in;
drh37407122021-07-23 18:43:58 +00004425 const char *zDbFilename = p->pAuxDb->zDbFilename;
drh3ea557e2019-04-23 15:30:58 +00004426 unsigned int x[16];
drh2c8ee022018-12-13 18:59:30 +00004427 char zLine[1000];
drh37407122021-07-23 18:43:58 +00004428 if( zDbFilename ){
4429 in = fopen(zDbFilename, "r");
drh33746482018-12-13 15:06:26 +00004430 if( in==0 ){
drh37407122021-07-23 18:43:58 +00004431 utf8_printf(stderr, "cannot open \"%s\" for reading\n", zDbFilename);
drh33746482018-12-13 15:06:26 +00004432 return 0;
4433 }
drh2c8ee022018-12-13 18:59:30 +00004434 nLine = 0;
drh33746482018-12-13 15:06:26 +00004435 }else{
drh60379d42018-12-13 18:30:01 +00004436 in = p->in;
drh2c8ee022018-12-13 18:59:30 +00004437 nLine = p->lineno;
drh5bf46442019-05-03 02:41:36 +00004438 if( in==0 ) in = stdin;
drh33746482018-12-13 15:06:26 +00004439 }
4440 *pnData = 0;
drh2c8ee022018-12-13 18:59:30 +00004441 nLine++;
drh33746482018-12-13 15:06:26 +00004442 if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
4443 rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
4444 if( rc!=2 ) goto readHexDb_error;
drh68feae52019-05-09 11:18:41 +00004445 if( n<0 ) goto readHexDb_error;
drh09ea1252019-07-17 15:05:16 +00004446 if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
4447 n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */
drh68feae52019-05-09 11:18:41 +00004448 a = sqlite3_malloc( n ? n : 1 );
drh33746482018-12-13 15:06:26 +00004449 if( a==0 ){
4450 utf8_printf(stderr, "Out of memory!\n");
4451 goto readHexDb_error;
4452 }
4453 memset(a, 0, n);
4454 if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
4455 utf8_printf(stderr, "invalid pagesize\n");
4456 goto readHexDb_error;
4457 }
drh2c8ee022018-12-13 18:59:30 +00004458 for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
drh33746482018-12-13 15:06:26 +00004459 rc = sscanf(zLine, "| page %d offset %d", &j, &k);
4460 if( rc==2 ){
4461 iOffset = k;
4462 continue;
4463 }
4464 if( strncmp(zLine, "| end ", 6)==0 ){
4465 break;
4466 }
drh3ea557e2019-04-23 15:30:58 +00004467 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 +00004468 &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
4469 &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
4470 if( rc==17 ){
4471 k = iOffset+j;
drhf354e772018-12-13 22:58:52 +00004472 if( k+16<=n ){
drh3ea557e2019-04-23 15:30:58 +00004473 int ii;
4474 for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
drh33746482018-12-13 15:06:26 +00004475 }
drh33746482018-12-13 15:06:26 +00004476 }
4477 }
4478 *pnData = n;
drh2c8ee022018-12-13 18:59:30 +00004479 if( in!=p->in ){
4480 fclose(in);
4481 }else{
4482 p->lineno = nLine;
4483 }
drh33746482018-12-13 15:06:26 +00004484 return a;
4485
4486readHexDb_error:
drh68feae52019-05-09 11:18:41 +00004487 if( in!=p->in ){
drh33746482018-12-13 15:06:26 +00004488 fclose(in);
4489 }else{
drh60379d42018-12-13 18:30:01 +00004490 while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
drh2c8ee022018-12-13 18:59:30 +00004491 nLine++;
drh33746482018-12-13 15:06:26 +00004492 if(strncmp(zLine, "| end ", 6)==0 ) break;
4493 }
drh2c8ee022018-12-13 18:59:30 +00004494 p->lineno = nLine;
drh33746482018-12-13 15:06:26 +00004495 }
4496 sqlite3_free(a);
4497 utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
4498 return 0;
4499}
drh8d889af2021-05-08 17:18:23 +00004500#endif /* SQLITE_OMIT_DESERIALIZE */
drh33746482018-12-13 15:06:26 +00004501
danb1825882019-04-23 20:48:32 +00004502/*
dan9c014f82019-04-25 19:23:15 +00004503** Scalar function "shell_int32". The first argument to this function
4504** must be a blob. The second a non-negative integer. This function
4505** reads and returns a 32-bit big-endian integer from byte
4506** offset (4*<arg2>) of the blob.
4507*/
4508static void shellInt32(
4509 sqlite3_context *context,
4510 int argc,
4511 sqlite3_value **argv
4512){
4513 const unsigned char *pBlob;
4514 int nBlob;
4515 int iInt;
drh9546c762019-05-10 17:50:33 +00004516
4517 UNUSED_PARAMETER(argc);
dan9c014f82019-04-25 19:23:15 +00004518 nBlob = sqlite3_value_bytes(argv[0]);
4519 pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
4520 iInt = sqlite3_value_int(argv[1]);
4521
4522 if( iInt>=0 && (iInt+1)*4<=nBlob ){
4523 const unsigned char *a = &pBlob[iInt*4];
4524 sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24)
4525 + ((sqlite3_int64)a[1]<<16)
4526 + ((sqlite3_int64)a[2]<< 8)
4527 + ((sqlite3_int64)a[3]<< 0);
4528 sqlite3_result_int64(context, iVal);
4529 }
4530}
4531
4532/*
drha2de66c2019-08-06 20:26:17 +00004533** Scalar function "shell_idquote(X)" returns string X quoted as an identifier,
4534** using "..." with internal double-quote characters doubled.
4535*/
4536static void shellIdQuote(
4537 sqlite3_context *context,
4538 int argc,
4539 sqlite3_value **argv
4540){
4541 const char *zName = (const char*)sqlite3_value_text(argv[0]);
drh51755a72019-08-08 19:40:29 +00004542 UNUSED_PARAMETER(argc);
drha2de66c2019-08-06 20:26:17 +00004543 if( zName ){
4544 char *z = sqlite3_mprintf("\"%w\"", zName);
4545 sqlite3_result_text(context, z, -1, sqlite3_free);
4546 }
4547}
4548
4549/*
drhddcfe922020-09-15 12:29:35 +00004550** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
4551*/
4552static void shellUSleepFunc(
4553 sqlite3_context *context,
drhd36f5882020-11-25 16:28:04 +00004554 int argcUnused,
drhddcfe922020-09-15 12:29:35 +00004555 sqlite3_value **argv
4556){
4557 int sleep = sqlite3_value_int(argv[0]);
drhd36f5882020-11-25 16:28:04 +00004558 (void)argcUnused;
drhddcfe922020-09-15 12:29:35 +00004559 sqlite3_sleep(sleep/1000);
4560 sqlite3_result_int(context, sleep);
4561}
4562
4563/*
danb1825882019-04-23 20:48:32 +00004564** Scalar function "shell_escape_crnl" used by the .recover command.
4565** The argument passed to this function is the output of built-in
4566** function quote(). If the first character of the input is "'",
4567** indicating that the value passed to quote() was a text value,
4568** then this function searches the input for "\n" and "\r" characters
4569** and adds a wrapper similar to the following:
4570**
4571** replace(replace(<input>, '\n', char(10), '\r', char(13));
4572**
4573** Or, if the first character of the input is not "'", then a copy
4574** of the input is returned.
4575*/
4576static void shellEscapeCrnl(
4577 sqlite3_context *context,
4578 int argc,
4579 sqlite3_value **argv
4580){
4581 const char *zText = (const char*)sqlite3_value_text(argv[0]);
drh9546c762019-05-10 17:50:33 +00004582 UNUSED_PARAMETER(argc);
danb1825882019-04-23 20:48:32 +00004583 if( zText[0]=='\'' ){
4584 int nText = sqlite3_value_bytes(argv[0]);
4585 int i;
4586 char zBuf1[20];
4587 char zBuf2[20];
4588 const char *zNL = 0;
4589 const char *zCR = 0;
4590 int nCR = 0;
4591 int nNL = 0;
4592
4593 for(i=0; zText[i]; i++){
4594 if( zNL==0 && zText[i]=='\n' ){
4595 zNL = unused_string(zText, "\\n", "\\012", zBuf1);
4596 nNL = (int)strlen(zNL);
4597 }
4598 if( zCR==0 && zText[i]=='\r' ){
4599 zCR = unused_string(zText, "\\r", "\\015", zBuf2);
4600 nCR = (int)strlen(zCR);
4601 }
4602 }
4603
4604 if( zNL || zCR ){
4605 int iOut = 0;
4606 i64 nMax = (nNL > nCR) ? nNL : nCR;
dan51f5ffa2019-04-29 11:41:46 +00004607 i64 nAlloc = nMax * nText + (nMax+64)*2;
danb1825882019-04-23 20:48:32 +00004608 char *zOut = (char*)sqlite3_malloc64(nAlloc);
4609 if( zOut==0 ){
4610 sqlite3_result_error_nomem(context);
4611 return;
4612 }
4613
4614 if( zNL && zCR ){
4615 memcpy(&zOut[iOut], "replace(replace(", 16);
4616 iOut += 16;
4617 }else{
4618 memcpy(&zOut[iOut], "replace(", 8);
4619 iOut += 8;
4620 }
4621 for(i=0; zText[i]; i++){
4622 if( zText[i]=='\n' ){
4623 memcpy(&zOut[iOut], zNL, nNL);
4624 iOut += nNL;
4625 }else if( zText[i]=='\r' ){
4626 memcpy(&zOut[iOut], zCR, nCR);
4627 iOut += nCR;
4628 }else{
4629 zOut[iOut] = zText[i];
4630 iOut++;
4631 }
4632 }
4633
4634 if( zNL ){
4635 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
4636 memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
4637 memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
4638 }
4639 if( zCR ){
4640 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
4641 memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
4642 memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
4643 }
4644
4645 sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
4646 sqlite3_free(zOut);
4647 return;
4648 }
4649 }
4650
4651 sqlite3_result_value(context, argv[0]);
4652}
4653
drhbe4ccb22018-05-17 20:04:24 +00004654/* Flags for open_db().
4655**
4656** The default behavior of open_db() is to exit(1) if the database fails to
4657** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
4658** but still returns without calling exit.
4659**
4660** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a
4661** ZIP archive if the file does not exist or is empty and its name matches
4662** the *.zip pattern.
4663*/
4664#define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */
4665#define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */
4666
drh1fa6d9f2018-01-06 21:46:01 +00004667/*
drh2ce15c32017-07-11 13:34:40 +00004668** Make sure the database is open. If it is not, then open it. If
4669** the database fails to open, print an error message and exit.
4670*/
drhbe4ccb22018-05-17 20:04:24 +00004671static void open_db(ShellState *p, int openFlags){
drh2ce15c32017-07-11 13:34:40 +00004672 if( p->db==0 ){
drh37407122021-07-23 18:43:58 +00004673 const char *zDbFilename = p->pAuxDb->zDbFilename;
drhf2072d12018-05-11 15:10:11 +00004674 if( p->openMode==SHELL_OPEN_UNSPEC ){
drh37407122021-07-23 18:43:58 +00004675 if( zDbFilename==0 || zDbFilename[0]==0 ){
drhf2072d12018-05-11 15:10:11 +00004676 p->openMode = SHELL_OPEN_NORMAL;
drhbe4ccb22018-05-17 20:04:24 +00004677 }else{
drh37407122021-07-23 18:43:58 +00004678 p->openMode = (u8)deduceDatabaseType(zDbFilename,
drhbe4ccb22018-05-17 20:04:24 +00004679 (openFlags & OPEN_DB_ZIPFILE)!=0);
drhf2072d12018-05-11 15:10:11 +00004680 }
drh1fa6d9f2018-01-06 21:46:01 +00004681 }
4682 switch( p->openMode ){
4683 case SHELL_OPEN_APPENDVFS: {
drh37407122021-07-23 18:43:58 +00004684 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004685 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
drh1fa6d9f2018-01-06 21:46:01 +00004686 break;
4687 }
drh33746482018-12-13 15:06:26 +00004688 case SHELL_OPEN_HEXDB:
drh60f34ae2018-10-30 13:19:49 +00004689 case SHELL_OPEN_DESERIALIZE: {
4690 sqlite3_open(0, &p->db);
4691 break;
4692 }
drh1fa6d9f2018-01-06 21:46:01 +00004693 case SHELL_OPEN_ZIPFILE: {
4694 sqlite3_open(":memory:", &p->db);
4695 break;
4696 }
drhee269a62018-02-14 23:27:43 +00004697 case SHELL_OPEN_READONLY: {
drh37407122021-07-23 18:43:58 +00004698 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004699 SQLITE_OPEN_READONLY|p->openFlags, 0);
drhee269a62018-02-14 23:27:43 +00004700 break;
4701 }
drh1fa6d9f2018-01-06 21:46:01 +00004702 case SHELL_OPEN_UNSPEC:
4703 case SHELL_OPEN_NORMAL: {
drh37407122021-07-23 18:43:58 +00004704 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004705 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
drh1fa6d9f2018-01-06 21:46:01 +00004706 break;
4707 }
4708 }
drh2ce15c32017-07-11 13:34:40 +00004709 globalDb = p->db;
4710 if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
4711 utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
drh37407122021-07-23 18:43:58 +00004712 zDbFilename, sqlite3_errmsg(p->db));
drhf25cc4f2019-01-04 14:29:21 +00004713 if( openFlags & OPEN_DB_KEEPALIVE ){
4714 sqlite3_open(":memory:", &p->db);
4715 return;
4716 }
drh2ce15c32017-07-11 13:34:40 +00004717 exit(1);
4718 }
4719#ifndef SQLITE_OMIT_LOAD_EXTENSION
4720 sqlite3_enable_load_extension(p->db, 1);
4721#endif
4722 sqlite3_fileio_init(p->db, 0, 0);
4723 sqlite3_shathree_init(p->db, 0, 0);
drh56eb09b2017-07-11 13:59:07 +00004724 sqlite3_completion_init(p->db, 0, 0);
drhf05dd032020-04-14 15:53:58 +00004725 sqlite3_uint_init(p->db, 0, 0);
drhbeb9def2020-06-22 19:12:23 +00004726 sqlite3_decimal_init(p->db, 0, 0);
drh64689902021-06-03 13:51:31 +00004727 sqlite3_regexp_init(p->db, 0, 0);
drh8cda77d2020-06-24 15:06:29 +00004728 sqlite3_ieee_init(p->db, 0, 0);
mistachkin72c38d82020-08-28 18:47:39 +00004729 sqlite3_series_init(p->db, 0, 0);
dan1b162162019-04-27 20:15:15 +00004730#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00004731 sqlite3_dbdata_init(p->db, 0, 0);
dan1b162162019-04-27 20:15:15 +00004732#endif
dan72afc3c2017-12-05 18:32:40 +00004733#ifdef SQLITE_HAVE_ZLIB
dan9ebfaad2017-12-26 20:39:58 +00004734 sqlite3_zipfile_init(p->db, 0, 0);
dand1b51d42017-12-16 19:11:26 +00004735 sqlite3_sqlar_init(p->db, 0, 0);
dan72afc3c2017-12-05 18:32:40 +00004736#endif
drhceba7922018-01-01 21:28:25 +00004737 sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
drh2ce15c32017-07-11 13:34:40 +00004738 shellAddSchemaName, 0, 0);
drh667a2a22018-01-02 00:04:37 +00004739 sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
4740 shellModuleSchema, 0, 0);
drh634c70f2018-01-10 16:50:18 +00004741 sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
4742 shellPutsFunc, 0, 0);
danb1825882019-04-23 20:48:32 +00004743 sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0,
4744 shellEscapeCrnl, 0, 0);
dan9c014f82019-04-25 19:23:15 +00004745 sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
4746 shellInt32, 0, 0);
drha2de66c2019-08-06 20:26:17 +00004747 sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
4748 shellIdQuote, 0, 0);
drhddcfe922020-09-15 12:29:35 +00004749 sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
4750 shellUSleepFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00004751#ifndef SQLITE_NOHAVE_SYSTEM
drh97913132018-01-11 00:04:00 +00004752 sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
4753 editFunc, 0, 0);
4754 sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
4755 editFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00004756#endif
drh1fa6d9f2018-01-06 21:46:01 +00004757 if( p->openMode==SHELL_OPEN_ZIPFILE ){
4758 char *zSql = sqlite3_mprintf(
drh37407122021-07-23 18:43:58 +00004759 "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename);
drh1fa6d9f2018-01-06 21:46:01 +00004760 sqlite3_exec(p->db, zSql, 0, 0, 0);
4761 sqlite3_free(zSql);
drha751f392018-10-30 15:31:22 +00004762 }
drh8d889af2021-05-08 17:18:23 +00004763#ifndef SQLITE_OMIT_DESERIALIZE
drh33746482018-12-13 15:06:26 +00004764 else
4765 if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
mistachkin99490932018-12-17 22:19:57 +00004766 int rc;
drh60f34ae2018-10-30 13:19:49 +00004767 int nData = 0;
drh33746482018-12-13 15:06:26 +00004768 unsigned char *aData;
4769 if( p->openMode==SHELL_OPEN_DESERIALIZE ){
drh37407122021-07-23 18:43:58 +00004770 aData = (unsigned char*)readFile(zDbFilename, &nData);
drh33746482018-12-13 15:06:26 +00004771 }else{
4772 aData = readHexDb(p, &nData);
4773 if( aData==0 ){
drh33746482018-12-13 15:06:26 +00004774 return;
4775 }
4776 }
mistachkin99490932018-12-17 22:19:57 +00004777 rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
drh60f34ae2018-10-30 13:19:49 +00004778 SQLITE_DESERIALIZE_RESIZEABLE |
4779 SQLITE_DESERIALIZE_FREEONCLOSE);
4780 if( rc ){
4781 utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
4782 }
drh6ca64482019-01-22 16:06:20 +00004783 if( p->szMax>0 ){
4784 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
4785 }
drh1fa6d9f2018-01-06 21:46:01 +00004786 }
drha751f392018-10-30 15:31:22 +00004787#endif
drh2ce15c32017-07-11 13:34:40 +00004788 }
drhb97e2ad2021-08-26 18:31:39 +00004789 if( p->bSafeModePersist && p->db!=0 ){
4790 sqlite3_set_authorizer(p->db, safeModeAuth, p);
4791 }
drh2ce15c32017-07-11 13:34:40 +00004792}
4793
drh9e804032018-05-18 17:11:50 +00004794/*
4795** Attempt to close the databaes connection. Report errors.
4796*/
4797void close_db(sqlite3 *db){
4798 int rc = sqlite3_close(db);
4799 if( rc ){
4800 utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
4801 rc, sqlite3_errmsg(db));
4802 }
4803}
4804
drh56eb09b2017-07-11 13:59:07 +00004805#if HAVE_READLINE || HAVE_EDITLINE
4806/*
4807** Readline completion callbacks
4808*/
4809static char *readline_completion_generator(const char *text, int state){
4810 static sqlite3_stmt *pStmt = 0;
4811 char *zRet;
4812 if( state==0 ){
4813 char *zSql;
drh56eb09b2017-07-11 13:59:07 +00004814 sqlite3_finalize(pStmt);
4815 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
4816 " FROM completion(%Q) ORDER BY 1", text);
4817 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
4818 sqlite3_free(zSql);
4819 }
4820 if( sqlite3_step(pStmt)==SQLITE_ROW ){
drh968d8712017-07-14 00:28:28 +00004821 zRet = strdup((const char*)sqlite3_column_text(pStmt, 0));
drh56eb09b2017-07-11 13:59:07 +00004822 }else{
4823 sqlite3_finalize(pStmt);
4824 pStmt = 0;
4825 zRet = 0;
4826 }
4827 return zRet;
4828}
4829static char **readline_completion(const char *zText, int iStart, int iEnd){
4830 rl_attempted_completion_over = 1;
4831 return rl_completion_matches(zText, readline_completion_generator);
4832}
4833
4834#elif HAVE_LINENOISE
4835/*
4836** Linenoise completion callback
4837*/
4838static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
drhaf2770f2018-01-05 14:55:43 +00004839 int nLine = strlen30(zLine);
drh56eb09b2017-07-11 13:59:07 +00004840 int i, iStart;
4841 sqlite3_stmt *pStmt = 0;
4842 char *zSql;
4843 char zBuf[1000];
4844
4845 if( nLine>sizeof(zBuf)-30 ) return;
drh1615c372018-05-12 23:56:22 +00004846 if( zLine[0]=='.' || zLine[0]=='#') return;
drh56eb09b2017-07-11 13:59:07 +00004847 for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
4848 if( i==nLine-1 ) return;
4849 iStart = i+1;
4850 memcpy(zBuf, zLine, iStart);
4851 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
4852 " FROM completion(%Q,%Q) ORDER BY 1",
4853 &zLine[iStart], zLine);
4854 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
4855 sqlite3_free(zSql);
4856 sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
4857 while( sqlite3_step(pStmt)==SQLITE_ROW ){
4858 const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
4859 int nCompletion = sqlite3_column_bytes(pStmt, 0);
4860 if( iStart+nCompletion < sizeof(zBuf)-1 ){
4861 memcpy(zBuf+iStart, zCompletion, nCompletion+1);
4862 linenoiseAddCompletion(lc, zBuf);
4863 }
4864 }
4865 sqlite3_finalize(pStmt);
4866}
4867#endif
4868
drh2ce15c32017-07-11 13:34:40 +00004869/*
4870** Do C-language style dequoting.
4871**
4872** \a -> alarm
4873** \b -> backspace
4874** \t -> tab
4875** \n -> newline
4876** \v -> vertical tab
4877** \f -> form feed
4878** \r -> carriage return
4879** \s -> space
4880** \" -> "
4881** \' -> '
4882** \\ -> backslash
4883** \NNN -> ascii character NNN in octal
4884*/
4885static void resolve_backslashes(char *z){
4886 int i, j;
4887 char c;
4888 while( *z && *z!='\\' ) z++;
4889 for(i=j=0; (c = z[i])!=0; i++, j++){
4890 if( c=='\\' && z[i+1]!=0 ){
4891 c = z[++i];
4892 if( c=='a' ){
4893 c = '\a';
4894 }else if( c=='b' ){
4895 c = '\b';
4896 }else if( c=='t' ){
4897 c = '\t';
4898 }else if( c=='n' ){
4899 c = '\n';
4900 }else if( c=='v' ){
4901 c = '\v';
4902 }else if( c=='f' ){
4903 c = '\f';
4904 }else if( c=='r' ){
4905 c = '\r';
4906 }else if( c=='"' ){
4907 c = '"';
4908 }else if( c=='\'' ){
4909 c = '\'';
4910 }else if( c=='\\' ){
4911 c = '\\';
4912 }else if( c>='0' && c<='7' ){
4913 c -= '0';
4914 if( z[i+1]>='0' && z[i+1]<='7' ){
4915 i++;
4916 c = (c<<3) + z[i] - '0';
4917 if( z[i+1]>='0' && z[i+1]<='7' ){
4918 i++;
4919 c = (c<<3) + z[i] - '0';
4920 }
4921 }
4922 }
4923 }
4924 z[j] = c;
4925 }
4926 if( j<i ) z[j] = 0;
4927}
4928
4929/*
drh2ce15c32017-07-11 13:34:40 +00004930** Interpret zArg as either an integer or a boolean value. Return 1 or 0
4931** for TRUE and FALSE. Return the integer value if appropriate.
4932*/
4933static int booleanValue(const char *zArg){
4934 int i;
4935 if( zArg[0]=='0' && zArg[1]=='x' ){
4936 for(i=2; hexDigitValue(zArg[i])>=0; i++){}
4937 }else{
4938 for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
4939 }
4940 if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
4941 if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
4942 return 1;
4943 }
4944 if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
4945 return 0;
4946 }
4947 utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
4948 zArg);
4949 return 0;
4950}
4951
4952/*
4953** Set or clear a shell flag according to a boolean value.
4954*/
4955static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){
4956 if( booleanValue(zArg) ){
4957 ShellSetFlag(p, mFlag);
4958 }else{
4959 ShellClearFlag(p, mFlag);
4960 }
4961}
4962
4963/*
4964** Close an output file, assuming it is not stderr or stdout
4965*/
4966static void output_file_close(FILE *f){
4967 if( f && f!=stdout && f!=stderr ) fclose(f);
4968}
4969
4970/*
4971** Try to open an output file. The names "stdout" and "stderr" are
4972** recognized and do the right thing. NULL is returned if the output
4973** filename is "off".
4974*/
drha92a01a2018-01-10 22:15:37 +00004975static FILE *output_file_open(const char *zFile, int bTextMode){
drh2ce15c32017-07-11 13:34:40 +00004976 FILE *f;
4977 if( strcmp(zFile,"stdout")==0 ){
4978 f = stdout;
4979 }else if( strcmp(zFile, "stderr")==0 ){
4980 f = stderr;
4981 }else if( strcmp(zFile, "off")==0 ){
4982 f = 0;
4983 }else{
drha92a01a2018-01-10 22:15:37 +00004984 f = fopen(zFile, bTextMode ? "w" : "wb");
drh2ce15c32017-07-11 13:34:40 +00004985 if( f==0 ){
4986 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
4987 }
4988 }
4989 return f;
4990}
4991
drh707821f2018-12-05 13:39:06 +00004992#ifndef SQLITE_OMIT_TRACE
drh2ce15c32017-07-11 13:34:40 +00004993/*
4994** A routine for handling output from sqlite3_trace().
4995*/
4996static int sql_trace_callback(
drh707821f2018-12-05 13:39:06 +00004997 unsigned mType, /* The trace type */
4998 void *pArg, /* The ShellState pointer */
4999 void *pP, /* Usually a pointer to sqlite_stmt */
5000 void *pX /* Auxiliary output */
drh2ce15c32017-07-11 13:34:40 +00005001){
drh707821f2018-12-05 13:39:06 +00005002 ShellState *p = (ShellState*)pArg;
5003 sqlite3_stmt *pStmt;
5004 const char *zSql;
5005 int nSql;
5006 if( p->traceOut==0 ) return 0;
5007 if( mType==SQLITE_TRACE_CLOSE ){
5008 utf8_printf(p->traceOut, "-- closing database connection\n");
5009 return 0;
5010 }
5011 if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){
5012 zSql = (const char*)pX;
5013 }else{
5014 pStmt = (sqlite3_stmt*)pP;
5015 switch( p->eTraceType ){
5016 case SHELL_TRACE_EXPANDED: {
5017 zSql = sqlite3_expanded_sql(pStmt);
5018 break;
5019 }
5020#ifdef SQLITE_ENABLE_NORMALIZE
5021 case SHELL_TRACE_NORMALIZED: {
5022 zSql = sqlite3_normalized_sql(pStmt);
5023 break;
5024 }
5025#endif
5026 default: {
5027 zSql = sqlite3_sql(pStmt);
5028 break;
5029 }
5030 }
5031 }
5032 if( zSql==0 ) return 0;
5033 nSql = strlen30(zSql);
5034 while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
5035 switch( mType ){
5036 case SQLITE_TRACE_ROW:
5037 case SQLITE_TRACE_STMT: {
5038 utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql);
5039 break;
5040 }
5041 case SQLITE_TRACE_PROFILE: {
5042 sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
5043 utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec);
5044 break;
5045 }
drh2ce15c32017-07-11 13:34:40 +00005046 }
5047 return 0;
5048}
5049#endif
drh2ce15c32017-07-11 13:34:40 +00005050
5051/*
5052** A no-op routine that runs with the ".breakpoint" doc-command. This is
5053** a useful spot to set a debugger breakpoint.
5054*/
5055static void test_breakpoint(void){
5056 static int nCall = 0;
5057 nCall++;
5058}
5059
5060/*
5061** An object used to read a CSV and other files for import.
5062*/
5063typedef struct ImportCtx ImportCtx;
5064struct ImportCtx {
5065 const char *zFile; /* Name of the input file */
5066 FILE *in; /* Read the CSV text from this input stream */
drh97767842020-05-29 19:39:35 +00005067 int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */
drh2ce15c32017-07-11 13:34:40 +00005068 char *z; /* Accumulated text for a field */
5069 int n; /* Number of bytes in z */
5070 int nAlloc; /* Space allocated for z[] */
5071 int nLine; /* Current line number */
drhccb37812020-03-09 15:39:39 +00005072 int nRow; /* Number of rows imported */
5073 int nErr; /* Number of errors encountered */
drh2ce15c32017-07-11 13:34:40 +00005074 int bNotFirst; /* True if one or more bytes already read */
5075 int cTerm; /* Character that terminated the most recent field */
5076 int cColSep; /* The column separator character. (Usually ",") */
5077 int cRowSep; /* The row separator character. (Usually "\n") */
5078};
5079
drh97767842020-05-29 19:39:35 +00005080/* Clean up resourced used by an ImportCtx */
5081static void import_cleanup(ImportCtx *p){
drh42c2a042020-05-29 20:16:19 +00005082 if( p->in!=0 && p->xCloser!=0 ){
drh97767842020-05-29 19:39:35 +00005083 p->xCloser(p->in);
5084 p->in = 0;
5085 }
5086 sqlite3_free(p->z);
5087 p->z = 0;
5088}
5089
drh2ce15c32017-07-11 13:34:40 +00005090/* Append a single byte to z[] */
5091static void import_append_char(ImportCtx *p, int c){
5092 if( p->n+1>=p->nAlloc ){
5093 p->nAlloc += p->nAlloc + 100;
5094 p->z = sqlite3_realloc64(p->z, p->nAlloc);
drh4b5345c2018-04-24 13:07:40 +00005095 if( p->z==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00005096 }
5097 p->z[p->n++] = (char)c;
5098}
5099
5100/* Read a single field of CSV text. Compatible with rfc4180 and extended
5101** with the option of having a separator other than ",".
5102**
5103** + Input comes from p->in.
5104** + Store results in p->z of length p->n. Space to hold p->z comes
5105** from sqlite3_malloc64().
5106** + Use p->cSep as the column separator. The default is ",".
5107** + Use p->rSep as the row separator. The default is "\n".
5108** + Keep track of the line number in p->nLine.
5109** + Store the character that terminates the field in p->cTerm. Store
5110** EOF on end-of-file.
5111** + Report syntax errors on stderr
5112*/
5113static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
5114 int c;
5115 int cSep = p->cColSep;
5116 int rSep = p->cRowSep;
5117 p->n = 0;
5118 c = fgetc(p->in);
5119 if( c==EOF || seenInterrupt ){
5120 p->cTerm = EOF;
5121 return 0;
5122 }
5123 if( c=='"' ){
5124 int pc, ppc;
5125 int startLine = p->nLine;
5126 int cQuote = c;
5127 pc = ppc = 0;
5128 while( 1 ){
5129 c = fgetc(p->in);
5130 if( c==rSep ) p->nLine++;
5131 if( c==cQuote ){
5132 if( pc==cQuote ){
5133 pc = 0;
5134 continue;
5135 }
5136 }
5137 if( (c==cSep && pc==cQuote)
5138 || (c==rSep && pc==cQuote)
5139 || (c==rSep && pc=='\r' && ppc==cQuote)
5140 || (c==EOF && pc==cQuote)
5141 ){
5142 do{ p->n--; }while( p->z[p->n]!=cQuote );
5143 p->cTerm = c;
5144 break;
5145 }
5146 if( pc==cQuote && c!='\r' ){
5147 utf8_printf(stderr, "%s:%d: unescaped %c character\n",
5148 p->zFile, p->nLine, cQuote);
5149 }
5150 if( c==EOF ){
5151 utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
5152 p->zFile, startLine, cQuote);
5153 p->cTerm = c;
5154 break;
5155 }
5156 import_append_char(p, c);
5157 ppc = pc;
5158 pc = c;
5159 }
5160 }else{
5161 /* If this is the first field being parsed and it begins with the
5162 ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
5163 if( (c&0xff)==0xef && p->bNotFirst==0 ){
5164 import_append_char(p, c);
5165 c = fgetc(p->in);
5166 if( (c&0xff)==0xbb ){
5167 import_append_char(p, c);
5168 c = fgetc(p->in);
5169 if( (c&0xff)==0xbf ){
5170 p->bNotFirst = 1;
5171 p->n = 0;
5172 return csv_read_one_field(p);
5173 }
5174 }
5175 }
5176 while( c!=EOF && c!=cSep && c!=rSep ){
5177 import_append_char(p, c);
5178 c = fgetc(p->in);
5179 }
5180 if( c==rSep ){
5181 p->nLine++;
5182 if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
5183 }
5184 p->cTerm = c;
5185 }
5186 if( p->z ) p->z[p->n] = 0;
5187 p->bNotFirst = 1;
5188 return p->z;
5189}
5190
5191/* Read a single field of ASCII delimited text.
5192**
5193** + Input comes from p->in.
5194** + Store results in p->z of length p->n. Space to hold p->z comes
5195** from sqlite3_malloc64().
5196** + Use p->cSep as the column separator. The default is "\x1F".
5197** + Use p->rSep as the row separator. The default is "\x1E".
5198** + Keep track of the row number in p->nLine.
5199** + Store the character that terminates the field in p->cTerm. Store
5200** EOF on end-of-file.
5201** + Report syntax errors on stderr
5202*/
5203static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
5204 int c;
5205 int cSep = p->cColSep;
5206 int rSep = p->cRowSep;
5207 p->n = 0;
5208 c = fgetc(p->in);
5209 if( c==EOF || seenInterrupt ){
5210 p->cTerm = EOF;
5211 return 0;
5212 }
5213 while( c!=EOF && c!=cSep && c!=rSep ){
5214 import_append_char(p, c);
5215 c = fgetc(p->in);
5216 }
5217 if( c==rSep ){
5218 p->nLine++;
5219 }
5220 p->cTerm = c;
5221 if( p->z ) p->z[p->n] = 0;
5222 return p->z;
5223}
5224
5225/*
5226** Try to transfer data for table zTable. If an error is seen while
5227** moving forward, try to go backwards. The backwards movement won't
5228** work for WITHOUT ROWID tables.
5229*/
5230static void tryToCloneData(
5231 ShellState *p,
5232 sqlite3 *newDb,
5233 const char *zTable
5234){
5235 sqlite3_stmt *pQuery = 0;
5236 sqlite3_stmt *pInsert = 0;
5237 char *zQuery = 0;
5238 char *zInsert = 0;
5239 int rc;
5240 int i, j, n;
drhaf2770f2018-01-05 14:55:43 +00005241 int nTable = strlen30(zTable);
drh2ce15c32017-07-11 13:34:40 +00005242 int k = 0;
5243 int cnt = 0;
5244 const int spinRate = 10000;
5245
5246 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
5247 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5248 if( rc ){
5249 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5250 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5251 zQuery);
5252 goto end_data_xfer;
5253 }
5254 n = sqlite3_column_count(pQuery);
5255 zInsert = sqlite3_malloc64(200 + nTable + n*3);
drh4b5345c2018-04-24 13:07:40 +00005256 if( zInsert==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00005257 sqlite3_snprintf(200+nTable,zInsert,
5258 "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
drhaf2770f2018-01-05 14:55:43 +00005259 i = strlen30(zInsert);
drh2ce15c32017-07-11 13:34:40 +00005260 for(j=1; j<n; j++){
5261 memcpy(zInsert+i, ",?", 2);
5262 i += 2;
5263 }
5264 memcpy(zInsert+i, ");", 3);
5265 rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
5266 if( rc ){
5267 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5268 sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
5269 zQuery);
5270 goto end_data_xfer;
5271 }
5272 for(k=0; k<2; k++){
5273 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5274 for(i=0; i<n; i++){
5275 switch( sqlite3_column_type(pQuery, i) ){
5276 case SQLITE_NULL: {
5277 sqlite3_bind_null(pInsert, i+1);
5278 break;
5279 }
5280 case SQLITE_INTEGER: {
5281 sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
5282 break;
5283 }
5284 case SQLITE_FLOAT: {
5285 sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
5286 break;
5287 }
5288 case SQLITE_TEXT: {
5289 sqlite3_bind_text(pInsert, i+1,
5290 (const char*)sqlite3_column_text(pQuery,i),
5291 -1, SQLITE_STATIC);
5292 break;
5293 }
5294 case SQLITE_BLOB: {
5295 sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
5296 sqlite3_column_bytes(pQuery,i),
5297 SQLITE_STATIC);
5298 break;
5299 }
5300 }
5301 } /* End for */
5302 rc = sqlite3_step(pInsert);
5303 if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
5304 utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
5305 sqlite3_errmsg(newDb));
5306 }
5307 sqlite3_reset(pInsert);
5308 cnt++;
5309 if( (cnt%spinRate)==0 ){
5310 printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
5311 fflush(stdout);
5312 }
5313 } /* End while */
5314 if( rc==SQLITE_DONE ) break;
5315 sqlite3_finalize(pQuery);
5316 sqlite3_free(zQuery);
5317 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
5318 zTable);
5319 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5320 if( rc ){
5321 utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
5322 break;
5323 }
5324 } /* End for(k=0...) */
5325
5326end_data_xfer:
5327 sqlite3_finalize(pQuery);
5328 sqlite3_finalize(pInsert);
5329 sqlite3_free(zQuery);
5330 sqlite3_free(zInsert);
5331}
5332
5333
5334/*
5335** Try to transfer all rows of the schema that match zWhere. For
5336** each row, invoke xForEach() on the object defined by that row.
5337** If an error is encountered while moving forward through the
drh067b92b2020-06-19 15:24:12 +00005338** sqlite_schema table, try again moving backwards.
drh2ce15c32017-07-11 13:34:40 +00005339*/
5340static void tryToCloneSchema(
5341 ShellState *p,
5342 sqlite3 *newDb,
5343 const char *zWhere,
5344 void (*xForEach)(ShellState*,sqlite3*,const char*)
5345){
5346 sqlite3_stmt *pQuery = 0;
5347 char *zQuery = 0;
5348 int rc;
5349 const unsigned char *zName;
5350 const unsigned char *zSql;
5351 char *zErrMsg = 0;
5352
drh067b92b2020-06-19 15:24:12 +00005353 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005354 " WHERE %s", zWhere);
5355 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5356 if( rc ){
5357 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5358 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5359 zQuery);
5360 goto end_schema_xfer;
5361 }
5362 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5363 zName = sqlite3_column_text(pQuery, 0);
5364 zSql = sqlite3_column_text(pQuery, 1);
5365 printf("%s... ", zName); fflush(stdout);
5366 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5367 if( zErrMsg ){
5368 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5369 sqlite3_free(zErrMsg);
5370 zErrMsg = 0;
5371 }
5372 if( xForEach ){
5373 xForEach(p, newDb, (const char*)zName);
5374 }
5375 printf("done\n");
5376 }
5377 if( rc!=SQLITE_DONE ){
5378 sqlite3_finalize(pQuery);
5379 sqlite3_free(zQuery);
drh067b92b2020-06-19 15:24:12 +00005380 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005381 " WHERE %s ORDER BY rowid DESC", zWhere);
5382 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5383 if( rc ){
5384 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5385 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5386 zQuery);
5387 goto end_schema_xfer;
5388 }
5389 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5390 zName = sqlite3_column_text(pQuery, 0);
5391 zSql = sqlite3_column_text(pQuery, 1);
5392 printf("%s... ", zName); fflush(stdout);
5393 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5394 if( zErrMsg ){
5395 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5396 sqlite3_free(zErrMsg);
5397 zErrMsg = 0;
5398 }
5399 if( xForEach ){
5400 xForEach(p, newDb, (const char*)zName);
5401 }
5402 printf("done\n");
5403 }
5404 }
5405end_schema_xfer:
5406 sqlite3_finalize(pQuery);
5407 sqlite3_free(zQuery);
5408}
5409
5410/*
5411** Open a new database file named "zNewDb". Try to recover as much information
5412** as possible out of the main database (which might be corrupt) and write it
5413** into zNewDb.
5414*/
5415static void tryToClone(ShellState *p, const char *zNewDb){
5416 int rc;
5417 sqlite3 *newDb = 0;
5418 if( access(zNewDb,0)==0 ){
5419 utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
5420 return;
5421 }
5422 rc = sqlite3_open(zNewDb, &newDb);
5423 if( rc ){
5424 utf8_printf(stderr, "Cannot create output database: %s\n",
5425 sqlite3_errmsg(newDb));
5426 }else{
5427 sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
5428 sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
5429 tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
5430 tryToCloneSchema(p, newDb, "type!='table'", 0);
5431 sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
5432 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
5433 }
drh9e804032018-05-18 17:11:50 +00005434 close_db(newDb);
drh2ce15c32017-07-11 13:34:40 +00005435}
5436
5437/*
drh13c20932018-01-10 21:41:55 +00005438** Change the output file back to stdout.
5439**
5440** If the p->doXdgOpen flag is set, that means the output was being
5441** redirected to a temporary file named by p->zTempFile. In that case,
5442** launch start/open/xdg-open on that temporary file.
drh2ce15c32017-07-11 13:34:40 +00005443*/
5444static void output_reset(ShellState *p){
5445 if( p->outfile[0]=='|' ){
5446#ifndef SQLITE_OMIT_POPEN
5447 pclose(p->out);
5448#endif
5449 }else{
5450 output_file_close(p->out);
drh04a28c32018-01-31 01:38:44 +00005451#ifndef SQLITE_NOHAVE_SYSTEM
drh13c20932018-01-10 21:41:55 +00005452 if( p->doXdgOpen ){
5453 const char *zXdgOpenCmd =
5454#if defined(_WIN32)
5455 "start";
5456#elif defined(__APPLE__)
5457 "open";
5458#else
5459 "xdg-open";
5460#endif
5461 char *zCmd;
5462 zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
drha92a01a2018-01-10 22:15:37 +00005463 if( system(zCmd) ){
5464 utf8_printf(stderr, "Failed: [%s]\n", zCmd);
drh1d9ea272020-04-17 23:46:54 +00005465 }else{
5466 /* Give the start/open/xdg-open command some time to get
5467 ** going before we continue, and potential delete the
5468 ** p->zTempFile data file out from under it */
5469 sqlite3_sleep(2000);
drha92a01a2018-01-10 22:15:37 +00005470 }
drh13c20932018-01-10 21:41:55 +00005471 sqlite3_free(zCmd);
drh3c484e82018-01-10 22:27:21 +00005472 outputModePop(p);
drh13c20932018-01-10 21:41:55 +00005473 p->doXdgOpen = 0;
5474 }
drh04a28c32018-01-31 01:38:44 +00005475#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
drh2ce15c32017-07-11 13:34:40 +00005476 }
5477 p->outfile[0] = 0;
5478 p->out = stdout;
5479}
5480
5481/*
5482** Run an SQL command and return the single integer result.
5483*/
5484static int db_int(ShellState *p, const char *zSql){
5485 sqlite3_stmt *pStmt;
5486 int res = 0;
5487 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
5488 if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
5489 res = sqlite3_column_int(pStmt,0);
5490 }
5491 sqlite3_finalize(pStmt);
5492 return res;
5493}
5494
5495/*
5496** Convert a 2-byte or 4-byte big-endian integer into a native integer
5497*/
5498static unsigned int get2byteInt(unsigned char *a){
5499 return (a[0]<<8) + a[1];
5500}
5501static unsigned int get4byteInt(unsigned char *a){
5502 return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
5503}
5504
5505/*
drh76c12062020-01-14 13:13:19 +00005506** Implementation of the ".dbinfo" command.
drh2ce15c32017-07-11 13:34:40 +00005507**
5508** Return 1 on error, 2 to exit, and 0 otherwise.
5509*/
5510static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
5511 static const struct { const char *zName; int ofst; } aField[] = {
5512 { "file change counter:", 24 },
5513 { "database page count:", 28 },
5514 { "freelist page count:", 36 },
5515 { "schema cookie:", 40 },
5516 { "schema format:", 44 },
5517 { "default cache size:", 48 },
5518 { "autovacuum top root:", 52 },
5519 { "incremental vacuum:", 64 },
5520 { "text encoding:", 56 },
5521 { "user version:", 60 },
5522 { "application id:", 68 },
5523 { "software version:", 96 },
5524 };
5525 static const struct { const char *zName; const char *zSql; } aQuery[] = {
5526 { "number of tables:",
5527 "SELECT count(*) FROM %s WHERE type='table'" },
5528 { "number of indexes:",
5529 "SELECT count(*) FROM %s WHERE type='index'" },
5530 { "number of triggers:",
5531 "SELECT count(*) FROM %s WHERE type='trigger'" },
5532 { "number of views:",
5533 "SELECT count(*) FROM %s WHERE type='view'" },
5534 { "schema size:",
5535 "SELECT total(length(sql)) FROM %s" },
5536 };
drh87c889c2019-03-20 18:22:51 +00005537 int i, rc;
drhea99a312018-07-18 19:09:07 +00005538 unsigned iDataVersion;
drh2ce15c32017-07-11 13:34:40 +00005539 char *zSchemaTab;
5540 char *zDb = nArg>=2 ? azArg[1] : "main";
drh512e6c32017-10-11 17:51:08 +00005541 sqlite3_stmt *pStmt = 0;
drh2ce15c32017-07-11 13:34:40 +00005542 unsigned char aHdr[100];
5543 open_db(p, 0);
5544 if( p->db==0 ) return 1;
drh87c889c2019-03-20 18:22:51 +00005545 rc = sqlite3_prepare_v2(p->db,
5546 "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
5547 -1, &pStmt, 0);
5548 if( rc ){
drh451f89a2020-04-28 23:09:56 +00005549 utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
drh87c889c2019-03-20 18:22:51 +00005550 sqlite3_finalize(pStmt);
5551 return 1;
5552 }
drh512e6c32017-10-11 17:51:08 +00005553 sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
5554 if( sqlite3_step(pStmt)==SQLITE_ROW
5555 && sqlite3_column_bytes(pStmt,0)>100
5556 ){
5557 memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
5558 sqlite3_finalize(pStmt);
5559 }else{
drh2ce15c32017-07-11 13:34:40 +00005560 raw_printf(stderr, "unable to read database header\n");
drh512e6c32017-10-11 17:51:08 +00005561 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00005562 return 1;
5563 }
5564 i = get2byteInt(aHdr+16);
5565 if( i==1 ) i = 65536;
5566 utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
5567 utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
5568 utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
5569 utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
5570 for(i=0; i<ArraySize(aField); i++){
5571 int ofst = aField[i].ofst;
5572 unsigned int val = get4byteInt(aHdr + ofst);
5573 utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
5574 switch( ofst ){
5575 case 56: {
5576 if( val==1 ) raw_printf(p->out, " (utf8)");
5577 if( val==2 ) raw_printf(p->out, " (utf16le)");
5578 if( val==3 ) raw_printf(p->out, " (utf16be)");
5579 }
5580 }
5581 raw_printf(p->out, "\n");
5582 }
5583 if( zDb==0 ){
drh067b92b2020-06-19 15:24:12 +00005584 zSchemaTab = sqlite3_mprintf("main.sqlite_schema");
drh2ce15c32017-07-11 13:34:40 +00005585 }else if( strcmp(zDb,"temp")==0 ){
drh067b92b2020-06-19 15:24:12 +00005586 zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
drh2ce15c32017-07-11 13:34:40 +00005587 }else{
drh067b92b2020-06-19 15:24:12 +00005588 zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
drh2ce15c32017-07-11 13:34:40 +00005589 }
5590 for(i=0; i<ArraySize(aQuery); i++){
5591 char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
5592 int val = db_int(p, zSql);
5593 sqlite3_free(zSql);
5594 utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
5595 }
5596 sqlite3_free(zSchemaTab);
drhea99a312018-07-18 19:09:07 +00005597 sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
5598 utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
drh2ce15c32017-07-11 13:34:40 +00005599 return 0;
5600}
5601
5602/*
5603** Print the current sqlite3_errmsg() value to stderr and return 1.
5604*/
5605static int shellDatabaseError(sqlite3 *db){
5606 const char *zErr = sqlite3_errmsg(db);
5607 utf8_printf(stderr, "Error: %s\n", zErr);
5608 return 1;
5609}
5610
5611/*
drh2ce15c32017-07-11 13:34:40 +00005612** Compare the pattern in zGlob[] against the text in z[]. Return TRUE
5613** if they match and FALSE (0) if they do not match.
5614**
5615** Globbing rules:
5616**
5617** '*' Matches any sequence of zero or more characters.
5618**
5619** '?' Matches exactly one character.
5620**
5621** [...] Matches one character from the enclosed list of
5622** characters.
5623**
5624** [^...] Matches one character not in the enclosed list.
5625**
5626** '#' Matches any sequence of one or more digits with an
5627** optional + or - sign in front
5628**
5629** ' ' Any span of whitespace matches any other span of
5630** whitespace.
5631**
5632** Extra whitespace at the end of z[] is ignored.
5633*/
5634static int testcase_glob(const char *zGlob, const char *z){
5635 int c, c2;
5636 int invert;
5637 int seen;
5638
5639 while( (c = (*(zGlob++)))!=0 ){
5640 if( IsSpace(c) ){
5641 if( !IsSpace(*z) ) return 0;
5642 while( IsSpace(*zGlob) ) zGlob++;
5643 while( IsSpace(*z) ) z++;
5644 }else if( c=='*' ){
5645 while( (c=(*(zGlob++))) == '*' || c=='?' ){
5646 if( c=='?' && (*(z++))==0 ) return 0;
5647 }
5648 if( c==0 ){
5649 return 1;
5650 }else if( c=='[' ){
5651 while( *z && testcase_glob(zGlob-1,z)==0 ){
5652 z++;
5653 }
5654 return (*z)!=0;
5655 }
5656 while( (c2 = (*(z++)))!=0 ){
5657 while( c2!=c ){
5658 c2 = *(z++);
5659 if( c2==0 ) return 0;
5660 }
5661 if( testcase_glob(zGlob,z) ) return 1;
5662 }
5663 return 0;
5664 }else if( c=='?' ){
5665 if( (*(z++))==0 ) return 0;
5666 }else if( c=='[' ){
5667 int prior_c = 0;
5668 seen = 0;
5669 invert = 0;
5670 c = *(z++);
5671 if( c==0 ) return 0;
5672 c2 = *(zGlob++);
5673 if( c2=='^' ){
5674 invert = 1;
5675 c2 = *(zGlob++);
5676 }
5677 if( c2==']' ){
5678 if( c==']' ) seen = 1;
5679 c2 = *(zGlob++);
5680 }
5681 while( c2 && c2!=']' ){
5682 if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
5683 c2 = *(zGlob++);
5684 if( c>=prior_c && c<=c2 ) seen = 1;
5685 prior_c = 0;
5686 }else{
5687 if( c==c2 ){
5688 seen = 1;
5689 }
5690 prior_c = c2;
5691 }
5692 c2 = *(zGlob++);
5693 }
5694 if( c2==0 || (seen ^ invert)==0 ) return 0;
5695 }else if( c=='#' ){
5696 if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++;
5697 if( !IsDigit(z[0]) ) return 0;
5698 z++;
5699 while( IsDigit(z[0]) ){ z++; }
5700 }else{
5701 if( c!=(*(z++)) ) return 0;
5702 }
5703 }
5704 while( IsSpace(*z) ){ z++; }
5705 return *z==0;
5706}
5707
5708
5709/*
5710** Compare the string as a command-line option with either one or two
5711** initial "-" characters.
5712*/
5713static int optionMatch(const char *zStr, const char *zOpt){
5714 if( zStr[0]!='-' ) return 0;
5715 zStr++;
5716 if( zStr[0]=='-' ) zStr++;
5717 return strcmp(zStr, zOpt)==0;
5718}
5719
5720/*
5721** Delete a file.
5722*/
5723int shellDeleteFile(const char *zFilename){
5724 int rc;
5725#ifdef _WIN32
5726 wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
5727 rc = _wunlink(z);
5728 sqlite3_free(z);
5729#else
5730 rc = unlink(zFilename);
5731#endif
5732 return rc;
5733}
5734
drh13c20932018-01-10 21:41:55 +00005735/*
5736** Try to delete the temporary file (if there is one) and free the
5737** memory used to hold the name of the temp file.
5738*/
5739static void clearTempFile(ShellState *p){
5740 if( p->zTempFile==0 ) return;
drh536c3452018-01-11 00:38:39 +00005741 if( p->doXdgOpen ) return;
drh13c20932018-01-10 21:41:55 +00005742 if( shellDeleteFile(p->zTempFile) ) return;
5743 sqlite3_free(p->zTempFile);
5744 p->zTempFile = 0;
5745}
5746
5747/*
5748** Create a new temp file name with the given suffix.
5749*/
5750static void newTempFile(ShellState *p, const char *zSuffix){
5751 clearTempFile(p);
5752 sqlite3_free(p->zTempFile);
5753 p->zTempFile = 0;
drh7f3bf8a2018-01-10 21:50:08 +00005754 if( p->db ){
5755 sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
5756 }
drh13c20932018-01-10 21:41:55 +00005757 if( p->zTempFile==0 ){
drh1d9ea272020-04-17 23:46:54 +00005758 /* If p->db is an in-memory database then the TEMPFILENAME file-control
5759 ** will not work and we will need to fallback to guessing */
5760 char *zTemp;
drh13c20932018-01-10 21:41:55 +00005761 sqlite3_uint64 r;
5762 sqlite3_randomness(sizeof(r), &r);
drh1d9ea272020-04-17 23:46:54 +00005763 zTemp = getenv("TEMP");
5764 if( zTemp==0 ) zTemp = getenv("TMP");
5765 if( zTemp==0 ){
5766#ifdef _WIN32
5767 zTemp = "\\tmp";
5768#else
5769 zTemp = "/tmp";
5770#endif
5771 }
5772 p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix);
drh13c20932018-01-10 21:41:55 +00005773 }else{
5774 p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
5775 }
5776 if( p->zTempFile==0 ){
5777 raw_printf(stderr, "out of memory\n");
5778 exit(1);
5779 }
5780}
5781
drh2ce15c32017-07-11 13:34:40 +00005782
5783/*
5784** The implementation of SQL scalar function fkey_collate_clause(), used
5785** by the ".lint fkey-indexes" command. This scalar function is always
5786** called with four arguments - the parent table name, the parent column name,
5787** the child table name and the child column name.
5788**
5789** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
5790**
5791** If either of the named tables or columns do not exist, this function
5792** returns an empty string. An empty string is also returned if both tables
5793** and columns exist but have the same default collation sequence. Or,
5794** if both exist but the default collation sequences are different, this
5795** function returns the string " COLLATE <parent-collation>", where
5796** <parent-collation> is the default collation sequence of the parent column.
5797*/
5798static void shellFkeyCollateClause(
5799 sqlite3_context *pCtx,
5800 int nVal,
5801 sqlite3_value **apVal
5802){
5803 sqlite3 *db = sqlite3_context_db_handle(pCtx);
5804 const char *zParent;
5805 const char *zParentCol;
5806 const char *zParentSeq;
5807 const char *zChild;
5808 const char *zChildCol;
5809 const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */
5810 int rc;
5811
5812 assert( nVal==4 );
5813 zParent = (const char*)sqlite3_value_text(apVal[0]);
5814 zParentCol = (const char*)sqlite3_value_text(apVal[1]);
5815 zChild = (const char*)sqlite3_value_text(apVal[2]);
5816 zChildCol = (const char*)sqlite3_value_text(apVal[3]);
5817
5818 sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
5819 rc = sqlite3_table_column_metadata(
5820 db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0
5821 );
5822 if( rc==SQLITE_OK ){
5823 rc = sqlite3_table_column_metadata(
5824 db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0
5825 );
5826 }
5827
5828 if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){
5829 char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq);
5830 sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
5831 sqlite3_free(z);
5832 }
5833}
5834
5835
5836/*
5837** The implementation of dot-command ".lint fkey-indexes".
5838*/
5839static int lintFkeyIndexes(
5840 ShellState *pState, /* Current shell tool state */
5841 char **azArg, /* Array of arguments passed to dot command */
5842 int nArg /* Number of entries in azArg[] */
5843){
5844 sqlite3 *db = pState->db; /* Database handle to query "main" db of */
5845 FILE *out = pState->out; /* Stream to write non-error output to */
5846 int bVerbose = 0; /* If -verbose is present */
5847 int bGroupByParent = 0; /* If -groupbyparent is present */
5848 int i; /* To iterate through azArg[] */
5849 const char *zIndent = ""; /* How much to indent CREATE INDEX by */
5850 int rc; /* Return code */
5851 sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */
5852
5853 /*
5854 ** This SELECT statement returns one row for each foreign key constraint
5855 ** in the schema of the main database. The column values are:
5856 **
5857 ** 0. The text of an SQL statement similar to:
5858 **
danf9679312017-12-01 18:40:18 +00005859 ** "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?"
drh2ce15c32017-07-11 13:34:40 +00005860 **
danf9679312017-12-01 18:40:18 +00005861 ** This SELECT is similar to the one that the foreign keys implementation
5862 ** needs to run internally on child tables. If there is an index that can
drh2ce15c32017-07-11 13:34:40 +00005863 ** be used to optimize this query, then it can also be used by the FK
5864 ** implementation to optimize DELETE or UPDATE statements on the parent
5865 ** table.
5866 **
5867 ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by
5868 ** the EXPLAIN QUERY PLAN command matches this pattern, then the schema
5869 ** contains an index that can be used to optimize the query.
5870 **
5871 ** 2. Human readable text that describes the child table and columns. e.g.
5872 **
5873 ** "child_table(child_key1, child_key2)"
5874 **
5875 ** 3. Human readable text that describes the parent table and columns. e.g.
5876 **
5877 ** "parent_table(parent_key1, parent_key2)"
5878 **
5879 ** 4. A full CREATE INDEX statement for an index that could be used to
5880 ** optimize DELETE or UPDATE statements on the parent table. e.g.
5881 **
5882 ** "CREATE INDEX child_table_child_key ON child_table(child_key)"
5883 **
5884 ** 5. The name of the parent table.
5885 **
5886 ** These six values are used by the C logic below to generate the report.
5887 */
5888 const char *zSql =
5889 "SELECT "
danf9679312017-12-01 18:40:18 +00005890 " 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
drh2ce15c32017-07-11 13:34:40 +00005891 " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
5892 " || fkey_collate_clause("
5893 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
5894 ", "
drh82102332021-03-20 15:11:29 +00005895 " 'SEARCH ' || s.name || ' USING COVERING INDEX*('"
drh2ce15c32017-07-11 13:34:40 +00005896 " || group_concat('*=?', ' AND ') || ')'"
5897 ", "
5898 " s.name || '(' || group_concat(f.[from], ', ') || ')'"
5899 ", "
5900 " f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
5901 ", "
5902 " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
5903 " || ' ON ' || quote(s.name) || '('"
5904 " || group_concat(quote(f.[from]) ||"
5905 " fkey_collate_clause("
5906 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
5907 " || ');'"
5908 ", "
5909 " f.[table] "
drh067b92b2020-06-19 15:24:12 +00005910 "FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f "
drh2ce15c32017-07-11 13:34:40 +00005911 "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
5912 "GROUP BY s.name, f.id "
5913 "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
5914 ;
drh82102332021-03-20 15:11:29 +00005915 const char *zGlobIPK = "SEARCH * USING INTEGER PRIMARY KEY (rowid=?)";
drh2ce15c32017-07-11 13:34:40 +00005916
5917 for(i=2; i<nArg; i++){
drhaf2770f2018-01-05 14:55:43 +00005918 int n = strlen30(azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00005919 if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
5920 bVerbose = 1;
5921 }
5922 else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
5923 bGroupByParent = 1;
5924 zIndent = " ";
5925 }
5926 else{
5927 raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
5928 azArg[0], azArg[1]
5929 );
5930 return SQLITE_ERROR;
5931 }
5932 }
5933
5934 /* Register the fkey_collate_clause() SQL function */
5935 rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
5936 0, shellFkeyCollateClause, 0, 0
5937 );
5938
5939
5940 if( rc==SQLITE_OK ){
5941 rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
5942 }
5943 if( rc==SQLITE_OK ){
5944 sqlite3_bind_int(pSql, 1, bGroupByParent);
5945 }
5946
5947 if( rc==SQLITE_OK ){
5948 int rc2;
5949 char *zPrev = 0;
5950 while( SQLITE_ROW==sqlite3_step(pSql) ){
5951 int res = -1;
5952 sqlite3_stmt *pExplain = 0;
5953 const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
5954 const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
5955 const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
5956 const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
5957 const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
5958 const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
5959
5960 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
5961 if( rc!=SQLITE_OK ) break;
5962 if( SQLITE_ROW==sqlite3_step(pExplain) ){
5963 const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
5964 res = (
5965 0==sqlite3_strglob(zGlob, zPlan)
5966 || 0==sqlite3_strglob(zGlobIPK, zPlan)
5967 );
5968 }
5969 rc = sqlite3_finalize(pExplain);
5970 if( rc!=SQLITE_OK ) break;
5971
5972 if( res<0 ){
5973 raw_printf(stderr, "Error: internal error");
5974 break;
5975 }else{
5976 if( bGroupByParent
5977 && (bVerbose || res==0)
5978 && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
5979 ){
5980 raw_printf(out, "-- Parent table %s\n", zParent);
5981 sqlite3_free(zPrev);
5982 zPrev = sqlite3_mprintf("%s", zParent);
5983 }
5984
5985 if( res==0 ){
5986 raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
5987 }else if( bVerbose ){
5988 raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
5989 zIndent, zFrom, zTarget
5990 );
5991 }
5992 }
5993 }
5994 sqlite3_free(zPrev);
5995
5996 if( rc!=SQLITE_OK ){
5997 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
5998 }
5999
6000 rc2 = sqlite3_finalize(pSql);
6001 if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
6002 rc = rc2;
6003 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
6004 }
6005 }else{
6006 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
6007 }
6008
6009 return rc;
6010}
6011
6012/*
6013** Implementation of ".lint" dot command.
6014*/
6015static int lintDotCommand(
6016 ShellState *pState, /* Current shell tool state */
6017 char **azArg, /* Array of arguments passed to dot command */
6018 int nArg /* Number of entries in azArg[] */
6019){
6020 int n;
drhaf2770f2018-01-05 14:55:43 +00006021 n = (nArg>=2 ? strlen30(azArg[1]) : 0);
drh2ce15c32017-07-11 13:34:40 +00006022 if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
6023 return lintFkeyIndexes(pState, azArg, nArg);
6024
6025 usage:
6026 raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
6027 raw_printf(stderr, "Where sub-commands are:\n");
6028 raw_printf(stderr, " fkey-indexes\n");
6029 return SQLITE_ERROR;
6030}
6031
dan1b162162019-04-27 20:15:15 +00006032#if !defined SQLITE_OMIT_VIRTUALTABLE
danfd0245d2017-12-07 15:44:29 +00006033static void shellPrepare(
dand4b56e52017-12-12 20:04:59 +00006034 sqlite3 *db,
danfd0245d2017-12-07 15:44:29 +00006035 int *pRc,
6036 const char *zSql,
6037 sqlite3_stmt **ppStmt
6038){
6039 *ppStmt = 0;
6040 if( *pRc==SQLITE_OK ){
dand4b56e52017-12-12 20:04:59 +00006041 int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
danfd0245d2017-12-07 15:44:29 +00006042 if( rc!=SQLITE_OK ){
6043 raw_printf(stderr, "sql error: %s (%d)\n",
dand4b56e52017-12-12 20:04:59 +00006044 sqlite3_errmsg(db), sqlite3_errcode(db)
danfd0245d2017-12-07 15:44:29 +00006045 );
6046 *pRc = rc;
6047 }
6048 }
6049}
6050
drh9546c762019-05-10 17:50:33 +00006051/*
6052** Create a prepared statement using printf-style arguments for the SQL.
6053**
6054** This routine is could be marked "static". But it is not always used,
6055** depending on compile-time options. By omitting the "static", we avoid
6056** nuisance compiler warnings about "defined but not used".
6057*/
6058void shellPreparePrintf(
dan3f67ddf2017-12-13 20:04:53 +00006059 sqlite3 *db,
6060 int *pRc,
danac15e2d2017-12-14 19:15:07 +00006061 sqlite3_stmt **ppStmt,
6062 const char *zFmt,
6063 ...
dan3f67ddf2017-12-13 20:04:53 +00006064){
danac15e2d2017-12-14 19:15:07 +00006065 *ppStmt = 0;
6066 if( *pRc==SQLITE_OK ){
6067 va_list ap;
6068 char *z;
6069 va_start(ap, zFmt);
6070 z = sqlite3_vmprintf(zFmt, ap);
drh1dbb1472018-10-11 10:37:24 +00006071 va_end(ap);
dan3f67ddf2017-12-13 20:04:53 +00006072 if( z==0 ){
6073 *pRc = SQLITE_NOMEM;
6074 }else{
6075 shellPrepare(db, pRc, z, ppStmt);
6076 sqlite3_free(z);
6077 }
dan3f67ddf2017-12-13 20:04:53 +00006078 }
6079}
6080
drh9546c762019-05-10 17:50:33 +00006081/* Finalize the prepared statement created using shellPreparePrintf().
6082**
6083** This routine is could be marked "static". But it is not always used,
6084** depending on compile-time options. By omitting the "static", we avoid
6085** nuisance compiler warnings about "defined but not used".
6086*/
6087void shellFinalize(
danfd0245d2017-12-07 15:44:29 +00006088 int *pRc,
6089 sqlite3_stmt *pStmt
6090){
dan25c12182017-12-07 21:03:33 +00006091 if( pStmt ){
6092 sqlite3 *db = sqlite3_db_handle(pStmt);
6093 int rc = sqlite3_finalize(pStmt);
6094 if( *pRc==SQLITE_OK ){
6095 if( rc!=SQLITE_OK ){
6096 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
6097 }
6098 *pRc = rc;
6099 }
6100 }
danfd0245d2017-12-07 15:44:29 +00006101}
6102
drh9546c762019-05-10 17:50:33 +00006103/* Reset the prepared statement created using shellPreparePrintf().
6104**
6105** This routine is could be marked "static". But it is not always used,
6106** depending on compile-time options. By omitting the "static", we avoid
6107** nuisance compiler warnings about "defined but not used".
6108*/
6109void shellReset(
danfd0245d2017-12-07 15:44:29 +00006110 int *pRc,
6111 sqlite3_stmt *pStmt
6112){
6113 int rc = sqlite3_reset(pStmt);
dan5a78b812017-12-27 18:54:11 +00006114 if( *pRc==SQLITE_OK ){
6115 if( rc!=SQLITE_OK ){
6116 sqlite3 *db = sqlite3_db_handle(pStmt);
6117 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
6118 }
6119 *pRc = rc;
6120 }
danfd0245d2017-12-07 15:44:29 +00006121}
dan1b162162019-04-27 20:15:15 +00006122#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
6123
6124#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drhe2754c12019-08-26 12:50:01 +00006125/******************************************************************************
dan1b162162019-04-27 20:15:15 +00006126** The ".archive" or ".ar" command.
6127*/
drhe37c0e12018-01-06 19:19:50 +00006128/*
dan88be0202017-12-09 17:58:02 +00006129** Structure representing a single ".ar" command.
6130*/
6131typedef struct ArCommand ArCommand;
6132struct ArCommand {
drhb376b3d2018-01-10 13:11:51 +00006133 u8 eCmd; /* An AR_CMD_* value */
6134 u8 bVerbose; /* True if --verbose */
drha5676c42018-01-10 15:17:34 +00006135 u8 bZip; /* True if the archive is a ZIP */
drhb376b3d2018-01-10 13:11:51 +00006136 u8 bDryRun; /* True if --dry-run */
drha5676c42018-01-10 15:17:34 +00006137 u8 bAppend; /* True if --append */
drhd0f9cdc2018-05-17 14:09:06 +00006138 u8 fromCmdLine; /* Run from -A instead of .archive */
drhb376b3d2018-01-10 13:11:51 +00006139 int nArg; /* Number of command arguments */
drha5676c42018-01-10 15:17:34 +00006140 char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
dan88be0202017-12-09 17:58:02 +00006141 const char *zFile; /* --file argument, or NULL */
6142 const char *zDir; /* --directory argument, or NULL */
dan88be0202017-12-09 17:58:02 +00006143 char **azArg; /* Array of command arguments */
drhb376b3d2018-01-10 13:11:51 +00006144 ShellState *p; /* Shell state */
6145 sqlite3 *db; /* Database containing the archive */
dan88be0202017-12-09 17:58:02 +00006146};
6147
6148/*
6149** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
6150*/
dan0d0547f2017-12-14 15:40:42 +00006151static int arUsage(FILE *f){
drh98aa2ab2018-09-26 16:53:51 +00006152 showHelp(f,"archive");
dan0d0547f2017-12-14 15:40:42 +00006153 return SQLITE_ERROR;
6154}
6155
6156/*
6157** Print an error message for the .ar command to stderr and return
6158** SQLITE_ERROR.
6159*/
drhd0f9cdc2018-05-17 14:09:06 +00006160static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
dan0d0547f2017-12-14 15:40:42 +00006161 va_list ap;
6162 char *z;
6163 va_start(ap, zFmt);
6164 z = sqlite3_vmprintf(zFmt, ap);
6165 va_end(ap);
drhd0f9cdc2018-05-17 14:09:06 +00006166 utf8_printf(stderr, "Error: %s\n", z);
6167 if( pAr->fromCmdLine ){
6168 utf8_printf(stderr, "Use \"-A\" for more help\n");
6169 }else{
6170 utf8_printf(stderr, "Use \".archive --help\" for more help\n");
6171 }
dan0d0547f2017-12-14 15:40:42 +00006172 sqlite3_free(z);
dan88be0202017-12-09 17:58:02 +00006173 return SQLITE_ERROR;
6174}
6175
6176/*
6177** Values for ArCommand.eCmd.
6178*/
dand4b56e52017-12-12 20:04:59 +00006179#define AR_CMD_CREATE 1
drhb17ea912019-03-25 14:24:19 +00006180#define AR_CMD_UPDATE 2
6181#define AR_CMD_INSERT 3
6182#define AR_CMD_EXTRACT 4
6183#define AR_CMD_LIST 5
6184#define AR_CMD_HELP 6
dand4b56e52017-12-12 20:04:59 +00006185
6186/*
6187** Other (non-command) switches.
6188*/
drhb17ea912019-03-25 14:24:19 +00006189#define AR_SWITCH_VERBOSE 7
6190#define AR_SWITCH_FILE 8
6191#define AR_SWITCH_DIRECTORY 9
6192#define AR_SWITCH_APPEND 10
6193#define AR_SWITCH_DRYRUN 11
dand4b56e52017-12-12 20:04:59 +00006194
6195static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
6196 switch( eSwitch ){
6197 case AR_CMD_CREATE:
6198 case AR_CMD_EXTRACT:
6199 case AR_CMD_LIST:
6200 case AR_CMD_UPDATE:
drhb17ea912019-03-25 14:24:19 +00006201 case AR_CMD_INSERT:
dan0d0547f2017-12-14 15:40:42 +00006202 case AR_CMD_HELP:
6203 if( pAr->eCmd ){
drhd0f9cdc2018-05-17 14:09:06 +00006204 return arErrorMsg(pAr, "multiple command options");
dan0d0547f2017-12-14 15:40:42 +00006205 }
dand4b56e52017-12-12 20:04:59 +00006206 pAr->eCmd = eSwitch;
6207 break;
6208
drhb376b3d2018-01-10 13:11:51 +00006209 case AR_SWITCH_DRYRUN:
6210 pAr->bDryRun = 1;
6211 break;
dand4b56e52017-12-12 20:04:59 +00006212 case AR_SWITCH_VERBOSE:
6213 pAr->bVerbose = 1;
6214 break;
drha5676c42018-01-10 15:17:34 +00006215 case AR_SWITCH_APPEND:
6216 pAr->bAppend = 1;
drhca7733b2018-01-10 18:09:20 +00006217 /* Fall thru into --file */
dand4b56e52017-12-12 20:04:59 +00006218 case AR_SWITCH_FILE:
6219 pAr->zFile = zArg;
6220 break;
6221 case AR_SWITCH_DIRECTORY:
6222 pAr->zDir = zArg;
6223 break;
6224 }
6225
6226 return SQLITE_OK;
6227}
dan88be0202017-12-09 17:58:02 +00006228
6229/*
6230** Parse the command line for an ".ar" command. The results are written into
6231** structure (*pAr). SQLITE_OK is returned if the command line is parsed
6232** successfully, otherwise an error message is written to stderr and
6233** SQLITE_ERROR returned.
6234*/
6235static int arParseCommand(
6236 char **azArg, /* Array of arguments passed to dot command */
6237 int nArg, /* Number of entries in azArg[] */
6238 ArCommand *pAr /* Populate this object */
6239){
dand4b56e52017-12-12 20:04:59 +00006240 struct ArSwitch {
dand4b56e52017-12-12 20:04:59 +00006241 const char *zLong;
drhb376b3d2018-01-10 13:11:51 +00006242 char cShort;
6243 u8 eSwitch;
6244 u8 bArg;
dand4b56e52017-12-12 20:04:59 +00006245 } aSwitch[] = {
drhb376b3d2018-01-10 13:11:51 +00006246 { "create", 'c', AR_CMD_CREATE, 0 },
6247 { "extract", 'x', AR_CMD_EXTRACT, 0 },
drhb17ea912019-03-25 14:24:19 +00006248 { "insert", 'i', AR_CMD_INSERT, 0 },
drhb376b3d2018-01-10 13:11:51 +00006249 { "list", 't', AR_CMD_LIST, 0 },
6250 { "update", 'u', AR_CMD_UPDATE, 0 },
6251 { "help", 'h', AR_CMD_HELP, 0 },
6252 { "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
6253 { "file", 'f', AR_SWITCH_FILE, 1 },
drhca7733b2018-01-10 18:09:20 +00006254 { "append", 'a', AR_SWITCH_APPEND, 1 },
drhb376b3d2018-01-10 13:11:51 +00006255 { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
drhb376b3d2018-01-10 13:11:51 +00006256 { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
dand4b56e52017-12-12 20:04:59 +00006257 };
6258 int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
6259 struct ArSwitch *pEnd = &aSwitch[nSwitch];
6260
dan88be0202017-12-09 17:58:02 +00006261 if( nArg<=1 ){
drh98aa2ab2018-09-26 16:53:51 +00006262 utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
dan0d0547f2017-12-14 15:40:42 +00006263 return arUsage(stderr);
dan88be0202017-12-09 17:58:02 +00006264 }else{
6265 char *z = azArg[1];
dan88be0202017-12-09 17:58:02 +00006266 if( z[0]!='-' ){
6267 /* Traditional style [tar] invocation */
6268 int i;
6269 int iArg = 2;
6270 for(i=0; z[i]; i++){
dand4b56e52017-12-12 20:04:59 +00006271 const char *zArg = 0;
6272 struct ArSwitch *pOpt;
6273 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6274 if( z[i]==pOpt->cShort ) break;
dan88be0202017-12-09 17:58:02 +00006275 }
dan0d0547f2017-12-14 15:40:42 +00006276 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006277 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006278 }
dand4b56e52017-12-12 20:04:59 +00006279 if( pOpt->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006280 if( iArg>=nArg ){
drhd0f9cdc2018-05-17 14:09:06 +00006281 return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
dan0d0547f2017-12-14 15:40:42 +00006282 }
dand4b56e52017-12-12 20:04:59 +00006283 zArg = azArg[iArg++];
6284 }
6285 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
dan88be0202017-12-09 17:58:02 +00006286 }
dan88be0202017-12-09 17:58:02 +00006287 pAr->nArg = nArg-iArg;
6288 if( pAr->nArg>0 ){
6289 pAr->azArg = &azArg[iArg];
6290 }
dand4b56e52017-12-12 20:04:59 +00006291 }else{
6292 /* Non-traditional invocation */
6293 int iArg;
6294 for(iArg=1; iArg<nArg; iArg++){
6295 int n;
6296 z = azArg[iArg];
6297 if( z[0]!='-' ){
6298 /* All remaining command line words are command arguments. */
6299 pAr->azArg = &azArg[iArg];
6300 pAr->nArg = nArg-iArg;
6301 break;
6302 }
drhaf2770f2018-01-05 14:55:43 +00006303 n = strlen30(z);
dand4b56e52017-12-12 20:04:59 +00006304
6305 if( z[1]!='-' ){
6306 int i;
6307 /* One or more short options */
6308 for(i=1; i<n; i++){
6309 const char *zArg = 0;
6310 struct ArSwitch *pOpt;
6311 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6312 if( z[i]==pOpt->cShort ) break;
6313 }
dan0d0547f2017-12-14 15:40:42 +00006314 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006315 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006316 }
dand4b56e52017-12-12 20:04:59 +00006317 if( pOpt->bArg ){
6318 if( i<(n-1) ){
6319 zArg = &z[i+1];
6320 i = n;
6321 }else{
dan0d0547f2017-12-14 15:40:42 +00006322 if( iArg>=(nArg-1) ){
drhe2754c12019-08-26 12:50:01 +00006323 return arErrorMsg(pAr, "option requires an argument: %c",
6324 z[i]);
dan0d0547f2017-12-14 15:40:42 +00006325 }
dand4b56e52017-12-12 20:04:59 +00006326 zArg = azArg[++iArg];
6327 }
6328 }
6329 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
6330 }
6331 }else if( z[2]=='\0' ){
6332 /* A -- option, indicating that all remaining command line words
6333 ** are command arguments. */
6334 pAr->azArg = &azArg[iArg+1];
6335 pAr->nArg = nArg-iArg-1;
6336 break;
6337 }else{
6338 /* A long option */
6339 const char *zArg = 0; /* Argument for option, if any */
6340 struct ArSwitch *pMatch = 0; /* Matching option */
6341 struct ArSwitch *pOpt; /* Iterator */
6342 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6343 const char *zLong = pOpt->zLong;
drhaf2770f2018-01-05 14:55:43 +00006344 if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
dand4b56e52017-12-12 20:04:59 +00006345 if( pMatch ){
drhd0f9cdc2018-05-17 14:09:06 +00006346 return arErrorMsg(pAr, "ambiguous option: %s",z);
dand4b56e52017-12-12 20:04:59 +00006347 }else{
6348 pMatch = pOpt;
6349 }
6350 }
6351 }
6352
6353 if( pMatch==0 ){
drhd0f9cdc2018-05-17 14:09:06 +00006354 return arErrorMsg(pAr, "unrecognized option: %s", z);
dand4b56e52017-12-12 20:04:59 +00006355 }
6356 if( pMatch->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006357 if( iArg>=(nArg-1) ){
drhd0f9cdc2018-05-17 14:09:06 +00006358 return arErrorMsg(pAr, "option requires an argument: %s", z);
dan0d0547f2017-12-14 15:40:42 +00006359 }
dand4b56e52017-12-12 20:04:59 +00006360 zArg = azArg[++iArg];
6361 }
6362 if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
6363 }
6364 }
dan88be0202017-12-09 17:58:02 +00006365 }
6366 }
6367
6368 return SQLITE_OK;
6369}
6370
6371/*
dan3f67ddf2017-12-13 20:04:53 +00006372** This function assumes that all arguments within the ArCommand.azArg[]
6373** array refer to archive members, as for the --extract or --list commands.
6374** It checks that each of them are present. If any specified file is not
6375** present in the archive, an error is printed to stderr and an error
6376** code returned. Otherwise, if all specified arguments are present in
6377** the archive, SQLITE_OK is returned.
6378**
6379** This function strips any trailing '/' characters from each argument.
6380** This is consistent with the way the [tar] command seems to work on
6381** Linux.
6382*/
drhb376b3d2018-01-10 13:11:51 +00006383static int arCheckEntries(ArCommand *pAr){
dan3f67ddf2017-12-13 20:04:53 +00006384 int rc = SQLITE_OK;
6385 if( pAr->nArg ){
drhb376b3d2018-01-10 13:11:51 +00006386 int i, j;
dan3f67ddf2017-12-13 20:04:53 +00006387 sqlite3_stmt *pTest = 0;
6388
drhb376b3d2018-01-10 13:11:51 +00006389 shellPreparePrintf(pAr->db, &rc, &pTest,
6390 "SELECT name FROM %s WHERE name=$name",
6391 pAr->zSrcTable
dan5a78b812017-12-27 18:54:11 +00006392 );
drhb376b3d2018-01-10 13:11:51 +00006393 j = sqlite3_bind_parameter_index(pTest, "$name");
dan3f67ddf2017-12-13 20:04:53 +00006394 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
6395 char *z = pAr->azArg[i];
drhaf2770f2018-01-05 14:55:43 +00006396 int n = strlen30(z);
dan3f67ddf2017-12-13 20:04:53 +00006397 int bOk = 0;
6398 while( n>0 && z[n-1]=='/' ) n--;
6399 z[n] = '\0';
drhb376b3d2018-01-10 13:11:51 +00006400 sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
dan3f67ddf2017-12-13 20:04:53 +00006401 if( SQLITE_ROW==sqlite3_step(pTest) ){
6402 bOk = 1;
6403 }
6404 shellReset(&rc, pTest);
6405 if( rc==SQLITE_OK && bOk==0 ){
drhb376b3d2018-01-10 13:11:51 +00006406 utf8_printf(stderr, "not found in archive: %s\n", z);
dan3f67ddf2017-12-13 20:04:53 +00006407 rc = SQLITE_ERROR;
6408 }
6409 }
6410 shellFinalize(&rc, pTest);
6411 }
dan3f67ddf2017-12-13 20:04:53 +00006412 return rc;
6413}
6414
6415/*
6416** Format a WHERE clause that can be used against the "sqlar" table to
6417** identify all archive members that match the command arguments held
6418** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
6419** The caller is responsible for eventually calling sqlite3_free() on
6420** any non-NULL (*pzWhere) value.
6421*/
6422static void arWhereClause(
6423 int *pRc,
6424 ArCommand *pAr,
danac15e2d2017-12-14 19:15:07 +00006425 char **pzWhere /* OUT: New WHERE clause */
dan3f67ddf2017-12-13 20:04:53 +00006426){
6427 char *zWhere = 0;
6428 if( *pRc==SQLITE_OK ){
danac15e2d2017-12-14 19:15:07 +00006429 if( pAr->nArg==0 ){
6430 zWhere = sqlite3_mprintf("1");
6431 }else{
6432 int i;
6433 const char *zSep = "";
6434 for(i=0; i<pAr->nArg; i++){
6435 const char *z = pAr->azArg[i];
6436 zWhere = sqlite3_mprintf(
drhb376b3d2018-01-10 13:11:51 +00006437 "%z%s name = '%q' OR substr(name,1,%d) = '%q/'",
6438 zWhere, zSep, z, strlen30(z)+1, z
6439 );
danac15e2d2017-12-14 19:15:07 +00006440 if( zWhere==0 ){
6441 *pRc = SQLITE_NOMEM;
6442 break;
6443 }
6444 zSep = " OR ";
dan3f67ddf2017-12-13 20:04:53 +00006445 }
dan3f67ddf2017-12-13 20:04:53 +00006446 }
6447 }
6448 *pzWhere = zWhere;
6449}
6450
6451/*
dan88be0202017-12-09 17:58:02 +00006452** Implementation of .ar "lisT" command.
6453*/
drhb376b3d2018-01-10 13:11:51 +00006454static int arListCommand(ArCommand *pAr){
danb5090e42017-12-27 21:13:21 +00006455 const char *zSql = "SELECT %s FROM %s WHERE %s";
danb5090e42017-12-27 21:13:21 +00006456 const char *azCols[] = {
6457 "name",
drh410cad92018-01-10 17:19:16 +00006458 "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
danb5090e42017-12-27 21:13:21 +00006459 };
dan5a78b812017-12-27 18:54:11 +00006460
dan3f67ddf2017-12-13 20:04:53 +00006461 char *zWhere = 0;
6462 sqlite3_stmt *pSql = 0;
6463 int rc;
6464
drhb376b3d2018-01-10 13:11:51 +00006465 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006466 arWhereClause(&rc, pAr, &zWhere);
6467
drhb376b3d2018-01-10 13:11:51 +00006468 shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
6469 pAr->zSrcTable, zWhere);
drhb376b3d2018-01-10 13:11:51 +00006470 if( pAr->bDryRun ){
6471 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
6472 }else{
6473 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
6474 if( pAr->bVerbose ){
drh410cad92018-01-10 17:19:16 +00006475 utf8_printf(pAr->p->out, "%s % 10d %s %s\n",
6476 sqlite3_column_text(pSql, 0),
drhb376b3d2018-01-10 13:11:51 +00006477 sqlite3_column_int(pSql, 1),
6478 sqlite3_column_text(pSql, 2),
6479 sqlite3_column_text(pSql, 3)
6480 );
6481 }else{
6482 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
6483 }
danb5090e42017-12-27 21:13:21 +00006484 }
dan3f67ddf2017-12-13 20:04:53 +00006485 }
dan5a78b812017-12-27 18:54:11 +00006486 shellFinalize(&rc, pSql);
drhd0f9cdc2018-05-17 14:09:06 +00006487 sqlite3_free(zWhere);
dan3f67ddf2017-12-13 20:04:53 +00006488 return rc;
dan88be0202017-12-09 17:58:02 +00006489}
6490
6491
danfd0245d2017-12-07 15:44:29 +00006492/*
6493** Implementation of .ar "eXtract" command.
6494*/
drhb376b3d2018-01-10 13:11:51 +00006495static int arExtractCommand(ArCommand *pAr){
dan25c12182017-12-07 21:03:33 +00006496 const char *zSql1 =
dand1b51d42017-12-16 19:11:26 +00006497 "SELECT "
drhb376b3d2018-01-10 13:11:51 +00006498 " ($dir || name),"
6499 " writefile(($dir || name), %s, mode, mtime) "
drh0cfd46a2018-06-06 01:18:01 +00006500 "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
6501 " AND name NOT GLOB '*..[/\\]*'";
dan5a78b812017-12-27 18:54:11 +00006502
6503 const char *azExtraArg[] = {
6504 "sqlar_uncompress(data, sz)",
dan7c15ac12018-01-08 19:59:59 +00006505 "data"
dan5a78b812017-12-27 18:54:11 +00006506 };
dan5a78b812017-12-27 18:54:11 +00006507
danfd0245d2017-12-07 15:44:29 +00006508 sqlite3_stmt *pSql = 0;
6509 int rc = SQLITE_OK;
dan2ad09492017-12-09 18:28:22 +00006510 char *zDir = 0;
dan3f67ddf2017-12-13 20:04:53 +00006511 char *zWhere = 0;
drhb376b3d2018-01-10 13:11:51 +00006512 int i, j;
dan2ad09492017-12-09 18:28:22 +00006513
dan3f67ddf2017-12-13 20:04:53 +00006514 /* If arguments are specified, check that they actually exist within
6515 ** the archive before proceeding. And formulate a WHERE clause to
6516 ** match them. */
drhb376b3d2018-01-10 13:11:51 +00006517 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006518 arWhereClause(&rc, pAr, &zWhere);
6519
6520 if( rc==SQLITE_OK ){
6521 if( pAr->zDir ){
6522 zDir = sqlite3_mprintf("%s/", pAr->zDir);
6523 }else{
6524 zDir = sqlite3_mprintf("");
6525 }
6526 if( zDir==0 ) rc = SQLITE_NOMEM;
dan2ad09492017-12-09 18:28:22 +00006527 }
danfd0245d2017-12-07 15:44:29 +00006528
drhb376b3d2018-01-10 13:11:51 +00006529 shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
6530 azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
dan5a78b812017-12-27 18:54:11 +00006531 );
6532
dan2ad09492017-12-09 18:28:22 +00006533 if( rc==SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00006534 j = sqlite3_bind_parameter_index(pSql, "$dir");
6535 sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
dan25c12182017-12-07 21:03:33 +00006536
danac15e2d2017-12-14 19:15:07 +00006537 /* Run the SELECT statement twice. The first time, writefile() is called
6538 ** for all archive members that should be extracted. The second time,
6539 ** only for the directories. This is because the timestamps for
6540 ** extracted directories must be reset after they are populated (as
6541 ** populating them changes the timestamp). */
6542 for(i=0; i<2; i++){
drhb376b3d2018-01-10 13:11:51 +00006543 j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
6544 sqlite3_bind_int(pSql, j, i);
6545 if( pAr->bDryRun ){
6546 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
6547 }else{
6548 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
6549 if( i==0 && pAr->bVerbose ){
6550 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
6551 }
danac15e2d2017-12-14 19:15:07 +00006552 }
6553 }
6554 shellReset(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00006555 }
danac15e2d2017-12-14 19:15:07 +00006556 shellFinalize(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00006557 }
dan25c12182017-12-07 21:03:33 +00006558
dan2ad09492017-12-09 18:28:22 +00006559 sqlite3_free(zDir);
dan3f67ddf2017-12-13 20:04:53 +00006560 sqlite3_free(zWhere);
danfd0245d2017-12-07 15:44:29 +00006561 return rc;
6562}
6563
drhb376b3d2018-01-10 13:11:51 +00006564/*
6565** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out.
6566*/
6567static int arExecSql(ArCommand *pAr, const char *zSql){
6568 int rc;
6569 if( pAr->bDryRun ){
6570 utf8_printf(pAr->p->out, "%s\n", zSql);
6571 rc = SQLITE_OK;
6572 }else{
drh410cad92018-01-10 17:19:16 +00006573 char *zErr = 0;
6574 rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
6575 if( zErr ){
6576 utf8_printf(stdout, "ERROR: %s\n", zErr);
6577 sqlite3_free(zErr);
6578 }
drhb376b3d2018-01-10 13:11:51 +00006579 }
6580 return rc;
6581}
6582
dan1ad3f612017-12-11 20:22:02 +00006583
danfd0245d2017-12-07 15:44:29 +00006584/*
drhb17ea912019-03-25 14:24:19 +00006585** Implementation of .ar "create", "insert", and "update" commands.
6586**
6587** create -> Create a new SQL archive
6588** insert -> Insert or reinsert all files listed
6589** update -> Insert files that have changed or that were not
6590** previously in the archive
danfd0245d2017-12-07 15:44:29 +00006591**
6592** Create the "sqlar" table in the database if it does not already exist.
6593** Then add each file in the azFile[] array to the archive. Directories
6594** are added recursively. If argument bVerbose is non-zero, a message is
6595** printed on stdout for each file archived.
dan06741a32017-12-13 20:17:18 +00006596**
6597** The create command is the same as update, except that it drops
drhb17ea912019-03-25 14:24:19 +00006598** any existing "sqlar" table before beginning. The "insert" command
6599** always overwrites every file named on the command-line, where as
6600** "update" only overwrites if the size or mtime or mode has changed.
danfd0245d2017-12-07 15:44:29 +00006601*/
drhb376b3d2018-01-10 13:11:51 +00006602static int arCreateOrUpdateCommand(
dan06741a32017-12-13 20:17:18 +00006603 ArCommand *pAr, /* Command arguments and options */
drhb17ea912019-03-25 14:24:19 +00006604 int bUpdate, /* true for a --create. */
6605 int bOnlyIfChanged /* Only update if file has changed */
danfd0245d2017-12-07 15:44:29 +00006606){
dand4b56e52017-12-12 20:04:59 +00006607 const char *zCreate =
drhafba1802018-01-06 15:49:57 +00006608 "CREATE TABLE IF NOT EXISTS sqlar(\n"
6609 " name TEXT PRIMARY KEY, -- name of the file\n"
6610 " mode INT, -- access permissions\n"
6611 " mtime INT, -- last modification time\n"
6612 " sz INT, -- original file size\n"
6613 " data BLOB -- compressed content\n"
6614 ")";
dand4b56e52017-12-12 20:04:59 +00006615 const char *zDrop = "DROP TABLE IF EXISTS sqlar";
drh1bf208c2018-03-09 21:54:01 +00006616 const char *zInsertFmt[2] = {
6617 "REPLACE INTO %s(name,mode,mtime,sz,data)\n"
drh634c70f2018-01-10 16:50:18 +00006618 " SELECT\n"
6619 " %s,\n"
6620 " mode,\n"
6621 " mtime,\n"
drh410cad92018-01-10 17:19:16 +00006622 " CASE substr(lsmode(mode),1,1)\n"
6623 " WHEN '-' THEN length(data)\n"
6624 " WHEN 'd' THEN 0\n"
drh634c70f2018-01-10 16:50:18 +00006625 " ELSE -1 END,\n"
drh69d2d352018-03-09 22:18:53 +00006626 " sqlar_compress(data)\n"
drhb17ea912019-03-25 14:24:19 +00006627 " FROM fsdir(%Q,%Q) AS disk\n"
6628 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
6629 ,
drh1bf208c2018-03-09 21:54:01 +00006630 "REPLACE INTO %s(name,mode,mtime,data)\n"
6631 " SELECT\n"
6632 " %s,\n"
6633 " mode,\n"
6634 " mtime,\n"
6635 " data\n"
drhb17ea912019-03-25 14:24:19 +00006636 " FROM fsdir(%Q,%Q) AS disk\n"
6637 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
drh1bf208c2018-03-09 21:54:01 +00006638 };
danfd0245d2017-12-07 15:44:29 +00006639 int i; /* For iterating through azFile[] */
6640 int rc; /* Return code */
drh1bf208c2018-03-09 21:54:01 +00006641 const char *zTab = 0; /* SQL table into which to insert */
6642 char *zSql;
6643 char zTemp[50];
drhb17ea912019-03-25 14:24:19 +00006644 char *zExists = 0;
danfd0245d2017-12-07 15:44:29 +00006645
drh1bf208c2018-03-09 21:54:01 +00006646 arExecSql(pAr, "PRAGMA page_size=512");
drhb376b3d2018-01-10 13:11:51 +00006647 rc = arExecSql(pAr, "SAVEPOINT ar;");
danfd0245d2017-12-07 15:44:29 +00006648 if( rc!=SQLITE_OK ) return rc;
drh1bf208c2018-03-09 21:54:01 +00006649 zTemp[0] = 0;
6650 if( pAr->bZip ){
6651 /* Initialize the zipfile virtual table, if necessary */
6652 if( pAr->zFile ){
6653 sqlite3_uint64 r;
6654 sqlite3_randomness(sizeof(r),&r);
6655 sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
6656 zTab = zTemp;
6657 zSql = sqlite3_mprintf(
6658 "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)",
6659 zTab, pAr->zFile
6660 );
6661 rc = arExecSql(pAr, zSql);
6662 sqlite3_free(zSql);
6663 }else{
6664 zTab = "zip";
6665 }
6666 }else{
6667 /* Initialize the table for an SQLAR */
6668 zTab = "sqlar";
6669 if( bUpdate==0 ){
6670 rc = arExecSql(pAr, zDrop);
6671 if( rc!=SQLITE_OK ) goto end_ar_transaction;
6672 }
6673 rc = arExecSql(pAr, zCreate);
dan06741a32017-12-13 20:17:18 +00006674 }
drhb17ea912019-03-25 14:24:19 +00006675 if( bOnlyIfChanged ){
6676 zExists = sqlite3_mprintf(
6677 " AND NOT EXISTS("
6678 "SELECT 1 FROM %s AS mem"
6679 " WHERE mem.name=disk.name"
6680 " AND mem.mtime=disk.mtime"
6681 " AND mem.mode=disk.mode)", zTab);
6682 }else{
6683 zExists = sqlite3_mprintf("");
6684 }
6685 if( zExists==0 ) rc = SQLITE_NOMEM;
dan88be0202017-12-09 17:58:02 +00006686 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
mistachkince2052b2018-03-23 00:31:53 +00006687 char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
drh634c70f2018-01-10 16:50:18 +00006688 pAr->bVerbose ? "shell_putsnl(name)" : "name",
drhb17ea912019-03-25 14:24:19 +00006689 pAr->azArg[i], pAr->zDir, zExists);
mistachkince2052b2018-03-23 00:31:53 +00006690 rc = arExecSql(pAr, zSql2);
6691 sqlite3_free(zSql2);
danfd0245d2017-12-07 15:44:29 +00006692 }
drh1bf208c2018-03-09 21:54:01 +00006693end_ar_transaction:
danfd0245d2017-12-07 15:44:29 +00006694 if( rc!=SQLITE_OK ){
drh2bd207f2019-01-11 17:19:59 +00006695 sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
danfd0245d2017-12-07 15:44:29 +00006696 }else{
drhb376b3d2018-01-10 13:11:51 +00006697 rc = arExecSql(pAr, "RELEASE ar;");
drh1bf208c2018-03-09 21:54:01 +00006698 if( pAr->bZip && pAr->zFile ){
6699 zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
6700 arExecSql(pAr, zSql);
6701 sqlite3_free(zSql);
6702 }
danfd0245d2017-12-07 15:44:29 +00006703 }
drhb17ea912019-03-25 14:24:19 +00006704 sqlite3_free(zExists);
danfd0245d2017-12-07 15:44:29 +00006705 return rc;
6706}
6707
6708/*
6709** Implementation of ".ar" dot command.
6710*/
6711static int arDotCommand(
drhe2754c12019-08-26 12:50:01 +00006712 ShellState *pState, /* Current shell tool state */
6713 int fromCmdLine, /* True if -A command-line option, not .ar cmd */
6714 char **azArg, /* Array of arguments passed to dot command */
6715 int nArg /* Number of entries in azArg[] */
danfd0245d2017-12-07 15:44:29 +00006716){
dan88be0202017-12-09 17:58:02 +00006717 ArCommand cmd;
6718 int rc;
drh34660642018-01-10 17:39:54 +00006719 memset(&cmd, 0, sizeof(cmd));
drhd0f9cdc2018-05-17 14:09:06 +00006720 cmd.fromCmdLine = fromCmdLine;
dan88be0202017-12-09 17:58:02 +00006721 rc = arParseCommand(azArg, nArg, &cmd);
6722 if( rc==SQLITE_OK ){
drha5676c42018-01-10 15:17:34 +00006723 int eDbType = SHELL_OPEN_UNSPEC;
drhb376b3d2018-01-10 13:11:51 +00006724 cmd.p = pState;
6725 cmd.db = pState->db;
drha5676c42018-01-10 15:17:34 +00006726 if( cmd.zFile ){
drh1bf208c2018-03-09 21:54:01 +00006727 eDbType = deduceDatabaseType(cmd.zFile, 1);
drha5676c42018-01-10 15:17:34 +00006728 }else{
6729 eDbType = pState->openMode;
6730 }
6731 if( eDbType==SHELL_OPEN_ZIPFILE ){
drh1bf208c2018-03-09 21:54:01 +00006732 if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){
6733 if( cmd.zFile==0 ){
6734 cmd.zSrcTable = sqlite3_mprintf("zip");
6735 }else{
6736 cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
6737 }
dan5a78b812017-12-27 18:54:11 +00006738 }
drha5676c42018-01-10 15:17:34 +00006739 cmd.bZip = 1;
dan5a78b812017-12-27 18:54:11 +00006740 }else if( cmd.zFile ){
dand4b56e52017-12-12 20:04:59 +00006741 int flags;
drha5676c42018-01-10 15:17:34 +00006742 if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
drhb17ea912019-03-25 14:24:19 +00006743 if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
6744 || cmd.eCmd==AR_CMD_UPDATE ){
dand4b56e52017-12-12 20:04:59 +00006745 flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
6746 }else{
6747 flags = SQLITE_OPEN_READONLY;
6748 }
drha82c95b2018-01-10 14:00:00 +00006749 cmd.db = 0;
drha5676c42018-01-10 15:17:34 +00006750 if( cmd.bDryRun ){
6751 utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
6752 eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
6753 }
6754 rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
6755 eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
dand4b56e52017-12-12 20:04:59 +00006756 if( rc!=SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00006757 utf8_printf(stderr, "cannot open file: %s (%s)\n",
6758 cmd.zFile, sqlite3_errmsg(cmd.db)
dand4b56e52017-12-12 20:04:59 +00006759 );
drha5676c42018-01-10 15:17:34 +00006760 goto end_ar_command;
dand4b56e52017-12-12 20:04:59 +00006761 }
drhb376b3d2018-01-10 13:11:51 +00006762 sqlite3_fileio_init(cmd.db, 0, 0);
drhb376b3d2018-01-10 13:11:51 +00006763 sqlite3_sqlar_init(cmd.db, 0, 0);
drh34660642018-01-10 17:39:54 +00006764 sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
6765 shellPutsFunc, 0, 0);
6766
dand4b56e52017-12-12 20:04:59 +00006767 }
drhd0f9cdc2018-05-17 14:09:06 +00006768 if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
drh634c70f2018-01-10 16:50:18 +00006769 if( cmd.eCmd!=AR_CMD_CREATE
6770 && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
6771 ){
drha5676c42018-01-10 15:17:34 +00006772 utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
6773 rc = SQLITE_ERROR;
6774 goto end_ar_command;
6775 }
6776 cmd.zSrcTable = sqlite3_mprintf("sqlar");
6777 }
dand4b56e52017-12-12 20:04:59 +00006778
dan88be0202017-12-09 17:58:02 +00006779 switch( cmd.eCmd ){
6780 case AR_CMD_CREATE:
drhb17ea912019-03-25 14:24:19 +00006781 rc = arCreateOrUpdateCommand(&cmd, 0, 0);
dan88be0202017-12-09 17:58:02 +00006782 break;
danfd0245d2017-12-07 15:44:29 +00006783
dan88be0202017-12-09 17:58:02 +00006784 case AR_CMD_EXTRACT:
drhb376b3d2018-01-10 13:11:51 +00006785 rc = arExtractCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00006786 break;
6787
6788 case AR_CMD_LIST:
drhb376b3d2018-01-10 13:11:51 +00006789 rc = arListCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00006790 break;
6791
dan0d0547f2017-12-14 15:40:42 +00006792 case AR_CMD_HELP:
6793 arUsage(pState->out);
6794 break;
6795
drhb17ea912019-03-25 14:24:19 +00006796 case AR_CMD_INSERT:
6797 rc = arCreateOrUpdateCommand(&cmd, 1, 0);
6798 break;
6799
dan88be0202017-12-09 17:58:02 +00006800 default:
6801 assert( cmd.eCmd==AR_CMD_UPDATE );
drhb17ea912019-03-25 14:24:19 +00006802 rc = arCreateOrUpdateCommand(&cmd, 1, 1);
dan88be0202017-12-09 17:58:02 +00006803 break;
danfd0245d2017-12-07 15:44:29 +00006804 }
6805 }
drha5676c42018-01-10 15:17:34 +00006806end_ar_command:
6807 if( cmd.db!=pState->db ){
drh9e804032018-05-18 17:11:50 +00006808 close_db(cmd.db);
drha5676c42018-01-10 15:17:34 +00006809 }
6810 sqlite3_free(cmd.zSrcTable);
danfd0245d2017-12-07 15:44:29 +00006811
dan88be0202017-12-09 17:58:02 +00006812 return rc;
danfd0245d2017-12-07 15:44:29 +00006813}
drhe37c0e12018-01-06 19:19:50 +00006814/* End of the ".archive" or ".ar" command logic
drhe2754c12019-08-26 12:50:01 +00006815*******************************************************************************/
drhe37c0e12018-01-06 19:19:50 +00006816#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
danfd0245d2017-12-07 15:44:29 +00006817
dan1b162162019-04-27 20:15:15 +00006818#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan42ebb012019-04-27 18:47:03 +00006819/*
6820** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
6821** Otherwise, the SQL statement or statements in zSql are executed using
6822** database connection db and the error code written to *pRc before
6823** this function returns.
6824*/
dan68cb86e2019-04-20 20:57:28 +00006825static void shellExec(sqlite3 *db, int *pRc, const char *zSql){
6826 int rc = *pRc;
6827 if( rc==SQLITE_OK ){
6828 char *zErr = 0;
6829 rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
6830 if( rc!=SQLITE_OK ){
6831 raw_printf(stderr, "SQL error: %s\n", zErr);
6832 }
drhf83d5012021-05-03 13:35:00 +00006833 sqlite3_free(zErr);
dan68cb86e2019-04-20 20:57:28 +00006834 *pRc = rc;
6835 }
6836}
6837
dan42ebb012019-04-27 18:47:03 +00006838/*
6839** Like shellExec(), except that zFmt is a printf() style format string.
6840*/
danc0b42432019-04-26 15:14:53 +00006841static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){
6842 char *z = 0;
6843 if( *pRc==SQLITE_OK ){
6844 va_list ap;
6845 va_start(ap, zFmt);
6846 z = sqlite3_vmprintf(zFmt, ap);
6847 va_end(ap);
6848 if( z==0 ){
6849 *pRc = SQLITE_NOMEM;
6850 }else{
6851 shellExec(db, pRc, z);
6852 }
6853 sqlite3_free(z);
6854 }
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, an attempt is made to allocate, zero and return a pointer
6860** to a buffer nByte bytes in size. If an OOM error occurs, *pRc is set
6861** to SQLITE_NOMEM and NULL returned.
6862*/
dan68cb86e2019-04-20 20:57:28 +00006863static void *shellMalloc(int *pRc, sqlite3_int64 nByte){
6864 void *pRet = 0;
6865 if( *pRc==SQLITE_OK ){
6866 pRet = sqlite3_malloc64(nByte);
6867 if( pRet==0 ){
6868 *pRc = SQLITE_NOMEM;
6869 }else{
6870 memset(pRet, 0, nByte);
6871 }
6872 }
6873 return pRet;
6874}
6875
dan42ebb012019-04-27 18:47:03 +00006876/*
6877** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
6878** Otherwise, zFmt is treated as a printf() style string. The result of
6879** formatting it along with any trailing arguments is written into a
6880** buffer obtained from sqlite3_malloc(), and pointer to which is returned.
6881** It is the responsibility of the caller to eventually free this buffer
6882** using a call to sqlite3_free().
6883**
6884** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL
6885** pointer returned.
6886*/
dan68cb86e2019-04-20 20:57:28 +00006887static char *shellMPrintf(int *pRc, const char *zFmt, ...){
6888 char *z = 0;
6889 if( *pRc==SQLITE_OK ){
6890 va_list ap;
6891 va_start(ap, zFmt);
6892 z = sqlite3_vmprintf(zFmt, ap);
6893 va_end(ap);
6894 if( z==0 ){
6895 *pRc = SQLITE_NOMEM;
6896 }
6897 }
6898 return z;
6899}
6900
dan42ebb012019-04-27 18:47:03 +00006901/*
6902** When running the ".recover" command, each output table, and the special
6903** orphaned row table if it is required, is represented by an instance
6904** of the following struct.
6905*/
dan68cb86e2019-04-20 20:57:28 +00006906typedef struct RecoverTable RecoverTable;
6907struct RecoverTable {
dan42ebb012019-04-27 18:47:03 +00006908 char *zQuoted; /* Quoted version of table name */
dan68cb86e2019-04-20 20:57:28 +00006909 int nCol; /* Number of columns in table */
6910 char **azlCol; /* Array of column lists */
dan42ebb012019-04-27 18:47:03 +00006911 int iPk; /* Index of IPK column */
dan68cb86e2019-04-20 20:57:28 +00006912};
6913
6914/*
dan42ebb012019-04-27 18:47:03 +00006915** Free a RecoverTable object allocated by recoverFindTable() or
6916** recoverOrphanTable().
dan68cb86e2019-04-20 20:57:28 +00006917*/
6918static void recoverFreeTable(RecoverTable *pTab){
6919 if( pTab ){
dan68cb86e2019-04-20 20:57:28 +00006920 sqlite3_free(pTab->zQuoted);
dan68cb86e2019-04-20 20:57:28 +00006921 if( pTab->azlCol ){
6922 int i;
dan98c5ad32019-04-26 21:11:37 +00006923 for(i=0; i<=pTab->nCol; i++){
dan68cb86e2019-04-20 20:57:28 +00006924 sqlite3_free(pTab->azlCol[i]);
6925 }
6926 sqlite3_free(pTab->azlCol);
6927 }
6928 sqlite3_free(pTab);
6929 }
6930}
6931
dan42ebb012019-04-27 18:47:03 +00006932/*
6933** This function is a no-op if (*pRc) is not SQLITE_OK when it is called.
6934** Otherwise, it allocates and returns a RecoverTable object based on the
6935** final four arguments passed to this function. It is the responsibility
6936** of the caller to eventually free the returned object using
6937** recoverFreeTable().
6938*/
6939static RecoverTable *recoverNewTable(
danb40af492019-04-22 20:52:12 +00006940 int *pRc, /* IN/OUT: Error code */
danb40af492019-04-22 20:52:12 +00006941 const char *zName, /* Name of table */
6942 const char *zSql, /* CREATE TABLE statement */
6943 int bIntkey,
6944 int nCol
6945){
6946 sqlite3 *dbtmp = 0; /* sqlite3 handle for testing CREATE TABLE */
6947 int rc = *pRc;
dan98c5ad32019-04-26 21:11:37 +00006948 RecoverTable *pTab = 0;
danb40af492019-04-22 20:52:12 +00006949
dan98c5ad32019-04-26 21:11:37 +00006950 pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable));
danb40af492019-04-22 20:52:12 +00006951 if( rc==SQLITE_OK ){
6952 int nSqlCol = 0;
6953 int bSqlIntkey = 0;
6954 sqlite3_stmt *pStmt = 0;
dan98c5ad32019-04-26 21:11:37 +00006955
danb40af492019-04-22 20:52:12 +00006956 rc = sqlite3_open("", &dbtmp);
6957 if( rc==SQLITE_OK ){
drha2de66c2019-08-06 20:26:17 +00006958 sqlite3_create_function(dbtmp, "shell_idquote", 1, SQLITE_UTF8, 0,
6959 shellIdQuote, 0, 0);
6960 }
6961 if( rc==SQLITE_OK ){
dan38f9c712019-04-23 18:03:02 +00006962 rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
6963 }
6964 if( rc==SQLITE_OK ){
danb40af492019-04-22 20:52:12 +00006965 rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0);
6966 if( rc==SQLITE_ERROR ){
6967 rc = SQLITE_OK;
6968 goto finished;
6969 }
6970 }
6971 shellPreparePrintf(dbtmp, &rc, &pStmt,
6972 "SELECT count(*) FROM pragma_table_info(%Q)", zName
6973 );
6974 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
6975 nSqlCol = sqlite3_column_int(pStmt, 0);
6976 }
6977 shellFinalize(&rc, pStmt);
6978
6979 if( rc!=SQLITE_OK || nSqlCol<nCol ){
6980 goto finished;
6981 }
6982
6983 shellPreparePrintf(dbtmp, &rc, &pStmt,
6984 "SELECT ("
6985 " SELECT substr(data,1,1)==X'0D' FROM sqlite_dbpage WHERE pgno=rootpage"
drh067b92b2020-06-19 15:24:12 +00006986 ") FROM sqlite_schema WHERE name = %Q", zName
danb40af492019-04-22 20:52:12 +00006987 );
6988 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
6989 bSqlIntkey = sqlite3_column_int(pStmt, 0);
6990 }
6991 shellFinalize(&rc, pStmt);
6992
6993 if( bIntkey==bSqlIntkey ){
dan98c5ad32019-04-26 21:11:37 +00006994 int i;
danb40af492019-04-22 20:52:12 +00006995 const char *zPk = "_rowid_";
6996 sqlite3_stmt *pPkFinder = 0;
6997
danf57bea32019-04-27 15:35:45 +00006998 /* If this is an intkey table and there is an INTEGER PRIMARY KEY,
6999 ** set zPk to the name of the PK column, and pTab->iPk to the index
7000 ** of the column, where columns are 0-numbered from left to right.
7001 ** Or, if this is a WITHOUT ROWID table or if there is no IPK column,
7002 ** leave zPk as "_rowid_" and pTab->iPk at -2. */
dan98c5ad32019-04-26 21:11:37 +00007003 pTab->iPk = -2;
7004 if( bIntkey ){
7005 shellPreparePrintf(dbtmp, &rc, &pPkFinder,
danb40af492019-04-22 20:52:12 +00007006 "SELECT cid, name FROM pragma_table_info(%Q) "
7007 " WHERE pk=1 AND type='integer' COLLATE nocase"
dan98c5ad32019-04-26 21:11:37 +00007008 " AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
7009 , zName, zName
7010 );
7011 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){
7012 pTab->iPk = sqlite3_column_int(pPkFinder, 0);
7013 zPk = (const char*)sqlite3_column_text(pPkFinder, 1);
7014 }
danb40af492019-04-22 20:52:12 +00007015 }
7016
drha2de66c2019-08-06 20:26:17 +00007017 pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName);
dan98c5ad32019-04-26 21:11:37 +00007018 pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
danb40af492019-04-22 20:52:12 +00007019 pTab->nCol = nSqlCol;
7020
dan98c5ad32019-04-26 21:11:37 +00007021 if( bIntkey ){
drha2de66c2019-08-06 20:26:17 +00007022 pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk);
danb40af492019-04-22 20:52:12 +00007023 }else{
dan98c5ad32019-04-26 21:11:37 +00007024 pTab->azlCol[0] = shellMPrintf(&rc, "");
danb40af492019-04-22 20:52:12 +00007025 }
dan98c5ad32019-04-26 21:11:37 +00007026 i = 1;
7027 shellPreparePrintf(dbtmp, &rc, &pStmt,
drha2de66c2019-08-06 20:26:17 +00007028 "SELECT %Q || group_concat(shell_idquote(name), ', ') "
danf57bea32019-04-27 15:35:45 +00007029 " FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
dan98c5ad32019-04-26 21:11:37 +00007030 "FROM pragma_table_info(%Q)",
danf57bea32019-04-27 15:35:45 +00007031 bIntkey ? ", " : "", pTab->iPk,
7032 bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ",
7033 zName
dan98c5ad32019-04-26 21:11:37 +00007034 );
7035 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7036 const char *zText = (const char*)sqlite3_column_text(pStmt, 0);
7037 pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText);
7038 i++;
7039 }
7040 shellFinalize(&rc, pStmt);
7041
danb40af492019-04-22 20:52:12 +00007042 shellFinalize(&rc, pPkFinder);
7043 }
7044 }
7045
7046 finished:
7047 sqlite3_close(dbtmp);
7048 *pRc = rc;
dan98779652019-05-09 14:15:19 +00007049 if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){
dan98c5ad32019-04-26 21:11:37 +00007050 recoverFreeTable(pTab);
7051 pTab = 0;
7052 }
7053 return pTab;
danb40af492019-04-22 20:52:12 +00007054}
7055
dan0aa01ee2019-04-27 19:36:49 +00007056/*
7057** This function is called to search the schema recovered from the
drh067b92b2020-06-19 15:24:12 +00007058** sqlite_schema table of the (possibly) corrupt database as part
dan0aa01ee2019-04-27 19:36:49 +00007059** of a ".recover" command. Specifically, for a table with root page
7060** iRoot and at least nCol columns. Additionally, if bIntkey is 0, the
7061** table must be a WITHOUT ROWID table, or if non-zero, not one of
7062** those.
7063**
7064** If a table is found, a (RecoverTable*) object is returned. Or, if
7065** no such table is found, but bIntkey is false and iRoot is the
7066** root page of an index in the recovered schema, then (*pbNoop) is
7067** set to true and NULL returned. Or, if there is no such table or
7068** index, NULL is returned and (*pbNoop) set to 0, indicating that
7069** the caller should write data to the orphans table.
7070*/
dan42ebb012019-04-27 18:47:03 +00007071static RecoverTable *recoverFindTable(
dan0aa01ee2019-04-27 19:36:49 +00007072 ShellState *pState, /* Shell state object */
7073 int *pRc, /* IN/OUT: Error code */
7074 int iRoot, /* Root page of table */
7075 int bIntkey, /* True for an intkey table */
7076 int nCol, /* Number of columns in table */
7077 int *pbNoop /* OUT: True if iRoot is root of index */
dan68cb86e2019-04-20 20:57:28 +00007078){
danb40af492019-04-22 20:52:12 +00007079 sqlite3_stmt *pStmt = 0;
dan68cb86e2019-04-20 20:57:28 +00007080 RecoverTable *pRet = 0;
danb40af492019-04-22 20:52:12 +00007081 int bNoop = 0;
7082 const char *zSql = 0;
7083 const char *zName = 0;
dan68cb86e2019-04-20 20:57:28 +00007084
danb40af492019-04-22 20:52:12 +00007085 /* Search the recovered schema for an object with root page iRoot. */
7086 shellPreparePrintf(pState->db, pRc, &pStmt,
7087 "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot
7088 );
7089 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7090 const char *zType = (const char*)sqlite3_column_text(pStmt, 0);
7091 if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){
7092 bNoop = 1;
7093 break;
7094 }
7095 if( sqlite3_stricmp(zType, "table")==0 ){
7096 zName = (const char*)sqlite3_column_text(pStmt, 1);
7097 zSql = (const char*)sqlite3_column_text(pStmt, 2);
dan42ebb012019-04-27 18:47:03 +00007098 pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol);
danb40af492019-04-22 20:52:12 +00007099 break;
7100 }
7101 }
dan98c5ad32019-04-26 21:11:37 +00007102
danb40af492019-04-22 20:52:12 +00007103 shellFinalize(pRc, pStmt);
dan98c5ad32019-04-26 21:11:37 +00007104 *pbNoop = bNoop;
7105 return pRet;
7106}
danb40af492019-04-22 20:52:12 +00007107
dan0aa01ee2019-04-27 19:36:49 +00007108/*
7109** Return a RecoverTable object representing the orphans table.
7110*/
dan98c5ad32019-04-26 21:11:37 +00007111static RecoverTable *recoverOrphanTable(
dan0aa01ee2019-04-27 19:36:49 +00007112 ShellState *pState, /* Shell state object */
7113 int *pRc, /* IN/OUT: Error code */
7114 const char *zLostAndFound, /* Base name for orphans table */
7115 int nCol /* Number of user data columns */
dan98c5ad32019-04-26 21:11:37 +00007116){
7117 RecoverTable *pTab = 0;
7118 if( nCol>=0 && *pRc==SQLITE_OK ){
7119 int i;
dan42ebb012019-04-27 18:47:03 +00007120
7121 /* This block determines the name of the orphan table. The prefered
7122 ** name is zLostAndFound. But if that clashes with another name
7123 ** in the recovered schema, try zLostAndFound_0, zLostAndFound_1
7124 ** and so on until a non-clashing name is found. */
7125 int iTab = 0;
7126 char *zTab = shellMPrintf(pRc, "%s", zLostAndFound);
7127 sqlite3_stmt *pTest = 0;
7128 shellPrepare(pState->db, pRc,
7129 "SELECT 1 FROM recovery.schema WHERE name=?", &pTest
dan68cb86e2019-04-20 20:57:28 +00007130 );
dan42ebb012019-04-27 18:47:03 +00007131 if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
7132 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){
7133 shellReset(pRc, pTest);
7134 sqlite3_free(zTab);
7135 zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++);
7136 sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
dan68cb86e2019-04-20 20:57:28 +00007137 }
dan42ebb012019-04-27 18:47:03 +00007138 shellFinalize(pRc, pTest);
dan68cb86e2019-04-20 20:57:28 +00007139
dan98c5ad32019-04-26 21:11:37 +00007140 pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
7141 if( pTab ){
drha2de66c2019-08-06 20:26:17 +00007142 pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab);
dan98c5ad32019-04-26 21:11:37 +00007143 pTab->nCol = nCol;
7144 pTab->iPk = -2;
7145 if( nCol>0 ){
7146 pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1));
7147 if( pTab->azlCol ){
7148 pTab->azlCol[nCol] = shellMPrintf(pRc, "");
7149 for(i=nCol-1; i>=0; i--){
7150 pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]);
7151 }
7152 }
danb40af492019-04-22 20:52:12 +00007153 }
dan68cb86e2019-04-20 20:57:28 +00007154
dan42ebb012019-04-27 18:47:03 +00007155 if( *pRc!=SQLITE_OK ){
7156 recoverFreeTable(pTab);
7157 pTab = 0;
7158 }else{
7159 raw_printf(pState->out,
7160 "CREATE TABLE %s(rootpgno INTEGER, "
7161 "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted
7162 );
7163 for(i=0; i<nCol; i++){
7164 raw_printf(pState->out, ", c%d", i);
7165 }
7166 raw_printf(pState->out, ");\n");
7167 }
dan98c5ad32019-04-26 21:11:37 +00007168 }
dan42ebb012019-04-27 18:47:03 +00007169 sqlite3_free(zTab);
dan68cb86e2019-04-20 20:57:28 +00007170 }
dan98c5ad32019-04-26 21:11:37 +00007171 return pTab;
dan68cb86e2019-04-20 20:57:28 +00007172}
7173
7174/*
7175** This function is called to recover data from the database. A script
7176** to construct a new database containing all recovered data is output
7177** on stream pState->out.
7178*/
danb9b71db2019-04-25 16:20:40 +00007179static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
dan68cb86e2019-04-20 20:57:28 +00007180 int rc = SQLITE_OK;
7181 sqlite3_stmt *pLoop = 0; /* Loop through all root pages */
danefa363b2019-04-24 20:48:55 +00007182 sqlite3_stmt *pPages = 0; /* Loop through all pages in a group */
7183 sqlite3_stmt *pCells = 0; /* Loop through all cells in a page */
danc0b42432019-04-26 15:14:53 +00007184 const char *zRecoveryDb = ""; /* Name of "recovery" database */
dan42ebb012019-04-27 18:47:03 +00007185 const char *zLostAndFound = "lost_and_found";
dan9c014f82019-04-25 19:23:15 +00007186 int i;
dan98c5ad32019-04-26 21:11:37 +00007187 int nOrphan = -1;
7188 RecoverTable *pOrphan = 0;
dan9c014f82019-04-25 19:23:15 +00007189
7190 int bFreelist = 1; /* 0 if --freelist-corrupt is specified */
dan8cce6b82019-09-14 16:44:51 +00007191 int bRowids = 1; /* 0 if --no-rowids */
dan9c014f82019-04-25 19:23:15 +00007192 for(i=1; i<nArg; i++){
7193 char *z = azArg[i];
7194 int n;
7195 if( z[0]=='-' && z[1]=='-' ) z++;
drh4245e042019-06-13 13:52:46 +00007196 n = strlen30(z);
dan9c014f82019-04-25 19:23:15 +00007197 if( n<=17 && memcmp("-freelist-corrupt", z, n)==0 ){
7198 bFreelist = 0;
dan42ebb012019-04-27 18:47:03 +00007199 }else
danc0b42432019-04-26 15:14:53 +00007200 if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
7201 i++;
7202 zRecoveryDb = azArg[i];
dan42ebb012019-04-27 18:47:03 +00007203 }else
7204 if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
7205 i++;
7206 zLostAndFound = azArg[i];
dan8cce6b82019-09-14 16:44:51 +00007207 }else
7208 if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
7209 bRowids = 0;
danc0b42432019-04-26 15:14:53 +00007210 }
dan9c014f82019-04-25 19:23:15 +00007211 else{
drhe2754c12019-08-26 12:50:01 +00007212 utf8_printf(stderr, "unexpected option: %s\n", azArg[i]);
7213 showHelp(pState->out, azArg[0]);
dan9c014f82019-04-25 19:23:15 +00007214 return 1;
7215 }
7216 }
dan68cb86e2019-04-20 20:57:28 +00007217
danc0b42432019-04-26 15:14:53 +00007218 shellExecPrintf(pState->db, &rc,
dan68cb86e2019-04-20 20:57:28 +00007219 /* Attach an in-memory database named 'recovery'. Create an indexed
7220 ** cache of the sqlite_dbptr virtual table. */
dan01c08bc2019-07-24 19:20:30 +00007221 "PRAGMA writable_schema = on;"
danc0b42432019-04-26 15:14:53 +00007222 "ATTACH %Q AS recovery;"
7223 "DROP TABLE IF EXISTS recovery.dbptr;"
7224 "DROP TABLE IF EXISTS recovery.freelist;"
7225 "DROP TABLE IF EXISTS recovery.map;"
7226 "DROP TABLE IF EXISTS recovery.schema;"
danc0b42432019-04-26 15:14:53 +00007227 "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb
dan9c014f82019-04-25 19:23:15 +00007228 );
7229
7230 if( bFreelist ){
7231 shellExec(pState->db, &rc,
7232 "WITH trunk(pgno) AS ("
7233 " SELECT shell_int32("
7234 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x "
7235 " WHERE x>0"
7236 " UNION"
7237 " SELECT shell_int32("
7238 " (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x "
7239 " FROM trunk WHERE x>0"
7240 "),"
7241 "freelist(data, n, freepgno) AS ("
danf6099e92019-05-09 16:57:39 +00007242 " SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno "
dan9c014f82019-04-25 19:23:15 +00007243 " FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno"
7244 " UNION ALL"
7245 " SELECT data, n-1, shell_int32(data, 2+n) "
7246 " FROM freelist WHERE n>=0"
7247 ")"
7248 "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;"
7249 );
7250 }
7251
dan95063c22019-07-24 08:15:09 +00007252 /* If this is an auto-vacuum database, add all pointer-map pages to
7253 ** the freelist table. Do this regardless of whether or not
7254 ** --freelist-corrupt was specified. */
7255 shellExec(pState->db, &rc,
7256 "WITH ptrmap(pgno) AS ("
7257 " SELECT 2 WHERE shell_int32("
7258 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 13"
7259 " )"
7260 " UNION ALL "
7261 " SELECT pgno+1+(SELECT page_size FROM pragma_page_size)/5 AS pp "
7262 " FROM ptrmap WHERE pp<=(SELECT page_count FROM pragma_page_count)"
7263 ")"
7264 "REPLACE INTO recovery.freelist SELECT pgno FROM ptrmap"
7265 );
7266
dan9c014f82019-04-25 19:23:15 +00007267 shellExec(pState->db, &rc,
danca424382019-04-26 15:40:27 +00007268 "CREATE TABLE recovery.dbptr("
7269 " pgno, child, PRIMARY KEY(child, pgno)"
7270 ") WITHOUT ROWID;"
7271 "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) "
7272 " SELECT * FROM sqlite_dbptr"
7273 " WHERE pgno NOT IN freelist AND child NOT IN freelist;"
7274
7275 /* Delete any pointer to page 1. This ensures that page 1 is considered
7276 ** a root page, regardless of how corrupt the db is. */
7277 "DELETE FROM recovery.dbptr WHERE child = 1;"
7278
7279 /* Delete all pointers to any pages that have more than one pointer
7280 ** to them. Such pages will be treated as root pages when recovering
7281 ** data. */
7282 "DELETE FROM recovery.dbptr WHERE child IN ("
7283 " SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1"
7284 ");"
7285
dan68cb86e2019-04-20 20:57:28 +00007286 /* Create the "map" table that will (eventually) contain instructions
7287 ** for dealing with each page in the db that contains one or more
7288 ** records. */
danb40af492019-04-22 20:52:12 +00007289 "CREATE TABLE recovery.map("
7290 "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT"
7291 ");"
dan68cb86e2019-04-20 20:57:28 +00007292
7293 /* Populate table [map]. If there are circular loops of pages in the
7294 ** database, the following adds all pages in such a loop to the map
7295 ** as individual root pages. This could be handled better. */
7296 "WITH pages(i, maxlen) AS ("
danb9b71db2019-04-25 16:20:40 +00007297 " SELECT page_count, ("
7298 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count"
dan13b87672019-05-09 11:45:21 +00007299 " ) FROM pragma_page_count WHERE page_count>0"
dan68cb86e2019-04-20 20:57:28 +00007300 " UNION ALL"
danb40af492019-04-22 20:52:12 +00007301 " SELECT i-1, ("
7302 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1"
7303 " ) FROM pages WHERE i>=2"
dan68cb86e2019-04-20 20:57:28 +00007304 ")"
danb40af492019-04-22 20:52:12 +00007305 "INSERT INTO recovery.map(pgno, maxlen, intkey, root) "
7306 " SELECT i, maxlen, NULL, ("
dan68cb86e2019-04-20 20:57:28 +00007307 " WITH p(orig, pgno, parent) AS ("
7308 " SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)"
dan39e04f82019-05-09 18:33:32 +00007309 " UNION "
dan68cb86e2019-04-20 20:57:28 +00007310 " SELECT i, p.parent, "
7311 " (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p"
7312 " )"
7313 " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
7314 ") "
dand790c9a2019-08-26 14:57:58 +00007315 "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;"
danb40af492019-04-22 20:52:12 +00007316 "UPDATE recovery.map AS o SET intkey = ("
7317 " SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
7318 ");"
dan68cb86e2019-04-20 20:57:28 +00007319
7320 /* Extract data from page 1 and any linked pages into table
drh067b92b2020-06-19 15:24:12 +00007321 ** recovery.schema. With the same schema as an sqlite_schema table. */
dan68cb86e2019-04-20 20:57:28 +00007322 "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
7323 "INSERT INTO recovery.schema SELECT "
7324 " max(CASE WHEN field=0 THEN value ELSE NULL END),"
7325 " max(CASE WHEN field=1 THEN value ELSE NULL END),"
7326 " max(CASE WHEN field=2 THEN value ELSE NULL END),"
7327 " max(CASE WHEN field=3 THEN value ELSE NULL END),"
7328 " max(CASE WHEN field=4 THEN value ELSE NULL END)"
7329 "FROM sqlite_dbdata WHERE pgno IN ("
7330 " SELECT pgno FROM recovery.map WHERE root=1"
7331 ")"
7332 "GROUP BY pgno, cell;"
dan98c5ad32019-04-26 21:11:37 +00007333 "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);"
dan68cb86e2019-04-20 20:57:28 +00007334 );
7335
danb40af492019-04-22 20:52:12 +00007336 /* Open a transaction, then print out all non-virtual, non-"sqlite_%"
7337 ** CREATE TABLE statements that extracted from the existing schema. */
7338 if( rc==SQLITE_OK ){
7339 sqlite3_stmt *pStmt = 0;
danf3210572019-08-06 18:40:36 +00007340 /* ".recover" might output content in an order which causes immediate
7341 ** foreign key constraints to be violated. So disable foreign-key
7342 ** constraint enforcement to prevent problems when running the output
7343 ** script. */
7344 raw_printf(pState->out, "PRAGMA foreign_keys=OFF;\n");
danb40af492019-04-22 20:52:12 +00007345 raw_printf(pState->out, "BEGIN;\n");
dan38f9c712019-04-23 18:03:02 +00007346 raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
7347 shellPrepare(pState->db, &rc,
danb40af492019-04-22 20:52:12 +00007348 "SELECT sql FROM recovery.schema "
dan38f9c712019-04-23 18:03:02 +00007349 "WHERE type='table' AND sql LIKE 'create table%'", &pStmt
danb40af492019-04-22 20:52:12 +00007350 );
7351 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7352 const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0);
dan38f9c712019-04-23 18:03:02 +00007353 raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n",
7354 &zCreateTable[12]
7355 );
danb40af492019-04-22 20:52:12 +00007356 }
7357 shellFinalize(&rc, pStmt);
7358 }
7359
dan98c5ad32019-04-26 21:11:37 +00007360 /* Figure out if an orphan table will be required. And if so, how many
7361 ** user columns it should contain */
7362 shellPrepare(pState->db, &rc,
dan98779652019-05-09 14:15:19 +00007363 "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1"
dan98c5ad32019-04-26 21:11:37 +00007364 , &pLoop
7365 );
7366 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
7367 nOrphan = sqlite3_column_int(pLoop, 0);
7368 }
7369 shellFinalize(&rc, pLoop);
7370 pLoop = 0;
dan98c5ad32019-04-26 21:11:37 +00007371
danefa363b2019-04-24 20:48:55 +00007372 shellPrepare(pState->db, &rc,
7373 "SELECT pgno FROM recovery.map WHERE root=?", &pPages
7374 );
dan8cce6b82019-09-14 16:44:51 +00007375
danefa363b2019-04-24 20:48:55 +00007376 shellPrepare(pState->db, &rc,
dan8cce6b82019-09-14 16:44:51 +00007377 "SELECT max(field), group_concat(shell_escape_crnl(quote"
7378 "(case when (? AND field<0) then NULL else value end)"
7379 "), ', ')"
dan9443dbc2019-07-24 20:10:27 +00007380 ", min(field) "
danefa363b2019-04-24 20:48:55 +00007381 "FROM sqlite_dbdata WHERE pgno = ? AND field != ?"
7382 "GROUP BY cell", &pCells
7383 );
7384
dan68cb86e2019-04-20 20:57:28 +00007385 /* Loop through each root page. */
danb40af492019-04-22 20:52:12 +00007386 shellPrepare(pState->db, &rc,
7387 "SELECT root, intkey, max(maxlen) FROM recovery.map"
dan38f9c712019-04-23 18:03:02 +00007388 " WHERE root>1 GROUP BY root, intkey ORDER BY root=("
7389 " SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'"
7390 ")", &pLoop
danb40af492019-04-22 20:52:12 +00007391 );
dan68cb86e2019-04-20 20:57:28 +00007392 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
7393 int iRoot = sqlite3_column_int(pLoop, 0);
danb40af492019-04-22 20:52:12 +00007394 int bIntkey = sqlite3_column_int(pLoop, 1);
7395 int nCol = sqlite3_column_int(pLoop, 2);
dan98c5ad32019-04-26 21:11:37 +00007396 int bNoop = 0;
dan68cb86e2019-04-20 20:57:28 +00007397 RecoverTable *pTab;
7398
dan9443dbc2019-07-24 20:10:27 +00007399 assert( bIntkey==0 || bIntkey==1 );
dan42ebb012019-04-27 18:47:03 +00007400 pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);
dan98c5ad32019-04-26 21:11:37 +00007401 if( bNoop || rc ) continue;
dan98779652019-05-09 14:15:19 +00007402 if( pTab==0 ){
7403 if( pOrphan==0 ){
7404 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
7405 }
7406 pTab = pOrphan;
7407 if( pTab==0 ) break;
7408 }
dan98c5ad32019-04-26 21:11:37 +00007409
drha2de66c2019-08-06 20:26:17 +00007410 if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){
dan98c5ad32019-04-26 21:11:37 +00007411 raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
7412 }
7413 sqlite3_bind_int(pPages, 1, iRoot);
dan8cce6b82019-09-14 16:44:51 +00007414 if( bRowids==0 && pTab->iPk<0 ){
7415 sqlite3_bind_int(pCells, 1, 1);
7416 }else{
7417 sqlite3_bind_int(pCells, 1, 0);
7418 }
7419 sqlite3_bind_int(pCells, 3, pTab->iPk);
dan98c5ad32019-04-26 21:11:37 +00007420
7421 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){
7422 int iPgno = sqlite3_column_int(pPages, 0);
dan8cce6b82019-09-14 16:44:51 +00007423 sqlite3_bind_int(pCells, 2, iPgno);
dan98c5ad32019-04-26 21:11:37 +00007424 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){
7425 int nField = sqlite3_column_int(pCells, 0);
dan9443dbc2019-07-24 20:10:27 +00007426 int iMin = sqlite3_column_int(pCells, 2);
dan98c5ad32019-04-26 21:11:37 +00007427 const char *zVal = (const char*)sqlite3_column_text(pCells, 1);
7428
dan9443dbc2019-07-24 20:10:27 +00007429 RecoverTable *pTab2 = pTab;
7430 if( pTab!=pOrphan && (iMin<0)!=bIntkey ){
7431 if( pOrphan==0 ){
7432 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
7433 }
7434 pTab2 = pOrphan;
7435 if( pTab2==0 ) break;
7436 }
7437
dan98c5ad32019-04-26 21:11:37 +00007438 nField = nField+1;
dan9443dbc2019-07-24 20:10:27 +00007439 if( pTab2==pOrphan ){
dan98c5ad32019-04-26 21:11:37 +00007440 raw_printf(pState->out,
7441 "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",
dan9443dbc2019-07-24 20:10:27 +00007442 pTab2->zQuoted, iRoot, iPgno, nField,
7443 iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField]
dan98c5ad32019-04-26 21:11:37 +00007444 );
7445 }else{
danefa363b2019-04-24 20:48:55 +00007446 raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n",
dan9443dbc2019-07-24 20:10:27 +00007447 pTab2->zQuoted, pTab2->azlCol[nField], zVal
danefa363b2019-04-24 20:48:55 +00007448 );
7449 }
dan68cb86e2019-04-20 20:57:28 +00007450 }
dan98c5ad32019-04-26 21:11:37 +00007451 shellReset(&rc, pCells);
dan68cb86e2019-04-20 20:57:28 +00007452 }
dan98c5ad32019-04-26 21:11:37 +00007453 shellReset(&rc, pPages);
7454 if( pTab!=pOrphan ) recoverFreeTable(pTab);
dan68cb86e2019-04-20 20:57:28 +00007455 }
7456 shellFinalize(&rc, pLoop);
danefa363b2019-04-24 20:48:55 +00007457 shellFinalize(&rc, pPages);
7458 shellFinalize(&rc, pCells);
dan98c5ad32019-04-26 21:11:37 +00007459 recoverFreeTable(pOrphan);
dan68cb86e2019-04-20 20:57:28 +00007460
dan38f9c712019-04-23 18:03:02 +00007461 /* The rest of the schema */
danb40af492019-04-22 20:52:12 +00007462 if( rc==SQLITE_OK ){
dan38f9c712019-04-23 18:03:02 +00007463 sqlite3_stmt *pStmt = 0;
7464 shellPrepare(pState->db, &rc,
7465 "SELECT sql, name FROM recovery.schema "
danb1825882019-04-23 20:48:32 +00007466 "WHERE sql NOT LIKE 'create table%'", &pStmt
dan38f9c712019-04-23 18:03:02 +00007467 );
7468 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7469 const char *zSql = (const char*)sqlite3_column_text(pStmt, 0);
7470 if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){
7471 const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
7472 char *zPrint = shellMPrintf(&rc,
drh067b92b2020-06-19 15:24:12 +00007473 "INSERT INTO sqlite_schema VALUES('table', %Q, %Q, 0, %Q)",
dan38f9c712019-04-23 18:03:02 +00007474 zName, zName, zSql
7475 );
7476 raw_printf(pState->out, "%s;\n", zPrint);
7477 sqlite3_free(zPrint);
7478 }else{
7479 raw_printf(pState->out, "%s;\n", zSql);
7480 }
7481 }
7482 shellFinalize(&rc, pStmt);
7483 }
7484
7485 if( rc==SQLITE_OK ){
7486 raw_printf(pState->out, "PRAGMA writable_schema = off;\n");
danb40af492019-04-22 20:52:12 +00007487 raw_printf(pState->out, "COMMIT;\n");
7488 }
dan68cb86e2019-04-20 20:57:28 +00007489 sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
7490 return rc;
7491}
dan1b162162019-04-27 20:15:15 +00007492#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
dan68cb86e2019-04-20 20:57:28 +00007493
drh2ce15c32017-07-11 13:34:40 +00007494/*
7495** If an input line begins with "." then invoke this routine to
7496** process that line.
7497**
7498** Return 1 on error, 2 to exit, and 0 otherwise.
7499*/
7500static int do_meta_command(char *zLine, ShellState *p){
7501 int h = 1;
7502 int nArg = 0;
7503 int n, c;
7504 int rc = 0;
drh5df84282019-08-17 19:45:25 +00007505 char *azArg[52];
drh2ce15c32017-07-11 13:34:40 +00007506
dan6b046be2018-01-09 15:25:55 +00007507#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00007508 if( p->expert.pExpert ){
7509 expertFinish(p, 1, 0);
7510 }
dan6b046be2018-01-09 15:25:55 +00007511#endif
dan43efc182017-12-19 17:42:13 +00007512
drh2ce15c32017-07-11 13:34:40 +00007513 /* Parse the input line into tokens.
7514 */
drh5df84282019-08-17 19:45:25 +00007515 while( zLine[h] && nArg<ArraySize(azArg)-1 ){
drh2ce15c32017-07-11 13:34:40 +00007516 while( IsSpace(zLine[h]) ){ h++; }
7517 if( zLine[h]==0 ) break;
7518 if( zLine[h]=='\'' || zLine[h]=='"' ){
7519 int delim = zLine[h++];
7520 azArg[nArg++] = &zLine[h];
7521 while( zLine[h] && zLine[h]!=delim ){
7522 if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
7523 h++;
7524 }
7525 if( zLine[h]==delim ){
7526 zLine[h++] = 0;
7527 }
7528 if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
7529 }else{
7530 azArg[nArg++] = &zLine[h];
7531 while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
7532 if( zLine[h] ) zLine[h++] = 0;
7533 resolve_backslashes(azArg[nArg-1]);
7534 }
7535 }
drh5df84282019-08-17 19:45:25 +00007536 azArg[nArg] = 0;
drh2ce15c32017-07-11 13:34:40 +00007537
7538 /* Process the input line.
7539 */
7540 if( nArg==0 ) return 0; /* no tokens, no error */
7541 n = strlen30(azArg[0]);
7542 c = azArg[0][0];
drh13c20932018-01-10 21:41:55 +00007543 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +00007544
7545#ifndef SQLITE_OMIT_AUTHORIZATION
7546 if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
7547 if( nArg!=2 ){
7548 raw_printf(stderr, "Usage: .auth ON|OFF\n");
7549 rc = 1;
7550 goto meta_command_exit;
7551 }
7552 open_db(p, 0);
7553 if( booleanValue(azArg[1]) ){
7554 sqlite3_set_authorizer(p->db, shellAuth, p);
drhb97e2ad2021-08-26 18:31:39 +00007555 }else if( p->bSafeModePersist ){
7556 sqlite3_set_authorizer(p->db, safeModeAuth, p);
drh2ce15c32017-07-11 13:34:40 +00007557 }else{
7558 sqlite3_set_authorizer(p->db, 0, 0);
7559 }
7560 }else
7561#endif
7562
drhe37c0e12018-01-06 19:19:50 +00007563#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
7564 if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
danfd0245d2017-12-07 15:44:29 +00007565 open_db(p, 0);
drhb97e2ad2021-08-26 18:31:39 +00007566 failIfSafeMode(p, "cannot run .archive in safe mode");
drhd0f9cdc2018-05-17 14:09:06 +00007567 rc = arDotCommand(p, 0, azArg, nArg);
danfd0245d2017-12-07 15:44:29 +00007568 }else
7569#endif
7570
drh2ce15c32017-07-11 13:34:40 +00007571 if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
7572 || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
7573 ){
7574 const char *zDestFile = 0;
7575 const char *zDb = 0;
7576 sqlite3 *pDest;
7577 sqlite3_backup *pBackup;
7578 int j;
drha50bffb2018-12-08 01:09:14 +00007579 int bAsync = 0;
drh69ed38a2018-05-14 00:23:08 +00007580 const char *zVfs = 0;
drhb97e2ad2021-08-26 18:31:39 +00007581 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00007582 for(j=1; j<nArg; j++){
7583 const char *z = azArg[j];
7584 if( z[0]=='-' ){
drh69ed38a2018-05-14 00:23:08 +00007585 if( z[1]=='-' ) z++;
7586 if( strcmp(z, "-append")==0 ){
7587 zVfs = "apndvfs";
7588 }else
drha50bffb2018-12-08 01:09:14 +00007589 if( strcmp(z, "-async")==0 ){
7590 bAsync = 1;
7591 }else
drh2ce15c32017-07-11 13:34:40 +00007592 {
7593 utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
7594 return 1;
7595 }
7596 }else if( zDestFile==0 ){
7597 zDestFile = azArg[j];
7598 }else if( zDb==0 ){
7599 zDb = zDestFile;
7600 zDestFile = azArg[j];
7601 }else{
drha50bffb2018-12-08 01:09:14 +00007602 raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
drh2ce15c32017-07-11 13:34:40 +00007603 return 1;
7604 }
7605 }
7606 if( zDestFile==0 ){
7607 raw_printf(stderr, "missing FILENAME argument on .backup\n");
7608 return 1;
7609 }
7610 if( zDb==0 ) zDb = "main";
drh69ed38a2018-05-14 00:23:08 +00007611 rc = sqlite3_open_v2(zDestFile, &pDest,
7612 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
drh2ce15c32017-07-11 13:34:40 +00007613 if( rc!=SQLITE_OK ){
7614 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
drh9e804032018-05-18 17:11:50 +00007615 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007616 return 1;
7617 }
drha50bffb2018-12-08 01:09:14 +00007618 if( bAsync ){
7619 sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
7620 0, 0, 0);
7621 }
drh2ce15c32017-07-11 13:34:40 +00007622 open_db(p, 0);
7623 pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
7624 if( pBackup==0 ){
7625 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
drh9e804032018-05-18 17:11:50 +00007626 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007627 return 1;
7628 }
7629 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
7630 sqlite3_backup_finish(pBackup);
7631 if( rc==SQLITE_DONE ){
7632 rc = 0;
7633 }else{
7634 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
7635 rc = 1;
7636 }
drh9e804032018-05-18 17:11:50 +00007637 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007638 }else
7639
7640 if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
7641 if( nArg==2 ){
7642 bail_on_error = booleanValue(azArg[1]);
7643 }else{
7644 raw_printf(stderr, "Usage: .bail on|off\n");
7645 rc = 1;
7646 }
7647 }else
7648
7649 if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
7650 if( nArg==2 ){
7651 if( booleanValue(azArg[1]) ){
7652 setBinaryMode(p->out, 1);
7653 }else{
7654 setTextMode(p->out, 1);
7655 }
7656 }else{
7657 raw_printf(stderr, "Usage: .binary on|off\n");
7658 rc = 1;
7659 }
7660 }else
7661
drh37407122021-07-23 18:43:58 +00007662 /* The undocumented ".breakpoint" command causes a call to the no-op
7663 ** routine named test_breakpoint().
7664 */
7665 if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
7666 test_breakpoint();
7667 }else
7668
drh2ce15c32017-07-11 13:34:40 +00007669 if( c=='c' && strcmp(azArg[0],"cd")==0 ){
drhb97e2ad2021-08-26 18:31:39 +00007670 failIfSafeMode(p, "cannot run .cd in safe mode");
drh2ce15c32017-07-11 13:34:40 +00007671 if( nArg==2 ){
7672#if defined(_WIN32) || defined(WIN32)
7673 wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
7674 rc = !SetCurrentDirectoryW(z);
7675 sqlite3_free(z);
7676#else
7677 rc = chdir(azArg[1]);
7678#endif
7679 if( rc ){
7680 utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
7681 rc = 1;
7682 }
7683 }else{
7684 raw_printf(stderr, "Usage: .cd DIRECTORY\n");
7685 rc = 1;
7686 }
7687 }else
7688
drh2ce15c32017-07-11 13:34:40 +00007689 if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
7690 if( nArg==2 ){
7691 setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
7692 }else{
7693 raw_printf(stderr, "Usage: .changes on|off\n");
7694 rc = 1;
7695 }
7696 }else
7697
7698 /* Cancel output redirection, if it is currently set (by .testcase)
7699 ** Then read the content of the testcase-out.txt file and compare against
7700 ** azArg[1]. If there are differences, report an error and exit.
7701 */
7702 if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
7703 char *zRes = 0;
7704 output_reset(p);
7705 if( nArg!=2 ){
7706 raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
7707 rc = 2;
7708 }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
7709 raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
7710 rc = 2;
7711 }else if( testcase_glob(azArg[1],zRes)==0 ){
7712 utf8_printf(stderr,
7713 "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
7714 p->zTestcase, azArg[1], zRes);
drhf30d3452017-10-17 13:44:46 +00007715 rc = 1;
drh2ce15c32017-07-11 13:34:40 +00007716 }else{
7717 utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
7718 p->nCheck++;
7719 }
7720 sqlite3_free(zRes);
7721 }else
7722
7723 if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
drhb97e2ad2021-08-26 18:31:39 +00007724 failIfSafeMode(p, "cannot run .clone in safe mode");
drh2ce15c32017-07-11 13:34:40 +00007725 if( nArg==2 ){
7726 tryToClone(p, azArg[1]);
7727 }else{
7728 raw_printf(stderr, "Usage: .clone FILENAME\n");
7729 rc = 1;
7730 }
7731 }else
7732
drh37407122021-07-23 18:43:58 +00007733 if( c=='c' && strncmp(azArg[0], "connection", n)==0 ){
7734 if( nArg==1 ){
7735 /* List available connections */
7736 int i;
7737 for(i=0; i<ArraySize(p->aAuxDb); i++){
7738 const char *zFile = p->aAuxDb[i].zDbFilename;
7739 if( p->aAuxDb[i].db==0 && p->pAuxDb!=&p->aAuxDb[i] ){
7740 zFile = "(not open)";
7741 }else if( zFile==0 ){
7742 zFile = "(memory)";
7743 }else if( zFile[0]==0 ){
7744 zFile = "(temporary-file)";
7745 }
7746 if( p->pAuxDb == &p->aAuxDb[i] ){
7747 utf8_printf(stdout, "ACTIVE %d: %s\n", i, zFile);
7748 }else if( p->aAuxDb[i].db!=0 ){
7749 utf8_printf(stdout, " %d: %s\n", i, zFile);
7750 }
7751 }
7752 }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){
7753 int i = azArg[1][0] - '0';
7754 if( p->pAuxDb != &p->aAuxDb[i] && i>=0 && i<ArraySize(p->aAuxDb) ){
7755 p->pAuxDb->db = p->db;
7756 p->pAuxDb = &p->aAuxDb[i];
7757 globalDb = p->db = p->pAuxDb->db;
7758 p->pAuxDb->db = 0;
7759 }
7760 }else if( nArg==3 && strcmp(azArg[1], "close")==0
7761 && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){
7762 int i = azArg[2][0] - '0';
7763 if( i<0 || i>=ArraySize(p->aAuxDb) ){
7764 /* No-op */
7765 }else if( p->pAuxDb == &p->aAuxDb[i] ){
7766 raw_printf(stderr, "cannot close the active database connection\n");
7767 rc = 1;
7768 }else if( p->aAuxDb[i].db ){
7769 session_close_all(p, i);
7770 close_db(p->aAuxDb[i].db);
7771 p->aAuxDb[i].db = 0;
7772 }
7773 }else{
7774 raw_printf(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n");
7775 rc = 1;
7776 }
7777 }else
7778
drh2ce15c32017-07-11 13:34:40 +00007779 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
drh60081a02020-08-26 19:07:18 +00007780 char **azName = 0;
7781 int nName = 0;
7782 sqlite3_stmt *pStmt;
drh60081a02020-08-26 19:07:18 +00007783 int i;
drh2ce15c32017-07-11 13:34:40 +00007784 open_db(p, 0);
drh60081a02020-08-26 19:07:18 +00007785 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
7786 if( rc ){
7787 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh2ce15c32017-07-11 13:34:40 +00007788 rc = 1;
drh60081a02020-08-26 19:07:18 +00007789 }else{
7790 while( sqlite3_step(pStmt)==SQLITE_ROW ){
7791 const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
7792 const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
7793 azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
7794 if( azName==0 ){ shell_out_of_memory(); /* Does not return */ }
7795 azName[nName*2] = strdup(zSchema);
7796 azName[nName*2+1] = strdup(zFile);
7797 nName++;
7798 }
drh2ce15c32017-07-11 13:34:40 +00007799 }
drh60081a02020-08-26 19:07:18 +00007800 sqlite3_finalize(pStmt);
7801 for(i=0; i<nName; i++){
7802 int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
7803 int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
7804 const char *z = azName[i*2+1];
7805 utf8_printf(p->out, "%s: %s %s%s\n",
7806 azName[i*2],
7807 z && z[0] ? z : "\"\"",
7808 bRdonly ? "r/o" : "r/w",
7809 eTxn==SQLITE_TXN_NONE ? "" :
7810 eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
7811 free(azName[i*2]);
7812 free(azName[i*2+1]);
7813 }
7814 sqlite3_free(azName);
drh2ce15c32017-07-11 13:34:40 +00007815 }else
7816
drh7df01192018-04-28 12:43:16 +00007817 if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
drheb7f2a02018-09-26 18:02:32 +00007818 static const struct DbConfigChoices {
7819 const char *zName;
7820 int op;
7821 } aDbConfig[] = {
drhb945bcd2019-12-31 22:52:10 +00007822 { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
7823 { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL },
7824 { "dqs_dml", SQLITE_DBCONFIG_DQS_DML },
drh0a6873b2019-06-14 21:25:25 +00007825 { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
drhb945bcd2019-12-31 22:52:10 +00007826 { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
drh0a6873b2019-06-14 21:25:25 +00007827 { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
drh11d88e62019-08-15 21:27:20 +00007828 { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
drh0a6873b2019-06-14 21:25:25 +00007829 { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
drhb945bcd2019-12-31 22:52:10 +00007830 { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
7831 { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
drh0a6873b2019-06-14 21:25:25 +00007832 { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
7833 { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
drh0a6873b2019-06-14 21:25:25 +00007834 { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
drhb945bcd2019-12-31 22:52:10 +00007835 { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
drhb77da372020-01-07 16:09:11 +00007836 { "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA },
dan07312a62019-06-21 14:05:27 +00007837 { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA },
drh7df01192018-04-28 12:43:16 +00007838 };
7839 int ii, v;
7840 open_db(p, 0);
7841 for(ii=0; ii<ArraySize(aDbConfig); ii++){
7842 if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
7843 if( nArg>=3 ){
7844 sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
7845 }
7846 sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
drhb945bcd2019-12-31 22:52:10 +00007847 utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
drh7df01192018-04-28 12:43:16 +00007848 if( nArg>1 ) break;
7849 }
7850 if( nArg>1 && ii==ArraySize(aDbConfig) ){
7851 utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
7852 utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
7853 }
7854 }else
7855
7856 if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00007857 rc = shell_dbinfo_command(p, nArg, azArg);
7858 }else
7859
dan1b162162019-04-27 20:15:15 +00007860#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00007861 if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){
7862 open_db(p, 0);
danb9b71db2019-04-25 16:20:40 +00007863 rc = recoverDatabaseCmd(p, nArg, azArg);
dan68cb86e2019-04-20 20:57:28 +00007864 }else
dan1b162162019-04-27 20:15:15 +00007865#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
dan68cb86e2019-04-20 20:57:28 +00007866
drh2ce15c32017-07-11 13:34:40 +00007867 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
drh8e9297f2020-03-25 12:50:13 +00007868 char *zLike = 0;
7869 char *zSql;
drh2ce15c32017-07-11 13:34:40 +00007870 int i;
7871 int savedShowHeader = p->showHeader;
drhf213b332018-07-05 17:35:46 +00007872 int savedShellFlags = p->shellFlgs;
drhc1962192020-10-12 16:54:28 +00007873 ShellClearFlag(p,
7874 SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
7875 |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
drh2ce15c32017-07-11 13:34:40 +00007876 for(i=1; i<nArg; i++){
7877 if( azArg[i][0]=='-' ){
7878 const char *z = azArg[i]+1;
7879 if( z[0]=='-' ) z++;
7880 if( strcmp(z,"preserve-rowids")==0 ){
7881#ifdef SQLITE_OMIT_VIRTUALTABLE
7882 raw_printf(stderr, "The --preserve-rowids option is not compatible"
7883 " with SQLITE_OMIT_VIRTUALTABLE\n");
7884 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00007885 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00007886 goto meta_command_exit;
7887#else
7888 ShellSetFlag(p, SHFLG_PreserveRowid);
7889#endif
7890 }else
7891 if( strcmp(z,"newlines")==0 ){
7892 ShellSetFlag(p, SHFLG_Newlines);
7893 }else
drhc1962192020-10-12 16:54:28 +00007894 if( strcmp(z,"data-only")==0 ){
7895 ShellSetFlag(p, SHFLG_DumpDataOnly);
7896 }else
7897 if( strcmp(z,"nosys")==0 ){
7898 ShellSetFlag(p, SHFLG_DumpNoSys);
7899 }else
drh2ce15c32017-07-11 13:34:40 +00007900 {
7901 raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
7902 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00007903 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00007904 goto meta_command_exit;
7905 }
drh2ce15c32017-07-11 13:34:40 +00007906 }else{
dan78a9d752021-05-25 11:39:14 +00007907 /* azArg[i] contains a LIKE pattern. This ".dump" request should
7908 ** only dump data for tables for which either the table name matches
7909 ** the LIKE pattern, or the table appears to be a shadow table of
7910 ** a virtual table for which the name matches the LIKE pattern.
7911 */
7912 char *zExpr = sqlite3_mprintf(
7913 "name LIKE %Q ESCAPE '\\' OR EXISTS ("
7914 " SELECT 1 FROM sqlite_schema WHERE "
7915 " name LIKE %Q ESCAPE '\\' AND"
7916 " sql LIKE 'CREATE VIRTUAL TABLE%%' AND"
7917 " substr(o.name, 1, length(name)+1) == (name||'_')"
7918 ")", azArg[i], azArg[i]
7919 );
7920
7921 if( zLike ){
7922 zLike = sqlite3_mprintf("%z OR %z", zLike, zExpr);
7923 }else{
7924 zLike = zExpr;
7925 }
drh2ce15c32017-07-11 13:34:40 +00007926 }
7927 }
dan68cb86e2019-04-20 20:57:28 +00007928
drh2ce15c32017-07-11 13:34:40 +00007929 open_db(p, 0);
dan68cb86e2019-04-20 20:57:28 +00007930
drhc1962192020-10-12 16:54:28 +00007931 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
7932 /* When playing back a "dump", the content might appear in an order
7933 ** which causes immediate foreign key constraints to be violated.
7934 ** So disable foreign-key constraint enforcement to prevent problems. */
7935 raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
7936 raw_printf(p->out, "BEGIN TRANSACTION;\n");
7937 }
drh2ce15c32017-07-11 13:34:40 +00007938 p->writableSchema = 0;
7939 p->showHeader = 0;
7940 /* Set writable_schema=ON since doing so forces SQLite to initialize
drh067b92b2020-06-19 15:24:12 +00007941 ** as much of the schema as it can even if the sqlite_schema table is
drh2ce15c32017-07-11 13:34:40 +00007942 ** corrupt. */
7943 sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
7944 p->nErr = 0;
drh8e9297f2020-03-25 12:50:13 +00007945 if( zLike==0 ) zLike = sqlite3_mprintf("true");
7946 zSql = sqlite3_mprintf(
dan78a9d752021-05-25 11:39:14 +00007947 "SELECT name, type, sql FROM sqlite_schema AS o "
drh8e9297f2020-03-25 12:50:13 +00007948 "WHERE (%s) AND type=='table'"
7949 " AND sql NOT NULL"
7950 " ORDER BY tbl_name='sqlite_sequence', rowid",
7951 zLike
7952 );
7953 run_schema_dump_query(p,zSql);
7954 sqlite3_free(zSql);
drhc1962192020-10-12 16:54:28 +00007955 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
7956 zSql = sqlite3_mprintf(
dan78a9d752021-05-25 11:39:14 +00007957 "SELECT sql FROM sqlite_schema AS o "
drhc1962192020-10-12 16:54:28 +00007958 "WHERE (%s) AND sql NOT NULL"
7959 " AND type IN ('index','trigger','view')",
7960 zLike
7961 );
7962 run_table_dump_query(p, zSql);
7963 sqlite3_free(zSql);
7964 }
drh8e9297f2020-03-25 12:50:13 +00007965 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00007966 if( p->writableSchema ){
7967 raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
7968 p->writableSchema = 0;
7969 }
7970 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
7971 sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
drhc1962192020-10-12 16:54:28 +00007972 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
7973 raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
7974 }
drh2ce15c32017-07-11 13:34:40 +00007975 p->showHeader = savedShowHeader;
drhf213b332018-07-05 17:35:46 +00007976 p->shellFlgs = savedShellFlags;
drh2ce15c32017-07-11 13:34:40 +00007977 }else
7978
7979 if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
7980 if( nArg==2 ){
7981 setOrClearFlag(p, SHFLG_Echo, azArg[1]);
7982 }else{
7983 raw_printf(stderr, "Usage: .echo on|off\n");
7984 rc = 1;
7985 }
7986 }else
7987
7988 if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
7989 if( nArg==2 ){
drhe2ca99c2018-05-02 00:33:43 +00007990 p->autoEQPtest = 0;
drhb4e50392019-01-26 15:40:04 +00007991 if( p->autoEQPtrace ){
7992 if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
7993 p->autoEQPtrace = 0;
7994 }
drh2ce15c32017-07-11 13:34:40 +00007995 if( strcmp(azArg[1],"full")==0 ){
drhada70452017-12-21 21:02:27 +00007996 p->autoEQP = AUTOEQP_full;
7997 }else if( strcmp(azArg[1],"trigger")==0 ){
7998 p->autoEQP = AUTOEQP_trigger;
drhb4e50392019-01-26 15:40:04 +00007999#ifdef SQLITE_DEBUG
drhe2ca99c2018-05-02 00:33:43 +00008000 }else if( strcmp(azArg[1],"test")==0 ){
8001 p->autoEQP = AUTOEQP_on;
8002 p->autoEQPtest = 1;
drhb4e50392019-01-26 15:40:04 +00008003 }else if( strcmp(azArg[1],"trace")==0 ){
8004 p->autoEQP = AUTOEQP_full;
8005 p->autoEQPtrace = 1;
8006 open_db(p, 0);
drh067b92b2020-06-19 15:24:12 +00008007 sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0);
drhb4e50392019-01-26 15:40:04 +00008008 sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
8009#endif
drh2ce15c32017-07-11 13:34:40 +00008010 }else{
mistachkinb71aa092018-01-23 00:05:18 +00008011 p->autoEQP = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00008012 }
8013 }else{
drhb4e50392019-01-26 15:40:04 +00008014 raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
drh2ce15c32017-07-11 13:34:40 +00008015 rc = 1;
8016 }
8017 }else
8018
8019 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
8020 if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
8021 rc = 2;
8022 }else
8023
8024 /* The ".explain" command is automatic now. It is largely pointless. It
8025 ** retained purely for backwards compatibility */
8026 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
8027 int val = 1;
8028 if( nArg>=2 ){
8029 if( strcmp(azArg[1],"auto")==0 ){
8030 val = 99;
8031 }else{
8032 val = booleanValue(azArg[1]);
8033 }
8034 }
8035 if( val==1 && p->mode!=MODE_Explain ){
8036 p->normalMode = p->mode;
8037 p->mode = MODE_Explain;
8038 p->autoExplain = 0;
8039 }else if( val==0 ){
8040 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
8041 p->autoExplain = 0;
8042 }else if( val==99 ){
8043 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
8044 p->autoExplain = 1;
8045 }
8046 }else
8047
dan6b046be2018-01-09 15:25:55 +00008048#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00008049 if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
8050 open_db(p, 0);
8051 expertDotCommand(p, azArg, nArg);
8052 }else
dan6b046be2018-01-09 15:25:55 +00008053#endif
dan43efc182017-12-19 17:42:13 +00008054
drhd985f722019-06-05 14:29:53 +00008055 if( c=='f' && strncmp(azArg[0], "filectrl", n)==0 ){
8056 static const struct {
8057 const char *zCtrlName; /* Name of a test-control option */
8058 int ctrlCode; /* Integer code for that option */
8059 const char *zUsage; /* Usage notes */
8060 } aCtrl[] = {
drhd985f722019-06-05 14:29:53 +00008061 { "chunk_size", SQLITE_FCNTL_CHUNK_SIZE, "SIZE" },
drh18a4bbd2020-12-17 15:17:42 +00008062 { "data_version", SQLITE_FCNTL_DATA_VERSION, "" },
drhd985f722019-06-05 14:29:53 +00008063 { "has_moved", SQLITE_FCNTL_HAS_MOVED, "" },
8064 { "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" },
drh18a4bbd2020-12-17 15:17:42 +00008065 { "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" },
8066 /* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/
8067 { "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" },
drh541ef2c2020-04-20 16:21:30 +00008068 { "reserve_bytes", SQLITE_FCNTL_RESERVE_BYTES, "[N]" },
drh18a4bbd2020-12-17 15:17:42 +00008069 { "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" },
8070 { "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" },
8071 /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/
drhd985f722019-06-05 14:29:53 +00008072 };
8073 int filectrl = -1;
8074 int iCtrl = -1;
drh4245e042019-06-13 13:52:46 +00008075 sqlite3_int64 iRes = 0; /* Integer result to display if rc2==1 */
8076 int isOk = 0; /* 0: usage 1: %lld 2: no-result */
drhd985f722019-06-05 14:29:53 +00008077 int n2, i;
8078 const char *zCmd = 0;
drh541ef2c2020-04-20 16:21:30 +00008079 const char *zSchema = 0;
drhd985f722019-06-05 14:29:53 +00008080
8081 open_db(p, 0);
8082 zCmd = nArg>=2 ? azArg[1] : "help";
8083
drh541ef2c2020-04-20 16:21:30 +00008084 if( zCmd[0]=='-'
8085 && (strcmp(zCmd,"--schema")==0 || strcmp(zCmd,"-schema")==0)
8086 && nArg>=4
8087 ){
8088 zSchema = azArg[2];
8089 for(i=3; i<nArg; i++) azArg[i-2] = azArg[i];
8090 nArg -= 2;
8091 zCmd = azArg[1];
8092 }
8093
drhd985f722019-06-05 14:29:53 +00008094 /* The argument can optionally begin with "-" or "--" */
8095 if( zCmd[0]=='-' && zCmd[1] ){
8096 zCmd++;
8097 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
8098 }
8099
8100 /* --help lists all file-controls */
8101 if( strcmp(zCmd,"help")==0 ){
8102 utf8_printf(p->out, "Available file-controls:\n");
8103 for(i=0; i<ArraySize(aCtrl); i++){
8104 utf8_printf(p->out, " .filectrl %s %s\n",
8105 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
8106 }
8107 rc = 1;
8108 goto meta_command_exit;
8109 }
8110
8111 /* convert filectrl text option to value. allow any unique prefix
8112 ** of the option name, or a numerical value. */
8113 n2 = strlen30(zCmd);
8114 for(i=0; i<ArraySize(aCtrl); i++){
8115 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
8116 if( filectrl<0 ){
8117 filectrl = aCtrl[i].ctrlCode;
8118 iCtrl = i;
8119 }else{
8120 utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n"
8121 "Use \".filectrl --help\" for help\n", zCmd);
8122 rc = 1;
8123 goto meta_command_exit;
8124 }
8125 }
8126 }
8127 if( filectrl<0 ){
8128 utf8_printf(stderr,"Error: unknown file-control: %s\n"
8129 "Use \".filectrl --help\" for help\n", zCmd);
8130 }else{
8131 switch(filectrl){
8132 case SQLITE_FCNTL_SIZE_LIMIT: {
8133 if( nArg!=2 && nArg!=3 ) break;
8134 iRes = nArg==3 ? integerValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00008135 sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
drhd985f722019-06-05 14:29:53 +00008136 isOk = 1;
8137 break;
8138 }
8139 case SQLITE_FCNTL_LOCK_TIMEOUT:
8140 case SQLITE_FCNTL_CHUNK_SIZE: {
8141 int x;
8142 if( nArg!=3 ) break;
8143 x = (int)integerValue(azArg[2]);
drh541ef2c2020-04-20 16:21:30 +00008144 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008145 isOk = 2;
8146 break;
8147 }
8148 case SQLITE_FCNTL_PERSIST_WAL:
8149 case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
8150 int x;
8151 if( nArg!=2 && nArg!=3 ) break;
8152 x = nArg==3 ? booleanValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00008153 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008154 iRes = x;
8155 isOk = 1;
8156 break;
8157 }
drh18a4bbd2020-12-17 15:17:42 +00008158 case SQLITE_FCNTL_DATA_VERSION:
drhd985f722019-06-05 14:29:53 +00008159 case SQLITE_FCNTL_HAS_MOVED: {
8160 int x;
8161 if( nArg!=2 ) break;
drh541ef2c2020-04-20 16:21:30 +00008162 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008163 iRes = x;
8164 isOk = 1;
8165 break;
8166 }
8167 case SQLITE_FCNTL_TEMPFILENAME: {
8168 char *z = 0;
8169 if( nArg!=2 ) break;
drh541ef2c2020-04-20 16:21:30 +00008170 sqlite3_file_control(p->db, zSchema, filectrl, &z);
drhd985f722019-06-05 14:29:53 +00008171 if( z ){
8172 utf8_printf(p->out, "%s\n", z);
8173 sqlite3_free(z);
8174 }
8175 isOk = 2;
8176 break;
8177 }
drh541ef2c2020-04-20 16:21:30 +00008178 case SQLITE_FCNTL_RESERVE_BYTES: {
8179 int x;
8180 if( nArg>=3 ){
8181 x = atoi(azArg[2]);
8182 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8183 }
8184 x = -1;
8185 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8186 utf8_printf(p->out,"%d\n", x);
8187 isOk = 2;
8188 break;
8189 }
drhd985f722019-06-05 14:29:53 +00008190 }
8191 }
8192 if( isOk==0 && iCtrl>=0 ){
8193 utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
8194 rc = 1;
8195 }else if( isOk==1 ){
drhe2500762019-06-13 14:07:41 +00008196 char zBuf[100];
8197 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
8198 raw_printf(p->out, "%s\n", zBuf);
drhd985f722019-06-05 14:29:53 +00008199 }
8200 }else
8201
drh2ce15c32017-07-11 13:34:40 +00008202 if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
8203 ShellState data;
drh2ce15c32017-07-11 13:34:40 +00008204 int doStats = 0;
8205 memcpy(&data, p, sizeof(data));
8206 data.showHeader = 0;
8207 data.cMode = data.mode = MODE_Semi;
8208 if( nArg==2 && optionMatch(azArg[1], "indent") ){
8209 data.cMode = data.mode = MODE_Pretty;
8210 nArg = 1;
8211 }
8212 if( nArg!=1 ){
8213 raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
8214 rc = 1;
8215 goto meta_command_exit;
8216 }
8217 open_db(p, 0);
8218 rc = sqlite3_exec(p->db,
8219 "SELECT sql FROM"
8220 " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
drh067b92b2020-06-19 15:24:12 +00008221 " FROM sqlite_schema UNION ALL"
8222 " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
drh2ce15c32017-07-11 13:34:40 +00008223 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
drh69935c02021-06-25 11:14:10 +00008224 "ORDER BY x",
drhf83d5012021-05-03 13:35:00 +00008225 callback, &data, 0
drh2ce15c32017-07-11 13:34:40 +00008226 );
8227 if( rc==SQLITE_OK ){
8228 sqlite3_stmt *pStmt;
8229 rc = sqlite3_prepare_v2(p->db,
drh067b92b2020-06-19 15:24:12 +00008230 "SELECT rowid FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00008231 " WHERE name GLOB 'sqlite_stat[134]'",
8232 -1, &pStmt, 0);
8233 doStats = sqlite3_step(pStmt)==SQLITE_ROW;
8234 sqlite3_finalize(pStmt);
8235 }
8236 if( doStats==0 ){
8237 raw_printf(p->out, "/* No STAT tables available */\n");
8238 }else{
drh067b92b2020-06-19 15:24:12 +00008239 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00008240 data.cMode = data.mode = MODE_Insert;
8241 data.zDestTable = "sqlite_stat1";
drhf83d5012021-05-03 13:35:00 +00008242 shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
drh2ce15c32017-07-11 13:34:40 +00008243 data.zDestTable = "sqlite_stat4";
drhf83d5012021-05-03 13:35:00 +00008244 shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
drh067b92b2020-06-19 15:24:12 +00008245 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00008246 }
8247 }else
8248
8249 if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
8250 if( nArg==2 ){
8251 p->showHeader = booleanValue(azArg[1]);
drhc0605082020-06-05 00:54:27 +00008252 p->shellFlgs |= SHFLG_HeaderSet;
drh2ce15c32017-07-11 13:34:40 +00008253 }else{
8254 raw_printf(stderr, "Usage: .headers on|off\n");
8255 rc = 1;
8256 }
8257 }else
8258
8259 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
drh98aa2ab2018-09-26 16:53:51 +00008260 if( nArg>=2 ){
drhe93f8262018-10-11 16:53:37 +00008261 n = showHelp(p->out, azArg[1]);
drh98aa2ab2018-09-26 16:53:51 +00008262 if( n==0 ){
8263 utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
8264 }
8265 }else{
8266 showHelp(p->out, 0);
8267 }
drh2ce15c32017-07-11 13:34:40 +00008268 }else
8269
8270 if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
drhccb37812020-03-09 15:39:39 +00008271 char *zTable = 0; /* Insert data into this table */
8272 char *zFile = 0; /* Name of file to extra content from */
drh2ce15c32017-07-11 13:34:40 +00008273 sqlite3_stmt *pStmt = NULL; /* A statement */
8274 int nCol; /* Number of columns in the table */
8275 int nByte; /* Number of bytes in an SQL string */
8276 int i, j; /* Loop counters */
8277 int needCommit; /* True to COMMIT or ROLLBACK at end */
8278 int nSep; /* Number of bytes in p->colSeparator[] */
8279 char *zSql; /* An SQL statement */
8280 ImportCtx sCtx; /* Reader context */
8281 char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
drhccb37812020-03-09 15:39:39 +00008282 int eVerbose = 0; /* Larger for more console output */
8283 int nSkip = 0; /* Initial lines to skip */
8284 int useOutputMode = 1; /* Use output mode to determine separators */
drh2ce15c32017-07-11 13:34:40 +00008285
drhb97e2ad2021-08-26 18:31:39 +00008286 failIfSafeMode(p, "cannot run .import in safe mode");
drhccb37812020-03-09 15:39:39 +00008287 memset(&sCtx, 0, sizeof(sCtx));
8288 if( p->mode==MODE_Ascii ){
8289 xRead = ascii_read_one_field;
8290 }else{
8291 xRead = csv_read_one_field;
8292 }
8293 for(i=1; i<nArg; i++){
8294 char *z = azArg[i];
8295 if( z[0]=='-' && z[1]=='-' ) z++;
8296 if( z[0]!='-' ){
8297 if( zFile==0 ){
8298 zFile = z;
8299 }else if( zTable==0 ){
8300 zTable = z;
8301 }else{
8302 utf8_printf(p->out, "ERROR: extra argument: \"%s\". Usage:\n", z);
8303 showHelp(p->out, "import");
8304 rc = 1;
8305 goto meta_command_exit;
8306 }
8307 }else if( strcmp(z,"-v")==0 ){
8308 eVerbose++;
8309 }else if( strcmp(z,"-skip")==0 && i<nArg-1 ){
8310 nSkip = integerValue(azArg[++i]);
8311 }else if( strcmp(z,"-ascii")==0 ){
8312 sCtx.cColSep = SEP_Unit[0];
8313 sCtx.cRowSep = SEP_Record[0];
8314 xRead = ascii_read_one_field;
8315 useOutputMode = 0;
8316 }else if( strcmp(z,"-csv")==0 ){
8317 sCtx.cColSep = ',';
8318 sCtx.cRowSep = '\n';
8319 xRead = csv_read_one_field;
8320 useOutputMode = 0;
8321 }else{
8322 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", z);
8323 showHelp(p->out, "import");
8324 rc = 1;
8325 goto meta_command_exit;
8326 }
8327 }
8328 if( zTable==0 ){
8329 utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
8330 zFile==0 ? "FILE" : "TABLE");
8331 showHelp(p->out, "import");
8332 rc = 1;
drh2ce15c32017-07-11 13:34:40 +00008333 goto meta_command_exit;
8334 }
drh2ce15c32017-07-11 13:34:40 +00008335 seenInterrupt = 0;
drh2ce15c32017-07-11 13:34:40 +00008336 open_db(p, 0);
drhccb37812020-03-09 15:39:39 +00008337 if( useOutputMode ){
8338 /* If neither the --csv or --ascii options are specified, then set
8339 ** the column and row separator characters from the output mode. */
8340 nSep = strlen30(p->colSeparator);
8341 if( nSep==0 ){
8342 raw_printf(stderr,
8343 "Error: non-null column separator required for import\n");
8344 rc = 1;
8345 goto meta_command_exit;
8346 }
8347 if( nSep>1 ){
8348 raw_printf(stderr,
8349 "Error: multi-character column separators not allowed"
8350 " for import\n");
8351 rc = 1;
8352 goto meta_command_exit;
8353 }
drh2ce15c32017-07-11 13:34:40 +00008354 nSep = strlen30(p->rowSeparator);
drhccb37812020-03-09 15:39:39 +00008355 if( nSep==0 ){
8356 raw_printf(stderr,
8357 "Error: non-null row separator required for import\n");
8358 rc = 1;
8359 goto meta_command_exit;
8360 }
8361 if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator,SEP_CrLf)==0 ){
8362 /* When importing CSV (only), if the row separator is set to the
8363 ** default output row separator, change it to the default input
8364 ** row separator. This avoids having to maintain different input
8365 ** and output row separators. */
8366 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8367 nSep = strlen30(p->rowSeparator);
8368 }
8369 if( nSep>1 ){
8370 raw_printf(stderr, "Error: multi-character row separators not allowed"
8371 " for import\n");
8372 rc = 1;
8373 goto meta_command_exit;
8374 }
8375 sCtx.cColSep = p->colSeparator[0];
8376 sCtx.cRowSep = p->rowSeparator[0];
drh2ce15c32017-07-11 13:34:40 +00008377 }
8378 sCtx.zFile = zFile;
8379 sCtx.nLine = 1;
8380 if( sCtx.zFile[0]=='|' ){
8381#ifdef SQLITE_OMIT_POPEN
8382 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
drhccb37812020-03-09 15:39:39 +00008383 rc = 1;
8384 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008385#else
8386 sCtx.in = popen(sCtx.zFile+1, "r");
8387 sCtx.zFile = "<pipe>";
drh97767842020-05-29 19:39:35 +00008388 sCtx.xCloser = pclose;
drh2ce15c32017-07-11 13:34:40 +00008389#endif
8390 }else{
8391 sCtx.in = fopen(sCtx.zFile, "rb");
drh97767842020-05-29 19:39:35 +00008392 sCtx.xCloser = fclose;
drh2ce15c32017-07-11 13:34:40 +00008393 }
drh2ce15c32017-07-11 13:34:40 +00008394 if( sCtx.in==0 ){
8395 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
drhccb37812020-03-09 15:39:39 +00008396 rc = 1;
8397 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008398 }
drhccb37812020-03-09 15:39:39 +00008399 if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
8400 char zSep[2];
8401 zSep[1] = 0;
8402 zSep[0] = sCtx.cColSep;
8403 utf8_printf(p->out, "Column separator ");
8404 output_c_string(p->out, zSep);
8405 utf8_printf(p->out, ", row separator ");
8406 zSep[0] = sCtx.cRowSep;
8407 output_c_string(p->out, zSep);
8408 utf8_printf(p->out, "\n");
8409 }
8410 while( (nSkip--)>0 ){
8411 while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
drhccb37812020-03-09 15:39:39 +00008412 }
drhc6712642020-10-12 17:57:29 +00008413 zSql = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
drh2ce15c32017-07-11 13:34:40 +00008414 if( zSql==0 ){
drh97767842020-05-29 19:39:35 +00008415 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00008416 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00008417 }
8418 nByte = strlen30(zSql);
8419 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8420 import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
8421 if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
drhc6712642020-10-12 17:57:29 +00008422 char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"", zTable);
drh2ce15c32017-07-11 13:34:40 +00008423 char cSep = '(';
8424 while( xRead(&sCtx) ){
8425 zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z);
8426 cSep = ',';
8427 if( sCtx.cTerm!=sCtx.cColSep ) break;
8428 }
8429 if( cSep=='(' ){
8430 sqlite3_free(zCreate);
drh97767842020-05-29 19:39:35 +00008431 import_cleanup(&sCtx);
drh2ce15c32017-07-11 13:34:40 +00008432 utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
drhccb37812020-03-09 15:39:39 +00008433 rc = 1;
8434 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008435 }
8436 zCreate = sqlite3_mprintf("%z\n)", zCreate);
drhccb37812020-03-09 15:39:39 +00008437 if( eVerbose>=1 ){
8438 utf8_printf(p->out, "%s\n", zCreate);
8439 }
drh2ce15c32017-07-11 13:34:40 +00008440 rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
8441 sqlite3_free(zCreate);
8442 if( rc ){
drhc6712642020-10-12 17:57:29 +00008443 utf8_printf(stderr, "CREATE TABLE \"%s\"(...) failed: %s\n", zTable,
drh2ce15c32017-07-11 13:34:40 +00008444 sqlite3_errmsg(p->db));
drh97767842020-05-29 19:39:35 +00008445 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008446 rc = 1;
8447 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008448 }
8449 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8450 }
8451 sqlite3_free(zSql);
8452 if( rc ){
8453 if (pStmt) sqlite3_finalize(pStmt);
8454 utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
drh97767842020-05-29 19:39:35 +00008455 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008456 rc = 1;
8457 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008458 }
8459 nCol = sqlite3_column_count(pStmt);
8460 sqlite3_finalize(pStmt);
8461 pStmt = 0;
8462 if( nCol==0 ) return 0; /* no columns, no error */
8463 zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
8464 if( zSql==0 ){
drh97767842020-05-29 19:39:35 +00008465 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00008466 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00008467 }
8468 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
8469 j = strlen30(zSql);
8470 for(i=1; i<nCol; i++){
8471 zSql[j++] = ',';
8472 zSql[j++] = '?';
8473 }
8474 zSql[j++] = ')';
8475 zSql[j] = 0;
drhccb37812020-03-09 15:39:39 +00008476 if( eVerbose>=2 ){
8477 utf8_printf(p->out, "Insert using: %s\n", zSql);
8478 }
drh2ce15c32017-07-11 13:34:40 +00008479 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8480 sqlite3_free(zSql);
8481 if( rc ){
8482 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
8483 if (pStmt) sqlite3_finalize(pStmt);
drh97767842020-05-29 19:39:35 +00008484 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008485 rc = 1;
8486 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008487 }
8488 needCommit = sqlite3_get_autocommit(p->db);
8489 if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
8490 do{
8491 int startLine = sCtx.nLine;
8492 for(i=0; i<nCol; i++){
8493 char *z = xRead(&sCtx);
8494 /*
8495 ** Did we reach end-of-file before finding any columns?
8496 ** If so, stop instead of NULL filling the remaining columns.
8497 */
8498 if( z==0 && i==0 ) break;
8499 /*
8500 ** Did we reach end-of-file OR end-of-line before finding any
8501 ** columns in ASCII mode? If so, stop instead of NULL filling
8502 ** the remaining columns.
8503 */
8504 if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
8505 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
8506 if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
8507 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
8508 "filling the rest with NULL\n",
8509 sCtx.zFile, startLine, nCol, i+1);
8510 i += 2;
8511 while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
8512 }
8513 }
8514 if( sCtx.cTerm==sCtx.cColSep ){
8515 do{
8516 xRead(&sCtx);
8517 i++;
8518 }while( sCtx.cTerm==sCtx.cColSep );
8519 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
8520 "extras ignored\n",
8521 sCtx.zFile, startLine, nCol, i);
8522 }
8523 if( i>=nCol ){
8524 sqlite3_step(pStmt);
8525 rc = sqlite3_reset(pStmt);
8526 if( rc!=SQLITE_OK ){
8527 utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
8528 startLine, sqlite3_errmsg(p->db));
drhccb37812020-03-09 15:39:39 +00008529 sCtx.nErr++;
8530 }else{
8531 sCtx.nRow++;
drh2ce15c32017-07-11 13:34:40 +00008532 }
8533 }
8534 }while( sCtx.cTerm!=EOF );
8535
drh97767842020-05-29 19:39:35 +00008536 import_cleanup(&sCtx);
drh2ce15c32017-07-11 13:34:40 +00008537 sqlite3_finalize(pStmt);
8538 if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
drhccb37812020-03-09 15:39:39 +00008539 if( eVerbose>0 ){
8540 utf8_printf(p->out,
8541 "Added %d rows with %d errors using %d lines of input\n",
8542 sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
8543 }
drh2ce15c32017-07-11 13:34:40 +00008544 }else
8545
8546#ifndef SQLITE_UNTESTABLE
8547 if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
8548 char *zSql;
8549 char *zCollist = 0;
8550 sqlite3_stmt *pStmt;
8551 int tnum = 0;
drh491c5be2019-10-18 15:58:50 +00008552 int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */
8553 int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
drh2ce15c32017-07-11 13:34:40 +00008554 int i;
drh48d219a2018-04-23 18:38:48 +00008555 if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
8556 utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
8557 " .imposter off\n");
drh491c5be2019-10-18 15:58:50 +00008558 /* Also allowed, but not documented:
8559 **
8560 ** .imposter TABLE IMPOSTER
8561 **
8562 ** where TABLE is a WITHOUT ROWID table. In that case, the
8563 ** imposter is another WITHOUT ROWID table with the columns in
8564 ** storage order. */
drh2ce15c32017-07-11 13:34:40 +00008565 rc = 1;
8566 goto meta_command_exit;
8567 }
8568 open_db(p, 0);
drh48d219a2018-04-23 18:38:48 +00008569 if( nArg==2 ){
8570 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
8571 goto meta_command_exit;
8572 }
drh491c5be2019-10-18 15:58:50 +00008573 zSql = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00008574 "SELECT rootpage, 0 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00008575 " WHERE name='%q' AND type='index'"
8576 "UNION ALL "
drh067b92b2020-06-19 15:24:12 +00008577 "SELECT rootpage, 1 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00008578 " WHERE name='%q' AND type='table'"
8579 " AND sql LIKE '%%without%%rowid%%'",
8580 azArg[1], azArg[1]
8581 );
drh2ce15c32017-07-11 13:34:40 +00008582 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8583 sqlite3_free(zSql);
8584 if( sqlite3_step(pStmt)==SQLITE_ROW ){
8585 tnum = sqlite3_column_int(pStmt, 0);
drh491c5be2019-10-18 15:58:50 +00008586 isWO = sqlite3_column_int(pStmt, 1);
drh2ce15c32017-07-11 13:34:40 +00008587 }
8588 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00008589 zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
8590 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8591 sqlite3_free(zSql);
8592 i = 0;
8593 while( sqlite3_step(pStmt)==SQLITE_ROW ){
8594 char zLabel[20];
8595 const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
8596 i++;
8597 if( zCol==0 ){
8598 if( sqlite3_column_int(pStmt,1)==-1 ){
8599 zCol = "_ROWID_";
8600 }else{
8601 sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
8602 zCol = zLabel;
8603 }
8604 }
drh491c5be2019-10-18 15:58:50 +00008605 if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){
8606 lenPK = (int)strlen(zCollist);
8607 }
drh2ce15c32017-07-11 13:34:40 +00008608 if( zCollist==0 ){
8609 zCollist = sqlite3_mprintf("\"%w\"", zCol);
8610 }else{
8611 zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
8612 }
8613 }
8614 sqlite3_finalize(pStmt);
drh491c5be2019-10-18 15:58:50 +00008615 if( i==0 || tnum==0 ){
8616 utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
8617 rc = 1;
8618 sqlite3_free(zCollist);
8619 goto meta_command_exit;
8620 }
8621 if( lenPK==0 ) lenPK = 100000;
drh2ce15c32017-07-11 13:34:40 +00008622 zSql = sqlite3_mprintf(
drh491c5be2019-10-18 15:58:50 +00008623 "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
8624 azArg[2], zCollist, lenPK, zCollist);
drh2ce15c32017-07-11 13:34:40 +00008625 sqlite3_free(zCollist);
8626 rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
8627 if( rc==SQLITE_OK ){
8628 rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
8629 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
8630 if( rc ){
8631 utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
8632 }else{
8633 utf8_printf(stdout, "%s;\n", zSql);
8634 raw_printf(stdout,
drh491c5be2019-10-18 15:58:50 +00008635 "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
8636 azArg[1], isWO ? "table" : "index"
drh2ce15c32017-07-11 13:34:40 +00008637 );
8638 }
8639 }else{
8640 raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
8641 rc = 1;
8642 }
8643 sqlite3_free(zSql);
8644 }else
8645#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
8646
8647#ifdef SQLITE_ENABLE_IOTRACE
8648 if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
8649 SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
8650 if( iotrace && iotrace!=stdout ) fclose(iotrace);
8651 iotrace = 0;
8652 if( nArg<2 ){
8653 sqlite3IoTrace = 0;
8654 }else if( strcmp(azArg[1], "-")==0 ){
8655 sqlite3IoTrace = iotracePrintf;
8656 iotrace = stdout;
8657 }else{
8658 iotrace = fopen(azArg[1], "w");
8659 if( iotrace==0 ){
8660 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
8661 sqlite3IoTrace = 0;
8662 rc = 1;
8663 }else{
8664 sqlite3IoTrace = iotracePrintf;
8665 }
8666 }
8667 }else
8668#endif
8669
8670 if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
8671 static const struct {
8672 const char *zLimitName; /* Name of a limit */
8673 int limitCode; /* Integer code for that limit */
8674 } aLimit[] = {
8675 { "length", SQLITE_LIMIT_LENGTH },
8676 { "sql_length", SQLITE_LIMIT_SQL_LENGTH },
8677 { "column", SQLITE_LIMIT_COLUMN },
8678 { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
8679 { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
8680 { "vdbe_op", SQLITE_LIMIT_VDBE_OP },
8681 { "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
8682 { "attached", SQLITE_LIMIT_ATTACHED },
8683 { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
8684 { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER },
8685 { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
8686 { "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
8687 };
8688 int i, n2;
8689 open_db(p, 0);
8690 if( nArg==1 ){
8691 for(i=0; i<ArraySize(aLimit); i++){
8692 printf("%20s %d\n", aLimit[i].zLimitName,
8693 sqlite3_limit(p->db, aLimit[i].limitCode, -1));
8694 }
8695 }else if( nArg>3 ){
8696 raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
8697 rc = 1;
8698 goto meta_command_exit;
8699 }else{
8700 int iLimit = -1;
8701 n2 = strlen30(azArg[1]);
8702 for(i=0; i<ArraySize(aLimit); i++){
8703 if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
8704 if( iLimit<0 ){
8705 iLimit = i;
8706 }else{
8707 utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
8708 rc = 1;
8709 goto meta_command_exit;
8710 }
8711 }
8712 }
8713 if( iLimit<0 ){
8714 utf8_printf(stderr, "unknown limit: \"%s\"\n"
8715 "enter \".limits\" with no arguments for a list.\n",
8716 azArg[1]);
8717 rc = 1;
8718 goto meta_command_exit;
8719 }
8720 if( nArg==3 ){
8721 sqlite3_limit(p->db, aLimit[iLimit].limitCode,
8722 (int)integerValue(azArg[2]));
8723 }
8724 printf("%20s %d\n", aLimit[iLimit].zLimitName,
8725 sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
8726 }
8727 }else
8728
8729 if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
8730 open_db(p, 0);
8731 lintDotCommand(p, azArg, nArg);
8732 }else
8733
8734#ifndef SQLITE_OMIT_LOAD_EXTENSION
8735 if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
8736 const char *zFile, *zProc;
8737 char *zErrMsg = 0;
drhb97e2ad2021-08-26 18:31:39 +00008738 failIfSafeMode(p, "cannot run .load in safe mode");
drh2ce15c32017-07-11 13:34:40 +00008739 if( nArg<2 ){
8740 raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
8741 rc = 1;
8742 goto meta_command_exit;
8743 }
8744 zFile = azArg[1];
8745 zProc = nArg>=3 ? azArg[2] : 0;
8746 open_db(p, 0);
8747 rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
8748 if( rc!=SQLITE_OK ){
8749 utf8_printf(stderr, "Error: %s\n", zErrMsg);
8750 sqlite3_free(zErrMsg);
8751 rc = 1;
8752 }
8753 }else
8754#endif
8755
8756 if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
drhb97e2ad2021-08-26 18:31:39 +00008757 failIfSafeMode(p, "cannot run .log in safe mode");
drh2ce15c32017-07-11 13:34:40 +00008758 if( nArg!=2 ){
8759 raw_printf(stderr, "Usage: .log FILENAME\n");
8760 rc = 1;
8761 }else{
8762 const char *zFile = azArg[1];
8763 output_file_close(p->pLog);
drha92a01a2018-01-10 22:15:37 +00008764 p->pLog = output_file_open(zFile, 0);
drh2ce15c32017-07-11 13:34:40 +00008765 }
8766 }else
8767
8768 if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
8769 const char *zMode = nArg>=2 ? azArg[1] : "";
drhaf2770f2018-01-05 14:55:43 +00008770 int n2 = strlen30(zMode);
drh2ce15c32017-07-11 13:34:40 +00008771 int c2 = zMode[0];
8772 if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){
8773 p->mode = MODE_Line;
8774 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8775 }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
8776 p->mode = MODE_Column;
drhc0605082020-06-05 00:54:27 +00008777 if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){
8778 p->showHeader = 1;
8779 }
drh2ce15c32017-07-11 13:34:40 +00008780 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8781 }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
8782 p->mode = MODE_List;
8783 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
8784 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8785 }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){
8786 p->mode = MODE_Html;
8787 }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
8788 p->mode = MODE_Tcl;
8789 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
8790 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8791 }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
8792 p->mode = MODE_Csv;
8793 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
8794 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
8795 }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
8796 p->mode = MODE_List;
8797 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
8798 }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
8799 p->mode = MODE_Insert;
8800 set_table_name(p, nArg>=3 ? azArg[2] : "table");
8801 }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
8802 p->mode = MODE_Quote;
drhc6835732020-05-28 20:37:17 +00008803 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
8804 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +00008805 }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
8806 p->mode = MODE_Ascii;
8807 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
8808 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
drh30c54a02020-05-28 23:49:50 +00008809 }else if( c2=='m' && strncmp(azArg[1],"markdown",n2)==0 ){
8810 p->mode = MODE_Markdown;
8811 }else if( c2=='t' && strncmp(azArg[1],"table",n2)==0 ){
8812 p->mode = MODE_Table;
drh0908e382020-06-04 18:05:39 +00008813 }else if( c2=='b' && strncmp(azArg[1],"box",n2)==0 ){
8814 p->mode = MODE_Box;
drh30c54a02020-05-28 23:49:50 +00008815 }else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){
8816 p->mode = MODE_Json;
drh2ce15c32017-07-11 13:34:40 +00008817 }else if( nArg==1 ){
8818 raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
8819 }else{
8820 raw_printf(stderr, "Error: mode should be one of: "
drh0908e382020-06-04 18:05:39 +00008821 "ascii box column csv html insert json line list markdown "
drh30c54a02020-05-28 23:49:50 +00008822 "quote table tabs tcl\n");
drh2ce15c32017-07-11 13:34:40 +00008823 rc = 1;
8824 }
8825 p->cMode = p->mode;
8826 }else
8827
drhb97e2ad2021-08-26 18:31:39 +00008828 if( c=='n' && strcmp(azArg[0], "nonce")==0 ){
8829 if( nArg!=2 ){
8830 raw_printf(stderr, "Usage: .nonce NONCE\n");
8831 rc = 1;
8832 }else if( p->zNonce==0 || strcmp(azArg[1],p->zNonce)!=0 ){
8833 raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n", p->lineno, azArg[1]);
8834 exit(1);
8835 }
8836 p->bSafeMode = 0;
8837 return 0; /* Return immediately to bypass the safe mode reset
8838 ** at the end of this procedure */
8839 }else
8840
drh2ce15c32017-07-11 13:34:40 +00008841 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
8842 if( nArg==2 ){
8843 sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
8844 "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
8845 }else{
8846 raw_printf(stderr, "Usage: .nullvalue STRING\n");
8847 rc = 1;
8848 }
8849 }else
8850
drh4a3a3eb2020-02-29 15:53:48 +00008851#ifdef SQLITE_DEBUG
8852 if( c=='o' && strcmp(azArg[0],"oom")==0 ){
8853 int i;
8854 for(i=1; i<nArg; i++){
8855 const char *z = azArg[i];
8856 if( z[0]=='-' && z[1]=='-' ) z++;
8857 if( strcmp(z,"-repeat")==0 ){
8858 if( i==nArg-1 ){
8859 raw_printf(p->out, "missing argument on \"%s\"\n", azArg[i]);
8860 rc = 1;
8861 }else{
8862 oomRepeat = (int)integerValue(azArg[++i]);
8863 }
8864 }else if( IsDigit(z[0]) ){
8865 oomCounter = (int)integerValue(azArg[i]);
8866 }else{
8867 raw_printf(p->out, "unknown argument: \"%s\"\n", azArg[i]);
8868 raw_printf(p->out, "Usage: .oom [--repeat N] [M]\n");
8869 rc = 1;
8870 }
8871 }
8872 if( rc==0 ){
8873 raw_printf(p->out, "oomCounter = %d\n", oomCounter);
8874 raw_printf(p->out, "oomRepeat = %d\n", oomRepeat);
8875 }
8876 }else
8877#endif /* SQLITE_DEBUG */
8878
drh2ce15c32017-07-11 13:34:40 +00008879 if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
drhf30bbce2020-12-02 18:27:48 +00008880 char *zNewFilename = 0; /* Name of the database file to open */
8881 int iName = 1; /* Index in azArg[] of the filename */
8882 int newFlag = 0; /* True to delete file before opening */
drh2ce15c32017-07-11 13:34:40 +00008883 /* Close the existing database */
drh37407122021-07-23 18:43:58 +00008884 session_close_all(p, -1);
drh9e804032018-05-18 17:11:50 +00008885 close_db(p->db);
drh2ce15c32017-07-11 13:34:40 +00008886 p->db = 0;
drh37407122021-07-23 18:43:58 +00008887 p->pAuxDb->zDbFilename = 0;
8888 sqlite3_free(p->pAuxDb->zFreeOnClose);
8889 p->pAuxDb->zFreeOnClose = 0;
drh1fa6d9f2018-01-06 21:46:01 +00008890 p->openMode = SHELL_OPEN_UNSPEC;
drh0933aad2019-11-18 17:46:38 +00008891 p->openFlags = 0;
drh6ca64482019-01-22 16:06:20 +00008892 p->szMax = 0;
drh2ce15c32017-07-11 13:34:40 +00008893 /* Check for command-line arguments */
drhf30bbce2020-12-02 18:27:48 +00008894 for(iName=1; iName<nArg; iName++){
drh2ce15c32017-07-11 13:34:40 +00008895 const char *z = azArg[iName];
8896 if( optionMatch(z,"new") ){
8897 newFlag = 1;
drh3baed312018-03-08 18:14:41 +00008898#ifdef SQLITE_HAVE_ZLIB
drh1fa6d9f2018-01-06 21:46:01 +00008899 }else if( optionMatch(z, "zip") ){
8900 p->openMode = SHELL_OPEN_ZIPFILE;
8901#endif
8902 }else if( optionMatch(z, "append") ){
8903 p->openMode = SHELL_OPEN_APPENDVFS;
drhee269a62018-02-14 23:27:43 +00008904 }else if( optionMatch(z, "readonly") ){
8905 p->openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +00008906 }else if( optionMatch(z, "nofollow") ){
8907 p->openFlags |= SQLITE_OPEN_NOFOLLOW;
drhdff34ab2021-06-24 18:23:54 +00008908 }else if( optionMatch(z, "excl") ){
8909 p->openFlags |= SQLITE_OPEN_EXCLUSIVE;
drh8d889af2021-05-08 17:18:23 +00008910#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +00008911 }else if( optionMatch(z, "deserialize") ){
8912 p->openMode = SHELL_OPEN_DESERIALIZE;
drh33746482018-12-13 15:06:26 +00008913 }else if( optionMatch(z, "hexdb") ){
8914 p->openMode = SHELL_OPEN_HEXDB;
drh6ca64482019-01-22 16:06:20 +00008915 }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
8916 p->szMax = integerValue(azArg[++iName]);
drh8d889af2021-05-08 17:18:23 +00008917#endif /* SQLITE_OMIT_DESERIALIZE */
drh2ce15c32017-07-11 13:34:40 +00008918 }else if( z[0]=='-' ){
8919 utf8_printf(stderr, "unknown option: %s\n", z);
8920 rc = 1;
8921 goto meta_command_exit;
drhf30bbce2020-12-02 18:27:48 +00008922 }else if( zNewFilename ){
8923 utf8_printf(stderr, "extra argument: \"%s\"\n", z);
8924 rc = 1;
8925 goto meta_command_exit;
8926 }else{
8927 zNewFilename = sqlite3_mprintf("%s", z);
drh2ce15c32017-07-11 13:34:40 +00008928 }
8929 }
8930 /* If a filename is specified, try to open it first */
drh33746482018-12-13 15:06:26 +00008931 if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
drhb97e2ad2021-08-26 18:31:39 +00008932 if( newFlag && !p->bSafeMode ) shellDeleteFile(zNewFilename);
8933 if( p->bSafeMode
8934 && p->openMode!=SHELL_OPEN_HEXDB
8935 && zNewFilename
8936 && strcmp(zNewFilename,":memory:")!=0
8937 ){
8938 failIfSafeMode(p, "cannot open disk-based database files in safe mode");
8939 }
drh37407122021-07-23 18:43:58 +00008940 p->pAuxDb->zDbFilename = zNewFilename;
drhbe4ccb22018-05-17 20:04:24 +00008941 open_db(p, OPEN_DB_KEEPALIVE);
drh2ce15c32017-07-11 13:34:40 +00008942 if( p->db==0 ){
8943 utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
8944 sqlite3_free(zNewFilename);
8945 }else{
drh37407122021-07-23 18:43:58 +00008946 p->pAuxDb->zFreeOnClose = zNewFilename;
drh2ce15c32017-07-11 13:34:40 +00008947 }
8948 }
8949 if( p->db==0 ){
8950 /* As a fall-back open a TEMP database */
drh37407122021-07-23 18:43:58 +00008951 p->pAuxDb->zDbFilename = 0;
drh2ce15c32017-07-11 13:34:40 +00008952 open_db(p, 0);
8953 }
8954 }else
8955
drh13c20932018-01-10 21:41:55 +00008956 if( (c=='o'
8957 && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
8958 || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
drh2ce15c32017-07-11 13:34:40 +00008959 ){
drh4b0229a2021-02-17 13:19:22 +00008960 char *zFile = 0;
drha92a01a2018-01-10 22:15:37 +00008961 int bTxtMode = 0;
drh7a431002020-04-18 14:12:00 +00008962 int i;
8963 int eMode = 0;
8964 int bBOM = 0;
drh5415ab42020-04-23 20:45:46 +00008965 int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */
drh7a431002020-04-18 14:12:00 +00008966
drhb97e2ad2021-08-26 18:31:39 +00008967 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh7a431002020-04-18 14:12:00 +00008968 if( c=='e' ){
8969 eMode = 'x';
8970 bOnce = 2;
8971 }else if( strncmp(azArg[0],"once",n)==0 ){
8972 bOnce = 1;
drh13c20932018-01-10 21:41:55 +00008973 }
drh7a431002020-04-18 14:12:00 +00008974 for(i=1; i<nArg; i++){
8975 char *z = azArg[i];
8976 if( z[0]=='-' ){
8977 if( z[1]=='-' ) z++;
8978 if( strcmp(z,"-bom")==0 ){
8979 bBOM = 1;
8980 }else if( c!='e' && strcmp(z,"-x")==0 ){
8981 eMode = 'x'; /* spreadsheet */
8982 }else if( c!='e' && strcmp(z,"-e")==0 ){
8983 eMode = 'e'; /* text editor */
8984 }else{
8985 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n",
8986 azArg[i]);
8987 showHelp(p->out, azArg[0]);
8988 rc = 1;
8989 goto meta_command_exit;
8990 }
drh4b0229a2021-02-17 13:19:22 +00008991 }else if( zFile==0 && eMode!='e' && eMode!='x' ){
8992 zFile = sqlite3_mprintf("%s", z);
8993 if( zFile[0]=='|' ){
8994 while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]);
8995 break;
8996 }
drh7a431002020-04-18 14:12:00 +00008997 }else{
8998 utf8_printf(p->out,"ERROR: extra parameter: \"%s\". Usage:\n",
8999 azArg[i]);
9000 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00009001 rc = 1;
drh4b0229a2021-02-17 13:19:22 +00009002 sqlite3_free(zFile);
drh2ce15c32017-07-11 13:34:40 +00009003 goto meta_command_exit;
9004 }
drh7a431002020-04-18 14:12:00 +00009005 }
drh4b0229a2021-02-17 13:19:22 +00009006 if( zFile==0 ) zFile = sqlite3_mprintf("stdout");
drh7a431002020-04-18 14:12:00 +00009007 if( bOnce ){
drh2ce15c32017-07-11 13:34:40 +00009008 p->outCount = 2;
9009 }else{
9010 p->outCount = 0;
9011 }
9012 output_reset(p);
drh04a28c32018-01-31 01:38:44 +00009013#ifndef SQLITE_NOHAVE_SYSTEM
drh7a431002020-04-18 14:12:00 +00009014 if( eMode=='e' || eMode=='x' ){
drh3c484e82018-01-10 22:27:21 +00009015 p->doXdgOpen = 1;
9016 outputModePush(p);
drh7a431002020-04-18 14:12:00 +00009017 if( eMode=='x' ){
9018 /* spreadsheet mode. Output as CSV. */
drh13c20932018-01-10 21:41:55 +00009019 newTempFile(p, "csv");
drh7a431002020-04-18 14:12:00 +00009020 ShellClearFlag(p, SHFLG_Echo);
drh13c20932018-01-10 21:41:55 +00009021 p->mode = MODE_Csv;
9022 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
9023 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
9024 }else{
drh7a431002020-04-18 14:12:00 +00009025 /* text editor mode */
drh13c20932018-01-10 21:41:55 +00009026 newTempFile(p, "txt");
drha92a01a2018-01-10 22:15:37 +00009027 bTxtMode = 1;
drh13c20932018-01-10 21:41:55 +00009028 }
drh4b0229a2021-02-17 13:19:22 +00009029 sqlite3_free(zFile);
9030 zFile = sqlite3_mprintf("%s", p->zTempFile);
drh13c20932018-01-10 21:41:55 +00009031 }
drh04a28c32018-01-31 01:38:44 +00009032#endif /* SQLITE_NOHAVE_SYSTEM */
drh2ce15c32017-07-11 13:34:40 +00009033 if( zFile[0]=='|' ){
9034#ifdef SQLITE_OMIT_POPEN
9035 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
9036 rc = 1;
9037 p->out = stdout;
9038#else
9039 p->out = popen(zFile + 1, "w");
9040 if( p->out==0 ){
9041 utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
9042 p->out = stdout;
9043 rc = 1;
9044 }else{
drh7a431002020-04-18 14:12:00 +00009045 if( bBOM ) fprintf(p->out,"\357\273\277");
drh2ce15c32017-07-11 13:34:40 +00009046 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
9047 }
9048#endif
9049 }else{
drha92a01a2018-01-10 22:15:37 +00009050 p->out = output_file_open(zFile, bTxtMode);
drh2ce15c32017-07-11 13:34:40 +00009051 if( p->out==0 ){
9052 if( strcmp(zFile,"off")!=0 ){
9053 utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
9054 }
9055 p->out = stdout;
9056 rc = 1;
9057 } else {
drh7a431002020-04-18 14:12:00 +00009058 if( bBOM ) fprintf(p->out,"\357\273\277");
drh2ce15c32017-07-11 13:34:40 +00009059 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
9060 }
9061 }
drh4b0229a2021-02-17 13:19:22 +00009062 sqlite3_free(zFile);
drh2ce15c32017-07-11 13:34:40 +00009063 }else
9064
drh9cb02642019-02-28 20:10:52 +00009065 if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
9066 open_db(p,0);
9067 if( nArg<=1 ) goto parameter_syntax_error;
9068
9069 /* .parameter clear
9070 ** Clear all bind parameters by dropping the TEMP table that holds them.
9071 */
9072 if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
drh65c29fd2019-03-25 21:56:26 +00009073 sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
drh9cb02642019-02-28 20:10:52 +00009074 0, 0, 0);
9075 }else
9076
9077 /* .parameter list
9078 ** List all bind parameters.
9079 */
9080 if( nArg==2 && strcmp(azArg[1],"list")==0 ){
9081 sqlite3_stmt *pStmt = 0;
9082 int rx;
9083 int len = 0;
9084 rx = sqlite3_prepare_v2(p->db,
9085 "SELECT max(length(key)) "
drh65c29fd2019-03-25 21:56:26 +00009086 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drh9cb02642019-02-28 20:10:52 +00009087 if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
9088 len = sqlite3_column_int(pStmt, 0);
9089 if( len>40 ) len = 40;
9090 }
9091 sqlite3_finalize(pStmt);
9092 pStmt = 0;
9093 if( len ){
9094 rx = sqlite3_prepare_v2(p->db,
9095 "SELECT key, quote(value) "
drh65c29fd2019-03-25 21:56:26 +00009096 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drh9cb02642019-02-28 20:10:52 +00009097 while( sqlite3_step(pStmt)==SQLITE_ROW ){
9098 utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
9099 sqlite3_column_text(pStmt,1));
9100 }
9101 sqlite3_finalize(pStmt);
9102 }
9103 }else
9104
9105 /* .parameter init
9106 ** Make sure the TEMP table used to hold bind parameters exists.
9107 ** Create it if necessary.
9108 */
9109 if( nArg==2 && strcmp(azArg[1],"init")==0 ){
9110 bind_table_init(p);
9111 }else
9112
9113 /* .parameter set NAME VALUE
9114 ** Set or reset a bind parameter. NAME should be the full parameter
9115 ** name exactly as it appears in the query. (ex: $abc, @def). The
9116 ** VALUE can be in either SQL literal notation, or if not it will be
9117 ** understood to be a text string.
9118 */
9119 if( nArg==4 && strcmp(azArg[1],"set")==0 ){
9120 int rx;
9121 char *zSql;
9122 sqlite3_stmt *pStmt;
9123 const char *zKey = azArg[2];
9124 const char *zValue = azArg[3];
9125 bind_table_init(p);
9126 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009127 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00009128 "VALUES(%Q,%s);", zKey, zValue);
9129 if( zSql==0 ) shell_out_of_memory();
9130 pStmt = 0;
9131 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9132 sqlite3_free(zSql);
9133 if( rx!=SQLITE_OK ){
9134 sqlite3_finalize(pStmt);
9135 pStmt = 0;
9136 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009137 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00009138 "VALUES(%Q,%Q);", zKey, zValue);
9139 if( zSql==0 ) shell_out_of_memory();
9140 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9141 sqlite3_free(zSql);
9142 if( rx!=SQLITE_OK ){
9143 utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
9144 sqlite3_finalize(pStmt);
9145 pStmt = 0;
9146 rc = 1;
9147 }
9148 }
9149 sqlite3_step(pStmt);
9150 sqlite3_finalize(pStmt);
9151 }else
9152
9153 /* .parameter unset NAME
9154 ** Remove the NAME binding from the parameter binding table, if it
9155 ** exists.
9156 */
9157 if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
9158 char *zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009159 "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
drh9cb02642019-02-28 20:10:52 +00009160 if( zSql==0 ) shell_out_of_memory();
9161 sqlite3_exec(p->db, zSql, 0, 0, 0);
9162 sqlite3_free(zSql);
9163 }else
9164 /* If no command name matches, show a syntax error */
9165 parameter_syntax_error:
9166 showHelp(p->out, "parameter");
9167 }else
9168
drh2ce15c32017-07-11 13:34:40 +00009169 if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
9170 int i;
9171 for(i=1; i<nArg; i++){
9172 if( i>1 ) raw_printf(p->out, " ");
9173 utf8_printf(p->out, "%s", azArg[i]);
9174 }
9175 raw_printf(p->out, "\n");
9176 }else
9177
drh569b1d92019-02-05 20:51:41 +00009178#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh3f83f592019-02-04 14:53:18 +00009179 if( c=='p' && n>=3 && strncmp(azArg[0], "progress", n)==0 ){
9180 int i;
drhfc4eeef2019-02-05 19:48:46 +00009181 int nn = 0;
drh3f83f592019-02-04 14:53:18 +00009182 p->flgProgress = 0;
9183 p->mxProgress = 0;
9184 p->nProgress = 0;
9185 for(i=1; i<nArg; i++){
9186 const char *z = azArg[i];
9187 if( z[0]=='-' ){
9188 z++;
9189 if( z[0]=='-' ) z++;
9190 if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009191 p->flgProgress |= SHELL_PROGRESS_QUIET;
drh3f83f592019-02-04 14:53:18 +00009192 continue;
9193 }
9194 if( strcmp(z,"reset")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009195 p->flgProgress |= SHELL_PROGRESS_RESET;
drh3f83f592019-02-04 14:53:18 +00009196 continue;
9197 }
9198 if( strcmp(z,"once")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009199 p->flgProgress |= SHELL_PROGRESS_ONCE;
drh3f83f592019-02-04 14:53:18 +00009200 continue;
9201 }
9202 if( strcmp(z,"limit")==0 ){
9203 if( i+1>=nArg ){
9204 utf8_printf(stderr, "Error: missing argument on --limit\n");
9205 rc = 1;
9206 goto meta_command_exit;
9207 }else{
9208 p->mxProgress = (int)integerValue(azArg[++i]);
9209 }
9210 continue;
9211 }
9212 utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
9213 rc = 1;
9214 goto meta_command_exit;
9215 }else{
drhfc4eeef2019-02-05 19:48:46 +00009216 nn = (int)integerValue(z);
drh3f83f592019-02-04 14:53:18 +00009217 }
9218 }
9219 open_db(p, 0);
drhfc4eeef2019-02-05 19:48:46 +00009220 sqlite3_progress_handler(p->db, nn, progress_handler, p);
drh3f83f592019-02-04 14:53:18 +00009221 }else
drh569b1d92019-02-05 20:51:41 +00009222#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
drh3f83f592019-02-04 14:53:18 +00009223
drh2ce15c32017-07-11 13:34:40 +00009224 if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
9225 if( nArg >= 2) {
9226 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
9227 }
9228 if( nArg >= 3) {
9229 strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
9230 }
9231 }else
9232
9233 if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
9234 rc = 2;
9235 }else
9236
9237 if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
drh60379d42018-12-13 18:30:01 +00009238 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +00009239 int savedLineno = p->lineno;
drhb97e2ad2021-08-26 18:31:39 +00009240 failIfSafeMode(p, "cannot run .read in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009241 if( nArg!=2 ){
9242 raw_printf(stderr, "Usage: .read FILE\n");
9243 rc = 1;
9244 goto meta_command_exit;
9245 }
drh30497f42020-08-26 10:50:48 +00009246 if( azArg[1][0]=='|' ){
drh9d59e3b2021-03-12 01:49:08 +00009247#ifdef SQLITE_OMIT_POPEN
9248 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
9249 rc = 1;
9250 p->out = stdout;
9251#else
drh30497f42020-08-26 10:50:48 +00009252 p->in = popen(azArg[1]+1, "r");
9253 if( p->in==0 ){
9254 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
9255 rc = 1;
9256 }else{
9257 rc = process_input(p);
9258 pclose(p->in);
9259 }
drh9d59e3b2021-03-12 01:49:08 +00009260#endif
larrybrd96bcc72021-09-17 21:12:47 +00009261 }else if( (p->in = openChrSource(azArg[1]))==0 ){
drh2ce15c32017-07-11 13:34:40 +00009262 utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
9263 rc = 1;
9264 }else{
drh60379d42018-12-13 18:30:01 +00009265 rc = process_input(p);
9266 fclose(p->in);
drh2ce15c32017-07-11 13:34:40 +00009267 }
drh60379d42018-12-13 18:30:01 +00009268 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +00009269 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +00009270 }else
9271
9272 if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
9273 const char *zSrcFile;
9274 const char *zDb;
9275 sqlite3 *pSrc;
9276 sqlite3_backup *pBackup;
9277 int nTimeout = 0;
9278
drhb97e2ad2021-08-26 18:31:39 +00009279 failIfSafeMode(p, "cannot run .restore in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009280 if( nArg==2 ){
9281 zSrcFile = azArg[1];
9282 zDb = "main";
9283 }else if( nArg==3 ){
9284 zSrcFile = azArg[2];
9285 zDb = azArg[1];
9286 }else{
9287 raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
9288 rc = 1;
9289 goto meta_command_exit;
9290 }
9291 rc = sqlite3_open(zSrcFile, &pSrc);
9292 if( rc!=SQLITE_OK ){
9293 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
drh9e804032018-05-18 17:11:50 +00009294 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009295 return 1;
9296 }
9297 open_db(p, 0);
9298 pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
9299 if( pBackup==0 ){
9300 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh9e804032018-05-18 17:11:50 +00009301 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009302 return 1;
9303 }
9304 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
9305 || rc==SQLITE_BUSY ){
9306 if( rc==SQLITE_BUSY ){
9307 if( nTimeout++ >= 3 ) break;
9308 sqlite3_sleep(100);
9309 }
9310 }
9311 sqlite3_backup_finish(pBackup);
9312 if( rc==SQLITE_DONE ){
9313 rc = 0;
9314 }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
9315 raw_printf(stderr, "Error: source database is busy\n");
9316 rc = 1;
9317 }else{
9318 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9319 rc = 1;
9320 }
drh9e804032018-05-18 17:11:50 +00009321 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009322 }else
9323
drh2ce15c32017-07-11 13:34:40 +00009324 if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
9325 if( nArg==2 ){
mistachkinb71aa092018-01-23 00:05:18 +00009326 p->scanstatsOn = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00009327#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
9328 raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
9329#endif
9330 }else{
9331 raw_printf(stderr, "Usage: .scanstats on|off\n");
9332 rc = 1;
9333 }
9334 }else
9335
9336 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
9337 ShellText sSelect;
9338 ShellState data;
9339 char *zErrMsg = 0;
drh667a2a22018-01-02 00:04:37 +00009340 const char *zDiv = "(";
drhceba7922018-01-01 21:28:25 +00009341 const char *zName = 0;
drh2ce15c32017-07-11 13:34:40 +00009342 int iSchema = 0;
drhceba7922018-01-01 21:28:25 +00009343 int bDebug = 0;
drhbbb29ec2020-10-12 14:56:47 +00009344 int bNoSystemTabs = 0;
drhceba7922018-01-01 21:28:25 +00009345 int ii;
drh2ce15c32017-07-11 13:34:40 +00009346
9347 open_db(p, 0);
9348 memcpy(&data, p, sizeof(data));
9349 data.showHeader = 0;
9350 data.cMode = data.mode = MODE_Semi;
9351 initText(&sSelect);
drhceba7922018-01-01 21:28:25 +00009352 for(ii=1; ii<nArg; ii++){
9353 if( optionMatch(azArg[ii],"indent") ){
9354 data.cMode = data.mode = MODE_Pretty;
9355 }else if( optionMatch(azArg[ii],"debug") ){
9356 bDebug = 1;
drhbbb29ec2020-10-12 14:56:47 +00009357 }else if( optionMatch(azArg[ii],"nosys") ){
9358 bNoSystemTabs = 1;
9359 }else if( azArg[ii][0]=='-' ){
9360 utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
9361 rc = 1;
9362 goto meta_command_exit;
drhceba7922018-01-01 21:28:25 +00009363 }else if( zName==0 ){
9364 zName = azArg[ii];
drh2ce15c32017-07-11 13:34:40 +00009365 }else{
drhbbb29ec2020-10-12 14:56:47 +00009366 raw_printf(stderr, "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
drhceba7922018-01-01 21:28:25 +00009367 rc = 1;
9368 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00009369 }
drh2ce15c32017-07-11 13:34:40 +00009370 }
drhceba7922018-01-01 21:28:25 +00009371 if( zName!=0 ){
drh067b92b2020-06-19 15:24:12 +00009372 int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0
drh346a70c2020-06-15 20:27:35 +00009373 || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
9374 || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
9375 || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
drh067b92b2020-06-19 15:24:12 +00009376 if( isSchema ){
drh2ce15c32017-07-11 13:34:40 +00009377 char *new_argv[2], *new_colv[2];
drhc22b7162018-01-01 20:11:23 +00009378 new_argv[0] = sqlite3_mprintf(
9379 "CREATE TABLE %s (\n"
drh2ce15c32017-07-11 13:34:40 +00009380 " type text,\n"
9381 " name text,\n"
9382 " tbl_name text,\n"
9383 " rootpage integer,\n"
9384 " sql text\n"
drh346a70c2020-06-15 20:27:35 +00009385 ")", zName);
drh2ce15c32017-07-11 13:34:40 +00009386 new_argv[1] = 0;
9387 new_colv[0] = "sql";
9388 new_colv[1] = 0;
9389 callback(&data, 1, new_argv, new_colv);
drhc22b7162018-01-01 20:11:23 +00009390 sqlite3_free(new_argv[0]);
drh2ce15c32017-07-11 13:34:40 +00009391 }
drh2ce15c32017-07-11 13:34:40 +00009392 }
9393 if( zDiv ){
9394 sqlite3_stmt *pStmt = 0;
9395 rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
9396 -1, &pStmt, 0);
9397 if( rc ){
9398 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9399 sqlite3_finalize(pStmt);
9400 rc = 1;
9401 goto meta_command_exit;
9402 }
9403 appendText(&sSelect, "SELECT sql FROM", 0);
9404 iSchema = 0;
9405 while( sqlite3_step(pStmt)==SQLITE_ROW ){
9406 const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
9407 char zScNum[30];
9408 sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
9409 appendText(&sSelect, zDiv, 0);
9410 zDiv = " UNION ALL ";
drhceba7922018-01-01 21:28:25 +00009411 appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
9412 if( sqlite3_stricmp(zDb, "main")!=0 ){
drhea38f4f2019-07-13 17:21:47 +00009413 appendText(&sSelect, zDb, '\'');
drh2ce15c32017-07-11 13:34:40 +00009414 }else{
drhceba7922018-01-01 21:28:25 +00009415 appendText(&sSelect, "NULL", 0);
drh2ce15c32017-07-11 13:34:40 +00009416 }
drhceba7922018-01-01 21:28:25 +00009417 appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0);
9418 appendText(&sSelect, zScNum, 0);
9419 appendText(&sSelect, " AS snum, ", 0);
9420 appendText(&sSelect, zDb, '\'');
9421 appendText(&sSelect, " AS sname FROM ", 0);
drhea38f4f2019-07-13 17:21:47 +00009422 appendText(&sSelect, zDb, quoteChar(zDb));
drh067b92b2020-06-19 15:24:12 +00009423 appendText(&sSelect, ".sqlite_schema", 0);
drh2ce15c32017-07-11 13:34:40 +00009424 }
9425 sqlite3_finalize(pStmt);
drhcc3f3d12019-08-17 15:27:58 +00009426#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
drh667a2a22018-01-02 00:04:37 +00009427 if( zName ){
9428 appendText(&sSelect,
9429 " UNION ALL SELECT shell_module_schema(name),"
drhe2754c12019-08-26 12:50:01 +00009430 " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
9431 0);
drh667a2a22018-01-02 00:04:37 +00009432 }
drhcde7b772018-01-02 12:50:40 +00009433#endif
drh2ce15c32017-07-11 13:34:40 +00009434 appendText(&sSelect, ") WHERE ", 0);
drhceba7922018-01-01 21:28:25 +00009435 if( zName ){
9436 char *zQarg = sqlite3_mprintf("%Q", zName);
mistachkin9d107262018-03-23 14:24:34 +00009437 int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
9438 strchr(zName, '[') != 0;
drhceba7922018-01-01 21:28:25 +00009439 if( strchr(zName, '.') ){
drh2ce15c32017-07-11 13:34:40 +00009440 appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
9441 }else{
9442 appendText(&sSelect, "lower(tbl_name)", 0);
9443 }
mistachkin9d107262018-03-23 14:24:34 +00009444 appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0);
drh2ce15c32017-07-11 13:34:40 +00009445 appendText(&sSelect, zQarg, 0);
mistachkin9d107262018-03-23 14:24:34 +00009446 if( !bGlob ){
9447 appendText(&sSelect, " ESCAPE '\\' ", 0);
9448 }
drh2ce15c32017-07-11 13:34:40 +00009449 appendText(&sSelect, " AND ", 0);
9450 sqlite3_free(zQarg);
9451 }
drhbbb29ec2020-10-12 14:56:47 +00009452 if( bNoSystemTabs ){
9453 appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
9454 }
9455 appendText(&sSelect, "sql IS NOT NULL"
drh2ce15c32017-07-11 13:34:40 +00009456 " ORDER BY snum, rowid", 0);
drhceba7922018-01-01 21:28:25 +00009457 if( bDebug ){
9458 utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
9459 }else{
9460 rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
9461 }
drh2ce15c32017-07-11 13:34:40 +00009462 freeText(&sSelect);
9463 }
9464 if( zErrMsg ){
9465 utf8_printf(stderr,"Error: %s\n", zErrMsg);
9466 sqlite3_free(zErrMsg);
9467 rc = 1;
9468 }else if( rc != SQLITE_OK ){
9469 raw_printf(stderr,"Error: querying schema information\n");
9470 rc = 1;
9471 }else{
9472 rc = 0;
9473 }
9474 }else
9475
drh2ce15c32017-07-11 13:34:40 +00009476 if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
drhfda8e492020-12-04 16:04:45 +00009477 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
drhc0622a42020-12-04 01:17:57 +00009478 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
drh2ce15c32017-07-11 13:34:40 +00009479 }else
drh2ce15c32017-07-11 13:34:40 +00009480
9481#if defined(SQLITE_ENABLE_SESSION)
9482 if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
drh37407122021-07-23 18:43:58 +00009483 struct AuxDb *pAuxDb = p->pAuxDb;
9484 OpenSession *pSession = &pAuxDb->aSession[0];
drh2ce15c32017-07-11 13:34:40 +00009485 char **azCmd = &azArg[1];
9486 int iSes = 0;
9487 int nCmd = nArg - 1;
9488 int i;
9489 if( nArg<=1 ) goto session_syntax_error;
9490 open_db(p, 0);
9491 if( nArg>=3 ){
drh37407122021-07-23 18:43:58 +00009492 for(iSes=0; iSes<pAuxDb->nSession; iSes++){
9493 if( strcmp(pAuxDb->aSession[iSes].zName, azArg[1])==0 ) break;
drh2ce15c32017-07-11 13:34:40 +00009494 }
drh37407122021-07-23 18:43:58 +00009495 if( iSes<pAuxDb->nSession ){
9496 pSession = &pAuxDb->aSession[iSes];
drh2ce15c32017-07-11 13:34:40 +00009497 azCmd++;
9498 nCmd--;
9499 }else{
drh37407122021-07-23 18:43:58 +00009500 pSession = &pAuxDb->aSession[0];
drh2ce15c32017-07-11 13:34:40 +00009501 iSes = 0;
9502 }
9503 }
9504
9505 /* .session attach TABLE
9506 ** Invoke the sqlite3session_attach() interface to attach a particular
9507 ** table so that it is never filtered.
9508 */
9509 if( strcmp(azCmd[0],"attach")==0 ){
9510 if( nCmd!=2 ) goto session_syntax_error;
9511 if( pSession->p==0 ){
9512 session_not_open:
9513 raw_printf(stderr, "ERROR: No sessions are open\n");
9514 }else{
9515 rc = sqlite3session_attach(pSession->p, azCmd[1]);
9516 if( rc ){
9517 raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
9518 rc = 0;
9519 }
9520 }
9521 }else
9522
9523 /* .session changeset FILE
9524 ** .session patchset FILE
9525 ** Write a changeset or patchset into a file. The file is overwritten.
9526 */
9527 if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
9528 FILE *out = 0;
drhb97e2ad2021-08-26 18:31:39 +00009529 failIfSafeMode(p, "cannot run \".session %s\" in safe mode", azCmd[0]);
drh2ce15c32017-07-11 13:34:40 +00009530 if( nCmd!=2 ) goto session_syntax_error;
9531 if( pSession->p==0 ) goto session_not_open;
9532 out = fopen(azCmd[1], "wb");
9533 if( out==0 ){
drhe2754c12019-08-26 12:50:01 +00009534 utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
9535 azCmd[1]);
drh2ce15c32017-07-11 13:34:40 +00009536 }else{
9537 int szChng;
9538 void *pChng;
9539 if( azCmd[0][0]=='c' ){
9540 rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
9541 }else{
9542 rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
9543 }
9544 if( rc ){
9545 printf("Error: error code %d\n", rc);
9546 rc = 0;
9547 }
9548 if( pChng
9549 && fwrite(pChng, szChng, 1, out)!=1 ){
9550 raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
9551 szChng);
9552 }
9553 sqlite3_free(pChng);
9554 fclose(out);
9555 }
9556 }else
9557
9558 /* .session close
9559 ** Close the identified session
9560 */
9561 if( strcmp(azCmd[0], "close")==0 ){
9562 if( nCmd!=1 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009563 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009564 session_close(pSession);
drh37407122021-07-23 18:43:58 +00009565 pAuxDb->aSession[iSes] = pAuxDb->aSession[--pAuxDb->nSession];
drh2ce15c32017-07-11 13:34:40 +00009566 }
9567 }else
9568
9569 /* .session enable ?BOOLEAN?
9570 ** Query or set the enable flag
9571 */
9572 if( strcmp(azCmd[0], "enable")==0 ){
9573 int ii;
9574 if( nCmd>2 ) goto session_syntax_error;
9575 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
drh37407122021-07-23 18:43:58 +00009576 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009577 ii = sqlite3session_enable(pSession->p, ii);
9578 utf8_printf(p->out, "session %s enable flag = %d\n",
9579 pSession->zName, ii);
9580 }
9581 }else
9582
9583 /* .session filter GLOB ....
9584 ** Set a list of GLOB patterns of table names to be excluded.
9585 */
9586 if( strcmp(azCmd[0], "filter")==0 ){
9587 int ii, nByte;
9588 if( nCmd<2 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009589 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009590 for(ii=0; ii<pSession->nFilter; ii++){
9591 sqlite3_free(pSession->azFilter[ii]);
9592 }
9593 sqlite3_free(pSession->azFilter);
9594 nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
9595 pSession->azFilter = sqlite3_malloc( nByte );
9596 if( pSession->azFilter==0 ){
9597 raw_printf(stderr, "Error: out or memory\n");
9598 exit(1);
9599 }
9600 for(ii=1; ii<nCmd; ii++){
9601 pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
9602 }
9603 pSession->nFilter = ii-1;
9604 }
9605 }else
9606
9607 /* .session indirect ?BOOLEAN?
9608 ** Query or set the indirect flag
9609 */
9610 if( strcmp(azCmd[0], "indirect")==0 ){
9611 int ii;
9612 if( nCmd>2 ) goto session_syntax_error;
9613 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
drh37407122021-07-23 18:43:58 +00009614 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009615 ii = sqlite3session_indirect(pSession->p, ii);
9616 utf8_printf(p->out, "session %s indirect flag = %d\n",
9617 pSession->zName, ii);
9618 }
9619 }else
9620
9621 /* .session isempty
9622 ** Determine if the session is empty
9623 */
9624 if( strcmp(azCmd[0], "isempty")==0 ){
9625 int ii;
9626 if( nCmd!=1 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009627 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009628 ii = sqlite3session_isempty(pSession->p);
9629 utf8_printf(p->out, "session %s isempty flag = %d\n",
9630 pSession->zName, ii);
9631 }
9632 }else
9633
9634 /* .session list
9635 ** List all currently open sessions
9636 */
9637 if( strcmp(azCmd[0],"list")==0 ){
drh37407122021-07-23 18:43:58 +00009638 for(i=0; i<pAuxDb->nSession; i++){
9639 utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName);
drh2ce15c32017-07-11 13:34:40 +00009640 }
9641 }else
9642
9643 /* .session open DB NAME
9644 ** Open a new session called NAME on the attached database DB.
9645 ** DB is normally "main".
9646 */
9647 if( strcmp(azCmd[0],"open")==0 ){
9648 char *zName;
9649 if( nCmd!=3 ) goto session_syntax_error;
9650 zName = azCmd[2];
9651 if( zName[0]==0 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009652 for(i=0; i<pAuxDb->nSession; i++){
9653 if( strcmp(pAuxDb->aSession[i].zName,zName)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009654 utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
9655 goto meta_command_exit;
9656 }
9657 }
drh37407122021-07-23 18:43:58 +00009658 if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){
9659 raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession));
drh2ce15c32017-07-11 13:34:40 +00009660 goto meta_command_exit;
9661 }
drh37407122021-07-23 18:43:58 +00009662 pSession = &pAuxDb->aSession[pAuxDb->nSession];
drh2ce15c32017-07-11 13:34:40 +00009663 rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
9664 if( rc ){
9665 raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
9666 rc = 0;
9667 goto meta_command_exit;
9668 }
9669 pSession->nFilter = 0;
9670 sqlite3session_table_filter(pSession->p, session_filter, pSession);
drh37407122021-07-23 18:43:58 +00009671 pAuxDb->nSession++;
drh2ce15c32017-07-11 13:34:40 +00009672 pSession->zName = sqlite3_mprintf("%s", zName);
9673 }else
9674 /* If no command name matches, show a syntax error */
9675 session_syntax_error:
drheb7f2a02018-09-26 18:02:32 +00009676 showHelp(p->out, "session");
drh2ce15c32017-07-11 13:34:40 +00009677 }else
9678#endif
9679
9680#ifdef SQLITE_DEBUG
9681 /* Undocumented commands for internal testing. Subject to change
9682 ** without notice. */
9683 if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
9684 if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
9685 int i, v;
9686 for(i=1; i<nArg; i++){
9687 v = booleanValue(azArg[i]);
9688 utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
9689 }
9690 }
9691 if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
9692 int i; sqlite3_int64 v;
9693 for(i=1; i<nArg; i++){
9694 char zBuf[200];
9695 v = integerValue(azArg[i]);
9696 sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
9697 utf8_printf(p->out, "%s", zBuf);
9698 }
9699 }
9700 }else
9701#endif
9702
9703 if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){
9704 int bIsInit = 0; /* True to initialize the SELFTEST table */
9705 int bVerbose = 0; /* Verbose output */
9706 int bSelftestExists; /* True if SELFTEST already exists */
9707 int i, k; /* Loop counters */
9708 int nTest = 0; /* Number of tests runs */
9709 int nErr = 0; /* Number of errors seen */
9710 ShellText str; /* Answer for a query */
9711 sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
9712
9713 open_db(p,0);
9714 for(i=1; i<nArg; i++){
9715 const char *z = azArg[i];
9716 if( z[0]=='-' && z[1]=='-' ) z++;
9717 if( strcmp(z,"-init")==0 ){
9718 bIsInit = 1;
9719 }else
9720 if( strcmp(z,"-v")==0 ){
9721 bVerbose++;
9722 }else
9723 {
9724 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
9725 azArg[i], azArg[0]);
9726 raw_printf(stderr, "Should be one of: --init -v\n");
9727 rc = 1;
9728 goto meta_command_exit;
9729 }
9730 }
9731 if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
9732 != SQLITE_OK ){
9733 bSelftestExists = 0;
9734 }else{
9735 bSelftestExists = 1;
9736 }
9737 if( bIsInit ){
9738 createSelftestTable(p);
9739 bSelftestExists = 1;
9740 }
9741 initText(&str);
9742 appendText(&str, "x", 0);
9743 for(k=bSelftestExists; k>=0; k--){
9744 if( k==1 ){
9745 rc = sqlite3_prepare_v2(p->db,
9746 "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
9747 -1, &pStmt, 0);
9748 }else{
9749 rc = sqlite3_prepare_v2(p->db,
9750 "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
9751 " (1,'run','PRAGMA integrity_check','ok')",
9752 -1, &pStmt, 0);
9753 }
9754 if( rc ){
9755 raw_printf(stderr, "Error querying the selftest table\n");
9756 rc = 1;
9757 sqlite3_finalize(pStmt);
9758 goto meta_command_exit;
9759 }
9760 for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
9761 int tno = sqlite3_column_int(pStmt, 0);
9762 const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
9763 const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
9764 const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
9765
9766 k = 0;
9767 if( bVerbose>0 ){
9768 char *zQuote = sqlite3_mprintf("%q", zSql);
9769 printf("%d: %s %s\n", tno, zOp, zSql);
9770 sqlite3_free(zQuote);
9771 }
9772 if( strcmp(zOp,"memo")==0 ){
9773 utf8_printf(p->out, "%s\n", zSql);
9774 }else
9775 if( strcmp(zOp,"run")==0 ){
9776 char *zErrMsg = 0;
9777 str.n = 0;
9778 str.z[0] = 0;
9779 rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
9780 nTest++;
9781 if( bVerbose ){
9782 utf8_printf(p->out, "Result: %s\n", str.z);
9783 }
9784 if( rc || zErrMsg ){
9785 nErr++;
9786 rc = 1;
9787 utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
9788 sqlite3_free(zErrMsg);
9789 }else if( strcmp(zAns,str.z)!=0 ){
9790 nErr++;
9791 rc = 1;
9792 utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
9793 utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z);
9794 }
9795 }else
9796 {
9797 utf8_printf(stderr,
9798 "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
9799 rc = 1;
9800 break;
9801 }
9802 } /* End loop over rows of content from SELFTEST */
9803 sqlite3_finalize(pStmt);
9804 } /* End loop over k */
9805 freeText(&str);
9806 utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
9807 }else
9808
9809 if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
9810 if( nArg<2 || nArg>3 ){
9811 raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
9812 rc = 1;
9813 }
9814 if( nArg>=2 ){
9815 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
9816 "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
9817 }
9818 if( nArg>=3 ){
9819 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator,
9820 "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]);
9821 }
9822 }else
9823
9824 if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){
9825 const char *zLike = 0; /* Which table to checksum. 0 means everything */
9826 int i; /* Loop counter */
9827 int bSchema = 0; /* Also hash the schema */
9828 int bSeparate = 0; /* Hash each table separately */
9829 int iSize = 224; /* Hash algorithm to use */
9830 int bDebug = 0; /* Only show the query that would have run */
9831 sqlite3_stmt *pStmt; /* For querying tables names */
9832 char *zSql; /* SQL to be run */
9833 char *zSep; /* Separator */
9834 ShellText sSql; /* Complete SQL for the query to run the hash */
9835 ShellText sQuery; /* Set of queries used to read all content */
9836 open_db(p, 0);
9837 for(i=1; i<nArg; i++){
9838 const char *z = azArg[i];
9839 if( z[0]=='-' ){
9840 z++;
9841 if( z[0]=='-' ) z++;
9842 if( strcmp(z,"schema")==0 ){
9843 bSchema = 1;
9844 }else
9845 if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
9846 || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
9847 ){
9848 iSize = atoi(&z[5]);
9849 }else
9850 if( strcmp(z,"debug")==0 ){
9851 bDebug = 1;
9852 }else
9853 {
9854 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
9855 azArg[i], azArg[0]);
drhe2754c12019-08-26 12:50:01 +00009856 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00009857 rc = 1;
9858 goto meta_command_exit;
9859 }
9860 }else if( zLike ){
9861 raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
9862 rc = 1;
9863 goto meta_command_exit;
9864 }else{
9865 zLike = z;
9866 bSeparate = 1;
drhcedfecf2018-03-23 12:59:10 +00009867 if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1;
drh2ce15c32017-07-11 13:34:40 +00009868 }
9869 }
9870 if( bSchema ){
drh067b92b2020-06-19 15:24:12 +00009871 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00009872 " WHERE type='table' AND coalesce(rootpage,0)>1"
drh067b92b2020-06-19 15:24:12 +00009873 " UNION ALL SELECT 'sqlite_schema'"
drh2ce15c32017-07-11 13:34:40 +00009874 " ORDER BY 1 collate nocase";
9875 }else{
drh067b92b2020-06-19 15:24:12 +00009876 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00009877 " WHERE type='table' AND coalesce(rootpage,0)>1"
9878 " AND name NOT LIKE 'sqlite_%'"
9879 " ORDER BY 1 collate nocase";
9880 }
9881 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9882 initText(&sQuery);
9883 initText(&sSql);
9884 appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
9885 zSep = "VALUES(";
9886 while( SQLITE_ROW==sqlite3_step(pStmt) ){
9887 const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
9888 if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
9889 if( strncmp(zTab, "sqlite_",7)!=0 ){
9890 appendText(&sQuery,"SELECT * FROM ", 0);
9891 appendText(&sQuery,zTab,'"');
9892 appendText(&sQuery," NOT INDEXED;", 0);
drh067b92b2020-06-19 15:24:12 +00009893 }else if( strcmp(zTab, "sqlite_schema")==0 ){
9894 appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00009895 " ORDER BY name;", 0);
9896 }else if( strcmp(zTab, "sqlite_sequence")==0 ){
9897 appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
9898 " ORDER BY name;", 0);
9899 }else if( strcmp(zTab, "sqlite_stat1")==0 ){
9900 appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
9901 " ORDER BY tbl,idx;", 0);
drh175b8f02019-08-08 15:24:17 +00009902 }else if( strcmp(zTab, "sqlite_stat4")==0 ){
drh2ce15c32017-07-11 13:34:40 +00009903 appendText(&sQuery, "SELECT * FROM ", 0);
9904 appendText(&sQuery, zTab, 0);
9905 appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
9906 }
9907 appendText(&sSql, zSep, 0);
9908 appendText(&sSql, sQuery.z, '\'');
9909 sQuery.n = 0;
9910 appendText(&sSql, ",", 0);
9911 appendText(&sSql, zTab, '\'');
9912 zSep = "),(";
9913 }
9914 sqlite3_finalize(pStmt);
9915 if( bSeparate ){
9916 zSql = sqlite3_mprintf(
9917 "%s))"
9918 " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
9919 " FROM [sha3sum$query]",
9920 sSql.z, iSize);
9921 }else{
9922 zSql = sqlite3_mprintf(
9923 "%s))"
9924 " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
9925 " FROM [sha3sum$query]",
9926 sSql.z, iSize);
9927 }
9928 freeText(&sQuery);
9929 freeText(&sSql);
9930 if( bDebug ){
9931 utf8_printf(p->out, "%s\n", zSql);
9932 }else{
drha10b9992018-03-09 15:24:33 +00009933 shell_exec(p, zSql, 0);
drh2ce15c32017-07-11 13:34:40 +00009934 }
9935 sqlite3_free(zSql);
9936 }else
9937
drh04a28c32018-01-31 01:38:44 +00009938#ifndef SQLITE_NOHAVE_SYSTEM
drh2ce15c32017-07-11 13:34:40 +00009939 if( c=='s'
9940 && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
9941 ){
9942 char *zCmd;
9943 int i, x;
drhb97e2ad2021-08-26 18:31:39 +00009944 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00009945 if( nArg<2 ){
9946 raw_printf(stderr, "Usage: .system COMMAND\n");
9947 rc = 1;
9948 goto meta_command_exit;
9949 }
9950 zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
9951 for(i=2; i<nArg; i++){
9952 zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
9953 zCmd, azArg[i]);
9954 }
9955 x = system(zCmd);
9956 sqlite3_free(zCmd);
9957 if( x ) raw_printf(stderr, "System command returns %d\n", x);
9958 }else
drh04a28c32018-01-31 01:38:44 +00009959#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
drh2ce15c32017-07-11 13:34:40 +00009960
9961 if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
drhada70452017-12-21 21:02:27 +00009962 static const char *azBool[] = { "off", "on", "trigger", "full"};
drha6e6cf22021-01-09 19:10:04 +00009963 const char *zOut;
drh2ce15c32017-07-11 13:34:40 +00009964 int i;
9965 if( nArg!=1 ){
9966 raw_printf(stderr, "Usage: .show\n");
9967 rc = 1;
9968 goto meta_command_exit;
9969 }
9970 utf8_printf(p->out, "%12.12s: %s\n","echo",
9971 azBool[ShellHasFlag(p, SHFLG_Echo)]);
9972 utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
9973 utf8_printf(p->out, "%12.12s: %s\n","explain",
9974 p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
9975 utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
9976 utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
9977 utf8_printf(p->out, "%12.12s: ", "nullvalue");
9978 output_c_string(p->out, p->nullValue);
9979 raw_printf(p->out, "\n");
9980 utf8_printf(p->out,"%12.12s: %s\n","output",
9981 strlen30(p->outfile) ? p->outfile : "stdout");
9982 utf8_printf(p->out,"%12.12s: ", "colseparator");
9983 output_c_string(p->out, p->colSeparator);
9984 raw_printf(p->out, "\n");
9985 utf8_printf(p->out,"%12.12s: ", "rowseparator");
9986 output_c_string(p->out, p->rowSeparator);
9987 raw_printf(p->out, "\n");
drha6e6cf22021-01-09 19:10:04 +00009988 switch( p->statsOn ){
9989 case 0: zOut = "off"; break;
9990 default: zOut = "on"; break;
9991 case 2: zOut = "stmt"; break;
9992 case 3: zOut = "vmstep"; break;
9993 }
9994 utf8_printf(p->out, "%12.12s: %s\n","stats", zOut);
drh2ce15c32017-07-11 13:34:40 +00009995 utf8_printf(p->out, "%12.12s: ", "width");
drh0285d982020-05-29 14:38:43 +00009996 for (i=0;i<p->nWidth;i++) {
drh2ce15c32017-07-11 13:34:40 +00009997 raw_printf(p->out, "%d ", p->colWidth[i]);
9998 }
9999 raw_printf(p->out, "\n");
10000 utf8_printf(p->out, "%12.12s: %s\n", "filename",
drh37407122021-07-23 18:43:58 +000010001 p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : "");
drh2ce15c32017-07-11 13:34:40 +000010002 }else
10003
10004 if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
10005 if( nArg==2 ){
drha6e6cf22021-01-09 19:10:04 +000010006 if( strcmp(azArg[1],"stmt")==0 ){
10007 p->statsOn = 2;
10008 }else if( strcmp(azArg[1],"vmstep")==0 ){
10009 p->statsOn = 3;
10010 }else{
10011 p->statsOn = (u8)booleanValue(azArg[1]);
10012 }
drh2ce15c32017-07-11 13:34:40 +000010013 }else if( nArg==1 ){
10014 display_stats(p->db, p, 0);
10015 }else{
drha6e6cf22021-01-09 19:10:04 +000010016 raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n");
drh2ce15c32017-07-11 13:34:40 +000010017 rc = 1;
10018 }
10019 }else
10020
10021 if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0)
10022 || (c=='i' && (strncmp(azArg[0], "indices", n)==0
10023 || strncmp(azArg[0], "indexes", n)==0) )
10024 ){
10025 sqlite3_stmt *pStmt;
10026 char **azResult;
10027 int nRow, nAlloc;
10028 int ii;
10029 ShellText s;
10030 initText(&s);
10031 open_db(p, 0);
10032 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
drh9e804032018-05-18 17:11:50 +000010033 if( rc ){
10034 sqlite3_finalize(pStmt);
10035 return shellDatabaseError(p->db);
10036 }
drh2ce15c32017-07-11 13:34:40 +000010037
10038 if( nArg>2 && c=='i' ){
10039 /* It is an historical accident that the .indexes command shows an error
10040 ** when called with the wrong number of arguments whereas the .tables
10041 ** command does not. */
10042 raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
10043 rc = 1;
drh9e804032018-05-18 17:11:50 +000010044 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +000010045 goto meta_command_exit;
10046 }
10047 for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
10048 const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
10049 if( zDbName==0 ) continue;
10050 if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0);
10051 if( sqlite3_stricmp(zDbName, "main")==0 ){
10052 appendText(&s, "SELECT name FROM ", 0);
10053 }else{
10054 appendText(&s, "SELECT ", 0);
10055 appendText(&s, zDbName, '\'');
10056 appendText(&s, "||'.'||name FROM ", 0);
10057 }
10058 appendText(&s, zDbName, '"');
drh067b92b2020-06-19 15:24:12 +000010059 appendText(&s, ".sqlite_schema ", 0);
drh2ce15c32017-07-11 13:34:40 +000010060 if( c=='t' ){
10061 appendText(&s," WHERE type IN ('table','view')"
10062 " AND name NOT LIKE 'sqlite_%'"
10063 " AND name LIKE ?1", 0);
10064 }else{
10065 appendText(&s," WHERE type='index'"
10066 " AND tbl_name LIKE ?1", 0);
10067 }
10068 }
10069 rc = sqlite3_finalize(pStmt);
10070 appendText(&s, " ORDER BY 1", 0);
10071 rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
10072 freeText(&s);
10073 if( rc ) return shellDatabaseError(p->db);
10074
10075 /* Run the SQL statement prepared by the above block. Store the results
10076 ** as an array of nul-terminated strings in azResult[]. */
10077 nRow = nAlloc = 0;
10078 azResult = 0;
10079 if( nArg>1 ){
10080 sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
10081 }else{
10082 sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
10083 }
10084 while( sqlite3_step(pStmt)==SQLITE_ROW ){
10085 if( nRow>=nAlloc ){
10086 char **azNew;
10087 int n2 = nAlloc*2 + 10;
10088 azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
drh4b5345c2018-04-24 13:07:40 +000010089 if( azNew==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +000010090 nAlloc = n2;
10091 azResult = azNew;
10092 }
10093 azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
drh4b5345c2018-04-24 13:07:40 +000010094 if( 0==azResult[nRow] ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +000010095 nRow++;
10096 }
10097 if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
10098 rc = shellDatabaseError(p->db);
10099 }
10100
10101 /* Pretty-print the contents of array azResult[] to the output */
10102 if( rc==0 && nRow>0 ){
10103 int len, maxlen = 0;
10104 int i, j;
10105 int nPrintCol, nPrintRow;
10106 for(i=0; i<nRow; i++){
10107 len = strlen30(azResult[i]);
10108 if( len>maxlen ) maxlen = len;
10109 }
10110 nPrintCol = 80/(maxlen+2);
10111 if( nPrintCol<1 ) nPrintCol = 1;
10112 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
10113 for(i=0; i<nPrintRow; i++){
10114 for(j=i; j<nRow; j+=nPrintRow){
10115 char *zSp = j<nPrintRow ? "" : " ";
10116 utf8_printf(p->out, "%s%-*s", zSp, maxlen,
10117 azResult[j] ? azResult[j]:"");
10118 }
10119 raw_printf(p->out, "\n");
10120 }
10121 }
10122
10123 for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
10124 sqlite3_free(azResult);
10125 }else
10126
10127 /* Begin redirecting output to the file "testcase-out.txt" */
10128 if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
10129 output_reset(p);
drha92a01a2018-01-10 22:15:37 +000010130 p->out = output_file_open("testcase-out.txt", 0);
drh2ce15c32017-07-11 13:34:40 +000010131 if( p->out==0 ){
10132 raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
10133 }
10134 if( nArg>=2 ){
10135 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
10136 }else{
10137 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
10138 }
10139 }else
10140
10141#ifndef SQLITE_UNTESTABLE
drh35f51a42017-11-15 17:07:22 +000010142 if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010143 static const struct {
10144 const char *zCtrlName; /* Name of a test-control option */
10145 int ctrlCode; /* Integer code for that option */
drhef302e82017-11-15 19:14:08 +000010146 const char *zUsage; /* Usage notes */
drh2ce15c32017-07-11 13:34:40 +000010147 } aCtrl[] = {
drhe2754c12019-08-26 12:50:01 +000010148 { "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" },
10149 { "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" },
10150 /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/
10151 /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/
10152 { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" },
10153 { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN" },
10154 /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" },*/
10155 { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
drh171c50e2020-01-01 15:43:30 +000010156 { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "" },
drhe2754c12019-08-26 12:50:01 +000010157 { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" },
10158 { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" },
10159 { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" },
drh0d9de992017-12-26 18:04:23 +000010160#ifdef YYCOVERAGE
drhe2754c12019-08-26 12:50:01 +000010161 { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" },
drh0d9de992017-12-26 18:04:23 +000010162#endif
drhe2754c12019-08-26 12:50:01 +000010163 { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " },
10164 { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
10165 { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
10166 { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
drh37ccfcf2020-08-31 18:49:04 +000010167 { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, "" },
dan779e9902021-07-28 18:13:28 +000010168 { "sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, "NMAX" },
drhf3c12562021-06-04 13:16:46 +000010169 { "tune", SQLITE_TESTCTRL_TUNE, "ID VALUE" },
drh2ce15c32017-07-11 13:34:40 +000010170 };
10171 int testctrl = -1;
drhef302e82017-11-15 19:14:08 +000010172 int iCtrl = -1;
10173 int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */
10174 int isOk = 0;
drh2ce15c32017-07-11 13:34:40 +000010175 int i, n2;
mistachkinc6bc15a2017-11-21 21:14:32 +000010176 const char *zCmd = 0;
10177
drh2ce15c32017-07-11 13:34:40 +000010178 open_db(p, 0);
mistachkinc6bc15a2017-11-21 21:14:32 +000010179 zCmd = nArg>=2 ? azArg[1] : "help";
drh35f51a42017-11-15 17:07:22 +000010180
10181 /* The argument can optionally begin with "-" or "--" */
10182 if( zCmd[0]=='-' && zCmd[1] ){
10183 zCmd++;
10184 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
10185 }
10186
10187 /* --help lists all test-controls */
10188 if( strcmp(zCmd,"help")==0 ){
10189 utf8_printf(p->out, "Available test-controls:\n");
10190 for(i=0; i<ArraySize(aCtrl); i++){
drhef302e82017-11-15 19:14:08 +000010191 utf8_printf(p->out, " .testctrl %s %s\n",
10192 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
drh35f51a42017-11-15 17:07:22 +000010193 }
10194 rc = 1;
10195 goto meta_command_exit;
10196 }
drh2ce15c32017-07-11 13:34:40 +000010197
10198 /* convert testctrl text option to value. allow any unique prefix
10199 ** of the option name, or a numerical value. */
drh35f51a42017-11-15 17:07:22 +000010200 n2 = strlen30(zCmd);
drh2ce15c32017-07-11 13:34:40 +000010201 for(i=0; i<ArraySize(aCtrl); i++){
drh35f51a42017-11-15 17:07:22 +000010202 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010203 if( testctrl<0 ){
10204 testctrl = aCtrl[i].ctrlCode;
drhef302e82017-11-15 19:14:08 +000010205 iCtrl = i;
drh2ce15c32017-07-11 13:34:40 +000010206 }else{
drh35f51a42017-11-15 17:07:22 +000010207 utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
10208 "Use \".testctrl --help\" for help\n", zCmd);
10209 rc = 1;
10210 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +000010211 }
10212 }
10213 }
drhef302e82017-11-15 19:14:08 +000010214 if( testctrl<0 ){
drh35f51a42017-11-15 17:07:22 +000010215 utf8_printf(stderr,"Error: unknown test-control: %s\n"
10216 "Use \".testctrl --help\" for help\n", zCmd);
drh2ce15c32017-07-11 13:34:40 +000010217 }else{
10218 switch(testctrl){
10219
10220 /* sqlite3_test_control(int, db, int) */
10221 case SQLITE_TESTCTRL_OPTIMIZATIONS:
drh2ce15c32017-07-11 13:34:40 +000010222 if( nArg==3 ){
drhaf7b7652021-01-13 19:28:17 +000010223 unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
drh2ce15c32017-07-11 13:34:40 +000010224 rc2 = sqlite3_test_control(testctrl, p->db, opt);
drhef302e82017-11-15 19:14:08 +000010225 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010226 }
10227 break;
10228
10229 /* sqlite3_test_control(int) */
10230 case SQLITE_TESTCTRL_PRNG_SAVE:
10231 case SQLITE_TESTCTRL_PRNG_RESTORE:
drh2ce15c32017-07-11 13:34:40 +000010232 case SQLITE_TESTCTRL_BYTEORDER:
10233 if( nArg==2 ){
10234 rc2 = sqlite3_test_control(testctrl);
drhef302e82017-11-15 19:14:08 +000010235 isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
drh2ce15c32017-07-11 13:34:40 +000010236 }
10237 break;
10238
10239 /* sqlite3_test_control(int, uint) */
10240 case SQLITE_TESTCTRL_PENDING_BYTE:
10241 if( nArg==3 ){
10242 unsigned int opt = (unsigned int)integerValue(azArg[2]);
10243 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010244 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010245 }
10246 break;
10247
drh2e6d83b2019-08-03 01:39:20 +000010248 /* sqlite3_test_control(int, int, sqlite3*) */
10249 case SQLITE_TESTCTRL_PRNG_SEED:
10250 if( nArg==3 || nArg==4 ){
drh51755a72019-08-08 19:40:29 +000010251 int ii = (int)integerValue(azArg[2]);
drh2e6d83b2019-08-03 01:39:20 +000010252 sqlite3 *db;
drh41428a92019-08-12 16:25:11 +000010253 if( ii==0 && strcmp(azArg[2],"random")==0 ){
10254 sqlite3_randomness(sizeof(ii),&ii);
10255 printf("-- random seed: %d\n", ii);
10256 }
drh2e6d83b2019-08-03 01:39:20 +000010257 if( nArg==3 ){
10258 db = 0;
10259 }else{
10260 db = p->db;
10261 /* Make sure the schema has been loaded */
10262 sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);
10263 }
drh51755a72019-08-08 19:40:29 +000010264 rc2 = sqlite3_test_control(testctrl, ii, db);
drh2e6d83b2019-08-03 01:39:20 +000010265 isOk = 3;
10266 }
10267 break;
10268
drh2ce15c32017-07-11 13:34:40 +000010269 /* sqlite3_test_control(int, int) */
10270 case SQLITE_TESTCTRL_ASSERT:
10271 case SQLITE_TESTCTRL_ALWAYS:
drhef302e82017-11-15 19:14:08 +000010272 if( nArg==3 ){
10273 int opt = booleanValue(azArg[2]);
10274 rc2 = sqlite3_test_control(testctrl, opt);
10275 isOk = 1;
10276 }
10277 break;
10278
10279 /* sqlite3_test_control(int, int) */
10280 case SQLITE_TESTCTRL_LOCALTIME_FAULT:
drh2ce15c32017-07-11 13:34:40 +000010281 case SQLITE_TESTCTRL_NEVER_CORRUPT:
10282 if( nArg==3 ){
10283 int opt = booleanValue(azArg[2]);
10284 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010285 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010286 }
10287 break;
10288
drh171c50e2020-01-01 15:43:30 +000010289 /* sqlite3_test_control(sqlite3*) */
10290 case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
10291 rc2 = sqlite3_test_control(testctrl, p->db);
drh2a83c102020-01-01 23:02:35 +000010292 isOk = 3;
drh171c50e2020-01-01 15:43:30 +000010293 break;
10294
drh2ce15c32017-07-11 13:34:40 +000010295 case SQLITE_TESTCTRL_IMPOSTER:
10296 if( nArg==5 ){
10297 rc2 = sqlite3_test_control(testctrl, p->db,
10298 azArg[2],
10299 integerValue(azArg[3]),
10300 integerValue(azArg[4]));
drhef302e82017-11-15 19:14:08 +000010301 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010302 }
10303 break;
drh0d9de992017-12-26 18:04:23 +000010304
drh37ccfcf2020-08-31 18:49:04 +000010305 case SQLITE_TESTCTRL_SEEK_COUNT: {
10306 u64 x = 0;
10307 rc2 = sqlite3_test_control(testctrl, p->db, &x);
10308 utf8_printf(p->out, "%llu\n", x);
10309 isOk = 3;
10310 break;
10311 }
10312
drh0d9de992017-12-26 18:04:23 +000010313#ifdef YYCOVERAGE
drhf3c12562021-06-04 13:16:46 +000010314 case SQLITE_TESTCTRL_PARSER_COVERAGE: {
drh0d9de992017-12-26 18:04:23 +000010315 if( nArg==2 ){
10316 sqlite3_test_control(testctrl, p->out);
10317 isOk = 3;
10318 }
drhf3c12562021-06-04 13:16:46 +000010319 break;
10320 }
10321#endif
10322#ifdef SQLITE_DEBUG
10323 case SQLITE_TESTCTRL_TUNE: {
10324 if( nArg==4 ){
10325 int id = (int)integerValue(azArg[2]);
drh2d26cfc2021-06-04 13:40:26 +000010326 int val = (int)integerValue(azArg[3]);
10327 sqlite3_test_control(testctrl, id, &val);
10328 isOk = 3;
10329 }else if( nArg==3 ){
10330 int id = (int)integerValue(azArg[2]);
10331 sqlite3_test_control(testctrl, -id, &rc2);
10332 isOk = 1;
10333 }else if( nArg==2 ){
10334 int id = 1;
10335 while(1){
10336 int val = 0;
10337 rc2 = sqlite3_test_control(testctrl, -id, &val);
10338 if( rc2!=SQLITE_OK ) break;
10339 if( id>1 ) utf8_printf(p->out, " ");
10340 utf8_printf(p->out, "%d: %d", id, val);
10341 id++;
10342 }
10343 if( id>1 ) utf8_printf(p->out, "\n");
drhf3c12562021-06-04 13:16:46 +000010344 isOk = 3;
10345 }
10346 break;
10347 }
drh0d9de992017-12-26 18:04:23 +000010348#endif
dan779e9902021-07-28 18:13:28 +000010349 case SQLITE_TESTCTRL_SORTER_MMAP:
10350 if( nArg==3 ){
10351 int opt = (unsigned int)integerValue(azArg[2]);
10352 rc2 = sqlite3_test_control(testctrl, p->db, opt);
10353 isOk = 3;
10354 }
10355 break;
drh2ce15c32017-07-11 13:34:40 +000010356 }
10357 }
drhef302e82017-11-15 19:14:08 +000010358 if( isOk==0 && iCtrl>=0 ){
drhe2754c12019-08-26 12:50:01 +000010359 utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
drhef302e82017-11-15 19:14:08 +000010360 rc = 1;
10361 }else if( isOk==1 ){
10362 raw_printf(p->out, "%d\n", rc2);
10363 }else if( isOk==2 ){
10364 raw_printf(p->out, "0x%08x\n", rc2);
10365 }
drh2ce15c32017-07-11 13:34:40 +000010366 }else
10367#endif /* !defined(SQLITE_UNTESTABLE) */
10368
10369 if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
10370 open_db(p, 0);
10371 sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
10372 }else
10373
10374 if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
10375 if( nArg==2 ){
10376 enableTimer = booleanValue(azArg[1]);
10377 if( enableTimer && !HAS_TIMER ){
10378 raw_printf(stderr, "Error: timer not available on this system.\n");
10379 enableTimer = 0;
10380 }
10381 }else{
10382 raw_printf(stderr, "Usage: .timer on|off\n");
10383 rc = 1;
10384 }
10385 }else
10386
drh707821f2018-12-05 13:39:06 +000010387#ifndef SQLITE_OMIT_TRACE
drh2ce15c32017-07-11 13:34:40 +000010388 if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
drh707821f2018-12-05 13:39:06 +000010389 int mType = 0;
10390 int jj;
drh2ce15c32017-07-11 13:34:40 +000010391 open_db(p, 0);
drh707821f2018-12-05 13:39:06 +000010392 for(jj=1; jj<nArg; jj++){
10393 const char *z = azArg[jj];
10394 if( z[0]=='-' ){
10395 if( optionMatch(z, "expanded") ){
10396 p->eTraceType = SHELL_TRACE_EXPANDED;
10397 }
10398#ifdef SQLITE_ENABLE_NORMALIZE
10399 else if( optionMatch(z, "normalized") ){
10400 p->eTraceType = SHELL_TRACE_NORMALIZED;
10401 }
10402#endif
10403 else if( optionMatch(z, "plain") ){
10404 p->eTraceType = SHELL_TRACE_PLAIN;
10405 }
10406 else if( optionMatch(z, "profile") ){
10407 mType |= SQLITE_TRACE_PROFILE;
10408 }
10409 else if( optionMatch(z, "row") ){
10410 mType |= SQLITE_TRACE_ROW;
10411 }
10412 else if( optionMatch(z, "stmt") ){
10413 mType |= SQLITE_TRACE_STMT;
10414 }
10415 else if( optionMatch(z, "close") ){
10416 mType |= SQLITE_TRACE_CLOSE;
10417 }
10418 else {
10419 raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
10420 rc = 1;
10421 goto meta_command_exit;
10422 }
10423 }else{
10424 output_file_close(p->traceOut);
10425 p->traceOut = output_file_open(azArg[1], 0);
10426 }
drh2ce15c32017-07-11 13:34:40 +000010427 }
drh2ce15c32017-07-11 13:34:40 +000010428 if( p->traceOut==0 ){
10429 sqlite3_trace_v2(p->db, 0, 0, 0);
10430 }else{
drh707821f2018-12-05 13:39:06 +000010431 if( mType==0 ) mType = SQLITE_TRACE_STMT;
10432 sqlite3_trace_v2(p->db, mType, sql_trace_callback, p);
drh2ce15c32017-07-11 13:34:40 +000010433 }
drh2ce15c32017-07-11 13:34:40 +000010434 }else
drh707821f2018-12-05 13:39:06 +000010435#endif /* !defined(SQLITE_OMIT_TRACE) */
drh2ce15c32017-07-11 13:34:40 +000010436
drhe2b7a762019-10-02 00:25:08 +000010437#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhcc5979d2019-08-16 22:58:29 +000010438 if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){
10439 int ii;
drh8c754a32019-08-19 20:35:30 +000010440 int lenOpt;
drh5df84282019-08-17 19:45:25 +000010441 char *zOpt;
drhcc5979d2019-08-16 22:58:29 +000010442 if( nArg<2 ){
drh5df84282019-08-17 19:45:25 +000010443 raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
drhcc5979d2019-08-16 22:58:29 +000010444 rc = 1;
10445 goto meta_command_exit;
10446 }
10447 open_db(p, 0);
drh5df84282019-08-17 19:45:25 +000010448 zOpt = azArg[1];
10449 if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
drh8c754a32019-08-19 20:35:30 +000010450 lenOpt = (int)strlen(zOpt);
10451 if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){
drh5df84282019-08-17 19:45:25 +000010452 assert( azArg[nArg]==0 );
drh8c754a32019-08-19 20:35:30 +000010453 sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0);
drh5df84282019-08-17 19:45:25 +000010454 }else{
10455 for(ii=1; ii<nArg; ii++){
10456 sqlite3_create_module(p->db, azArg[ii], 0, 0);
10457 }
drhcc5979d2019-08-16 22:58:29 +000010458 }
10459 }else
10460#endif
10461
drh2ce15c32017-07-11 13:34:40 +000010462#if SQLITE_USER_AUTHENTICATION
10463 if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
10464 if( nArg<2 ){
10465 raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
10466 rc = 1;
10467 goto meta_command_exit;
10468 }
10469 open_db(p, 0);
10470 if( strcmp(azArg[1],"login")==0 ){
10471 if( nArg!=4 ){
10472 raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
10473 rc = 1;
10474 goto meta_command_exit;
10475 }
drhe2754c12019-08-26 12:50:01 +000010476 rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
10477 strlen30(azArg[3]));
drh2ce15c32017-07-11 13:34:40 +000010478 if( rc ){
10479 utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
10480 rc = 1;
10481 }
10482 }else if( strcmp(azArg[1],"add")==0 ){
10483 if( nArg!=5 ){
10484 raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
10485 rc = 1;
10486 goto meta_command_exit;
10487 }
drhaf2770f2018-01-05 14:55:43 +000010488 rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000010489 booleanValue(azArg[4]));
10490 if( rc ){
10491 raw_printf(stderr, "User-Add failed: %d\n", rc);
10492 rc = 1;
10493 }
10494 }else if( strcmp(azArg[1],"edit")==0 ){
10495 if( nArg!=5 ){
10496 raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
10497 rc = 1;
10498 goto meta_command_exit;
10499 }
drhaf2770f2018-01-05 14:55:43 +000010500 rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000010501 booleanValue(azArg[4]));
10502 if( rc ){
10503 raw_printf(stderr, "User-Edit failed: %d\n", rc);
10504 rc = 1;
10505 }
10506 }else if( strcmp(azArg[1],"delete")==0 ){
10507 if( nArg!=3 ){
10508 raw_printf(stderr, "Usage: .user delete USER\n");
10509 rc = 1;
10510 goto meta_command_exit;
10511 }
10512 rc = sqlite3_user_delete(p->db, azArg[2]);
10513 if( rc ){
10514 raw_printf(stderr, "User-Delete failed: %d\n", rc);
10515 rc = 1;
10516 }
10517 }else{
10518 raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
10519 rc = 1;
10520 goto meta_command_exit;
10521 }
10522 }else
10523#endif /* SQLITE_USER_AUTHENTICATION */
10524
10525 if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
10526 utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
10527 sqlite3_libversion(), sqlite3_sourceid());
drh0ed2fd82018-01-16 20:05:27 +000010528#if SQLITE_HAVE_ZLIB
10529 utf8_printf(p->out, "zlib version %s\n", zlibVersion());
10530#endif
10531#define CTIMEOPT_VAL_(opt) #opt
10532#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
10533#if defined(__clang__) && defined(__clang_major__)
10534 utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
10535 CTIMEOPT_VAL(__clang_minor__) "."
10536 CTIMEOPT_VAL(__clang_patchlevel__) "\n");
10537#elif defined(_MSC_VER)
10538 utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n");
10539#elif defined(__GNUC__) && defined(__VERSION__)
10540 utf8_printf(p->out, "gcc-" __VERSION__ "\n");
10541#endif
drh2ce15c32017-07-11 13:34:40 +000010542 }else
10543
10544 if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
10545 const char *zDbName = nArg==2 ? azArg[1] : "main";
10546 sqlite3_vfs *pVfs = 0;
10547 if( p->db ){
10548 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
10549 if( pVfs ){
10550 utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
10551 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
10552 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
10553 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
10554 }
10555 }
10556 }else
10557
10558 if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){
10559 sqlite3_vfs *pVfs;
10560 sqlite3_vfs *pCurrent = 0;
10561 if( p->db ){
10562 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
10563 }
10564 for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
10565 utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName,
10566 pVfs==pCurrent ? " <--- CURRENT" : "");
10567 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
10568 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
10569 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
10570 if( pVfs->pNext ){
10571 raw_printf(p->out, "-----------------------------------\n");
10572 }
10573 }
10574 }else
10575
10576 if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
10577 const char *zDbName = nArg==2 ? azArg[1] : "main";
10578 char *zVfsName = 0;
10579 if( p->db ){
10580 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
10581 if( zVfsName ){
10582 utf8_printf(p->out, "%s\n", zVfsName);
10583 sqlite3_free(zVfsName);
10584 }
10585 }
10586 }else
10587
drh2ce15c32017-07-11 13:34:40 +000010588 if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
drhc0622a42020-12-04 01:17:57 +000010589 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
10590 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x);
drh2ce15c32017-07-11 13:34:40 +000010591 }else
drh2ce15c32017-07-11 13:34:40 +000010592
10593 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
10594 int j;
10595 assert( nArg<=ArraySize(azArg) );
drh0285d982020-05-29 14:38:43 +000010596 p->nWidth = nArg-1;
10597 p->colWidth = realloc(p->colWidth, p->nWidth*sizeof(int)*2);
10598 if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory();
10599 if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
10600 for(j=1; j<nArg; j++){
drh2ce15c32017-07-11 13:34:40 +000010601 p->colWidth[j-1] = (int)integerValue(azArg[j]);
10602 }
10603 }else
10604
10605 {
10606 utf8_printf(stderr, "Error: unknown command or invalid arguments: "
10607 " \"%s\". Enter \".help\" for help\n", azArg[0]);
10608 rc = 1;
10609 }
10610
10611meta_command_exit:
10612 if( p->outCount ){
10613 p->outCount--;
10614 if( p->outCount==0 ) output_reset(p);
10615 }
drhb97e2ad2021-08-26 18:31:39 +000010616 p->bSafeMode = p->bSafeModePersist;
drh2ce15c32017-07-11 13:34:40 +000010617 return rc;
10618}
10619
larrybr8bc4cbc2021-09-10 00:58:46 +000010620/* Line scan result and intermediate states (supporting scan resumption)
drh2ce15c32017-07-11 13:34:40 +000010621*/
larrybr8bc4cbc2021-09-10 00:58:46 +000010622typedef enum {
larrybr7e009842021-09-18 21:35:22 +000010623 QSS_HasDark = 1<<CHAR_BIT, QSS_EndingSemi = 2<<CHAR_BIT,
10624 QSS_CharMask = (1<<CHAR_BIT)-1, QSS_ScanMask = 3<<CHAR_BIT,
larrybra96bbe92021-09-10 19:45:22 +000010625 QSS_Start = 0
larrybr8bc4cbc2021-09-10 00:58:46 +000010626} QuickScanState;
larrybr7e009842021-09-18 21:35:22 +000010627#define QSS_SETV(qss, newst) ((newst) | ((qss) & QSS_ScanMask))
10628#define QSS_INPLAIN(qss) (((qss)&QSS_CharMask)==QSS_Start)
10629#define QSS_PLAINWHITE(qss) (((qss)&~QSS_EndingSemi)==QSS_Start)
larrybra96bbe92021-09-10 19:45:22 +000010630#define QSS_PLAINDARK(qss) (((qss)&~QSS_EndingSemi)==QSS_HasDark)
larrybr7e009842021-09-18 21:35:22 +000010631#define QSS_SEMITERM(qss) (((qss)&~QSS_HasDark)==QSS_EndingSemi)
drh2ce15c32017-07-11 13:34:40 +000010632
10633/*
larrybr8bc4cbc2021-09-10 00:58:46 +000010634** Scan line for classification to guide shell's handling.
10635** The scan is resumable for subsequent lines when prior
10636** return values are passed as the 2nd argument.
drh2ce15c32017-07-11 13:34:40 +000010637*/
larrybr8bc4cbc2021-09-10 00:58:46 +000010638static QuickScanState quickscan(char *zLine, QuickScanState qss){
10639 char cin;
larrybr7e009842021-09-18 21:35:22 +000010640 char cWait = (char)qss; /* intentional narrowing loss */
10641 if( cWait==0 ){
10642 PlainScan:
larrybr8bc4cbc2021-09-10 00:58:46 +000010643 while (cin = *zLine++){
10644 if( IsSpace(cin) )
10645 continue;
10646 switch (cin){
10647 case '-':
larrybr7e009842021-09-18 21:35:22 +000010648 if( *zLine!='-' )
10649 break;
10650 while((cin = *++zLine)!=0 )
10651 if( cin=='\n')
10652 goto PlainScan;
10653 return qss;
larrybr8bc4cbc2021-09-10 00:58:46 +000010654 case ';':
larrybra96bbe92021-09-10 19:45:22 +000010655 qss |= QSS_EndingSemi;
10656 continue;
larrybr8bc4cbc2021-09-10 00:58:46 +000010657 case '/':
10658 if( *zLine=='*' ){
10659 ++zLine;
larrybr7e009842021-09-18 21:35:22 +000010660 cWait = '*';
10661 qss = QSS_SETV(qss, cWait);
10662 goto TermScan;
larrybr8bc4cbc2021-09-10 00:58:46 +000010663 }
10664 break;
larrybra96bbe92021-09-10 19:45:22 +000010665 case '[':
10666 cin = ']';
10667 /* fall thru */
10668 case '`': case '\'': case '"':
larrybr7e009842021-09-18 21:35:22 +000010669 cWait = cin;
10670 qss = QSS_HasDark | cWait;
10671 goto TermScan;
larrybr8bc4cbc2021-09-10 00:58:46 +000010672 default:
10673 break;
10674 }
larrybr7e009842021-09-18 21:35:22 +000010675 qss = (qss & ~QSS_EndingSemi) | QSS_HasDark;
drh2ce15c32017-07-11 13:34:40 +000010676 }
larrybr7e009842021-09-18 21:35:22 +000010677 }else{
10678 TermScan:
10679 while (cin = *zLine++){
10680 if( cin==cWait ){
10681 switch( cWait ){
10682 case '*':
10683 if( *zLine != '/' )
10684 continue;
10685 ++zLine;
10686 cWait = 0;
10687 qss = QSS_SETV(qss, 0);
10688 goto PlainScan;
10689 case '`': case '\'': case '"':
10690 if(*zLine==cWait){
larrybr8d463ce2021-09-11 02:42:04 +000010691 ++zLine;
larrybr7e009842021-09-18 21:35:22 +000010692 continue;
10693 }
10694 /* fall thru */
10695 case ']':
10696 cWait = 0;
10697 qss = QSS_SETV(qss, 0);
10698 goto PlainScan;
10699 default: assert(0);
larrybr8bc4cbc2021-09-10 00:58:46 +000010700 }
10701 }
10702 }
drh2ce15c32017-07-11 13:34:40 +000010703 }
larrybr8bc4cbc2021-09-10 00:58:46 +000010704 return qss;
drh2ce15c32017-07-11 13:34:40 +000010705}
10706
10707/*
10708** Return TRUE if the line typed in is an SQL command terminator other
10709** than a semi-colon. The SQL Server style "go" command is understood
10710** as is the Oracle "/".
10711*/
larrybr8bc4cbc2021-09-10 00:58:46 +000010712static int line_is_command_terminator(char *zLine){
drh2ce15c32017-07-11 13:34:40 +000010713 while( IsSpace(zLine[0]) ){ zLine++; };
larrybr8bc4cbc2021-09-10 00:58:46 +000010714 if( zLine[0]=='/' )
10715 zLine += 1; /* Oracle */
10716 else if ( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o' )
10717 zLine += 2; /* SQL Server */
10718 else
10719 return 0;
larrybra96bbe92021-09-10 19:45:22 +000010720 return quickscan(zLine,QSS_Start)==QSS_Start;
drh2ce15c32017-07-11 13:34:40 +000010721}
10722
10723/*
drh56f17742018-01-24 01:58:49 +000010724** We need a default sqlite3_complete() implementation to use in case
10725** the shell is compiled with SQLITE_OMIT_COMPLETE. The default assumes
10726** any arbitrary text is a complete SQL statement. This is not very
10727** user-friendly, but it does seem to work.
10728*/
10729#ifdef SQLITE_OMIT_COMPLETE
danc86b23b2018-11-16 14:36:42 +000010730#define sqlite3_complete(x) 1
drh56f17742018-01-24 01:58:49 +000010731#endif
10732
10733/*
drh2ce15c32017-07-11 13:34:40 +000010734** Return true if zSql is a complete SQL statement. Return false if it
10735** ends in the middle of a string literal or C-style comment.
10736*/
10737static int line_is_complete(char *zSql, int nSql){
10738 int rc;
10739 if( zSql==0 ) return 1;
10740 zSql[nSql] = ';';
10741 zSql[nSql+1] = 0;
10742 rc = sqlite3_complete(zSql);
10743 zSql[nSql] = 0;
10744 return rc;
10745}
10746
10747/*
drhfc29a862018-05-11 19:11:18 +000010748** Run a single line of SQL. Return the number of errors.
drh2ce15c32017-07-11 13:34:40 +000010749*/
10750static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
10751 int rc;
10752 char *zErrMsg = 0;
10753
10754 open_db(p, 0);
10755 if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
drhfc4eeef2019-02-05 19:48:46 +000010756 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
drh2ce15c32017-07-11 13:34:40 +000010757 BEGIN_TIMER;
drha10b9992018-03-09 15:24:33 +000010758 rc = shell_exec(p, zSql, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000010759 END_TIMER;
10760 if( rc || zErrMsg ){
10761 char zPrefix[100];
10762 if( in!=0 || !stdin_is_interactive ){
10763 sqlite3_snprintf(sizeof(zPrefix), zPrefix,
10764 "Error: near line %d:", startline);
10765 }else{
10766 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
10767 }
10768 if( zErrMsg!=0 ){
10769 utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
10770 sqlite3_free(zErrMsg);
10771 zErrMsg = 0;
10772 }else{
10773 utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
10774 }
10775 return 1;
10776 }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
drh6d9f0342021-09-22 10:28:50 +000010777 char zLineBuf[2000];
10778 sqlite3_snprintf(sizeof(zLineBuf), zLineBuf,
10779 "changes: %lld total_changes: %lld",
larrybr10496f72021-06-23 16:07:20 +000010780 sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
drh6d9f0342021-09-22 10:28:50 +000010781 raw_printf(p->out, "%s\n", zLineBuf);
drh2ce15c32017-07-11 13:34:40 +000010782 }
10783 return 0;
10784}
10785
10786
10787/*
10788** Read input from *in and process it. If *in==0 then input
10789** is interactive - the user is typing it it. Otherwise, input
10790** is coming from a file or device. A prompt is issued and history
10791** is saved only if input is interactive. An interrupt signal will
10792** cause this routine to exit immediately, unless input is interactive.
10793**
10794** Return the number of errors.
10795*/
drh60379d42018-12-13 18:30:01 +000010796static int process_input(ShellState *p){
drh2ce15c32017-07-11 13:34:40 +000010797 char *zLine = 0; /* A single input line */
10798 char *zSql = 0; /* Accumulated SQL text */
10799 int nLine; /* Length of current line */
10800 int nSql = 0; /* Bytes of zSql[] used */
10801 int nAlloc = 0; /* Allocated zSql[] space */
10802 int nSqlPrior = 0; /* Bytes of zSql[] used by prior line */
10803 int rc; /* Error code */
10804 int errCnt = 0; /* Number of errors seen */
drh2ce15c32017-07-11 13:34:40 +000010805 int startline = 0; /* Line number for start of current input */
larrybr7e009842021-09-18 21:35:22 +000010806 QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */
drh2ce15c32017-07-11 13:34:40 +000010807
drh2c8ee022018-12-13 18:59:30 +000010808 p->lineno = 0;
drh60379d42018-12-13 18:30:01 +000010809 while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
drh2ce15c32017-07-11 13:34:40 +000010810 fflush(p->out);
drh60379d42018-12-13 18:30:01 +000010811 zLine = one_input_line(p->in, zLine, nSql>0);
drh2ce15c32017-07-11 13:34:40 +000010812 if( zLine==0 ){
10813 /* End of input */
drh60379d42018-12-13 18:30:01 +000010814 if( p->in==0 && stdin_is_interactive ) printf("\n");
drh2ce15c32017-07-11 13:34:40 +000010815 break;
10816 }
10817 if( seenInterrupt ){
drh60379d42018-12-13 18:30:01 +000010818 if( p->in!=0 ) break;
drh2ce15c32017-07-11 13:34:40 +000010819 seenInterrupt = 0;
10820 }
drh2c8ee022018-12-13 18:59:30 +000010821 p->lineno++;
larrybr7e009842021-09-18 21:35:22 +000010822 if( QSS_INPLAIN(qss)
larrybr8bc4cbc2021-09-10 00:58:46 +000010823 && line_is_command_terminator(zLine)
10824 && line_is_complete(zSql, nSql) ){
10825 memcpy(zLine,";",2);
10826 }
10827 qss = quickscan(zLine, qss);
10828 if( QSS_PLAINWHITE(qss) && nSql==0 ){
10829 if( ShellHasFlag(p, SHFLG_Echo) )
10830 printf("%s\n", zLine);
10831 /* Just swallow leading whitespace */
10832 continue;
drh2ce15c32017-07-11 13:34:40 +000010833 }
drh1615c372018-05-12 23:56:22 +000010834 if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
drh2ce15c32017-07-11 13:34:40 +000010835 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
drh1615c372018-05-12 23:56:22 +000010836 if( zLine[0]=='.' ){
10837 rc = do_meta_command(zLine, p);
10838 if( rc==2 ){ /* exit requested */
10839 break;
10840 }else if( rc ){
10841 errCnt++;
10842 }
drh2ce15c32017-07-11 13:34:40 +000010843 }
10844 continue;
10845 }
drh2ce15c32017-07-11 13:34:40 +000010846 nLine = strlen30(zLine);
10847 if( nSql+nLine+2>=nAlloc ){
larrybr31bffb42021-09-08 21:49:03 +000010848 /* Grow buffer by half-again increments when big. */
10849 nAlloc = nSql+(nSql>>1)+nLine+100;
drh2ce15c32017-07-11 13:34:40 +000010850 zSql = realloc(zSql, nAlloc);
drh4b5345c2018-04-24 13:07:40 +000010851 if( zSql==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +000010852 }
10853 nSqlPrior = nSql;
10854 if( nSql==0 ){
10855 int i;
10856 for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
10857 assert( nAlloc>0 && zSql!=0 );
10858 memcpy(zSql, zLine+i, nLine+1-i);
drh2c8ee022018-12-13 18:59:30 +000010859 startline = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000010860 nSql = nLine-i;
10861 }else{
10862 zSql[nSql++] = '\n';
10863 memcpy(zSql+nSql, zLine, nLine+1);
10864 nSql += nLine;
10865 }
larrybra96bbe92021-09-10 19:45:22 +000010866 if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){
drh60379d42018-12-13 18:30:01 +000010867 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000010868 nSql = 0;
10869 if( p->outCount ){
10870 output_reset(p);
10871 p->outCount = 0;
drh13c20932018-01-10 21:41:55 +000010872 }else{
10873 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +000010874 }
drhb97e2ad2021-08-26 18:31:39 +000010875 p->bSafeMode = p->bSafeModePersist;
larrybr8bc4cbc2021-09-10 00:58:46 +000010876 }else if( nSql && QSS_PLAINWHITE(qss) ){
drh2ce15c32017-07-11 13:34:40 +000010877 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
10878 nSql = 0;
10879 }
10880 }
larrybr8bc4cbc2021-09-10 00:58:46 +000010881 if( nSql && QSS_PLAINDARK(qss) ){
drh60379d42018-12-13 18:30:01 +000010882 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000010883 }
10884 free(zSql);
10885 free(zLine);
10886 return errCnt>0;
10887}
10888
10889/*
10890** Return a pathname which is the user's home directory. A
10891** 0 return indicates an error of some kind.
10892*/
10893static char *find_home_dir(int clearFlag){
10894 static char *home_dir = NULL;
10895 if( clearFlag ){
10896 free(home_dir);
10897 home_dir = 0;
10898 return 0;
10899 }
10900 if( home_dir ) return home_dir;
10901
10902#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
10903 && !defined(__RTP__) && !defined(_WRS_KERNEL)
10904 {
10905 struct passwd *pwent;
10906 uid_t uid = getuid();
10907 if( (pwent=getpwuid(uid)) != NULL) {
10908 home_dir = pwent->pw_dir;
10909 }
10910 }
10911#endif
10912
10913#if defined(_WIN32_WCE)
10914 /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
10915 */
10916 home_dir = "/";
10917#else
10918
10919#if defined(_WIN32) || defined(WIN32)
10920 if (!home_dir) {
10921 home_dir = getenv("USERPROFILE");
10922 }
10923#endif
10924
10925 if (!home_dir) {
10926 home_dir = getenv("HOME");
10927 }
10928
10929#if defined(_WIN32) || defined(WIN32)
10930 if (!home_dir) {
10931 char *zDrive, *zPath;
10932 int n;
10933 zDrive = getenv("HOMEDRIVE");
10934 zPath = getenv("HOMEPATH");
10935 if( zDrive && zPath ){
10936 n = strlen30(zDrive) + strlen30(zPath) + 1;
10937 home_dir = malloc( n );
10938 if( home_dir==0 ) return 0;
10939 sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
10940 return home_dir;
10941 }
10942 home_dir = "c:\\";
10943 }
10944#endif
10945
10946#endif /* !_WIN32_WCE */
10947
10948 if( home_dir ){
10949 int n = strlen30(home_dir) + 1;
10950 char *z = malloc( n );
10951 if( z ) memcpy(z, home_dir, n);
10952 home_dir = z;
10953 }
10954
10955 return home_dir;
10956}
10957
10958/*
10959** Read input from the file given by sqliterc_override. Or if that
10960** parameter is NULL, take input from ~/.sqliterc
10961**
10962** Returns the number of errors.
10963*/
10964static void process_sqliterc(
10965 ShellState *p, /* Configuration data */
10966 const char *sqliterc_override /* Name of config file. NULL to use default */
10967){
10968 char *home_dir = NULL;
10969 const char *sqliterc = sqliterc_override;
10970 char *zBuf = 0;
drh60379d42018-12-13 18:30:01 +000010971 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +000010972 int savedLineno = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000010973
10974 if (sqliterc == NULL) {
10975 home_dir = find_home_dir(0);
10976 if( home_dir==0 ){
10977 raw_printf(stderr, "-- warning: cannot find home directory;"
10978 " cannot read ~/.sqliterc\n");
10979 return;
10980 }
drh2ce15c32017-07-11 13:34:40 +000010981 zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
10982 sqliterc = zBuf;
10983 }
drh60379d42018-12-13 18:30:01 +000010984 p->in = fopen(sqliterc,"rb");
10985 if( p->in ){
drh2ce15c32017-07-11 13:34:40 +000010986 if( stdin_is_interactive ){
10987 utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
10988 }
drhb7c46aa2020-11-25 13:59:47 +000010989 if( process_input(p) && bail_on_error ) exit(1);
drh60379d42018-12-13 18:30:01 +000010990 fclose(p->in);
drhb7c46aa2020-11-25 13:59:47 +000010991 }else if( sqliterc_override!=0 ){
10992 utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
10993 if( bail_on_error ) exit(1);
drh2ce15c32017-07-11 13:34:40 +000010994 }
drh60379d42018-12-13 18:30:01 +000010995 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +000010996 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +000010997 sqlite3_free(zBuf);
10998}
10999
11000/*
11001** Show available command line options
11002*/
11003static const char zOptions[] =
drhda57d962018-03-05 19:34:05 +000011004#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhad7fd5d2018-03-05 20:21:50 +000011005 " -A ARGS... run \".archive ARGS\" and exit\n"
drhda57d962018-03-05 19:34:05 +000011006#endif
drh3baed312018-03-08 18:14:41 +000011007 " -append append the database to the end of the file\n"
drh2ce15c32017-07-11 13:34:40 +000011008 " -ascii set output mode to 'ascii'\n"
11009 " -bail stop after hitting an error\n"
11010 " -batch force batch I/O\n"
drh0908e382020-06-04 18:05:39 +000011011 " -box set output mode to 'box'\n"
drh2ce15c32017-07-11 13:34:40 +000011012 " -column set output mode to 'column'\n"
11013 " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
11014 " -csv set output mode to 'csv'\n"
drh8d889af2021-05-08 17:18:23 +000011015#if !defined(SQLITE_OMIT_DESERIALIZE)
drh6ca64482019-01-22 16:06:20 +000011016 " -deserialize open the database using sqlite3_deserialize()\n"
11017#endif
drh2ce15c32017-07-11 13:34:40 +000011018 " -echo print commands before execution\n"
11019 " -init FILENAME read/process named file\n"
11020 " -[no]header turn headers on or off\n"
11021#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
11022 " -heap SIZE Size of heap for memsys3 or memsys5\n"
11023#endif
11024 " -help show this message\n"
11025 " -html set output mode to HTML\n"
11026 " -interactive force interactive I/O\n"
drh30c54a02020-05-28 23:49:50 +000011027 " -json set output mode to 'json'\n"
drh2ce15c32017-07-11 13:34:40 +000011028 " -line set output mode to 'line'\n"
11029 " -list set output mode to 'list'\n"
11030 " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
drh30c54a02020-05-28 23:49:50 +000011031 " -markdown set output mode to 'markdown'\n"
drh8d889af2021-05-08 17:18:23 +000011032#if !defined(SQLITE_OMIT_DESERIALIZE)
drh6ca64482019-01-22 16:06:20 +000011033 " -maxsize N maximum size for a --deserialize database\n"
11034#endif
drhaf482572019-02-04 19:52:39 +000011035 " -memtrace trace all memory allocations and deallocations\n"
drh2ce15c32017-07-11 13:34:40 +000011036 " -mmap N default mmap size set to N\n"
11037#ifdef SQLITE_ENABLE_MULTIPLEX
11038 " -multiplex enable the multiplexor VFS\n"
11039#endif
11040 " -newline SEP set output row separator. Default: '\\n'\n"
drh0933aad2019-11-18 17:46:38 +000011041 " -nofollow refuse to open symbolic links to database files\n"
drhb97e2ad2021-08-26 18:31:39 +000011042 " -nonce STRING set the safe-mode escape nonce\n"
drh2ce15c32017-07-11 13:34:40 +000011043 " -nullvalue TEXT set text string for NULL values. Default ''\n"
11044 " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
11045 " -quote set output mode to 'quote'\n"
drhee269a62018-02-14 23:27:43 +000011046 " -readonly open the database read-only\n"
drhb97e2ad2021-08-26 18:31:39 +000011047 " -safe enable safe-mode\n"
drh2ce15c32017-07-11 13:34:40 +000011048 " -separator SEP set output column separator. Default: '|'\n"
drha90d84f2018-04-18 15:21:13 +000011049#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11050 " -sorterref SIZE sorter references threshold size\n"
11051#endif
drh2ce15c32017-07-11 13:34:40 +000011052 " -stats print memory stats before each finalize\n"
drh30c54a02020-05-28 23:49:50 +000011053 " -table set output mode to 'table'\n"
drh2fa78182020-10-31 18:58:37 +000011054 " -tabs set output mode to 'tabs'\n"
drh2ce15c32017-07-11 13:34:40 +000011055 " -version show SQLite version\n"
11056 " -vfs NAME use NAME as the default VFS\n"
11057#ifdef SQLITE_ENABLE_VFSTRACE
11058 " -vfstrace enable tracing of all VFS calls\n"
11059#endif
drh3baed312018-03-08 18:14:41 +000011060#ifdef SQLITE_HAVE_ZLIB
11061 " -zip open the file as a ZIP Archive\n"
11062#endif
drh2ce15c32017-07-11 13:34:40 +000011063;
11064static void usage(int showDetail){
11065 utf8_printf(stderr,
11066 "Usage: %s [OPTIONS] FILENAME [SQL]\n"
11067 "FILENAME is the name of an SQLite database. A new database is created\n"
11068 "if the file does not previously exist.\n", Argv0);
11069 if( showDetail ){
11070 utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
11071 }else{
11072 raw_printf(stderr, "Use the -help option for additional information\n");
11073 }
11074 exit(1);
11075}
11076
11077/*
drhe7df8922018-04-18 10:44:58 +000011078** Internal check: Verify that the SQLite is uninitialized. Print a
11079** error message if it is initialized.
11080*/
11081static void verify_uninitialized(void){
11082 if( sqlite3_config(-1)==SQLITE_MISUSE ){
drh8e02a182018-05-30 07:24:41 +000011083 utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
drhe7df8922018-04-18 10:44:58 +000011084 " initialization.\n");
11085 }
11086}
11087
11088/*
drh2ce15c32017-07-11 13:34:40 +000011089** Initialize the state information in data
11090*/
11091static void main_init(ShellState *data) {
11092 memset(data, 0, sizeof(*data));
11093 data->normalMode = data->cMode = data->mode = MODE_List;
11094 data->autoExplain = 1;
drh37407122021-07-23 18:43:58 +000011095 data->pAuxDb = &data->aAuxDb[0];
drh2ce15c32017-07-11 13:34:40 +000011096 memcpy(data->colSeparator,SEP_Column, 2);
11097 memcpy(data->rowSeparator,SEP_Row, 2);
11098 data->showHeader = 0;
11099 data->shellFlgs = SHFLG_Lookaside;
drhe7df8922018-04-18 10:44:58 +000011100 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000011101 sqlite3_config(SQLITE_CONFIG_URI, 1);
11102 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
11103 sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
11104 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
11105 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
11106}
11107
11108/*
11109** Output text to the console in a font that attracts extra attention.
11110*/
11111#ifdef _WIN32
11112static void printBold(const char *zText){
mistachkin43e86272020-04-09 15:31:22 +000011113#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000011114 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
11115 CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
11116 GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
11117 SetConsoleTextAttribute(out,
11118 FOREGROUND_RED|FOREGROUND_INTENSITY
11119 );
mistachkin43e86272020-04-09 15:31:22 +000011120#endif
drh2ce15c32017-07-11 13:34:40 +000011121 printf("%s", zText);
mistachkin43e86272020-04-09 15:31:22 +000011122#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000011123 SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
mistachkin43e86272020-04-09 15:31:22 +000011124#endif
drh2ce15c32017-07-11 13:34:40 +000011125}
11126#else
11127static void printBold(const char *zText){
11128 printf("\033[1m%s\033[0m", zText);
11129}
11130#endif
11131
11132/*
11133** Get the argument to an --option. Throw an error and die if no argument
11134** is available.
11135*/
11136static char *cmdline_option_value(int argc, char **argv, int i){
11137 if( i==argc ){
11138 utf8_printf(stderr, "%s: Error: missing argument to %s\n",
11139 argv[0], argv[argc-1]);
11140 exit(1);
11141 }
11142 return argv[i];
11143}
11144
11145#ifndef SQLITE_SHELL_IS_UTF8
dan39b6bd52021-03-04 18:31:07 +000011146# if (defined(_WIN32) || defined(WIN32)) \
11147 && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
drh2ce15c32017-07-11 13:34:40 +000011148# define SQLITE_SHELL_IS_UTF8 (0)
11149# else
11150# define SQLITE_SHELL_IS_UTF8 (1)
11151# endif
11152#endif
11153
11154#if SQLITE_SHELL_IS_UTF8
11155int SQLITE_CDECL main(int argc, char **argv){
11156#else
11157int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
11158 char **argv;
11159#endif
11160 char *zErrMsg = 0;
11161 ShellState data;
11162 const char *zInitFile = 0;
11163 int i;
11164 int rc = 0;
11165 int warnInmemoryDb = 0;
11166 int readStdin = 1;
11167 int nCmd = 0;
11168 char **azCmd = 0;
dan16a47422018-04-18 09:16:11 +000011169 const char *zVfs = 0; /* Value of -vfs command-line option */
drh1f22f622018-05-17 13:29:14 +000011170#if !SQLITE_SHELL_IS_UTF8
11171 char **argvToFree = 0;
11172 int argcToFree = 0;
11173#endif
drh2ce15c32017-07-11 13:34:40 +000011174
11175 setBinaryMode(stdin, 0);
11176 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
11177 stdin_is_interactive = isatty(0);
11178 stdout_is_console = isatty(1);
11179
drh4a3a3eb2020-02-29 15:53:48 +000011180#ifdef SQLITE_DEBUG
11181 registerOomSimulator();
11182#endif
11183
mistachkin1e8487d2018-07-22 06:25:35 +000011184#if !defined(_WIN32_WCE)
11185 if( getenv("SQLITE_DEBUG_BREAK") ){
11186 if( isatty(0) && isatty(2) ){
11187 fprintf(stderr,
11188 "attach debugger to process %d and press any key to continue.\n",
11189 GETPID());
11190 fgetc(stdin);
11191 }else{
11192#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +000011193#if SQLITE_OS_WINRT
11194 __debugbreak();
11195#else
mistachkin1e8487d2018-07-22 06:25:35 +000011196 DebugBreak();
mistachkin43e86272020-04-09 15:31:22 +000011197#endif
mistachkin1e8487d2018-07-22 06:25:35 +000011198#elif defined(SIGTRAP)
11199 raise(SIGTRAP);
11200#endif
11201 }
11202 }
11203#endif
11204
drh2ce15c32017-07-11 13:34:40 +000011205#if USE_SYSTEM_SQLITE+0!=1
drhb3c45232017-08-28 14:33:27 +000011206 if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
drh2ce15c32017-07-11 13:34:40 +000011207 utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
11208 sqlite3_sourceid(), SQLITE_SOURCE_ID);
11209 exit(1);
11210 }
11211#endif
11212 main_init(&data);
drh501ea052018-02-15 01:03:37 +000011213
11214 /* On Windows, we must translate command-line arguments into UTF-8.
11215 ** The SQLite memory allocator subsystem has to be enabled in order to
11216 ** do this. But we want to run an sqlite3_shutdown() afterwards so that
11217 ** subsequent sqlite3_config() calls will work. So copy all results into
11218 ** memory that does not come from the SQLite memory allocator.
11219 */
drh4b18c1d2018-02-04 20:33:13 +000011220#if !SQLITE_SHELL_IS_UTF8
drh501ea052018-02-15 01:03:37 +000011221 sqlite3_initialize();
drh1f22f622018-05-17 13:29:14 +000011222 argvToFree = malloc(sizeof(argv[0])*argc*2);
11223 argcToFree = argc;
11224 argv = argvToFree + argc;
drh4b5345c2018-04-24 13:07:40 +000011225 if( argv==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +000011226 for(i=0; i<argc; i++){
drh501ea052018-02-15 01:03:37 +000011227 char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
11228 int n;
drh4b5345c2018-04-24 13:07:40 +000011229 if( z==0 ) shell_out_of_memory();
drh501ea052018-02-15 01:03:37 +000011230 n = (int)strlen(z);
11231 argv[i] = malloc( n+1 );
drh4b5345c2018-04-24 13:07:40 +000011232 if( argv[i]==0 ) shell_out_of_memory();
drh501ea052018-02-15 01:03:37 +000011233 memcpy(argv[i], z, n+1);
drh1f22f622018-05-17 13:29:14 +000011234 argvToFree[i] = argv[i];
drh501ea052018-02-15 01:03:37 +000011235 sqlite3_free(z);
drh2ce15c32017-07-11 13:34:40 +000011236 }
drh501ea052018-02-15 01:03:37 +000011237 sqlite3_shutdown();
drh2ce15c32017-07-11 13:34:40 +000011238#endif
drh501ea052018-02-15 01:03:37 +000011239
drh2ce15c32017-07-11 13:34:40 +000011240 assert( argc>=1 && argv && argv[0] );
11241 Argv0 = argv[0];
11242
11243 /* Make sure we have a valid signal handler early, before anything
11244 ** else is done.
11245 */
11246#ifdef SIGINT
11247 signal(SIGINT, interrupt_handler);
mistachkinb4bab902017-10-27 17:09:44 +000011248#elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
11249 SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
drh2ce15c32017-07-11 13:34:40 +000011250#endif
11251
11252#ifdef SQLITE_SHELL_DBNAME_PROC
11253 {
11254 /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
11255 ** of a C-function that will provide the name of the database file. Use
11256 ** this compile-time option to embed this shell program in larger
11257 ** applications. */
11258 extern void SQLITE_SHELL_DBNAME_PROC(const char**);
drh37407122021-07-23 18:43:58 +000011259 SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename);
drh2ce15c32017-07-11 13:34:40 +000011260 warnInmemoryDb = 0;
11261 }
11262#endif
11263
11264 /* Do an initial pass through the command-line argument to locate
11265 ** the name of the database file, the name of the initialization file,
11266 ** the size of the alternative malloc heap,
11267 ** and the first command to execute.
11268 */
drhe7df8922018-04-18 10:44:58 +000011269 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000011270 for(i=1; i<argc; i++){
11271 char *z;
11272 z = argv[i];
11273 if( z[0]!='-' ){
drh37407122021-07-23 18:43:58 +000011274 if( data.aAuxDb->zDbFilename==0 ){
11275 data.aAuxDb->zDbFilename = z;
drh2ce15c32017-07-11 13:34:40 +000011276 }else{
11277 /* Excesss arguments are interpreted as SQL (or dot-commands) and
11278 ** mean that nothing is read from stdin */
11279 readStdin = 0;
11280 nCmd++;
11281 azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
drh4b5345c2018-04-24 13:07:40 +000011282 if( azCmd==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +000011283 azCmd[nCmd-1] = z;
11284 }
11285 }
11286 if( z[1]=='-' ) z++;
11287 if( strcmp(z,"-separator")==0
11288 || strcmp(z,"-nullvalue")==0
11289 || strcmp(z,"-newline")==0
11290 || strcmp(z,"-cmd")==0
11291 ){
11292 (void)cmdline_option_value(argc, argv, ++i);
11293 }else if( strcmp(z,"-init")==0 ){
11294 zInitFile = cmdline_option_value(argc, argv, ++i);
11295 }else if( strcmp(z,"-batch")==0 ){
11296 /* Need to check for batch mode here to so we can avoid printing
11297 ** informational messages (like from process_sqliterc) before
11298 ** we do the actual processing of arguments later in a second pass.
11299 */
11300 stdin_is_interactive = 0;
11301 }else if( strcmp(z,"-heap")==0 ){
11302#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
11303 const char *zSize;
11304 sqlite3_int64 szHeap;
11305
11306 zSize = cmdline_option_value(argc, argv, ++i);
11307 szHeap = integerValue(zSize);
11308 if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
11309 sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
11310#else
11311 (void)cmdline_option_value(argc, argv, ++i);
11312#endif
drh2ce15c32017-07-11 13:34:40 +000011313 }else if( strcmp(z,"-pagecache")==0 ){
drhf573b4f2020-09-28 13:34:05 +000011314 sqlite3_int64 n, sz;
11315 sz = integerValue(cmdline_option_value(argc,argv,++i));
drh2ce15c32017-07-11 13:34:40 +000011316 if( sz>70000 ) sz = 70000;
11317 if( sz<0 ) sz = 0;
drhf573b4f2020-09-28 13:34:05 +000011318 n = integerValue(cmdline_option_value(argc,argv,++i));
11319 if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
11320 n = 0xffffffffffffLL/sz;
11321 }
drh2ce15c32017-07-11 13:34:40 +000011322 sqlite3_config(SQLITE_CONFIG_PAGECACHE,
11323 (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
11324 data.shellFlgs |= SHFLG_Pagecache;
11325 }else if( strcmp(z,"-lookaside")==0 ){
11326 int n, sz;
11327 sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
11328 if( sz<0 ) sz = 0;
11329 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
11330 if( n<0 ) n = 0;
11331 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
11332 if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
drhaf6d1af2021-08-09 17:37:58 +000011333 }else if( strcmp(z,"-threadsafe")==0 ){
drh9d16fb12021-08-09 17:45:00 +000011334 int n;
11335 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
11336 switch( n ){
drhaf6d1af2021-08-09 17:37:58 +000011337 case 0: sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); break;
11338 case 2: sqlite3_config(SQLITE_CONFIG_MULTITHREAD); break;
11339 default: sqlite3_config(SQLITE_CONFIG_SERIALIZED); break;
11340 }
drh2ce15c32017-07-11 13:34:40 +000011341#ifdef SQLITE_ENABLE_VFSTRACE
11342 }else if( strcmp(z,"-vfstrace")==0 ){
11343 extern int vfstrace_register(
11344 const char *zTraceName,
11345 const char *zOldVfsName,
11346 int (*xOut)(const char*,void*),
11347 void *pOutArg,
11348 int makeDefault
11349 );
11350 vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
11351#endif
11352#ifdef SQLITE_ENABLE_MULTIPLEX
11353 }else if( strcmp(z,"-multiplex")==0 ){
11354 extern int sqlite3_multiple_initialize(const char*,int);
11355 sqlite3_multiplex_initialize(0, 1);
11356#endif
11357 }else if( strcmp(z,"-mmap")==0 ){
11358 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
11359 sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
drha90d84f2018-04-18 15:21:13 +000011360#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11361 }else if( strcmp(z,"-sorterref")==0 ){
11362 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
11363 sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz);
11364#endif
drh2ce15c32017-07-11 13:34:40 +000011365 }else if( strcmp(z,"-vfs")==0 ){
dan16a47422018-04-18 09:16:11 +000011366 zVfs = cmdline_option_value(argc, argv, ++i);
drh3baed312018-03-08 18:14:41 +000011367#ifdef SQLITE_HAVE_ZLIB
drh8682e122018-01-07 20:38:10 +000011368 }else if( strcmp(z,"-zip")==0 ){
11369 data.openMode = SHELL_OPEN_ZIPFILE;
11370#endif
11371 }else if( strcmp(z,"-append")==0 ){
11372 data.openMode = SHELL_OPEN_APPENDVFS;
drh8d889af2021-05-08 17:18:23 +000011373#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +000011374 }else if( strcmp(z,"-deserialize")==0 ){
11375 data.openMode = SHELL_OPEN_DESERIALIZE;
drh6ca64482019-01-22 16:06:20 +000011376 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
11377 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000011378#endif
drhee269a62018-02-14 23:27:43 +000011379 }else if( strcmp(z,"-readonly")==0 ){
11380 data.openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +000011381 }else if( strcmp(z,"-nofollow")==0 ){
11382 data.openFlags = SQLITE_OPEN_NOFOLLOW;
drhda57d962018-03-05 19:34:05 +000011383#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drh93b77312018-03-05 20:20:22 +000011384 }else if( strncmp(z, "-A",2)==0 ){
drhda57d962018-03-05 19:34:05 +000011385 /* All remaining command-line arguments are passed to the ".archive"
11386 ** command, so ignore them */
11387 break;
11388#endif
drh50b910a2019-01-21 14:55:03 +000011389 }else if( strcmp(z, "-memtrace")==0 ){
11390 sqlite3MemTraceActivate(stderr);
drhb7c46aa2020-11-25 13:59:47 +000011391 }else if( strcmp(z,"-bail")==0 ){
11392 bail_on_error = 1;
drhb97e2ad2021-08-26 18:31:39 +000011393 }else if( strcmp(z,"-nonce")==0 ){
11394 free(data.zNonce);
11395 data.zNonce = strdup(argv[++i]);
11396 }else if( strcmp(z,"-safe")==0 ){
11397 /* no-op - catch this on the second pass */
drh2ce15c32017-07-11 13:34:40 +000011398 }
11399 }
drhe7df8922018-04-18 10:44:58 +000011400 verify_uninitialized();
11401
dan16a47422018-04-18 09:16:11 +000011402
drhd11b8f62018-04-25 13:27:07 +000011403#ifdef SQLITE_SHELL_INIT_PROC
11404 {
11405 /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name
11406 ** of a C-function that will perform initialization actions on SQLite that
11407 ** occur just before or after sqlite3_initialize(). Use this compile-time
11408 ** option to embed this shell program in larger applications. */
11409 extern void SQLITE_SHELL_INIT_PROC(void);
11410 SQLITE_SHELL_INIT_PROC();
11411 }
11412#else
dan16a47422018-04-18 09:16:11 +000011413 /* All the sqlite3_config() calls have now been made. So it is safe
11414 ** to call sqlite3_initialize() and process any command line -vfs option. */
11415 sqlite3_initialize();
drhd11b8f62018-04-25 13:27:07 +000011416#endif
11417
dan16a47422018-04-18 09:16:11 +000011418 if( zVfs ){
11419 sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
11420 if( pVfs ){
11421 sqlite3_vfs_register(pVfs, 1);
11422 }else{
11423 utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
11424 exit(1);
11425 }
11426 }
11427
drh37407122021-07-23 18:43:58 +000011428 if( data.pAuxDb->zDbFilename==0 ){
drh2ce15c32017-07-11 13:34:40 +000011429#ifndef SQLITE_OMIT_MEMORYDB
drh37407122021-07-23 18:43:58 +000011430 data.pAuxDb->zDbFilename = ":memory:";
drh2ce15c32017-07-11 13:34:40 +000011431 warnInmemoryDb = argc==1;
11432#else
11433 utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
11434 return 1;
11435#endif
11436 }
11437 data.out = stdout;
drh8682e122018-01-07 20:38:10 +000011438 sqlite3_appendvfs_init(0,0,0);
drh2ce15c32017-07-11 13:34:40 +000011439
11440 /* Go ahead and open the database file if it already exists. If the
11441 ** file does not exist, delay opening it. This prevents empty database
11442 ** files from being created if a user mistypes the database name argument
11443 ** to the sqlite command-line tool.
11444 */
drh37407122021-07-23 18:43:58 +000011445 if( access(data.pAuxDb->zDbFilename, 0)==0 ){
drh2ce15c32017-07-11 13:34:40 +000011446 open_db(&data, 0);
11447 }
11448
11449 /* Process the initialization file if there is one. If no -init option
11450 ** is given on the command line, look for a file named ~/.sqliterc and
11451 ** try to process it.
11452 */
11453 process_sqliterc(&data,zInitFile);
11454
11455 /* Make a second pass through the command-line argument and set
11456 ** options. This second pass is delayed until after the initialization
11457 ** file is processed so that the command-line arguments will override
11458 ** settings in the initialization file.
11459 */
11460 for(i=1; i<argc; i++){
11461 char *z = argv[i];
11462 if( z[0]!='-' ) continue;
11463 if( z[1]=='-' ){ z++; }
11464 if( strcmp(z,"-init")==0 ){
11465 i++;
11466 }else if( strcmp(z,"-html")==0 ){
11467 data.mode = MODE_Html;
11468 }else if( strcmp(z,"-list")==0 ){
11469 data.mode = MODE_List;
11470 }else if( strcmp(z,"-quote")==0 ){
11471 data.mode = MODE_Quote;
drh9191c702020-08-17 09:11:21 +000011472 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma);
11473 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +000011474 }else if( strcmp(z,"-line")==0 ){
11475 data.mode = MODE_Line;
11476 }else if( strcmp(z,"-column")==0 ){
11477 data.mode = MODE_Column;
drh30c54a02020-05-28 23:49:50 +000011478 }else if( strcmp(z,"-json")==0 ){
11479 data.mode = MODE_Json;
11480 }else if( strcmp(z,"-markdown")==0 ){
11481 data.mode = MODE_Markdown;
11482 }else if( strcmp(z,"-table")==0 ){
11483 data.mode = MODE_Table;
drh0908e382020-06-04 18:05:39 +000011484 }else if( strcmp(z,"-box")==0 ){
11485 data.mode = MODE_Box;
drh2ce15c32017-07-11 13:34:40 +000011486 }else if( strcmp(z,"-csv")==0 ){
11487 data.mode = MODE_Csv;
11488 memcpy(data.colSeparator,",",2);
drh3baed312018-03-08 18:14:41 +000011489#ifdef SQLITE_HAVE_ZLIB
drh1fa6d9f2018-01-06 21:46:01 +000011490 }else if( strcmp(z,"-zip")==0 ){
11491 data.openMode = SHELL_OPEN_ZIPFILE;
11492#endif
11493 }else if( strcmp(z,"-append")==0 ){
11494 data.openMode = SHELL_OPEN_APPENDVFS;
drh8d889af2021-05-08 17:18:23 +000011495#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +000011496 }else if( strcmp(z,"-deserialize")==0 ){
11497 data.openMode = SHELL_OPEN_DESERIALIZE;
drh6ca64482019-01-22 16:06:20 +000011498 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
11499 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000011500#endif
drh4aafe592018-03-23 16:08:30 +000011501 }else if( strcmp(z,"-readonly")==0 ){
11502 data.openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +000011503 }else if( strcmp(z,"-nofollow")==0 ){
11504 data.openFlags |= SQLITE_OPEN_NOFOLLOW;
drh2ce15c32017-07-11 13:34:40 +000011505 }else if( strcmp(z,"-ascii")==0 ){
11506 data.mode = MODE_Ascii;
drh2fa78182020-10-31 18:58:37 +000011507 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit);
11508 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record);
11509 }else if( strcmp(z,"-tabs")==0 ){
11510 data.mode = MODE_List;
11511 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Tab);
11512 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +000011513 }else if( strcmp(z,"-separator")==0 ){
11514 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
11515 "%s",cmdline_option_value(argc,argv,++i));
11516 }else if( strcmp(z,"-newline")==0 ){
11517 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
11518 "%s",cmdline_option_value(argc,argv,++i));
11519 }else if( strcmp(z,"-nullvalue")==0 ){
11520 sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
11521 "%s",cmdline_option_value(argc,argv,++i));
11522 }else if( strcmp(z,"-header")==0 ){
11523 data.showHeader = 1;
larrybrae509122021-09-10 01:45:20 +000011524 ShellSetFlag(&data, SHFLG_HeaderSet);
11525 }else if( strcmp(z,"-noheader")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011526 data.showHeader = 0;
larrybrae509122021-09-10 01:45:20 +000011527 ShellSetFlag(&data, SHFLG_HeaderSet);
drh2ce15c32017-07-11 13:34:40 +000011528 }else if( strcmp(z,"-echo")==0 ){
11529 ShellSetFlag(&data, SHFLG_Echo);
11530 }else if( strcmp(z,"-eqp")==0 ){
drhada70452017-12-21 21:02:27 +000011531 data.autoEQP = AUTOEQP_on;
drh2ce15c32017-07-11 13:34:40 +000011532 }else if( strcmp(z,"-eqpfull")==0 ){
drhada70452017-12-21 21:02:27 +000011533 data.autoEQP = AUTOEQP_full;
drh2ce15c32017-07-11 13:34:40 +000011534 }else if( strcmp(z,"-stats")==0 ){
11535 data.statsOn = 1;
11536 }else if( strcmp(z,"-scanstats")==0 ){
11537 data.scanstatsOn = 1;
11538 }else if( strcmp(z,"-backslash")==0 ){
11539 /* Undocumented command-line option: -backslash
11540 ** Causes C-style backslash escapes to be evaluated in SQL statements
11541 ** prior to sending the SQL into SQLite. Useful for injecting
11542 ** crazy bytes in the middle of SQL statements for testing and debugging.
11543 */
11544 ShellSetFlag(&data, SHFLG_Backslash);
11545 }else if( strcmp(z,"-bail")==0 ){
drhb7c46aa2020-11-25 13:59:47 +000011546 /* No-op. The bail_on_error flag should already be set. */
drh2ce15c32017-07-11 13:34:40 +000011547 }else if( strcmp(z,"-version")==0 ){
11548 printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
11549 return 0;
11550 }else if( strcmp(z,"-interactive")==0 ){
11551 stdin_is_interactive = 1;
11552 }else if( strcmp(z,"-batch")==0 ){
11553 stdin_is_interactive = 0;
11554 }else if( strcmp(z,"-heap")==0 ){
11555 i++;
drh2ce15c32017-07-11 13:34:40 +000011556 }else if( strcmp(z,"-pagecache")==0 ){
11557 i+=2;
11558 }else if( strcmp(z,"-lookaside")==0 ){
11559 i+=2;
drhaf6d1af2021-08-09 17:37:58 +000011560 }else if( strcmp(z,"-threadsafe")==0 ){
11561 i+=2;
drhb97e2ad2021-08-26 18:31:39 +000011562 }else if( strcmp(z,"-nonce")==0 ){
11563 i += 2;
drh2ce15c32017-07-11 13:34:40 +000011564 }else if( strcmp(z,"-mmap")==0 ){
11565 i++;
drh50b910a2019-01-21 14:55:03 +000011566 }else if( strcmp(z,"-memtrace")==0 ){
11567 i++;
drha90d84f2018-04-18 15:21:13 +000011568#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11569 }else if( strcmp(z,"-sorterref")==0 ){
11570 i++;
11571#endif
drh2ce15c32017-07-11 13:34:40 +000011572 }else if( strcmp(z,"-vfs")==0 ){
11573 i++;
11574#ifdef SQLITE_ENABLE_VFSTRACE
11575 }else if( strcmp(z,"-vfstrace")==0 ){
11576 i++;
11577#endif
11578#ifdef SQLITE_ENABLE_MULTIPLEX
11579 }else if( strcmp(z,"-multiplex")==0 ){
11580 i++;
11581#endif
11582 }else if( strcmp(z,"-help")==0 ){
11583 usage(1);
11584 }else if( strcmp(z,"-cmd")==0 ){
11585 /* Run commands that follow -cmd first and separately from commands
11586 ** that simply appear on the command-line. This seems goofy. It would
11587 ** be better if all commands ran in the order that they appear. But
11588 ** we retain the goofy behavior for historical compatibility. */
11589 if( i==argc-1 ) break;
11590 z = cmdline_option_value(argc,argv,++i);
11591 if( z[0]=='.' ){
11592 rc = do_meta_command(z, &data);
11593 if( rc && bail_on_error ) return rc==2 ? 0 : rc;
11594 }else{
11595 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000011596 rc = shell_exec(&data, z, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000011597 if( zErrMsg!=0 ){
11598 utf8_printf(stderr,"Error: %s\n", zErrMsg);
11599 if( bail_on_error ) return rc!=0 ? rc : 1;
11600 }else if( rc!=0 ){
11601 utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
11602 if( bail_on_error ) return rc;
11603 }
11604 }
drhda57d962018-03-05 19:34:05 +000011605#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drh93b77312018-03-05 20:20:22 +000011606 }else if( strncmp(z, "-A", 2)==0 ){
drhda57d962018-03-05 19:34:05 +000011607 if( nCmd>0 ){
11608 utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
11609 " with \"%s\"\n", z);
11610 return 1;
11611 }
drhbe4ccb22018-05-17 20:04:24 +000011612 open_db(&data, OPEN_DB_ZIPFILE);
drh93b77312018-03-05 20:20:22 +000011613 if( z[2] ){
11614 argv[i] = &z[2];
drhd0f9cdc2018-05-17 14:09:06 +000011615 arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
drh93b77312018-03-05 20:20:22 +000011616 }else{
drhd0f9cdc2018-05-17 14:09:06 +000011617 arDotCommand(&data, 1, argv+i, argc-i);
drh93b77312018-03-05 20:20:22 +000011618 }
drhda57d962018-03-05 19:34:05 +000011619 readStdin = 0;
11620 break;
11621#endif
drhb97e2ad2021-08-26 18:31:39 +000011622 }else if( strcmp(z,"-safe")==0 ){
11623 data.bSafeMode = data.bSafeModePersist = 1;
drh2ce15c32017-07-11 13:34:40 +000011624 }else{
11625 utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
11626 raw_printf(stderr,"Use -help for a list of options.\n");
11627 return 1;
11628 }
11629 data.cMode = data.mode;
11630 }
11631
11632 if( !readStdin ){
11633 /* Run all arguments that do not begin with '-' as if they were separate
11634 ** command-line inputs, except for the argToSkip argument which contains
11635 ** the database filename.
11636 */
11637 for(i=0; i<nCmd; i++){
11638 if( azCmd[i][0]=='.' ){
11639 rc = do_meta_command(azCmd[i], &data);
danaff1a572020-11-17 21:09:56 +000011640 if( rc ){
11641 free(azCmd);
11642 return rc==2 ? 0 : rc;
11643 }
drh2ce15c32017-07-11 13:34:40 +000011644 }else{
11645 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000011646 rc = shell_exec(&data, azCmd[i], &zErrMsg);
danaff1a572020-11-17 21:09:56 +000011647 if( zErrMsg || rc ){
11648 if( zErrMsg!=0 ){
11649 utf8_printf(stderr,"Error: %s\n", zErrMsg);
11650 }else{
11651 utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
11652 }
11653 sqlite3_free(zErrMsg);
11654 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000011655 return rc!=0 ? rc : 1;
drh2ce15c32017-07-11 13:34:40 +000011656 }
11657 }
11658 }
drh2ce15c32017-07-11 13:34:40 +000011659 }else{
11660 /* Run commands received from standard input
11661 */
11662 if( stdin_is_interactive ){
11663 char *zHome;
drha9e4be32018-10-10 18:56:40 +000011664 char *zHistory;
drh2ce15c32017-07-11 13:34:40 +000011665 int nHistory;
11666 printf(
11667 "SQLite version %s %.19s\n" /*extra-version-info*/
11668 "Enter \".help\" for usage hints.\n",
11669 sqlite3_libversion(), sqlite3_sourceid()
11670 );
11671 if( warnInmemoryDb ){
11672 printf("Connected to a ");
11673 printBold("transient in-memory database");
11674 printf(".\nUse \".open FILENAME\" to reopen on a "
11675 "persistent database.\n");
11676 }
drha9e4be32018-10-10 18:56:40 +000011677 zHistory = getenv("SQLITE_HISTORY");
11678 if( zHistory ){
11679 zHistory = strdup(zHistory);
11680 }else if( (zHome = find_home_dir(0))!=0 ){
drh2ce15c32017-07-11 13:34:40 +000011681 nHistory = strlen30(zHome) + 20;
11682 if( (zHistory = malloc(nHistory))!=0 ){
11683 sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
11684 }
11685 }
11686 if( zHistory ){ shell_read_history(zHistory); }
drh56eb09b2017-07-11 13:59:07 +000011687#if HAVE_READLINE || HAVE_EDITLINE
11688 rl_attempted_completion_function = readline_completion;
11689#elif HAVE_LINENOISE
11690 linenoiseSetCompletionCallback(linenoise_completion);
11691#endif
drh60379d42018-12-13 18:30:01 +000011692 data.in = 0;
11693 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000011694 if( zHistory ){
drh5a75dd82017-07-18 20:59:40 +000011695 shell_stifle_history(2000);
drh2ce15c32017-07-11 13:34:40 +000011696 shell_write_history(zHistory);
11697 free(zHistory);
11698 }
11699 }else{
drh60379d42018-12-13 18:30:01 +000011700 data.in = stdin;
11701 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000011702 }
11703 }
danaff1a572020-11-17 21:09:56 +000011704 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000011705 set_table_name(&data, 0);
11706 if( data.db ){
drh37407122021-07-23 18:43:58 +000011707 session_close_all(&data, -1);
drh9e804032018-05-18 17:11:50 +000011708 close_db(data.db);
drh2ce15c32017-07-11 13:34:40 +000011709 }
drh37407122021-07-23 18:43:58 +000011710 for(i=0; i<ArraySize(data.aAuxDb); i++){
11711 sqlite3_free(data.aAuxDb[i].zFreeOnClose);
11712 if( data.aAuxDb[i].db ){
11713 session_close_all(&data, i);
11714 close_db(data.aAuxDb[i].db);
11715 }
11716 }
drh2ce15c32017-07-11 13:34:40 +000011717 find_home_dir(1);
drh536c3452018-01-11 00:38:39 +000011718 output_reset(&data);
11719 data.doXdgOpen = 0;
drh13c20932018-01-10 21:41:55 +000011720 clearTempFile(&data);
drh2ce15c32017-07-11 13:34:40 +000011721#if !SQLITE_SHELL_IS_UTF8
drh1f22f622018-05-17 13:29:14 +000011722 for(i=0; i<argcToFree; i++) free(argvToFree[i]);
11723 free(argvToFree);
drh2ce15c32017-07-11 13:34:40 +000011724#endif
drh0285d982020-05-29 14:38:43 +000011725 free(data.colWidth);
drhb97e2ad2021-08-26 18:31:39 +000011726 free(data.zNonce);
drh9e804032018-05-18 17:11:50 +000011727 /* Clear the global data structure so that valgrind will detect memory
11728 ** leaks */
11729 memset(&data, 0, sizeof(data));
drh2ce15c32017-07-11 13:34:40 +000011730 return rc;
11731}