blob: f743453b9f912660b683daee9520c15368a1b1a1 [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
430/*
431** This is the name of our program. It is set in main(), used
432** in a number of other places, mostly for error messages.
433*/
434static char *Argv0;
435
436/*
437** Prompt strings. Initialized in main. Settable with
438** .prompt main continue
439*/
440static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/
441static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */
442
443/*
444** Render output like fprintf(). Except, if the output is going to the
445** console and if this is running on a Windows machine, translate the
446** output from UTF-8 into MBCS.
447*/
448#if defined(_WIN32) || defined(WIN32)
449void utf8_printf(FILE *out, const char *zFormat, ...){
450 va_list ap;
451 va_start(ap, zFormat);
452 if( stdout_is_console && (out==stdout || out==stderr) ){
453 char *z1 = sqlite3_vmprintf(zFormat, ap);
454 char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0);
455 sqlite3_free(z1);
456 fputs(z2, out);
457 sqlite3_free(z2);
458 }else{
459 vfprintf(out, zFormat, ap);
460 }
461 va_end(ap);
462}
463#elif !defined(utf8_printf)
464# define utf8_printf fprintf
465#endif
466
467/*
468** Render output like fprintf(). This should not be used on anything that
469** includes string formatting (e.g. "%s").
470*/
471#if !defined(raw_printf)
472# define raw_printf fprintf
473#endif
474
drh4b5345c2018-04-24 13:07:40 +0000475/* Indicate out-of-memory and exit. */
476static void shell_out_of_memory(void){
477 raw_printf(stderr,"Error: out of memory\n");
478 exit(1);
479}
480
drhe3e25652021-12-16 13:29:28 +0000481/* Check a pointer to see if it is NULL. If it is NULL, exit with an
482** out-of-memory error.
483*/
484static void shell_check_oom(void *p){
485 if( p==0 ) shell_out_of_memory();
486}
487
drh2ce15c32017-07-11 13:34:40 +0000488/*
489** Write I/O traces to the following stream.
490*/
491#ifdef SQLITE_ENABLE_IOTRACE
492static FILE *iotrace = 0;
493#endif
494
495/*
496** This routine works like printf in that its first argument is a
497** format string and subsequent arguments are values to be substituted
498** in place of % fields. The result of formatting this string
499** is written to iotrace.
500*/
501#ifdef SQLITE_ENABLE_IOTRACE
502static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
503 va_list ap;
504 char *z;
505 if( iotrace==0 ) return;
506 va_start(ap, zFormat);
507 z = sqlite3_vmprintf(zFormat, ap);
508 va_end(ap);
509 utf8_printf(iotrace, "%s", z);
510 sqlite3_free(z);
511}
512#endif
513
514/*
515** Output string zUtf to stream pOut as w characters. If w is negative,
516** then right-justify the text. W is the width in UTF-8 characters, not
517** in bytes. This is different from the %*.*s specification in printf
518** since with %*.*s the width is measured in bytes, not characters.
519*/
520static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
521 int i;
522 int n;
523 int aw = w<0 ? -w : w;
drh2ce15c32017-07-11 13:34:40 +0000524 for(i=n=0; zUtf[i]; i++){
525 if( (zUtf[i]&0xc0)!=0x80 ){
526 n++;
527 if( n==aw ){
528 do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
529 break;
530 }
531 }
532 }
533 if( n>=aw ){
534 utf8_printf(pOut, "%.*s", i, zUtf);
535 }else if( w<0 ){
536 utf8_printf(pOut, "%*s%s", aw-n, "", zUtf);
537 }else{
538 utf8_printf(pOut, "%s%*s", zUtf, aw-n, "");
539 }
540}
541
542
543/*
544** Determines if a string is a number of not.
545*/
546static int isNumber(const char *z, int *realnum){
547 if( *z=='-' || *z=='+' ) z++;
548 if( !IsDigit(*z) ){
549 return 0;
550 }
551 z++;
552 if( realnum ) *realnum = 0;
553 while( IsDigit(*z) ){ z++; }
554 if( *z=='.' ){
555 z++;
556 if( !IsDigit(*z) ) return 0;
557 while( IsDigit(*z) ){ z++; }
558 if( realnum ) *realnum = 1;
559 }
560 if( *z=='e' || *z=='E' ){
561 z++;
562 if( *z=='+' || *z=='-' ) z++;
563 if( !IsDigit(*z) ) return 0;
564 while( IsDigit(*z) ){ z++; }
565 if( realnum ) *realnum = 1;
566 }
567 return *z==0;
568}
569
570/*
571** Compute a string length that is limited to what can be stored in
572** lower 30 bits of a 32-bit signed integer.
573*/
574static int strlen30(const char *z){
575 const char *z2 = z;
576 while( *z2 ){ z2++; }
577 return 0x3fffffff & (int)(z2 - z);
578}
579
580/*
581** Return the length of a string in characters. Multibyte UTF8 characters
582** count as a single character.
583*/
584static int strlenChar(const char *z){
585 int n = 0;
586 while( *z ){
587 if( (0xc0&*(z++))!=0x80 ) n++;
588 }
589 return n;
590}
591
592/*
larrybrd96bcc72021-09-17 21:12:47 +0000593** Return open FILE * if zFile exists, can be opened for read
594** and is an ordinary file or a character stream source.
595** Otherwise return 0.
drhbbd620e2020-07-20 23:33:11 +0000596*/
larrybrd96bcc72021-09-17 21:12:47 +0000597static FILE * openChrSource(const char *zFile){
drhbbd620e2020-07-20 23:33:11 +0000598#ifdef _WIN32
larrybrd0007852021-09-13 23:11:46 +0000599 struct _stat x = {0};
larrybrd0007852021-09-13 23:11:46 +0000600# define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0)
larrybrd96bcc72021-09-17 21:12:47 +0000601 /* On Windows, open first, then check the stream nature. This order
602 ** is necessary because _stat() and sibs, when checking a named pipe,
603 ** effectively break the pipe as its supplier sees it. */
604 FILE *rv = fopen(zFile, "rb");
605 if( rv==0 ) return 0;
606 if( _fstat(_fileno(rv), &x) != 0
607 || !STAT_CHR_SRC(x.st_mode)){
608 fclose(rv);
609 rv = 0;
610 }
611 return rv;
drhbbd620e2020-07-20 23:33:11 +0000612#else
larrybrd0007852021-09-13 23:11:46 +0000613 struct stat x = {0};
614 int rc = stat(zFile, &x);
615# define STAT_CHR_SRC(mode) (S_ISREG(mode)||S_ISFIFO(mode)||S_ISCHR(mode))
larrybrd96bcc72021-09-17 21:12:47 +0000616 if( rc!=0 ) return 0;
617 if( STAT_CHR_SRC(x.st_mode) ){
618 return fopen(zFile, "rb");
619 }else{
620 return 0;
621 }
drhbbd620e2020-07-20 23:33:11 +0000622#endif
larrybrd0007852021-09-13 23:11:46 +0000623#undef STAT_CHR_SRC
624}
drhbbd620e2020-07-20 23:33:11 +0000625
626/*
drh2ce15c32017-07-11 13:34:40 +0000627** This routine reads a line of text from FILE in, stores
628** the text in memory obtained from malloc() and returns a pointer
629** to the text. NULL is returned at end of file, or if malloc()
630** fails.
631**
632** If zLine is not NULL then it is a malloced buffer returned from
633** a previous call to this routine that may be reused.
634*/
635static char *local_getline(char *zLine, FILE *in){
636 int nLine = zLine==0 ? 0 : 100;
637 int n = 0;
638
639 while( 1 ){
640 if( n+100>nLine ){
641 nLine = nLine*2 + 100;
642 zLine = realloc(zLine, nLine);
drhe3e25652021-12-16 13:29:28 +0000643 shell_check_oom(zLine);
drh2ce15c32017-07-11 13:34:40 +0000644 }
645 if( fgets(&zLine[n], nLine - n, in)==0 ){
646 if( n==0 ){
647 free(zLine);
648 return 0;
649 }
650 zLine[n] = 0;
651 break;
652 }
653 while( zLine[n] ) n++;
654 if( n>0 && zLine[n-1]=='\n' ){
655 n--;
656 if( n>0 && zLine[n-1]=='\r' ) n--;
657 zLine[n] = 0;
658 break;
659 }
660 }
661#if defined(_WIN32) || defined(WIN32)
662 /* For interactive input on Windows systems, translate the
663 ** multi-byte characterset characters into UTF-8. */
664 if( stdin_is_interactive && in==stdin ){
665 char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
666 if( zTrans ){
667 int nTrans = strlen30(zTrans)+1;
668 if( nTrans>nLine ){
669 zLine = realloc(zLine, nTrans);
drhe3e25652021-12-16 13:29:28 +0000670 shell_check_oom(zLine);
drh2ce15c32017-07-11 13:34:40 +0000671 }
672 memcpy(zLine, zTrans, nTrans);
673 sqlite3_free(zTrans);
674 }
675 }
676#endif /* defined(_WIN32) || defined(WIN32) */
677 return zLine;
678}
679
680/*
681** Retrieve a single line of input text.
682**
683** If in==0 then read from standard input and prompt before each line.
684** If isContinuation is true, then a continuation prompt is appropriate.
685** If isContinuation is zero, then the main prompt should be used.
686**
687** If zPrior is not NULL then it is a buffer from a prior call to this
688** routine that can be reused.
689**
690** The result is stored in space obtained from malloc() and must either
691** be freed by the caller or else passed back into this routine via the
692** zPrior argument for reuse.
693*/
694static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
695 char *zPrompt;
696 char *zResult;
697 if( in!=0 ){
698 zResult = local_getline(zPrior, in);
699 }else{
700 zPrompt = isContinuation ? continuePrompt : mainPrompt;
701#if SHELL_USE_LOCAL_GETLINE
702 printf("%s", zPrompt);
703 fflush(stdout);
704 zResult = local_getline(zPrior, stdin);
705#else
706 free(zPrior);
707 zResult = shell_readline(zPrompt);
708 if( zResult && *zResult ) shell_add_history(zResult);
709#endif
710 }
711 return zResult;
712}
drh5af06982018-01-10 00:53:55 +0000713
714
715/*
716** Return the value of a hexadecimal digit. Return -1 if the input
717** is not a hex digit.
718*/
719static int hexDigitValue(char c){
720 if( c>='0' && c<='9' ) return c - '0';
721 if( c>='a' && c<='f' ) return c - 'a' + 10;
722 if( c>='A' && c<='F' ) return c - 'A' + 10;
723 return -1;
724}
725
726/*
727** Interpret zArg as an integer value, possibly with suffixes.
728*/
729static sqlite3_int64 integerValue(const char *zArg){
730 sqlite3_int64 v = 0;
731 static const struct { char *zSuffix; int iMult; } aMult[] = {
732 { "KiB", 1024 },
733 { "MiB", 1024*1024 },
734 { "GiB", 1024*1024*1024 },
735 { "KB", 1000 },
736 { "MB", 1000000 },
737 { "GB", 1000000000 },
738 { "K", 1000 },
739 { "M", 1000000 },
740 { "G", 1000000000 },
741 };
742 int i;
743 int isNeg = 0;
744 if( zArg[0]=='-' ){
745 isNeg = 1;
746 zArg++;
747 }else if( zArg[0]=='+' ){
748 zArg++;
749 }
750 if( zArg[0]=='0' && zArg[1]=='x' ){
751 int x;
752 zArg += 2;
753 while( (x = hexDigitValue(zArg[0]))>=0 ){
754 v = (v<<4) + x;
755 zArg++;
756 }
757 }else{
758 while( IsDigit(zArg[0]) ){
759 v = v*10 + zArg[0] - '0';
760 zArg++;
761 }
762 }
763 for(i=0; i<ArraySize(aMult); i++){
764 if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
765 v *= aMult[i].iMult;
766 break;
767 }
768 }
769 return isNeg? -v : v;
770}
771
drh2ce15c32017-07-11 13:34:40 +0000772/*
773** A variable length string to which one can append text.
774*/
775typedef struct ShellText ShellText;
776struct ShellText {
777 char *z;
778 int n;
779 int nAlloc;
780};
781
782/*
783** Initialize and destroy a ShellText object
784*/
785static void initText(ShellText *p){
786 memset(p, 0, sizeof(*p));
787}
788static void freeText(ShellText *p){
789 free(p->z);
790 initText(p);
791}
792
793/* zIn is either a pointer to a NULL-terminated string in memory obtained
794** from malloc(), or a NULL pointer. The string pointed to by zAppend is
795** added to zIn, and the result returned in memory obtained from malloc().
796** zIn, if it was not NULL, is freed.
797**
798** If the third argument, quote, is not '\0', then it is used as a
799** quote character for zAppend.
800*/
801static void appendText(ShellText *p, char const *zAppend, char quote){
802 int len;
803 int i;
804 int nAppend = strlen30(zAppend);
805
806 len = nAppend+p->n+1;
807 if( quote ){
808 len += 2;
809 for(i=0; i<nAppend; i++){
810 if( zAppend[i]==quote ) len++;
811 }
812 }
813
drh11a9ad52021-10-04 18:21:14 +0000814 if( p->z==0 || p->n+len>=p->nAlloc ){
drh2ce15c32017-07-11 13:34:40 +0000815 p->nAlloc = p->nAlloc*2 + len + 20;
816 p->z = realloc(p->z, p->nAlloc);
drhe3e25652021-12-16 13:29:28 +0000817 shell_check_oom(p->z);
drh2ce15c32017-07-11 13:34:40 +0000818 }
819
820 if( quote ){
821 char *zCsr = p->z+p->n;
822 *zCsr++ = quote;
823 for(i=0; i<nAppend; i++){
824 *zCsr++ = zAppend[i];
825 if( zAppend[i]==quote ) *zCsr++ = quote;
826 }
827 *zCsr++ = quote;
828 p->n = (int)(zCsr - p->z);
829 *zCsr = '\0';
830 }else{
831 memcpy(p->z+p->n, zAppend, nAppend);
832 p->n += nAppend;
833 p->z[p->n] = '\0';
834 }
835}
836
837/*
838** Attempt to determine if identifier zName needs to be quoted, either
839** because it contains non-alphanumeric characters, or because it is an
840** SQLite keyword. Be conservative in this estimate: When in doubt assume
841** that quoting is required.
842**
843** Return '"' if quoting is required. Return 0 if no quoting is required.
844*/
845static char quoteChar(const char *zName){
drhfc0ec3e2018-04-25 19:02:48 +0000846 int i;
drh2ce15c32017-07-11 13:34:40 +0000847 if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
848 for(i=0; zName[i]; i++){
849 if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
850 }
drhfc0ec3e2018-04-25 19:02:48 +0000851 return sqlite3_keyword_check(zName, i) ? '"' : 0;
drh2ce15c32017-07-11 13:34:40 +0000852}
853
854/*
drh667a2a22018-01-02 00:04:37 +0000855** Construct a fake object name and column list to describe the structure
856** of the view, virtual table, or table valued function zSchema.zName.
drhceba7922018-01-01 21:28:25 +0000857*/
drh667a2a22018-01-02 00:04:37 +0000858static char *shellFakeSchema(
drhceba7922018-01-01 21:28:25 +0000859 sqlite3 *db, /* The database connection containing the vtab */
860 const char *zSchema, /* Schema of the database holding the vtab */
861 const char *zName /* The name of the virtual table */
862){
863 sqlite3_stmt *pStmt = 0;
864 char *zSql;
drh1d315cf2018-01-01 21:49:43 +0000865 ShellText s;
866 char cQuote;
867 char *zDiv = "(";
drh667a2a22018-01-02 00:04:37 +0000868 int nRow = 0;
drhceba7922018-01-01 21:28:25 +0000869
drh1d315cf2018-01-01 21:49:43 +0000870 zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
871 zSchema ? zSchema : "main", zName);
drhe3e25652021-12-16 13:29:28 +0000872 shell_check_oom(zSql);
drhceba7922018-01-01 21:28:25 +0000873 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
874 sqlite3_free(zSql);
drh1d315cf2018-01-01 21:49:43 +0000875 initText(&s);
876 if( zSchema ){
877 cQuote = quoteChar(zSchema);
878 if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0;
879 appendText(&s, zSchema, cQuote);
880 appendText(&s, ".", 0);
drhceba7922018-01-01 21:28:25 +0000881 }
drh1d315cf2018-01-01 21:49:43 +0000882 cQuote = quoteChar(zName);
883 appendText(&s, zName, cQuote);
884 while( sqlite3_step(pStmt)==SQLITE_ROW ){
885 const char *zCol = (const char*)sqlite3_column_text(pStmt, 1);
drh667a2a22018-01-02 00:04:37 +0000886 nRow++;
drh1d315cf2018-01-01 21:49:43 +0000887 appendText(&s, zDiv, 0);
888 zDiv = ",";
drh621a5e02021-12-16 17:35:27 +0000889 if( zCol==0 ) zCol = "";
drh1d315cf2018-01-01 21:49:43 +0000890 cQuote = quoteChar(zCol);
891 appendText(&s, zCol, cQuote);
892 }
893 appendText(&s, ")", 0);
drhceba7922018-01-01 21:28:25 +0000894 sqlite3_finalize(pStmt);
drh667a2a22018-01-02 00:04:37 +0000895 if( nRow==0 ){
896 freeText(&s);
897 s.z = 0;
898 }
drh1d315cf2018-01-01 21:49:43 +0000899 return s.z;
drhceba7922018-01-01 21:28:25 +0000900}
901
902/*
drh667a2a22018-01-02 00:04:37 +0000903** SQL function: shell_module_schema(X)
904**
905** Return a fake schema for the table-valued function or eponymous virtual
906** table X.
907*/
908static void shellModuleSchema(
909 sqlite3_context *pCtx,
910 int nVal,
911 sqlite3_value **apVal
912){
drh511b1182021-12-16 13:56:04 +0000913 const char *zName;
914 char *zFake;
drhb9685182018-01-17 13:15:23 +0000915 UNUSED_PARAMETER(nVal);
drh511b1182021-12-16 13:56:04 +0000916 zName = (const char*)sqlite3_value_text(apVal[0]);
917 zFake = zName ? shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName) : 0;
drh667a2a22018-01-02 00:04:37 +0000918 if( zFake ){
dandcfbff92018-01-08 17:05:32 +0000919 sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
drh667a2a22018-01-02 00:04:37 +0000920 -1, sqlite3_free);
dandcfbff92018-01-08 17:05:32 +0000921 free(zFake);
drh667a2a22018-01-02 00:04:37 +0000922 }
923}
924
925/*
drh2ce15c32017-07-11 13:34:40 +0000926** SQL function: shell_add_schema(S,X)
927**
928** Add the schema name X to the CREATE statement in S and return the result.
929** Examples:
930**
931** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x);
932**
933** Also works on
934**
935** CREATE INDEX
936** CREATE UNIQUE INDEX
937** CREATE VIEW
938** CREATE TRIGGER
939** CREATE VIRTUAL TABLE
940**
941** This UDF is used by the .schema command to insert the schema name of
drh067b92b2020-06-19 15:24:12 +0000942** attached databases into the middle of the sqlite_schema.sql field.
drh2ce15c32017-07-11 13:34:40 +0000943*/
944static void shellAddSchemaName(
945 sqlite3_context *pCtx,
946 int nVal,
947 sqlite3_value **apVal
948){
949 static const char *aPrefix[] = {
950 "TABLE",
951 "INDEX",
952 "UNIQUE INDEX",
953 "VIEW",
954 "TRIGGER",
955 "VIRTUAL TABLE"
956 };
957 int i = 0;
958 const char *zIn = (const char*)sqlite3_value_text(apVal[0]);
959 const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
drh667a2a22018-01-02 00:04:37 +0000960 const char *zName = (const char*)sqlite3_value_text(apVal[2]);
drhceba7922018-01-01 21:28:25 +0000961 sqlite3 *db = sqlite3_context_db_handle(pCtx);
drhb9685182018-01-17 13:15:23 +0000962 UNUSED_PARAMETER(nVal);
drh2ce15c32017-07-11 13:34:40 +0000963 if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
drh37407122021-07-23 18:43:58 +0000964 for(i=0; i<ArraySize(aPrefix); i++){
drh2ce15c32017-07-11 13:34:40 +0000965 int n = strlen30(aPrefix[i]);
966 if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
drhceba7922018-01-01 21:28:25 +0000967 char *z = 0;
drh667a2a22018-01-02 00:04:37 +0000968 char *zFake = 0;
drhceba7922018-01-01 21:28:25 +0000969 if( zSchema ){
970 char cQuote = quoteChar(zSchema);
971 if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){
972 z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8);
973 }else{
974 z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8);
975 }
drh2ce15c32017-07-11 13:34:40 +0000976 }
drh667a2a22018-01-02 00:04:37 +0000977 if( zName
978 && aPrefix[i][0]=='V'
979 && (zFake = shellFakeSchema(db, zSchema, zName))!=0
980 ){
981 if( z==0 ){
dandcfbff92018-01-08 17:05:32 +0000982 z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake);
drh667a2a22018-01-02 00:04:37 +0000983 }else{
dandcfbff92018-01-08 17:05:32 +0000984 z = sqlite3_mprintf("%z\n/* %s */", z, zFake);
drh667a2a22018-01-02 00:04:37 +0000985 }
dandcfbff92018-01-08 17:05:32 +0000986 free(zFake);
drhceba7922018-01-01 21:28:25 +0000987 }
988 if( z ){
989 sqlite3_result_text(pCtx, z, -1, sqlite3_free);
990 return;
991 }
drh2ce15c32017-07-11 13:34:40 +0000992 }
993 }
994 }
995 sqlite3_result_value(pCtx, apVal[0]);
996}
997
998/*
999** The source code for several run-time loadable extensions is inserted
1000** below by the ../tool/mkshellc.tcl script. Before processing that included
1001** code, we need to override some macros to make the included program code
1002** work here in the middle of this regular program.
1003*/
1004#define SQLITE_EXTENSION_INIT1
drh89997982017-07-11 18:11:33 +00001005#define SQLITE_EXTENSION_INIT2(X) (void)(X)
drh2ce15c32017-07-11 13:34:40 +00001006
mistachkinacae8c32018-01-05 20:08:46 +00001007#if defined(_WIN32) && defined(_MSC_VER)
drh03491a12018-01-07 21:58:17 +00001008INCLUDE test_windirent.h
mistachkindfdfd8c2018-01-04 22:46:08 +00001009INCLUDE test_windirent.c
1010#define dirent DIRENT
mistachkindfdfd8c2018-01-04 22:46:08 +00001011#endif
drh2ce15c32017-07-11 13:34:40 +00001012INCLUDE ../ext/misc/shathree.c
1013INCLUDE ../ext/misc/fileio.c
drh56eb09b2017-07-11 13:59:07 +00001014INCLUDE ../ext/misc/completion.c
drh8682e122018-01-07 20:38:10 +00001015INCLUDE ../ext/misc/appendvfs.c
drh50b910a2019-01-21 14:55:03 +00001016INCLUDE ../ext/misc/memtrace.c
drhf05dd032020-04-14 15:53:58 +00001017INCLUDE ../ext/misc/uint.c
drhbeb9def2020-06-22 19:12:23 +00001018INCLUDE ../ext/misc/decimal.c
drh8cda77d2020-06-24 15:06:29 +00001019INCLUDE ../ext/misc/ieee754.c
mistachkin72c38d82020-08-28 18:47:39 +00001020INCLUDE ../ext/misc/series.c
drh64689902021-06-03 13:51:31 +00001021INCLUDE ../ext/misc/regexp.c
dan72afc3c2017-12-05 18:32:40 +00001022#ifdef SQLITE_HAVE_ZLIB
dan9ebfaad2017-12-26 20:39:58 +00001023INCLUDE ../ext/misc/zipfile.c
dand1b51d42017-12-16 19:11:26 +00001024INCLUDE ../ext/misc/sqlar.c
dan72afc3c2017-12-05 18:32:40 +00001025#endif
dan43efc182017-12-19 17:42:13 +00001026INCLUDE ../ext/expert/sqlite3expert.h
1027INCLUDE ../ext/expert/sqlite3expert.c
drh2ce15c32017-07-11 13:34:40 +00001028
dan1b162162019-04-27 20:15:15 +00001029#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00001030INCLUDE ../ext/misc/dbdata.c
dan1b162162019-04-27 20:15:15 +00001031#endif
dan68cb86e2019-04-20 20:57:28 +00001032
drh2ce15c32017-07-11 13:34:40 +00001033#if defined(SQLITE_ENABLE_SESSION)
1034/*
1035** State information for a single open session
1036*/
1037typedef struct OpenSession OpenSession;
1038struct OpenSession {
1039 char *zName; /* Symbolic name for this session */
1040 int nFilter; /* Number of xFilter rejection GLOB patterns */
1041 char **azFilter; /* Array of xFilter rejection GLOB patterns */
1042 sqlite3_session *p; /* The open session */
1043};
1044#endif
1045
dan43efc182017-12-19 17:42:13 +00001046typedef struct ExpertInfo ExpertInfo;
1047struct ExpertInfo {
1048 sqlite3expert *pExpert;
1049 int bVerbose;
1050};
1051
drh4b5345c2018-04-24 13:07:40 +00001052/* A single line in the EQP output */
1053typedef struct EQPGraphRow EQPGraphRow;
1054struct EQPGraphRow {
drhe2ca99c2018-05-02 00:33:43 +00001055 int iEqpId; /* ID for this row */
1056 int iParentId; /* ID of the parent row */
drh4b5345c2018-04-24 13:07:40 +00001057 EQPGraphRow *pNext; /* Next row in sequence */
1058 char zText[1]; /* Text to display for this row */
1059};
1060
1061/* All EQP output is collected into an instance of the following */
1062typedef struct EQPGraph EQPGraph;
1063struct EQPGraph {
1064 EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */
1065 EQPGraphRow *pLast; /* Last element of the pRow list */
1066 char zPrefix[100]; /* Graph prefix */
1067};
1068
drh2ce15c32017-07-11 13:34:40 +00001069/*
1070** State information about the database connection is contained in an
1071** instance of the following structure.
1072*/
1073typedef struct ShellState ShellState;
1074struct ShellState {
1075 sqlite3 *db; /* The database */
drh1fa6d9f2018-01-06 21:46:01 +00001076 u8 autoExplain; /* Automatically turn on .explain mode */
1077 u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
drhe2ca99c2018-05-02 00:33:43 +00001078 u8 autoEQPtest; /* autoEQP is in test mode */
drhb4e50392019-01-26 15:40:04 +00001079 u8 autoEQPtrace; /* autoEQP is in trace mode */
drh1fa6d9f2018-01-06 21:46:01 +00001080 u8 scanstatsOn; /* True to display scan stats before each finalize */
1081 u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
drh13c20932018-01-10 21:41:55 +00001082 u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
drh4b5345c2018-04-24 13:07:40 +00001083 u8 nEqpLevel; /* Depth of the EQP output graph */
drh707821f2018-12-05 13:39:06 +00001084 u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
drhb97e2ad2021-08-26 18:31:39 +00001085 u8 bSafeMode; /* True to prohibit unsafe operations */
1086 u8 bSafeModePersist; /* The long-term value of bSafeMode */
drha6e6cf22021-01-09 19:10:04 +00001087 unsigned statsOn; /* True to display memory stats before each finalize */
drh4b5345c2018-04-24 13:07:40 +00001088 unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */
drh2ce15c32017-07-11 13:34:40 +00001089 int outCount; /* Revert to stdout when reaching zero */
1090 int cnt; /* Number of records displayed so far */
drh2c8ee022018-12-13 18:59:30 +00001091 int lineno; /* Line number of last line read from in */
drh0933aad2019-11-18 17:46:38 +00001092 int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */
drh60379d42018-12-13 18:30:01 +00001093 FILE *in; /* Read commands from this stream */
drh2ce15c32017-07-11 13:34:40 +00001094 FILE *out; /* Write results here */
1095 FILE *traceOut; /* Output for sqlite3_trace() */
1096 int nErr; /* Number of errors seen */
1097 int mode; /* An output mode setting */
drh3c484e82018-01-10 22:27:21 +00001098 int modePrior; /* Saved mode */
drh2ce15c32017-07-11 13:34:40 +00001099 int cMode; /* temporary output mode for the current query */
1100 int normalMode; /* Output mode before ".explain on" */
1101 int writableSchema; /* True if PRAGMA writable_schema=ON */
1102 int showHeader; /* True to show column names in List or Column mode */
1103 int nCheck; /* Number of ".check" commands run */
drh3f83f592019-02-04 14:53:18 +00001104 unsigned nProgress; /* Number of progress callbacks encountered */
1105 unsigned mxProgress; /* Maximum progress callbacks before failing */
1106 unsigned flgProgress; /* Flags for the progress callback */
drh2ce15c32017-07-11 13:34:40 +00001107 unsigned shellFlgs; /* Various flags */
drh7a431002020-04-18 14:12:00 +00001108 unsigned priorShFlgs; /* Saved copy of flags */
drh6ca64482019-01-22 16:06:20 +00001109 sqlite3_int64 szMax; /* --maxsize argument to .open */
drh2ce15c32017-07-11 13:34:40 +00001110 char *zDestTable; /* Name of destination table when MODE_Insert */
drh13c20932018-01-10 21:41:55 +00001111 char *zTempFile; /* Temporary file that might need deleting */
drh2ce15c32017-07-11 13:34:40 +00001112 char zTestcase[30]; /* Name of current test case */
1113 char colSeparator[20]; /* Column separator character for several modes */
1114 char rowSeparator[20]; /* Row separator character for MODE_Ascii */
drh3c484e82018-01-10 22:27:21 +00001115 char colSepPrior[20]; /* Saved column separator */
1116 char rowSepPrior[20]; /* Saved row separator */
drh0285d982020-05-29 14:38:43 +00001117 int *colWidth; /* Requested width of each column in columnar modes */
1118 int *actualWidth; /* Actual width of each column */
1119 int nWidth; /* Number of slots in colWidth[] and actualWidth[] */
drh2ce15c32017-07-11 13:34:40 +00001120 char nullValue[20]; /* The text to print when a NULL comes back from
1121 ** the database */
1122 char outfile[FILENAME_MAX]; /* Filename for *out */
drh2ce15c32017-07-11 13:34:40 +00001123 sqlite3_stmt *pStmt; /* Current statement if any. */
1124 FILE *pLog; /* Write log output here */
drh37407122021-07-23 18:43:58 +00001125 struct AuxDb { /* Storage space for auxiliary database connections */
1126 sqlite3 *db; /* Connection pointer */
1127 const char *zDbFilename; /* Filename used to open the connection */
1128 char *zFreeOnClose; /* Free this memory allocation on close */
1129#if defined(SQLITE_ENABLE_SESSION)
1130 int nSession; /* Number of active sessions */
1131 OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */
1132#endif
1133 } aAuxDb[5], /* Array of all database connections */
1134 *pAuxDb; /* Currently active database connection */
drh2ce15c32017-07-11 13:34:40 +00001135 int *aiIndent; /* Array of indents used in MODE_Explain */
1136 int nIndent; /* Size of array aiIndent[] */
1137 int iIndent; /* Index of current op in aiIndent[] */
drhb97e2ad2021-08-26 18:31:39 +00001138 char *zNonce; /* Nonce for temporary safe-mode excapes */
drh4b5345c2018-04-24 13:07:40 +00001139 EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */
drhb97e2ad2021-08-26 18:31:39 +00001140 ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
drh2ce15c32017-07-11 13:34:40 +00001141};
1142
drh1fa6d9f2018-01-06 21:46:01 +00001143
drhada70452017-12-21 21:02:27 +00001144/* Allowed values for ShellState.autoEQP
1145*/
drhe2ca99c2018-05-02 00:33:43 +00001146#define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */
1147#define AUTOEQP_on 1 /* Automatic EQP is on */
1148#define AUTOEQP_trigger 2 /* On and also show plans for triggers */
1149#define AUTOEQP_full 3 /* Show full EXPLAIN */
drhada70452017-12-21 21:02:27 +00001150
drh1fa6d9f2018-01-06 21:46:01 +00001151/* Allowed values for ShellState.openMode
1152*/
drh60f34ae2018-10-30 13:19:49 +00001153#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
1154#define SHELL_OPEN_NORMAL 1 /* Normal database file */
1155#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
1156#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
1157#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
1158#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
drh33746482018-12-13 15:06:26 +00001159#define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */
drh1fa6d9f2018-01-06 21:46:01 +00001160
drh707821f2018-12-05 13:39:06 +00001161/* Allowed values for ShellState.eTraceType
1162*/
1163#define SHELL_TRACE_PLAIN 0 /* Show input SQL text */
1164#define SHELL_TRACE_EXPANDED 1 /* Show expanded SQL text */
1165#define SHELL_TRACE_NORMALIZED 2 /* Show normalized SQL text */
1166
drh3f83f592019-02-04 14:53:18 +00001167/* Bits in the ShellState.flgProgress variable */
drhfc4eeef2019-02-05 19:48:46 +00001168#define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */
1169#define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progres
1170 ** callback limit is reached, and for each
1171 ** top-level SQL statement */
1172#define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */
drh3f83f592019-02-04 14:53:18 +00001173
drh2ce15c32017-07-11 13:34:40 +00001174/*
1175** These are the allowed shellFlgs values
1176*/
drhb2a0f752017-08-28 15:51:35 +00001177#define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */
1178#define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */
1179#define SHFLG_Backslash 0x00000004 /* The --backslash option is used */
1180#define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */
1181#define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
1182#define SHFLG_CountChanges 0x00000020 /* .changes setting */
1183#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
larrybrae509122021-09-10 01:45:20 +00001184#define SHFLG_HeaderSet 0x00000080 /* showHeader has been specified */
drhc1962192020-10-12 16:54:28 +00001185#define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */
1186#define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */
drh2ce15c32017-07-11 13:34:40 +00001187
1188/*
1189** Macros for testing and setting shellFlgs
1190*/
1191#define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0)
1192#define ShellSetFlag(P,X) ((P)->shellFlgs|=(X))
1193#define ShellClearFlag(P,X) ((P)->shellFlgs&=(~(X)))
1194
1195/*
1196** These are the allowed modes.
1197*/
1198#define MODE_Line 0 /* One column per line. Blank line between records */
1199#define MODE_Column 1 /* One record per line in neat columns */
1200#define MODE_List 2 /* One record per line with a separator */
1201#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
1202#define MODE_Html 4 /* Generate an XHTML table */
1203#define MODE_Insert 5 /* Generate SQL "insert" statements */
1204#define MODE_Quote 6 /* Quote values as for SQL */
1205#define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */
1206#define MODE_Csv 8 /* Quote strings, numbers are plain */
1207#define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */
1208#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
1209#define MODE_Pretty 11 /* Pretty-print schemas */
drh4b5345c2018-04-24 13:07:40 +00001210#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
drh30c54a02020-05-28 23:49:50 +00001211#define MODE_Json 13 /* Output JSON */
1212#define MODE_Markdown 14 /* Markdown formatting */
1213#define MODE_Table 15 /* MySQL-style table formatting */
drh0908e382020-06-04 18:05:39 +00001214#define MODE_Box 16 /* Unicode box-drawing characters */
drh5d88be82021-12-09 16:17:43 +00001215#define MODE_Count 17 /* Output only a count of the rows of output */
1216#define MODE_Off 18 /* No query output shown */
drh2ce15c32017-07-11 13:34:40 +00001217
1218static const char *modeDescr[] = {
1219 "line",
1220 "column",
1221 "list",
1222 "semi",
1223 "html",
1224 "insert",
1225 "quote",
1226 "tcl",
1227 "csv",
1228 "explain",
1229 "ascii",
1230 "prettyprint",
drh30c54a02020-05-28 23:49:50 +00001231 "eqp",
1232 "json",
1233 "markdown",
drh0908e382020-06-04 18:05:39 +00001234 "table",
drh5d88be82021-12-09 16:17:43 +00001235 "box",
1236 "count",
1237 "off"
drh2ce15c32017-07-11 13:34:40 +00001238};
1239
1240/*
1241** These are the column/row/line separators used by the various
1242** import/export modes.
1243*/
1244#define SEP_Column "|"
1245#define SEP_Row "\n"
1246#define SEP_Tab "\t"
1247#define SEP_Space " "
1248#define SEP_Comma ","
1249#define SEP_CrLf "\r\n"
1250#define SEP_Unit "\x1F"
1251#define SEP_Record "\x1E"
1252
1253/*
drh2ce15c32017-07-11 13:34:40 +00001254** A callback for the sqlite3_log() interface.
1255*/
1256static void shellLog(void *pArg, int iErrCode, const char *zMsg){
1257 ShellState *p = (ShellState*)pArg;
1258 if( p->pLog==0 ) return;
1259 utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
1260 fflush(p->pLog);
1261}
1262
1263/*
drh634c70f2018-01-10 16:50:18 +00001264** SQL function: shell_putsnl(X)
1265**
1266** Write the text X to the screen (or whatever output is being directed)
1267** adding a newline at the end, and then return X.
1268*/
1269static void shellPutsFunc(
1270 sqlite3_context *pCtx,
1271 int nVal,
1272 sqlite3_value **apVal
1273){
1274 ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
drhb9685182018-01-17 13:15:23 +00001275 (void)nVal;
drh634c70f2018-01-10 16:50:18 +00001276 utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
1277 sqlite3_result_value(pCtx, apVal[0]);
1278}
1279
1280/*
drhb97e2ad2021-08-26 18:31:39 +00001281** If in safe mode, print an error message described by the arguments
1282** and exit immediately.
1283*/
1284static void failIfSafeMode(
1285 ShellState *p,
1286 const char *zErrMsg,
1287 ...
1288){
1289 if( p->bSafeMode ){
1290 va_list ap;
1291 char *zMsg;
1292 va_start(ap, zErrMsg);
1293 zMsg = sqlite3_vmprintf(zErrMsg, ap);
1294 va_end(ap);
1295 raw_printf(stderr, "line %d: ", p->lineno);
1296 utf8_printf(stderr, "%s\n", zMsg);
1297 exit(1);
1298 }
1299}
1300
1301/*
drh97913132018-01-11 00:04:00 +00001302** SQL function: edit(VALUE)
1303** edit(VALUE,EDITOR)
1304**
1305** These steps:
1306**
1307** (1) Write VALUE into a temporary file.
1308** (2) Run program EDITOR on that temporary file.
1309** (3) Read the temporary file back and return its content as the result.
1310** (4) Delete the temporary file
1311**
1312** If the EDITOR argument is omitted, use the value in the VISUAL
1313** environment variable. If still there is no EDITOR, through an error.
1314**
1315** Also throw an error if the EDITOR program returns a non-zero exit code.
1316*/
drh04a28c32018-01-31 01:38:44 +00001317#ifndef SQLITE_NOHAVE_SYSTEM
drh97913132018-01-11 00:04:00 +00001318static void editFunc(
1319 sqlite3_context *context,
1320 int argc,
1321 sqlite3_value **argv
1322){
1323 const char *zEditor;
1324 char *zTempFile = 0;
1325 sqlite3 *db;
1326 char *zCmd = 0;
1327 int bBin;
1328 int rc;
drhf018fd52018-08-06 02:08:53 +00001329 int hasCRNL = 0;
drh97913132018-01-11 00:04:00 +00001330 FILE *f = 0;
1331 sqlite3_int64 sz;
1332 sqlite3_int64 x;
1333 unsigned char *p = 0;
1334
1335 if( argc==2 ){
1336 zEditor = (const char*)sqlite3_value_text(argv[1]);
1337 }else{
1338 zEditor = getenv("VISUAL");
1339 }
1340 if( zEditor==0 ){
1341 sqlite3_result_error(context, "no editor for edit()", -1);
1342 return;
1343 }
1344 if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
1345 sqlite3_result_error(context, "NULL input to edit()", -1);
1346 return;
1347 }
1348 db = sqlite3_context_db_handle(context);
1349 zTempFile = 0;
1350 sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile);
1351 if( zTempFile==0 ){
1352 sqlite3_uint64 r = 0;
1353 sqlite3_randomness(sizeof(r), &r);
1354 zTempFile = sqlite3_mprintf("temp%llx", r);
1355 if( zTempFile==0 ){
1356 sqlite3_result_error_nomem(context);
1357 return;
1358 }
1359 }
1360 bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB;
drhf018fd52018-08-06 02:08:53 +00001361 /* When writing the file to be edited, do \n to \r\n conversions on systems
1362 ** that want \r\n line endings */
drh97913132018-01-11 00:04:00 +00001363 f = fopen(zTempFile, bBin ? "wb" : "w");
1364 if( f==0 ){
1365 sqlite3_result_error(context, "edit() cannot open temp file", -1);
1366 goto edit_func_end;
1367 }
1368 sz = sqlite3_value_bytes(argv[0]);
1369 if( bBin ){
dan4d02b5f2019-07-17 07:23:06 +00001370 x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001371 }else{
drhf018fd52018-08-06 02:08:53 +00001372 const char *z = (const char*)sqlite3_value_text(argv[0]);
1373 /* Remember whether or not the value originally contained \r\n */
1374 if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
dan4d02b5f2019-07-17 07:23:06 +00001375 x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001376 }
1377 fclose(f);
1378 f = 0;
1379 if( x!=sz ){
1380 sqlite3_result_error(context, "edit() could not write the whole file", -1);
1381 goto edit_func_end;
1382 }
1383 zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile);
1384 if( zCmd==0 ){
1385 sqlite3_result_error_nomem(context);
1386 goto edit_func_end;
1387 }
1388 rc = system(zCmd);
1389 sqlite3_free(zCmd);
1390 if( rc ){
1391 sqlite3_result_error(context, "EDITOR returned non-zero", -1);
1392 goto edit_func_end;
1393 }
drhf018fd52018-08-06 02:08:53 +00001394 f = fopen(zTempFile, "rb");
drh97913132018-01-11 00:04:00 +00001395 if( f==0 ){
1396 sqlite3_result_error(context,
1397 "edit() cannot reopen temp file after edit", -1);
1398 goto edit_func_end;
1399 }
1400 fseek(f, 0, SEEK_END);
1401 sz = ftell(f);
1402 rewind(f);
drhee37f8b2019-08-23 23:05:32 +00001403 p = sqlite3_malloc64( sz+1 );
drh97913132018-01-11 00:04:00 +00001404 if( p==0 ){
1405 sqlite3_result_error_nomem(context);
1406 goto edit_func_end;
1407 }
dan4d02b5f2019-07-17 07:23:06 +00001408 x = fread(p, 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001409 fclose(f);
1410 f = 0;
1411 if( x!=sz ){
1412 sqlite3_result_error(context, "could not read back the whole file", -1);
1413 goto edit_func_end;
1414 }
1415 if( bBin ){
mistachkinb71aa092018-01-23 00:05:18 +00001416 sqlite3_result_blob64(context, p, sz, sqlite3_free);
drh97913132018-01-11 00:04:00 +00001417 }else{
dan60bdcf52018-10-03 11:13:30 +00001418 sqlite3_int64 i, j;
drhf018fd52018-08-06 02:08:53 +00001419 if( hasCRNL ){
1420 /* If the original contains \r\n then do no conversions back to \n */
drhf018fd52018-08-06 02:08:53 +00001421 }else{
1422 /* If the file did not originally contain \r\n then convert any new
1423 ** \r\n back into \n */
1424 for(i=j=0; i<sz; i++){
1425 if( p[i]=='\r' && p[i+1]=='\n' ) i++;
1426 p[j++] = p[i];
1427 }
1428 sz = j;
1429 p[sz] = 0;
1430 }
mistachkinb71aa092018-01-23 00:05:18 +00001431 sqlite3_result_text64(context, (const char*)p, sz,
1432 sqlite3_free, SQLITE_UTF8);
drh97913132018-01-11 00:04:00 +00001433 }
1434 p = 0;
1435
1436edit_func_end:
1437 if( f ) fclose(f);
1438 unlink(zTempFile);
1439 sqlite3_free(zTempFile);
1440 sqlite3_free(p);
1441}
drh04a28c32018-01-31 01:38:44 +00001442#endif /* SQLITE_NOHAVE_SYSTEM */
drh97913132018-01-11 00:04:00 +00001443
1444/*
drh3c484e82018-01-10 22:27:21 +00001445** Save or restore the current output mode
1446*/
1447static void outputModePush(ShellState *p){
1448 p->modePrior = p->mode;
drh7a431002020-04-18 14:12:00 +00001449 p->priorShFlgs = p->shellFlgs;
drh3c484e82018-01-10 22:27:21 +00001450 memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));
1451 memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));
1452}
1453static void outputModePop(ShellState *p){
1454 p->mode = p->modePrior;
drh7a431002020-04-18 14:12:00 +00001455 p->shellFlgs = p->priorShFlgs;
drh3c484e82018-01-10 22:27:21 +00001456 memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
1457 memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
1458}
1459
1460/*
drh2ce15c32017-07-11 13:34:40 +00001461** Output the given string as a hex-encoded blob (eg. X'1234' )
1462*/
1463static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
1464 int i;
1465 char *zBlob = (char *)pBlob;
1466 raw_printf(out,"X'");
1467 for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); }
1468 raw_printf(out,"'");
1469}
1470
1471/*
1472** Find a string that is not found anywhere in z[]. Return a pointer
1473** to that string.
1474**
1475** Try to use zA and zB first. If both of those are already found in z[]
1476** then make up some string and store it in the buffer zBuf.
1477*/
1478static const char *unused_string(
1479 const char *z, /* Result must not appear anywhere in z */
1480 const char *zA, const char *zB, /* Try these first */
1481 char *zBuf /* Space to store a generated string */
1482){
1483 unsigned i = 0;
1484 if( strstr(z, zA)==0 ) return zA;
1485 if( strstr(z, zB)==0 ) return zB;
1486 do{
1487 sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
1488 }while( strstr(z,zBuf)!=0 );
1489 return zBuf;
1490}
1491
1492/*
1493** Output the given string as a quoted string using SQL quoting conventions.
1494**
1495** See also: output_quoted_escaped_string()
1496*/
1497static void output_quoted_string(FILE *out, const char *z){
1498 int i;
1499 char c;
1500 setBinaryMode(out, 1);
1501 for(i=0; (c = z[i])!=0 && c!='\''; i++){}
1502 if( c==0 ){
1503 utf8_printf(out,"'%s'",z);
1504 }else{
1505 raw_printf(out, "'");
1506 while( *z ){
1507 for(i=0; (c = z[i])!=0 && c!='\''; i++){}
1508 if( c=='\'' ) i++;
1509 if( i ){
1510 utf8_printf(out, "%.*s", i, z);
1511 z += i;
1512 }
1513 if( c=='\'' ){
1514 raw_printf(out, "'");
1515 continue;
1516 }
1517 if( c==0 ){
1518 break;
1519 }
1520 z++;
1521 }
1522 raw_printf(out, "'");
1523 }
1524 setTextMode(out, 1);
1525}
1526
1527/*
1528** Output the given string as a quoted string using SQL quoting conventions.
1529** Additionallly , escape the "\n" and "\r" characters so that they do not
1530** get corrupted by end-of-line translation facilities in some operating
1531** systems.
1532**
1533** This is like output_quoted_string() but with the addition of the \r\n
1534** escape mechanism.
1535*/
1536static void output_quoted_escaped_string(FILE *out, const char *z){
1537 int i;
1538 char c;
1539 setBinaryMode(out, 1);
1540 for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
1541 if( c==0 ){
1542 utf8_printf(out,"'%s'",z);
1543 }else{
1544 const char *zNL = 0;
1545 const char *zCR = 0;
1546 int nNL = 0;
1547 int nCR = 0;
1548 char zBuf1[20], zBuf2[20];
1549 for(i=0; z[i]; i++){
1550 if( z[i]=='\n' ) nNL++;
1551 if( z[i]=='\r' ) nCR++;
1552 }
1553 if( nNL ){
1554 raw_printf(out, "replace(");
1555 zNL = unused_string(z, "\\n", "\\012", zBuf1);
1556 }
1557 if( nCR ){
1558 raw_printf(out, "replace(");
1559 zCR = unused_string(z, "\\r", "\\015", zBuf2);
1560 }
1561 raw_printf(out, "'");
1562 while( *z ){
1563 for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
1564 if( c=='\'' ) i++;
1565 if( i ){
1566 utf8_printf(out, "%.*s", i, z);
1567 z += i;
1568 }
1569 if( c=='\'' ){
1570 raw_printf(out, "'");
1571 continue;
1572 }
1573 if( c==0 ){
1574 break;
1575 }
1576 z++;
1577 if( c=='\n' ){
1578 raw_printf(out, "%s", zNL);
1579 continue;
1580 }
1581 raw_printf(out, "%s", zCR);
1582 }
1583 raw_printf(out, "'");
1584 if( nCR ){
1585 raw_printf(out, ",'%s',char(13))", zCR);
1586 }
1587 if( nNL ){
1588 raw_printf(out, ",'%s',char(10))", zNL);
1589 }
1590 }
1591 setTextMode(out, 1);
1592}
1593
1594/*
1595** Output the given string as a quoted according to C or TCL quoting rules.
1596*/
1597static void output_c_string(FILE *out, const char *z){
1598 unsigned int c;
1599 fputc('"', out);
1600 while( (c = *(z++))!=0 ){
1601 if( c=='\\' ){
1602 fputc(c, out);
1603 fputc(c, out);
1604 }else if( c=='"' ){
1605 fputc('\\', out);
1606 fputc('"', out);
1607 }else if( c=='\t' ){
1608 fputc('\\', out);
1609 fputc('t', out);
1610 }else if( c=='\n' ){
1611 fputc('\\', out);
1612 fputc('n', out);
1613 }else if( c=='\r' ){
1614 fputc('\\', out);
1615 fputc('r', out);
1616 }else if( !isprint(c&0xff) ){
1617 raw_printf(out, "\\%03o", c&0xff);
1618 }else{
1619 fputc(c, out);
1620 }
1621 }
1622 fputc('"', out);
1623}
1624
1625/*
drh69c093d2020-05-29 00:21:43 +00001626** Output the given string as a quoted according to JSON quoting rules.
1627*/
1628static void output_json_string(FILE *out, const char *z, int n){
1629 unsigned int c;
1630 if( n<0 ) n = (int)strlen(z);
1631 fputc('"', out);
1632 while( n-- ){
1633 c = *(z++);
1634 if( c=='\\' || c=='"' ){
1635 fputc('\\', out);
1636 fputc(c, out);
1637 }else if( c<=0x1f ){
1638 fputc('\\', out);
1639 if( c=='\b' ){
1640 fputc('b', out);
1641 }else if( c=='\f' ){
1642 fputc('f', out);
1643 }else if( c=='\n' ){
1644 fputc('n', out);
1645 }else if( c=='\r' ){
1646 fputc('r', out);
1647 }else if( c=='\t' ){
1648 fputc('t', out);
1649 }else{
1650 raw_printf(out, "u%04x",c);
1651 }
1652 }else{
1653 fputc(c, out);
1654 }
1655 }
1656 fputc('"', out);
1657}
1658
1659/*
drh2ce15c32017-07-11 13:34:40 +00001660** Output the given string with characters that are special to
1661** HTML escaped.
1662*/
1663static void output_html_string(FILE *out, const char *z){
1664 int i;
1665 if( z==0 ) z = "";
1666 while( *z ){
1667 for(i=0; z[i]
1668 && z[i]!='<'
1669 && z[i]!='&'
1670 && z[i]!='>'
1671 && z[i]!='\"'
1672 && z[i]!='\'';
1673 i++){}
1674 if( i>0 ){
1675 utf8_printf(out,"%.*s",i,z);
1676 }
1677 if( z[i]=='<' ){
1678 raw_printf(out,"&lt;");
1679 }else if( z[i]=='&' ){
1680 raw_printf(out,"&amp;");
1681 }else if( z[i]=='>' ){
1682 raw_printf(out,"&gt;");
1683 }else if( z[i]=='\"' ){
1684 raw_printf(out,"&quot;");
1685 }else if( z[i]=='\'' ){
1686 raw_printf(out,"&#39;");
1687 }else{
1688 break;
1689 }
1690 z += i + 1;
1691 }
1692}
1693
1694/*
1695** If a field contains any character identified by a 1 in the following
1696** array, then the string must be quoted for CSV.
1697*/
1698static const char needCsvQuote[] = {
1699 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1700 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1701 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1702 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1703 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1704 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1705 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1706 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1707 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1708 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1709 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1710 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1711 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1712 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1713 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1714 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1715};
1716
1717/*
1718** Output a single term of CSV. Actually, p->colSeparator is used for
1719** the separator, which may or may not be a comma. p->nullValue is
1720** the null value. Strings are quoted if necessary. The separator
1721** is only issued if bSep is true.
1722*/
1723static void output_csv(ShellState *p, const char *z, int bSep){
1724 FILE *out = p->out;
1725 if( z==0 ){
1726 utf8_printf(out,"%s",p->nullValue);
1727 }else{
drh9cd0c3d2021-11-18 15:40:05 +00001728 unsigned i;
1729 for(i=0; z[i]; i++){
1730 if( needCsvQuote[((unsigned char*)z)[i]] ){
drh2ce15c32017-07-11 13:34:40 +00001731 i = 0;
1732 break;
1733 }
1734 }
drh9cd0c3d2021-11-18 15:40:05 +00001735 if( i==0 || strstr(z, p->colSeparator)!=0 ){
drh9b7affc2017-11-26 02:14:18 +00001736 char *zQuoted = sqlite3_mprintf("\"%w\"", z);
drhe3e25652021-12-16 13:29:28 +00001737 shell_check_oom(zQuoted);
drh9b7affc2017-11-26 02:14:18 +00001738 utf8_printf(out, "%s", zQuoted);
1739 sqlite3_free(zQuoted);
drh2ce15c32017-07-11 13:34:40 +00001740 }else{
1741 utf8_printf(out, "%s", z);
1742 }
1743 }
1744 if( bSep ){
1745 utf8_printf(p->out, "%s", p->colSeparator);
1746 }
1747}
1748
drh2ce15c32017-07-11 13:34:40 +00001749/*
1750** This routine runs when the user presses Ctrl-C
1751*/
1752static void interrupt_handler(int NotUsed){
1753 UNUSED_PARAMETER(NotUsed);
1754 seenInterrupt++;
1755 if( seenInterrupt>2 ) exit(1);
1756 if( globalDb ) sqlite3_interrupt(globalDb);
1757}
mistachkinb4bab902017-10-27 17:09:44 +00001758
1759#if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
1760/*
1761** This routine runs for console events (e.g. Ctrl-C) on Win32
1762*/
1763static BOOL WINAPI ConsoleCtrlHandler(
1764 DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */
1765){
1766 if( dwCtrlType==CTRL_C_EVENT ){
1767 interrupt_handler(0);
1768 return TRUE;
1769 }
1770 return FALSE;
1771}
drh2ce15c32017-07-11 13:34:40 +00001772#endif
1773
1774#ifndef SQLITE_OMIT_AUTHORIZATION
1775/*
drhb97e2ad2021-08-26 18:31:39 +00001776** This authorizer runs in safe mode.
1777*/
1778static int safeModeAuth(
1779 void *pClientData,
1780 int op,
1781 const char *zA1,
1782 const char *zA2,
1783 const char *zA3,
1784 const char *zA4
1785){
1786 ShellState *p = (ShellState*)pClientData;
1787 static const char *azProhibitedFunctions[] = {
1788 "edit",
1789 "fts3_tokenizer",
1790 "load_extension",
1791 "readfile",
1792 "writefile",
1793 "zipfile",
1794 "zipfile_cds",
1795 };
1796 UNUSED_PARAMETER(zA2);
1797 UNUSED_PARAMETER(zA3);
1798 UNUSED_PARAMETER(zA4);
1799 switch( op ){
1800 case SQLITE_ATTACH: {
1801 failIfSafeMode(p, "cannot run ATTACH in safe mode");
1802 break;
1803 }
1804 case SQLITE_FUNCTION: {
1805 int i;
1806 for(i=0; i<ArraySize(azProhibitedFunctions); i++){
1807 if( sqlite3_stricmp(zA1, azProhibitedFunctions[i])==0 ){
1808 failIfSafeMode(p, "cannot use the %s() function in safe mode",
1809 azProhibitedFunctions[i]);
1810 }
1811 }
1812 break;
1813 }
1814 }
1815 return SQLITE_OK;
1816}
1817
1818/*
drh2ce15c32017-07-11 13:34:40 +00001819** When the ".auth ON" is set, the following authorizer callback is
1820** invoked. It always returns SQLITE_OK.
1821*/
1822static int shellAuth(
1823 void *pClientData,
1824 int op,
1825 const char *zA1,
1826 const char *zA2,
1827 const char *zA3,
1828 const char *zA4
1829){
1830 ShellState *p = (ShellState*)pClientData;
1831 static const char *azAction[] = { 0,
1832 "CREATE_INDEX", "CREATE_TABLE", "CREATE_TEMP_INDEX",
1833 "CREATE_TEMP_TABLE", "CREATE_TEMP_TRIGGER", "CREATE_TEMP_VIEW",
1834 "CREATE_TRIGGER", "CREATE_VIEW", "DELETE",
1835 "DROP_INDEX", "DROP_TABLE", "DROP_TEMP_INDEX",
1836 "DROP_TEMP_TABLE", "DROP_TEMP_TRIGGER", "DROP_TEMP_VIEW",
1837 "DROP_TRIGGER", "DROP_VIEW", "INSERT",
1838 "PRAGMA", "READ", "SELECT",
1839 "TRANSACTION", "UPDATE", "ATTACH",
1840 "DETACH", "ALTER_TABLE", "REINDEX",
1841 "ANALYZE", "CREATE_VTABLE", "DROP_VTABLE",
1842 "FUNCTION", "SAVEPOINT", "RECURSIVE"
1843 };
1844 int i;
1845 const char *az[4];
1846 az[0] = zA1;
1847 az[1] = zA2;
1848 az[2] = zA3;
1849 az[3] = zA4;
1850 utf8_printf(p->out, "authorizer: %s", azAction[op]);
1851 for(i=0; i<4; i++){
1852 raw_printf(p->out, " ");
1853 if( az[i] ){
1854 output_c_string(p->out, az[i]);
1855 }else{
1856 raw_printf(p->out, "NULL");
1857 }
1858 }
1859 raw_printf(p->out, "\n");
drhb97e2ad2021-08-26 18:31:39 +00001860 if( p->bSafeMode ) (void)safeModeAuth(pClientData, op, zA1, zA2, zA3, zA4);
drh2ce15c32017-07-11 13:34:40 +00001861 return SQLITE_OK;
1862}
1863#endif
1864
1865/*
1866** Print a schema statement. Part of MODE_Semi and MODE_Pretty output.
1867**
1868** This routine converts some CREATE TABLE statements for shadow tables
1869** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
1870*/
1871static void printSchemaLine(FILE *out, const char *z, const char *zTail){
drh0a0536a2019-05-09 18:13:30 +00001872 if( z==0 ) return;
1873 if( zTail==0 ) return;
drh2ce15c32017-07-11 13:34:40 +00001874 if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
1875 utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
1876 }else{
1877 utf8_printf(out, "%s%s", z, zTail);
1878 }
1879}
1880static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
1881 char c = z[n];
1882 z[n] = 0;
1883 printSchemaLine(out, z, zTail);
1884 z[n] = c;
1885}
1886
1887/*
drh11be81d2018-01-06 15:46:20 +00001888** Return true if string z[] has nothing but whitespace and comments to the
1889** end of the first line.
1890*/
1891static int wsToEol(const char *z){
1892 int i;
1893 for(i=0; z[i]; i++){
1894 if( z[i]=='\n' ) return 1;
1895 if( IsSpace(z[i]) ) continue;
1896 if( z[i]=='-' && z[i+1]=='-' ) return 1;
1897 return 0;
1898 }
1899 return 1;
1900}
drh4b5345c2018-04-24 13:07:40 +00001901
1902/*
1903** Add a new entry to the EXPLAIN QUERY PLAN data
1904*/
drhe2ca99c2018-05-02 00:33:43 +00001905static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
drh4b5345c2018-04-24 13:07:40 +00001906 EQPGraphRow *pNew;
1907 int nText = strlen30(zText);
drhe2ca99c2018-05-02 00:33:43 +00001908 if( p->autoEQPtest ){
1909 utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
1910 }
drh4b5345c2018-04-24 13:07:40 +00001911 pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
drhe3e25652021-12-16 13:29:28 +00001912 shell_check_oom(pNew);
drhe2ca99c2018-05-02 00:33:43 +00001913 pNew->iEqpId = iEqpId;
1914 pNew->iParentId = p2;
drh4b5345c2018-04-24 13:07:40 +00001915 memcpy(pNew->zText, zText, nText+1);
1916 pNew->pNext = 0;
1917 if( p->sGraph.pLast ){
1918 p->sGraph.pLast->pNext = pNew;
1919 }else{
1920 p->sGraph.pRow = pNew;
1921 }
1922 p->sGraph.pLast = pNew;
1923}
1924
1925/*
1926** Free and reset the EXPLAIN QUERY PLAN data that has been collected
1927** in p->sGraph.
1928*/
1929static void eqp_reset(ShellState *p){
1930 EQPGraphRow *pRow, *pNext;
1931 for(pRow = p->sGraph.pRow; pRow; pRow = pNext){
1932 pNext = pRow->pNext;
1933 sqlite3_free(pRow);
1934 }
1935 memset(&p->sGraph, 0, sizeof(p->sGraph));
1936}
1937
drhe2ca99c2018-05-02 00:33:43 +00001938/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after
drh4b5345c2018-04-24 13:07:40 +00001939** pOld, or return the first such line if pOld is NULL
1940*/
drhe2ca99c2018-05-02 00:33:43 +00001941static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){
drh4b5345c2018-04-24 13:07:40 +00001942 EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow;
drhe2ca99c2018-05-02 00:33:43 +00001943 while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext;
drh4b5345c2018-04-24 13:07:40 +00001944 return pRow;
1945}
1946
drhe2ca99c2018-05-02 00:33:43 +00001947/* Render a single level of the graph that has iEqpId as its parent. Called
drh4b5345c2018-04-24 13:07:40 +00001948** recursively to render sublevels.
1949*/
drhe2ca99c2018-05-02 00:33:43 +00001950static void eqp_render_level(ShellState *p, int iEqpId){
drh4b5345c2018-04-24 13:07:40 +00001951 EQPGraphRow *pRow, *pNext;
drh4b5345c2018-04-24 13:07:40 +00001952 int n = strlen30(p->sGraph.zPrefix);
1953 char *z;
drhe2ca99c2018-05-02 00:33:43 +00001954 for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
1955 pNext = eqp_next_row(p, iEqpId, pRow);
drh4b5345c2018-04-24 13:07:40 +00001956 z = pRow->zText;
drhe2754c12019-08-26 12:50:01 +00001957 utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
1958 pNext ? "|--" : "`--", z);
drhe2188f02018-05-07 11:37:34 +00001959 if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){
drh4b5345c2018-04-24 13:07:40 +00001960 memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4);
drhe2ca99c2018-05-02 00:33:43 +00001961 eqp_render_level(p, pRow->iEqpId);
drh4b5345c2018-04-24 13:07:40 +00001962 p->sGraph.zPrefix[n] = 0;
1963 }
1964 }
1965}
1966
1967/*
1968** Display and reset the EXPLAIN QUERY PLAN data
1969*/
1970static void eqp_render(ShellState *p){
1971 EQPGraphRow *pRow = p->sGraph.pRow;
1972 if( pRow ){
1973 if( pRow->zText[0]=='-' ){
1974 if( pRow->pNext==0 ){
1975 eqp_reset(p);
1976 return;
1977 }
1978 utf8_printf(p->out, "%s\n", pRow->zText+3);
1979 p->sGraph.pRow = pRow->pNext;
1980 sqlite3_free(pRow);
1981 }else{
1982 utf8_printf(p->out, "QUERY PLAN\n");
1983 }
1984 p->sGraph.zPrefix[0] = 0;
1985 eqp_render_level(p, 0);
1986 eqp_reset(p);
1987 }
1988}
drh11be81d2018-01-06 15:46:20 +00001989
drh569b1d92019-02-05 20:51:41 +00001990#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh11be81d2018-01-06 15:46:20 +00001991/*
drh3f83f592019-02-04 14:53:18 +00001992** Progress handler callback.
1993*/
1994static int progress_handler(void *pClientData) {
1995 ShellState *p = (ShellState*)pClientData;
1996 p->nProgress++;
1997 if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
1998 raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
drhfc4eeef2019-02-05 19:48:46 +00001999 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
2000 if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
drh3f83f592019-02-04 14:53:18 +00002001 return 1;
2002 }
drhfc4eeef2019-02-05 19:48:46 +00002003 if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
drh3f83f592019-02-04 14:53:18 +00002004 raw_printf(p->out, "Progress %u\n", p->nProgress);
2005 }
2006 return 0;
2007}
drh569b1d92019-02-05 20:51:41 +00002008#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
drh3f83f592019-02-04 14:53:18 +00002009
2010/*
drh30c54a02020-05-28 23:49:50 +00002011** Print N dashes
2012*/
2013static void print_dashes(FILE *out, int N){
2014 const char zDash[] = "--------------------------------------------------";
2015 const int nDash = sizeof(zDash) - 1;
2016 while( N>nDash ){
2017 fputs(zDash, out);
2018 N -= nDash;
2019 }
2020 raw_printf(out, "%.*s", N, zDash);
2021}
2022
2023/*
drh0908e382020-06-04 18:05:39 +00002024** Print a markdown or table-style row separator using ascii-art
drh30c54a02020-05-28 23:49:50 +00002025*/
2026static void print_row_separator(
2027 ShellState *p,
2028 int nArg,
2029 const char *zSep
2030){
2031 int i;
drh0908e382020-06-04 18:05:39 +00002032 if( nArg>0 ){
drh30c54a02020-05-28 23:49:50 +00002033 fputs(zSep, p->out);
drh0908e382020-06-04 18:05:39 +00002034 print_dashes(p->out, p->actualWidth[0]+2);
2035 for(i=1; i<nArg; i++){
2036 fputs(zSep, p->out);
2037 print_dashes(p->out, p->actualWidth[i]+2);
2038 }
2039 fputs(zSep, p->out);
drh30c54a02020-05-28 23:49:50 +00002040 }
drh30c54a02020-05-28 23:49:50 +00002041 fputs("\n", p->out);
2042}
2043
2044/*
drh2ce15c32017-07-11 13:34:40 +00002045** This is the callback routine that the shell
2046** invokes for each row of a query result.
2047*/
2048static int shell_callback(
2049 void *pArg,
2050 int nArg, /* Number of result columns */
2051 char **azArg, /* Text of each result column */
2052 char **azCol, /* Column names */
drhd6f25242020-05-29 12:31:53 +00002053 int *aiType /* Column types. Might be NULL */
drh2ce15c32017-07-11 13:34:40 +00002054){
2055 int i;
2056 ShellState *p = (ShellState*)pArg;
2057
drhb3c45232017-08-28 14:33:27 +00002058 if( azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00002059 switch( p->cMode ){
drh5d88be82021-12-09 16:17:43 +00002060 case MODE_Count:
2061 case MODE_Off: {
2062 break;
2063 }
drh2ce15c32017-07-11 13:34:40 +00002064 case MODE_Line: {
2065 int w = 5;
2066 if( azArg==0 ) break;
2067 for(i=0; i<nArg; i++){
2068 int len = strlen30(azCol[i] ? azCol[i] : "");
2069 if( len>w ) w = len;
2070 }
2071 if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
2072 for(i=0; i<nArg; i++){
2073 utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
2074 azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
2075 }
2076 break;
2077 }
drh8c748632020-05-29 16:15:58 +00002078 case MODE_Explain: {
2079 static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
2080 if( nArg>ArraySize(aExplainWidth) ){
2081 nArg = ArraySize(aExplainWidth);
drh2ce15c32017-07-11 13:34:40 +00002082 }
2083 if( p->cnt++==0 ){
2084 for(i=0; i<nArg; i++){
drh8c748632020-05-29 16:15:58 +00002085 int w = aExplainWidth[i];
2086 utf8_width_print(p->out, w, azCol[i]);
2087 fputs(i==nArg-1 ? "\n" : " ", p->out);
drh2ce15c32017-07-11 13:34:40 +00002088 }
drhe566ceb2020-05-30 15:34:49 +00002089 for(i=0; i<nArg; i++){
2090 int w = aExplainWidth[i];
2091 print_dashes(p->out, w);
2092 fputs(i==nArg-1 ? "\n" : " ", p->out);
2093 }
drh2ce15c32017-07-11 13:34:40 +00002094 }
2095 if( azArg==0 ) break;
2096 for(i=0; i<nArg; i++){
drh8c748632020-05-29 16:15:58 +00002097 int w = aExplainWidth[i];
drhaa556b02021-01-13 12:59:20 +00002098 if( i==nArg-1 ) w = 0;
drh8c748632020-05-29 16:15:58 +00002099 if( azArg[i] && strlenChar(azArg[i])>w ){
2100 w = strlenChar(azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00002101 }
drh8c748632020-05-29 16:15:58 +00002102 if( i==1 && p->aiIndent && p->pStmt ){
2103 if( p->iIndent<p->nIndent ){
2104 utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
drh2ce15c32017-07-11 13:34:40 +00002105 }
drh8c748632020-05-29 16:15:58 +00002106 p->iIndent++;
drh2ce15c32017-07-11 13:34:40 +00002107 }
2108 utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
drh8c748632020-05-29 16:15:58 +00002109 fputs(i==nArg-1 ? "\n" : " ", p->out);
drh2ce15c32017-07-11 13:34:40 +00002110 }
2111 break;
2112 }
2113 case MODE_Semi: { /* .schema and .fullschema output */
2114 printSchemaLine(p->out, azArg[0], ";\n");
2115 break;
2116 }
2117 case MODE_Pretty: { /* .schema and .fullschema with --indent */
2118 char *z;
2119 int j;
2120 int nParen = 0;
2121 char cEnd = 0;
2122 char c;
2123 int nLine = 0;
2124 assert( nArg==1 );
2125 if( azArg[0]==0 ) break;
2126 if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
2127 || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
2128 ){
2129 utf8_printf(p->out, "%s;\n", azArg[0]);
2130 break;
2131 }
2132 z = sqlite3_mprintf("%s", azArg[0]);
drhe3e25652021-12-16 13:29:28 +00002133 shell_check_oom(z);
drh2ce15c32017-07-11 13:34:40 +00002134 j = 0;
2135 for(i=0; IsSpace(z[i]); i++){}
2136 for(; (c = z[i])!=0; i++){
2137 if( IsSpace(c) ){
drhc3cbd672017-10-05 19:12:10 +00002138 if( z[j-1]=='\r' ) z[j-1] = '\n';
drh2ce15c32017-07-11 13:34:40 +00002139 if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
2140 }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
2141 j--;
2142 }
2143 z[j++] = c;
2144 }
2145 while( j>0 && IsSpace(z[j-1]) ){ j--; }
2146 z[j] = 0;
2147 if( strlen30(z)>=79 ){
drhe2754c12019-08-26 12:50:01 +00002148 for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */
drh2ce15c32017-07-11 13:34:40 +00002149 if( c==cEnd ){
2150 cEnd = 0;
2151 }else if( c=='"' || c=='\'' || c=='`' ){
2152 cEnd = c;
2153 }else if( c=='[' ){
2154 cEnd = ']';
drh11be81d2018-01-06 15:46:20 +00002155 }else if( c=='-' && z[i+1]=='-' ){
2156 cEnd = '\n';
drh2ce15c32017-07-11 13:34:40 +00002157 }else if( c=='(' ){
2158 nParen++;
2159 }else if( c==')' ){
2160 nParen--;
2161 if( nLine>0 && nParen==0 && j>0 ){
2162 printSchemaLineN(p->out, z, j, "\n");
2163 j = 0;
2164 }
2165 }
2166 z[j++] = c;
drh11be81d2018-01-06 15:46:20 +00002167 if( nParen==1 && cEnd==0
2168 && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
2169 ){
drh2ce15c32017-07-11 13:34:40 +00002170 if( c=='\n' ) j--;
2171 printSchemaLineN(p->out, z, j, "\n ");
2172 j = 0;
2173 nLine++;
2174 while( IsSpace(z[i+1]) ){ i++; }
2175 }
2176 }
2177 z[j] = 0;
2178 }
2179 printSchemaLine(p->out, z, ";\n");
2180 sqlite3_free(z);
2181 break;
2182 }
2183 case MODE_List: {
2184 if( p->cnt++==0 && p->showHeader ){
2185 for(i=0; i<nArg; i++){
2186 utf8_printf(p->out,"%s%s",azCol[i],
2187 i==nArg-1 ? p->rowSeparator : p->colSeparator);
2188 }
2189 }
2190 if( azArg==0 ) break;
2191 for(i=0; i<nArg; i++){
2192 char *z = azArg[i];
2193 if( z==0 ) z = p->nullValue;
2194 utf8_printf(p->out, "%s", z);
2195 if( i<nArg-1 ){
2196 utf8_printf(p->out, "%s", p->colSeparator);
2197 }else{
2198 utf8_printf(p->out, "%s", p->rowSeparator);
2199 }
2200 }
2201 break;
2202 }
2203 case MODE_Html: {
2204 if( p->cnt++==0 && p->showHeader ){
2205 raw_printf(p->out,"<TR>");
2206 for(i=0; i<nArg; i++){
2207 raw_printf(p->out,"<TH>");
2208 output_html_string(p->out, azCol[i]);
2209 raw_printf(p->out,"</TH>\n");
2210 }
2211 raw_printf(p->out,"</TR>\n");
2212 }
2213 if( azArg==0 ) break;
2214 raw_printf(p->out,"<TR>");
2215 for(i=0; i<nArg; i++){
2216 raw_printf(p->out,"<TD>");
2217 output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
2218 raw_printf(p->out,"</TD>\n");
2219 }
2220 raw_printf(p->out,"</TR>\n");
2221 break;
2222 }
2223 case MODE_Tcl: {
2224 if( p->cnt++==0 && p->showHeader ){
2225 for(i=0; i<nArg; i++){
2226 output_c_string(p->out,azCol[i] ? azCol[i] : "");
2227 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
2228 }
2229 utf8_printf(p->out, "%s", p->rowSeparator);
2230 }
2231 if( azArg==0 ) break;
2232 for(i=0; i<nArg; i++){
2233 output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
2234 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
2235 }
2236 utf8_printf(p->out, "%s", p->rowSeparator);
2237 break;
2238 }
2239 case MODE_Csv: {
2240 setBinaryMode(p->out, 1);
2241 if( p->cnt++==0 && p->showHeader ){
2242 for(i=0; i<nArg; i++){
2243 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
2244 }
2245 utf8_printf(p->out, "%s", p->rowSeparator);
2246 }
2247 if( nArg>0 ){
2248 for(i=0; i<nArg; i++){
2249 output_csv(p, azArg[i], i<nArg-1);
2250 }
2251 utf8_printf(p->out, "%s", p->rowSeparator);
2252 }
2253 setTextMode(p->out, 1);
2254 break;
2255 }
2256 case MODE_Insert: {
2257 if( azArg==0 ) break;
2258 utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
2259 if( p->showHeader ){
2260 raw_printf(p->out,"(");
2261 for(i=0; i<nArg; i++){
2262 if( i>0 ) raw_printf(p->out, ",");
2263 if( quoteChar(azCol[i]) ){
2264 char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
drhe3e25652021-12-16 13:29:28 +00002265 shell_check_oom(z);
drh2ce15c32017-07-11 13:34:40 +00002266 utf8_printf(p->out, "%s", z);
2267 sqlite3_free(z);
2268 }else{
2269 raw_printf(p->out, "%s", azCol[i]);
2270 }
2271 }
2272 raw_printf(p->out,")");
2273 }
2274 p->cnt++;
2275 for(i=0; i<nArg; i++){
2276 raw_printf(p->out, i>0 ? "," : " VALUES(");
2277 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2278 utf8_printf(p->out,"NULL");
2279 }else if( aiType && aiType[i]==SQLITE_TEXT ){
2280 if( ShellHasFlag(p, SHFLG_Newlines) ){
2281 output_quoted_string(p->out, azArg[i]);
2282 }else{
2283 output_quoted_escaped_string(p->out, azArg[i]);
2284 }
2285 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
2286 utf8_printf(p->out,"%s", azArg[i]);
2287 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2288 char z[50];
2289 double r = sqlite3_column_double(p->pStmt, i);
drh2f1f8802018-06-13 17:19:20 +00002290 sqlite3_uint64 ur;
2291 memcpy(&ur,&r,sizeof(r));
2292 if( ur==0x7ff0000000000000LL ){
2293 raw_printf(p->out, "1e999");
2294 }else if( ur==0xfff0000000000000LL ){
2295 raw_printf(p->out, "-1e999");
2296 }else{
2297 sqlite3_snprintf(50,z,"%!.20g", r);
2298 raw_printf(p->out, "%s", z);
2299 }
drh2ce15c32017-07-11 13:34:40 +00002300 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2301 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2302 int nBlob = sqlite3_column_bytes(p->pStmt, i);
2303 output_hex_blob(p->out, pBlob, nBlob);
2304 }else if( isNumber(azArg[i], 0) ){
2305 utf8_printf(p->out,"%s", azArg[i]);
2306 }else if( ShellHasFlag(p, SHFLG_Newlines) ){
2307 output_quoted_string(p->out, azArg[i]);
2308 }else{
2309 output_quoted_escaped_string(p->out, azArg[i]);
2310 }
2311 }
2312 raw_printf(p->out,");\n");
2313 break;
2314 }
drh30c54a02020-05-28 23:49:50 +00002315 case MODE_Json: {
2316 if( azArg==0 ) break;
2317 if( p->cnt==0 ){
2318 fputs("[{", p->out);
2319 }else{
2320 fputs(",\n{", p->out);
2321 }
2322 p->cnt++;
2323 for(i=0; i<nArg; i++){
drh69c093d2020-05-29 00:21:43 +00002324 output_json_string(p->out, azCol[i], -1);
drh30c54a02020-05-28 23:49:50 +00002325 putc(':', p->out);
2326 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2327 fputs("null",p->out);
2328 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2329 char z[50];
2330 double r = sqlite3_column_double(p->pStmt, i);
2331 sqlite3_uint64 ur;
2332 memcpy(&ur,&r,sizeof(r));
2333 if( ur==0x7ff0000000000000LL ){
2334 raw_printf(p->out, "1e999");
2335 }else if( ur==0xfff0000000000000LL ){
2336 raw_printf(p->out, "-1e999");
2337 }else{
2338 sqlite3_snprintf(50,z,"%!.20g", r);
2339 raw_printf(p->out, "%s", z);
2340 }
2341 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2342 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2343 int nBlob = sqlite3_column_bytes(p->pStmt, i);
drh69c093d2020-05-29 00:21:43 +00002344 output_json_string(p->out, pBlob, nBlob);
drh30c54a02020-05-28 23:49:50 +00002345 }else if( aiType && aiType[i]==SQLITE_TEXT ){
drh69c093d2020-05-29 00:21:43 +00002346 output_json_string(p->out, azArg[i], -1);
drh30c54a02020-05-28 23:49:50 +00002347 }else{
2348 utf8_printf(p->out,"%s", azArg[i]);
2349 }
2350 if( i<nArg-1 ){
2351 putc(',', p->out);
2352 }
2353 }
2354 putc('}', p->out);
2355 break;
2356 }
drh2ce15c32017-07-11 13:34:40 +00002357 case MODE_Quote: {
2358 if( azArg==0 ) break;
2359 if( p->cnt==0 && p->showHeader ){
2360 for(i=0; i<nArg; i++){
drhc6835732020-05-28 20:37:17 +00002361 if( i>0 ) fputs(p->colSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002362 output_quoted_string(p->out, azCol[i]);
2363 }
drhc6835732020-05-28 20:37:17 +00002364 fputs(p->rowSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002365 }
2366 p->cnt++;
2367 for(i=0; i<nArg; i++){
drhc6835732020-05-28 20:37:17 +00002368 if( i>0 ) fputs(p->colSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002369 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2370 utf8_printf(p->out,"NULL");
2371 }else if( aiType && aiType[i]==SQLITE_TEXT ){
2372 output_quoted_string(p->out, azArg[i]);
2373 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
2374 utf8_printf(p->out,"%s", azArg[i]);
2375 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2376 char z[50];
2377 double r = sqlite3_column_double(p->pStmt, i);
2378 sqlite3_snprintf(50,z,"%!.20g", r);
2379 raw_printf(p->out, "%s", z);
2380 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2381 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2382 int nBlob = sqlite3_column_bytes(p->pStmt, i);
2383 output_hex_blob(p->out, pBlob, nBlob);
2384 }else if( isNumber(azArg[i], 0) ){
2385 utf8_printf(p->out,"%s", azArg[i]);
2386 }else{
2387 output_quoted_string(p->out, azArg[i]);
2388 }
2389 }
drhc6835732020-05-28 20:37:17 +00002390 fputs(p->rowSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002391 break;
2392 }
2393 case MODE_Ascii: {
2394 if( p->cnt++==0 && p->showHeader ){
2395 for(i=0; i<nArg; i++){
2396 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
2397 utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
2398 }
2399 utf8_printf(p->out, "%s", p->rowSeparator);
2400 }
2401 if( azArg==0 ) break;
2402 for(i=0; i<nArg; i++){
2403 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
2404 utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
2405 }
2406 utf8_printf(p->out, "%s", p->rowSeparator);
2407 break;
2408 }
drh4b5345c2018-04-24 13:07:40 +00002409 case MODE_EQP: {
drhe2ca99c2018-05-02 00:33:43 +00002410 eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]);
drh4b5345c2018-04-24 13:07:40 +00002411 break;
2412 }
drh2ce15c32017-07-11 13:34:40 +00002413 }
2414 return 0;
2415}
2416
2417/*
2418** This is the callback routine that the SQLite library
2419** invokes for each row of a query result.
2420*/
2421static int callback(void *pArg, int nArg, char **azArg, char **azCol){
2422 /* since we don't have type info, call the shell_callback with a NULL value */
2423 return shell_callback(pArg, nArg, azArg, azCol, NULL);
2424}
2425
2426/*
2427** This is the callback routine from sqlite3_exec() that appends all
2428** output onto the end of a ShellText object.
2429*/
2430static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
2431 ShellText *p = (ShellText*)pArg;
2432 int i;
2433 UNUSED_PARAMETER(az);
drhb3c45232017-08-28 14:33:27 +00002434 if( azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00002435 if( p->n ) appendText(p, "|", 0);
2436 for(i=0; i<nArg; i++){
2437 if( i ) appendText(p, ",", 0);
2438 if( azArg[i] ) appendText(p, azArg[i], 0);
2439 }
2440 return 0;
2441}
2442
2443/*
2444** Generate an appropriate SELFTEST table in the main database.
2445*/
2446static void createSelftestTable(ShellState *p){
2447 char *zErrMsg = 0;
2448 sqlite3_exec(p->db,
2449 "SAVEPOINT selftest_init;\n"
2450 "CREATE TABLE IF NOT EXISTS selftest(\n"
2451 " tno INTEGER PRIMARY KEY,\n" /* Test number */
2452 " op TEXT,\n" /* Operator: memo run */
2453 " cmd TEXT,\n" /* Command text */
2454 " ans TEXT\n" /* Desired answer */
2455 ");"
2456 "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n"
2457 "INSERT INTO [_shell$self](rowid,op,cmd)\n"
2458 " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n"
2459 " 'memo','Tests generated by --init');\n"
2460 "INSERT INTO [_shell$self]\n"
2461 " SELECT 'run',\n"
2462 " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql "
drh067b92b2020-06-19 15:24:12 +00002463 "FROM sqlite_schema ORDER BY 2'',224))',\n"
drh2ce15c32017-07-11 13:34:40 +00002464 " hex(sha3_query('SELECT type,name,tbl_name,sql "
drh067b92b2020-06-19 15:24:12 +00002465 "FROM sqlite_schema ORDER BY 2',224));\n"
drh2ce15c32017-07-11 13:34:40 +00002466 "INSERT INTO [_shell$self]\n"
2467 " SELECT 'run',"
2468 " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||"
2469 " printf('%w',name) || '\" NOT INDEXED'',224))',\n"
2470 " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"
2471 " FROM (\n"
drh067b92b2020-06-19 15:24:12 +00002472 " SELECT name FROM sqlite_schema\n"
drh2ce15c32017-07-11 13:34:40 +00002473 " WHERE type='table'\n"
2474 " AND name<>'selftest'\n"
2475 " AND coalesce(rootpage,0)>0\n"
2476 " )\n"
2477 " ORDER BY name;\n"
2478 "INSERT INTO [_shell$self]\n"
2479 " VALUES('run','PRAGMA integrity_check','ok');\n"
2480 "INSERT INTO selftest(tno,op,cmd,ans)"
2481 " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n"
2482 "DROP TABLE [_shell$self];"
2483 ,0,0,&zErrMsg);
2484 if( zErrMsg ){
2485 utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
2486 sqlite3_free(zErrMsg);
2487 }
2488 sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
2489}
2490
2491
2492/*
2493** Set the destination table field of the ShellState structure to
2494** the name of the table given. Escape any quote characters in the
2495** table name.
2496*/
2497static void set_table_name(ShellState *p, const char *zName){
2498 int i, n;
mistachkin2158a0c2017-09-09 00:51:36 +00002499 char cQuote;
drh2ce15c32017-07-11 13:34:40 +00002500 char *z;
2501
2502 if( p->zDestTable ){
2503 free(p->zDestTable);
2504 p->zDestTable = 0;
2505 }
2506 if( zName==0 ) return;
2507 cQuote = quoteChar(zName);
2508 n = strlen30(zName);
2509 if( cQuote ) n += n+2;
2510 z = p->zDestTable = malloc( n+1 );
drhe3e25652021-12-16 13:29:28 +00002511 shell_check_oom(z);
drh2ce15c32017-07-11 13:34:40 +00002512 n = 0;
2513 if( cQuote ) z[n++] = cQuote;
2514 for(i=0; zName[i]; i++){
2515 z[n++] = zName[i];
2516 if( zName[i]==cQuote ) z[n++] = cQuote;
2517 }
2518 if( cQuote ) z[n++] = cQuote;
2519 z[n] = 0;
2520}
2521
2522
2523/*
2524** Execute a query statement that will generate SQL output. Print
2525** the result columns, comma-separated, on a line and then add a
2526** semicolon terminator to the end of that line.
2527**
2528** If the number of columns is 1 and that column contains text "--"
2529** then write the semicolon on a separate line. That way, if a
2530** "--" comment occurs at the end of the statement, the comment
2531** won't consume the semicolon terminator.
2532*/
2533static int run_table_dump_query(
2534 ShellState *p, /* Query context */
drh8e9297f2020-03-25 12:50:13 +00002535 const char *zSelect /* SELECT statement to extract content */
drh2ce15c32017-07-11 13:34:40 +00002536){
2537 sqlite3_stmt *pSelect;
2538 int rc;
2539 int nResult;
2540 int i;
2541 const char *z;
2542 rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
2543 if( rc!=SQLITE_OK || !pSelect ){
2544 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
2545 sqlite3_errmsg(p->db));
2546 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
2547 return rc;
2548 }
2549 rc = sqlite3_step(pSelect);
2550 nResult = sqlite3_column_count(pSelect);
2551 while( rc==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00002552 z = (const char*)sqlite3_column_text(pSelect, 0);
2553 utf8_printf(p->out, "%s", z);
2554 for(i=1; i<nResult; i++){
2555 utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
2556 }
2557 if( z==0 ) z = "";
2558 while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
2559 if( z[0] ){
2560 raw_printf(p->out, "\n;\n");
2561 }else{
2562 raw_printf(p->out, ";\n");
2563 }
2564 rc = sqlite3_step(pSelect);
2565 }
2566 rc = sqlite3_finalize(pSelect);
2567 if( rc!=SQLITE_OK ){
2568 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
2569 sqlite3_errmsg(p->db));
2570 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
2571 }
2572 return rc;
2573}
2574
2575/*
larrybrf9a49b02021-10-26 16:57:09 +00002576** Allocate space and save off string indicating current error.
drh2ce15c32017-07-11 13:34:40 +00002577*/
2578static char *save_err_msg(
larrybrf9a49b02021-10-26 16:57:09 +00002579 sqlite3 *db, /* Database to query */
2580 const char *zWhen, /* Qualifier (format) wrapper */
2581 int rc /* Error code returned from API */
drh2ce15c32017-07-11 13:34:40 +00002582){
drhe3e25652021-12-16 13:29:28 +00002583 char *zErr;
2584 if( zWhen==0 ) zWhen = "%s (%d)";
2585 zErr = sqlite3_mprintf(zWhen, sqlite3_errmsg(db), rc);
2586 shell_check_oom(zErr);
2587 return zErr;
drh2ce15c32017-07-11 13:34:40 +00002588}
2589
2590#ifdef __linux__
2591/*
2592** Attempt to display I/O stats on Linux using /proc/PID/io
2593*/
2594static void displayLinuxIoStats(FILE *out){
2595 FILE *in;
2596 char z[200];
2597 sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
2598 in = fopen(z, "rb");
2599 if( in==0 ) return;
2600 while( fgets(z, sizeof(z), in)!=0 ){
2601 static const struct {
2602 const char *zPattern;
2603 const char *zDesc;
2604 } aTrans[] = {
2605 { "rchar: ", "Bytes received by read():" },
2606 { "wchar: ", "Bytes sent to write():" },
2607 { "syscr: ", "Read() system calls:" },
2608 { "syscw: ", "Write() system calls:" },
2609 { "read_bytes: ", "Bytes read from storage:" },
2610 { "write_bytes: ", "Bytes written to storage:" },
2611 { "cancelled_write_bytes: ", "Cancelled write bytes:" },
2612 };
2613 int i;
2614 for(i=0; i<ArraySize(aTrans); i++){
drhaf2770f2018-01-05 14:55:43 +00002615 int n = strlen30(aTrans[i].zPattern);
drh2ce15c32017-07-11 13:34:40 +00002616 if( strncmp(aTrans[i].zPattern, z, n)==0 ){
2617 utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
2618 break;
2619 }
2620 }
2621 }
2622 fclose(in);
2623}
2624#endif
2625
2626/*
2627** Display a single line of status using 64-bit values.
2628*/
2629static void displayStatLine(
2630 ShellState *p, /* The shell context */
2631 char *zLabel, /* Label for this one line */
2632 char *zFormat, /* Format for the result */
2633 int iStatusCtrl, /* Which status to display */
2634 int bReset /* True to reset the stats */
2635){
2636 sqlite3_int64 iCur = -1;
2637 sqlite3_int64 iHiwtr = -1;
2638 int i, nPercent;
2639 char zLine[200];
2640 sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset);
2641 for(i=0, nPercent=0; zFormat[i]; i++){
2642 if( zFormat[i]=='%' ) nPercent++;
2643 }
2644 if( nPercent>1 ){
2645 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr);
2646 }else{
2647 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
2648 }
2649 raw_printf(p->out, "%-36s %s\n", zLabel, zLine);
2650}
2651
2652/*
2653** Display memory stats.
2654*/
2655static int display_stats(
2656 sqlite3 *db, /* Database to query */
2657 ShellState *pArg, /* Pointer to ShellState */
2658 int bReset /* True to reset the stats */
2659){
2660 int iCur;
2661 int iHiwtr;
drh393344f2018-03-09 16:37:05 +00002662 FILE *out;
2663 if( pArg==0 || pArg->out==0 ) return 0;
2664 out = pArg->out;
drh2ce15c32017-07-11 13:34:40 +00002665
drha6e6cf22021-01-09 19:10:04 +00002666 if( pArg->pStmt && pArg->statsOn==2 ){
drh393344f2018-03-09 16:37:05 +00002667 int nCol, i, x;
2668 sqlite3_stmt *pStmt = pArg->pStmt;
2669 char z[100];
2670 nCol = sqlite3_column_count(pStmt);
2671 raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
2672 for(i=0; i<nCol; i++){
2673 sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
2674 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
drh929cce82018-03-17 16:26:36 +00002675#ifndef SQLITE_OMIT_DECLTYPE
drh393344f2018-03-09 16:37:05 +00002676 sqlite3_snprintf(30, z+x, "declared type:");
2677 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
drh929cce82018-03-17 16:26:36 +00002678#endif
2679#ifdef SQLITE_ENABLE_COLUMN_METADATA
drh393344f2018-03-09 16:37:05 +00002680 sqlite3_snprintf(30, z+x, "database name:");
2681 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
2682 sqlite3_snprintf(30, z+x, "table name:");
2683 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
2684 sqlite3_snprintf(30, z+x, "origin name:");
2685 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
drh929cce82018-03-17 16:26:36 +00002686#endif
drh2ce15c32017-07-11 13:34:40 +00002687 }
drh929cce82018-03-17 16:26:36 +00002688 }
drh2ce15c32017-07-11 13:34:40 +00002689
drha6e6cf22021-01-09 19:10:04 +00002690 if( pArg->statsOn==3 ){
2691 if( pArg->pStmt ){
2692 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
2693 raw_printf(pArg->out, "VM-steps: %d\n", iCur);
2694 }
2695 return 0;
2696 }
2697
drh393344f2018-03-09 16:37:05 +00002698 displayStatLine(pArg, "Memory Used:",
2699 "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
2700 displayStatLine(pArg, "Number of Outstanding Allocations:",
2701 "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
2702 if( pArg->shellFlgs & SHFLG_Pagecache ){
2703 displayStatLine(pArg, "Number of Pcache Pages Used:",
2704 "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
2705 }
2706 displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
2707 "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
2708 displayStatLine(pArg, "Largest Allocation:",
2709 "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
2710 displayStatLine(pArg, "Largest Pcache Allocation:",
2711 "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
2712#ifdef YYTRACKMAXSTACKDEPTH
2713 displayStatLine(pArg, "Deepest Parser Stack:",
2714 "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
2715#endif
2716
2717 if( db ){
drh2ce15c32017-07-11 13:34:40 +00002718 if( pArg->shellFlgs & SHFLG_Lookaside ){
2719 iHiwtr = iCur = -1;
2720 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
2721 &iCur, &iHiwtr, bReset);
2722 raw_printf(pArg->out,
2723 "Lookaside Slots Used: %d (max %d)\n",
2724 iCur, iHiwtr);
2725 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
2726 &iCur, &iHiwtr, bReset);
2727 raw_printf(pArg->out, "Successful lookaside attempts: %d\n",
2728 iHiwtr);
2729 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
2730 &iCur, &iHiwtr, bReset);
2731 raw_printf(pArg->out, "Lookaside failures due to size: %d\n",
2732 iHiwtr);
2733 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
2734 &iCur, &iHiwtr, bReset);
2735 raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n",
2736 iHiwtr);
2737 }
2738 iHiwtr = iCur = -1;
2739 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
2740 raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n",
2741 iCur);
2742 iHiwtr = iCur = -1;
2743 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
2744 raw_printf(pArg->out, "Page cache hits: %d\n", iCur);
2745 iHiwtr = iCur = -1;
2746 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
2747 raw_printf(pArg->out, "Page cache misses: %d\n", iCur);
2748 iHiwtr = iCur = -1;
2749 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
2750 raw_printf(pArg->out, "Page cache writes: %d\n", iCur);
2751 iHiwtr = iCur = -1;
drhffc78a42018-03-14 14:53:50 +00002752 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
2753 raw_printf(pArg->out, "Page cache spills: %d\n", iCur);
2754 iHiwtr = iCur = -1;
drh2ce15c32017-07-11 13:34:40 +00002755 sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
2756 raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n",
2757 iCur);
2758 iHiwtr = iCur = -1;
2759 sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
2760 raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
2761 iCur);
2762 }
2763
drh393344f2018-03-09 16:37:05 +00002764 if( pArg->pStmt ){
drh23d41e62021-12-06 21:45:31 +00002765 int iHit, iMiss;
drh2ce15c32017-07-11 13:34:40 +00002766 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
2767 bReset);
2768 raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
2769 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
2770 raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
2771 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
2772 raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
drh23d41e62021-12-06 21:45:31 +00002773 iHit = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_HIT, bReset);
2774 iMiss = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_MISS, bReset);
2775 if( iHit || iMiss ){
2776 raw_printf(pArg->out, "Bloom filter bypass taken: %d/%d\n",
2777 iHit, iHit+iMiss);
2778 }
drh2ce15c32017-07-11 13:34:40 +00002779 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
2780 raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
drhe2754c12019-08-26 12:50:01 +00002781 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
drh393344f2018-03-09 16:37:05 +00002782 raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
2783 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
2784 raw_printf(pArg->out, "Number of times run: %d\n", iCur);
2785 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
2786 raw_printf(pArg->out, "Memory used by prepared stmt: %d\n", iCur);
drh2ce15c32017-07-11 13:34:40 +00002787 }
2788
2789#ifdef __linux__
2790 displayLinuxIoStats(pArg->out);
2791#endif
2792
2793 /* Do not remove this machine readable comment: extra-stats-output-here */
2794
2795 return 0;
2796}
2797
2798/*
2799** Display scan stats.
2800*/
2801static void display_scanstats(
2802 sqlite3 *db, /* Database to query */
2803 ShellState *pArg /* Pointer to ShellState */
2804){
2805#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
2806 UNUSED_PARAMETER(db);
2807 UNUSED_PARAMETER(pArg);
2808#else
2809 int i, k, n, mx;
2810 raw_printf(pArg->out, "-------- scanstats --------\n");
2811 mx = 0;
2812 for(k=0; k<=mx; k++){
2813 double rEstLoop = 1.0;
2814 for(i=n=0; 1; i++){
2815 sqlite3_stmt *p = pArg->pStmt;
2816 sqlite3_int64 nLoop, nVisit;
2817 double rEst;
2818 int iSid;
2819 const char *zExplain;
2820 if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){
2821 break;
2822 }
2823 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
2824 if( iSid>mx ) mx = iSid;
2825 if( iSid!=k ) continue;
2826 if( n==0 ){
2827 rEstLoop = (double)nLoop;
2828 if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k);
2829 }
2830 n++;
2831 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
2832 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
2833 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
2834 utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
2835 rEstLoop *= rEst;
2836 raw_printf(pArg->out,
2837 " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
2838 nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
2839 );
2840 }
2841 }
2842 raw_printf(pArg->out, "---------------------------\n");
2843#endif
2844}
2845
2846/*
2847** Parameter azArray points to a zero-terminated array of strings. zStr
2848** points to a single nul-terminated string. Return non-zero if zStr
2849** is equal, according to strcmp(), to any of the strings in the array.
2850** Otherwise, return zero.
2851*/
2852static int str_in_array(const char *zStr, const char **azArray){
2853 int i;
2854 for(i=0; azArray[i]; i++){
2855 if( 0==strcmp(zStr, azArray[i]) ) return 1;
2856 }
2857 return 0;
2858}
2859
2860/*
2861** If compiled statement pSql appears to be an EXPLAIN statement, allocate
2862** and populate the ShellState.aiIndent[] array with the number of
2863** spaces each opcode should be indented before it is output.
2864**
2865** The indenting rules are:
2866**
2867** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
2868** all opcodes that occur between the p2 jump destination and the opcode
2869** itself by 2 spaces.
2870**
2871** * For each "Goto", if the jump destination is earlier in the program
2872** and ends on one of:
2873** Yield SeekGt SeekLt RowSetRead Rewind
2874** or if the P1 parameter is one instead of zero,
2875** then indent all opcodes between the earlier instruction
2876** and "Goto" by 2 spaces.
2877*/
2878static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
2879 const char *zSql; /* The text of the SQL statement */
2880 const char *z; /* Used to check if this is an EXPLAIN */
2881 int *abYield = 0; /* True if op is an OP_Yield */
2882 int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
2883 int iOp; /* Index of operation in p->aiIndent[] */
2884
drhf1949b62018-06-07 17:32:59 +00002885 const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
drh2ce15c32017-07-11 13:34:40 +00002886 const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
2887 "Rewind", 0 };
2888 const char *azGoto[] = { "Goto", 0 };
2889
2890 /* Try to figure out if this is really an EXPLAIN statement. If this
2891 ** cannot be verified, return early. */
2892 if( sqlite3_column_count(pSql)!=8 ){
2893 p->cMode = p->mode;
2894 return;
2895 }
2896 zSql = sqlite3_sql(pSql);
2897 if( zSql==0 ) return;
2898 for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
2899 if( sqlite3_strnicmp(z, "explain", 7) ){
2900 p->cMode = p->mode;
2901 return;
2902 }
2903
2904 for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
2905 int i;
2906 int iAddr = sqlite3_column_int(pSql, 0);
2907 const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
2908
2909 /* Set p2 to the P2 field of the current opcode. Then, assuming that
2910 ** p2 is an instruction address, set variable p2op to the index of that
2911 ** instruction in the aiIndent[] array. p2 and p2op may be different if
2912 ** the current instruction is part of a sub-program generated by an
2913 ** SQL trigger or foreign key. */
2914 int p2 = sqlite3_column_int(pSql, 3);
2915 int p2op = (p2 + (iOp-iAddr));
2916
2917 /* Grow the p->aiIndent array as required */
2918 if( iOp>=nAlloc ){
2919 if( iOp==0 ){
2920 /* Do further verfication that this is explain output. Abort if
2921 ** it is not */
2922 static const char *explainCols[] = {
2923 "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" };
2924 int jj;
2925 for(jj=0; jj<ArraySize(explainCols); jj++){
2926 if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
2927 p->cMode = p->mode;
2928 sqlite3_reset(pSql);
2929 return;
2930 }
2931 }
2932 }
2933 nAlloc += 100;
2934 p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
drhe3e25652021-12-16 13:29:28 +00002935 shell_check_oom(p->aiIndent);
drh2ce15c32017-07-11 13:34:40 +00002936 abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
drhe3e25652021-12-16 13:29:28 +00002937 shell_check_oom(abYield);
drh2ce15c32017-07-11 13:34:40 +00002938 }
2939 abYield[iOp] = str_in_array(zOp, azYield);
2940 p->aiIndent[iOp] = 0;
2941 p->nIndent = iOp+1;
2942
2943 if( str_in_array(zOp, azNext) ){
2944 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
2945 }
2946 if( str_in_array(zOp, azGoto) && p2op<p->nIndent
2947 && (abYield[p2op] || sqlite3_column_int(pSql, 2))
2948 ){
2949 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
2950 }
2951 }
2952
2953 p->iIndent = 0;
2954 sqlite3_free(abYield);
2955 sqlite3_reset(pSql);
2956}
2957
2958/*
2959** Free the array allocated by explain_data_prepare().
2960*/
2961static void explain_data_delete(ShellState *p){
2962 sqlite3_free(p->aiIndent);
2963 p->aiIndent = 0;
2964 p->nIndent = 0;
2965 p->iIndent = 0;
2966}
2967
2968/*
2969** Disable and restore .wheretrace and .selecttrace settings.
2970*/
drhc0622a42020-12-04 01:17:57 +00002971static unsigned int savedSelectTrace;
2972static unsigned int savedWhereTrace;
drh2ce15c32017-07-11 13:34:40 +00002973static void disable_debug_trace_modes(void){
drh0a2fb792020-12-04 16:58:20 +00002974 unsigned int zero = 0;
drhc0622a42020-12-04 01:17:57 +00002975 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace);
drh0a2fb792020-12-04 16:58:20 +00002976 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero);
drhc0622a42020-12-04 01:17:57 +00002977 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace);
drh0a2fb792020-12-04 16:58:20 +00002978 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero);
drh2ce15c32017-07-11 13:34:40 +00002979}
2980static void restore_debug_trace_modes(void){
drhc0622a42020-12-04 01:17:57 +00002981 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &savedSelectTrace);
2982 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &savedWhereTrace);
drh2ce15c32017-07-11 13:34:40 +00002983}
2984
drh9cb02642019-02-28 20:10:52 +00002985/* Create the TEMP table used to store parameter bindings */
2986static void bind_table_init(ShellState *p){
drh346f4e22019-03-25 21:35:41 +00002987 int wrSchema = 0;
drh4b86e202020-01-19 20:37:26 +00002988 int defensiveMode = 0;
2989 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
2990 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
drh346f4e22019-03-25 21:35:41 +00002991 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
2992 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
drh9cb02642019-02-28 20:10:52 +00002993 sqlite3_exec(p->db,
drh65c29fd2019-03-25 21:56:26 +00002994 "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
drh9cb02642019-02-28 20:10:52 +00002995 " key TEXT PRIMARY KEY,\n"
larrybrdabada62021-04-04 12:52:58 +00002996 " value\n"
drh9cb02642019-02-28 20:10:52 +00002997 ") WITHOUT ROWID;",
2998 0, 0, 0);
drh346f4e22019-03-25 21:35:41 +00002999 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
drh4b86e202020-01-19 20:37:26 +00003000 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0);
drh9cb02642019-02-28 20:10:52 +00003001}
3002
drh8b738d02019-02-25 18:43:54 +00003003/*
3004** Bind parameters on a prepared statement.
3005**
3006** Parameter bindings are taken from a TEMP table of the form:
3007**
drh1cb02632019-03-25 22:05:22 +00003008** CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
drh8b738d02019-02-25 18:43:54 +00003009** WITHOUT ROWID;
3010**
drh91654b22020-04-02 13:21:10 +00003011** No bindings occur if this table does not exist. The name of the table
3012** begins with "sqlite_" so that it will not collide with ordinary application
3013** tables. The table must be in the TEMP schema.
drh8b738d02019-02-25 18:43:54 +00003014*/
3015static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
3016 int nVar;
3017 int i;
3018 int rc;
3019 sqlite3_stmt *pQ = 0;
3020
3021 nVar = sqlite3_bind_parameter_count(pStmt);
3022 if( nVar==0 ) return; /* Nothing to do */
drh65c29fd2019-03-25 21:56:26 +00003023 if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters",
drh8b738d02019-02-25 18:43:54 +00003024 "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
3025 return; /* Parameter table does not exist */
3026 }
3027 rc = sqlite3_prepare_v2(pArg->db,
drh65c29fd2019-03-25 21:56:26 +00003028 "SELECT value FROM temp.sqlite_parameters"
drh8b738d02019-02-25 18:43:54 +00003029 " WHERE key=?1", -1, &pQ, 0);
3030 if( rc || pQ==0 ) return;
3031 for(i=1; i<=nVar; i++){
3032 char zNum[30];
3033 const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
3034 if( zVar==0 ){
3035 sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
3036 zVar = zNum;
3037 }
3038 sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
3039 if( sqlite3_step(pQ)==SQLITE_ROW ){
3040 sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
3041 }else{
3042 sqlite3_bind_null(pStmt, i);
3043 }
3044 sqlite3_reset(pQ);
3045 }
3046 sqlite3_finalize(pQ);
3047}
3048
drh30c54a02020-05-28 23:49:50 +00003049/*
drh0908e382020-06-04 18:05:39 +00003050** UTF8 box-drawing characters. Imagine box lines like this:
3051**
3052** 1
3053** |
3054** 4 --+-- 2
3055** |
3056** 3
3057**
3058** Each box characters has between 2 and 4 of the lines leading from
3059** the center. The characters are here identified by the numbers of
3060** their corresponding lines.
3061*/
3062#define BOX_24 "\342\224\200" /* U+2500 --- */
3063#define BOX_13 "\342\224\202" /* U+2502 | */
3064#define BOX_23 "\342\224\214" /* U+250c ,- */
3065#define BOX_34 "\342\224\220" /* U+2510 -, */
3066#define BOX_12 "\342\224\224" /* U+2514 '- */
3067#define BOX_14 "\342\224\230" /* U+2518 -' */
3068#define BOX_123 "\342\224\234" /* U+251c |- */
3069#define BOX_134 "\342\224\244" /* U+2524 -| */
3070#define BOX_234 "\342\224\254" /* U+252c -,- */
3071#define BOX_124 "\342\224\264" /* U+2534 -'- */
3072#define BOX_1234 "\342\224\274" /* U+253c -|- */
3073
3074/* Draw horizontal line N characters long using unicode box
3075** characters
3076*/
3077static void print_box_line(FILE *out, int N){
3078 const char zDash[] =
3079 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
3080 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
3081 const int nDash = sizeof(zDash) - 1;
3082 N *= 3;
3083 while( N>nDash ){
3084 utf8_printf(out, zDash);
3085 N -= nDash;
3086 }
3087 utf8_printf(out, "%.*s", N, zDash);
3088}
3089
3090/*
3091** Draw a horizontal separator for a MODE_Box table.
3092*/
3093static void print_box_row_separator(
3094 ShellState *p,
3095 int nArg,
3096 const char *zSep1,
3097 const char *zSep2,
3098 const char *zSep3
3099){
3100 int i;
3101 if( nArg>0 ){
3102 utf8_printf(p->out, "%s", zSep1);
3103 print_box_line(p->out, p->actualWidth[0]+2);
3104 for(i=1; i<nArg; i++){
3105 utf8_printf(p->out, "%s", zSep2);
3106 print_box_line(p->out, p->actualWidth[i]+2);
3107 }
3108 utf8_printf(p->out, "%s", zSep3);
3109 }
3110 fputs("\n", p->out);
3111}
3112
3113
3114
3115/*
drh30c54a02020-05-28 23:49:50 +00003116** Run a prepared statement and output the result in one of the
drh0908e382020-06-04 18:05:39 +00003117** table-oriented formats: MODE_Column, MODE_Markdown, MODE_Table,
3118** or MODE_Box.
drh30c54a02020-05-28 23:49:50 +00003119**
3120** This is different from ordinary exec_prepared_stmt() in that
3121** it has to run the entire query and gather the results into memory
3122** first, in order to determine column widths, before providing
3123** any output.
3124*/
drh8c748632020-05-29 16:15:58 +00003125static void exec_prepared_stmt_columnar(
3126 ShellState *p, /* Pointer to ShellState */
3127 sqlite3_stmt *pStmt /* Statment to run */
drh30c54a02020-05-28 23:49:50 +00003128){
drhf82ce382020-08-06 16:45:22 +00003129 sqlite3_int64 nRow = 0;
drh8c748632020-05-29 16:15:58 +00003130 int nColumn = 0;
3131 char **azData = 0;
drhf82ce382020-08-06 16:45:22 +00003132 sqlite3_int64 nAlloc = 0;
drh8c748632020-05-29 16:15:58 +00003133 const char *z;
3134 int rc;
drhf82ce382020-08-06 16:45:22 +00003135 sqlite3_int64 i, nData;
3136 int j, nTotal, w, n;
drh0908e382020-06-04 18:05:39 +00003137 const char *colSep = 0;
3138 const char *rowSep = 0;
drh30c54a02020-05-28 23:49:50 +00003139
drhf82ce382020-08-06 16:45:22 +00003140 rc = sqlite3_step(pStmt);
3141 if( rc!=SQLITE_ROW ) return;
3142 nColumn = sqlite3_column_count(pStmt);
3143 nAlloc = nColumn*4;
drh01a8ad22021-03-20 23:15:52 +00003144 if( nAlloc<=0 ) nAlloc = 1;
drhf82ce382020-08-06 16:45:22 +00003145 azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
drhe3e25652021-12-16 13:29:28 +00003146 shell_check_oom(azData);
drhf82ce382020-08-06 16:45:22 +00003147 for(i=0; i<nColumn; i++){
3148 azData[i] = strdup(sqlite3_column_name(pStmt,i));
drh8c748632020-05-29 16:15:58 +00003149 }
drhf82ce382020-08-06 16:45:22 +00003150 do{
3151 if( (nRow+2)*nColumn >= nAlloc ){
3152 nAlloc *= 2;
3153 azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*));
drhe3e25652021-12-16 13:29:28 +00003154 shell_check_oom(azData);
drhf82ce382020-08-06 16:45:22 +00003155 }
3156 nRow++;
3157 for(i=0; i<nColumn; i++){
3158 z = (const char*)sqlite3_column_text(pStmt,i);
3159 azData[nRow*nColumn + i] = z ? strdup(z) : 0;
3160 }
drh76fc88f2021-10-02 16:39:16 +00003161 }while( sqlite3_step(pStmt)==SQLITE_ROW );
drh8c748632020-05-29 16:15:58 +00003162 if( nColumn>p->nWidth ){
drh76fc88f2021-10-02 16:39:16 +00003163 p->colWidth = realloc(p->colWidth, (nColumn+1)*2*sizeof(int));
drhe3e25652021-12-16 13:29:28 +00003164 shell_check_oom(p->colWidth);
drh8c748632020-05-29 16:15:58 +00003165 for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0;
3166 p->nWidth = nColumn;
3167 p->actualWidth = &p->colWidth[nColumn];
3168 }
3169 memset(p->actualWidth, 0, nColumn*sizeof(int));
3170 for(i=0; i<nColumn; i++){
3171 w = p->colWidth[i];
3172 if( w<0 ) w = -w;
3173 p->actualWidth[i] = w;
3174 }
3175 nTotal = nColumn*(nRow+1);
3176 for(i=0; i<nTotal; i++){
3177 z = azData[i];
3178 if( z==0 ) z = p->nullValue;
3179 n = strlenChar(z);
3180 j = i%nColumn;
3181 if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
3182 }
drh99942982020-06-15 20:05:37 +00003183 if( seenInterrupt ) goto columnar_end;
drh01a8ad22021-03-20 23:15:52 +00003184 if( nColumn==0 ) goto columnar_end;
drh0908e382020-06-04 18:05:39 +00003185 switch( p->cMode ){
3186 case MODE_Column: {
3187 colSep = " ";
3188 rowSep = "\n";
3189 if( p->showHeader ){
3190 for(i=0; i<nColumn; i++){
3191 w = p->actualWidth[i];
3192 if( p->colWidth[i]<0 ) w = -w;
3193 utf8_width_print(p->out, w, azData[i]);
3194 fputs(i==nColumn-1?"\n":" ", p->out);
3195 }
3196 for(i=0; i<nColumn; i++){
3197 print_dashes(p->out, p->actualWidth[i]);
3198 fputs(i==nColumn-1?"\n":" ", p->out);
3199 }
3200 }
3201 break;
3202 }
3203 case MODE_Table: {
3204 colSep = " | ";
3205 rowSep = " |\n";
3206 print_row_separator(p, nColumn, "+");
3207 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003208 for(i=0; i<nColumn; i++){
3209 w = p->actualWidth[i];
drh0908e382020-06-04 18:05:39 +00003210 n = strlenChar(azData[i]);
3211 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
3212 fputs(i==nColumn-1?" |\n":" | ", p->out);
drh8c748632020-05-29 16:15:58 +00003213 }
drh0908e382020-06-04 18:05:39 +00003214 print_row_separator(p, nColumn, "+");
3215 break;
3216 }
3217 case MODE_Markdown: {
3218 colSep = " | ";
3219 rowSep = " |\n";
3220 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003221 for(i=0; i<nColumn; i++){
drh0908e382020-06-04 18:05:39 +00003222 w = p->actualWidth[i];
3223 n = strlenChar(azData[i]);
3224 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
3225 fputs(i==nColumn-1?" |\n":" | ", p->out);
drh8c748632020-05-29 16:15:58 +00003226 }
drh0908e382020-06-04 18:05:39 +00003227 print_row_separator(p, nColumn, "|");
3228 break;
drh8c748632020-05-29 16:15:58 +00003229 }
drh0908e382020-06-04 18:05:39 +00003230 case MODE_Box: {
3231 colSep = " " BOX_13 " ";
3232 rowSep = " " BOX_13 "\n";
3233 print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34);
3234 utf8_printf(p->out, BOX_13 " ");
3235 for(i=0; i<nColumn; i++){
3236 w = p->actualWidth[i];
3237 n = strlenChar(azData[i]);
3238 utf8_printf(p->out, "%*s%s%*s%s",
3239 (w-n)/2, "", azData[i], (w-n+1)/2, "",
3240 i==nColumn-1?" "BOX_13"\n":" "BOX_13" ");
3241 }
3242 print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
3243 break;
drh8c748632020-05-29 16:15:58 +00003244 }
drh8c748632020-05-29 16:15:58 +00003245 }
3246 for(i=nColumn, j=0; i<nTotal; i++, j++){
drh0908e382020-06-04 18:05:39 +00003247 if( j==0 && p->cMode!=MODE_Column ){
3248 utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| ");
3249 }
drh8c748632020-05-29 16:15:58 +00003250 z = azData[i];
3251 if( z==0 ) z = p->nullValue;
3252 w = p->actualWidth[j];
3253 if( p->colWidth[j]<0 ) w = -w;
3254 utf8_width_print(p->out, w, z);
3255 if( j==nColumn-1 ){
drh0908e382020-06-04 18:05:39 +00003256 utf8_printf(p->out, "%s", rowSep);
drh8c748632020-05-29 16:15:58 +00003257 j = -1;
drhdd853c32020-06-16 17:34:40 +00003258 if( seenInterrupt ) goto columnar_end;
drh8c748632020-05-29 16:15:58 +00003259 }else{
drh0908e382020-06-04 18:05:39 +00003260 utf8_printf(p->out, "%s", colSep);
drh8c748632020-05-29 16:15:58 +00003261 }
3262 }
3263 if( p->cMode==MODE_Table ){
3264 print_row_separator(p, nColumn, "+");
drh0908e382020-06-04 18:05:39 +00003265 }else if( p->cMode==MODE_Box ){
3266 print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14);
drh8c748632020-05-29 16:15:58 +00003267 }
drh99942982020-06-15 20:05:37 +00003268columnar_end:
drhdd853c32020-06-16 17:34:40 +00003269 if( seenInterrupt ){
3270 utf8_printf(p->out, "Interrupt\n");
3271 }
drhf82ce382020-08-06 16:45:22 +00003272 nData = (nRow+1)*nColumn;
3273 for(i=0; i<nData; i++) free(azData[i]);
3274 sqlite3_free(azData);
drh30c54a02020-05-28 23:49:50 +00003275}
drh30c54a02020-05-28 23:49:50 +00003276
drh2ce15c32017-07-11 13:34:40 +00003277/*
3278** Run a prepared statement
3279*/
3280static void exec_prepared_stmt(
3281 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003282 sqlite3_stmt *pStmt /* Statment to run */
drh2ce15c32017-07-11 13:34:40 +00003283){
3284 int rc;
drh5d88be82021-12-09 16:17:43 +00003285 sqlite3_uint64 nRow = 0;
drh2ce15c32017-07-11 13:34:40 +00003286
drh8c748632020-05-29 16:15:58 +00003287 if( pArg->cMode==MODE_Column
3288 || pArg->cMode==MODE_Table
drh0908e382020-06-04 18:05:39 +00003289 || pArg->cMode==MODE_Box
drh8c748632020-05-29 16:15:58 +00003290 || pArg->cMode==MODE_Markdown
3291 ){
3292 exec_prepared_stmt_columnar(pArg, pStmt);
3293 return;
3294 }
3295
drh2ce15c32017-07-11 13:34:40 +00003296 /* perform the first step. this will tell us if we
3297 ** have a result set or not and how wide it is.
3298 */
3299 rc = sqlite3_step(pStmt);
3300 /* if we have a result set... */
3301 if( SQLITE_ROW == rc ){
drha10b9992018-03-09 15:24:33 +00003302 /* allocate space for col name ptr, value ptr, and type */
3303 int nCol = sqlite3_column_count(pStmt);
3304 void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
3305 if( !pData ){
drhe85e1da2021-10-01 21:01:07 +00003306 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00003307 }else{
drha10b9992018-03-09 15:24:33 +00003308 char **azCols = (char **)pData; /* Names of result columns */
3309 char **azVals = &azCols[nCol]; /* Results */
3310 int *aiTypes = (int *)&azVals[nCol]; /* Result types */
3311 int i, x;
3312 assert(sizeof(int) <= sizeof(char *));
3313 /* save off ptrs to column names */
3314 for(i=0; i<nCol; i++){
3315 azCols[i] = (char *)sqlite3_column_name(pStmt, i);
3316 }
drh2ce15c32017-07-11 13:34:40 +00003317 do{
drh5d88be82021-12-09 16:17:43 +00003318 nRow++;
drha10b9992018-03-09 15:24:33 +00003319 /* extract the data and data types */
3320 for(i=0; i<nCol; i++){
3321 aiTypes[i] = x = sqlite3_column_type(pStmt, i);
3322 if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
3323 azVals[i] = "";
3324 }else{
3325 azVals[i] = (char*)sqlite3_column_text(pStmt, i);
3326 }
3327 if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
3328 rc = SQLITE_NOMEM;
3329 break; /* from for */
3330 }
3331 } /* end for */
3332
3333 /* if data and types extracted successfully... */
3334 if( SQLITE_ROW == rc ){
3335 /* call the supplied callback with the result row data */
3336 if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){
3337 rc = SQLITE_ABORT;
3338 }else{
3339 rc = sqlite3_step(pStmt);
3340 }
3341 }
3342 } while( SQLITE_ROW == rc );
3343 sqlite3_free(pData);
drh0908e382020-06-04 18:05:39 +00003344 if( pArg->cMode==MODE_Json ){
drh30c54a02020-05-28 23:49:50 +00003345 fputs("]\n", pArg->out);
drh5d88be82021-12-09 16:17:43 +00003346 }else if( pArg->cMode==MODE_Count ){
3347 printf("%llu row%s\n", nRow, nRow!=1 ? "s" : "");
drh30c54a02020-05-28 23:49:50 +00003348 }
drh2ce15c32017-07-11 13:34:40 +00003349 }
3350 }
3351}
3352
dan6b046be2018-01-09 15:25:55 +00003353#ifndef SQLITE_OMIT_VIRTUALTABLE
drh2ce15c32017-07-11 13:34:40 +00003354/*
dan43efc182017-12-19 17:42:13 +00003355** This function is called to process SQL if the previous shell command
3356** was ".expert". It passes the SQL in the second argument directly to
3357** the sqlite3expert object.
3358**
3359** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3360** code. In this case, (*pzErr) may be set to point to a buffer containing
3361** an English language error message. It is the responsibility of the
3362** caller to eventually free this buffer using sqlite3_free().
3363*/
3364static int expertHandleSQL(
3365 ShellState *pState,
3366 const char *zSql,
3367 char **pzErr
3368){
3369 assert( pState->expert.pExpert );
3370 assert( pzErr==0 || *pzErr==0 );
3371 return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr);
3372}
3373
3374/*
3375** This function is called either to silently clean up the object
3376** created by the ".expert" command (if bCancel==1), or to generate a
3377** report from it and then clean it up (if bCancel==0).
3378**
3379** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3380** code. In this case, (*pzErr) may be set to point to a buffer containing
3381** an English language error message. It is the responsibility of the
3382** caller to eventually free this buffer using sqlite3_free().
3383*/
3384static int expertFinish(
3385 ShellState *pState,
3386 int bCancel,
3387 char **pzErr
3388){
3389 int rc = SQLITE_OK;
3390 sqlite3expert *p = pState->expert.pExpert;
3391 assert( p );
3392 assert( bCancel || pzErr==0 || *pzErr==0 );
3393 if( bCancel==0 ){
3394 FILE *out = pState->out;
3395 int bVerbose = pState->expert.bVerbose;
3396
3397 rc = sqlite3_expert_analyze(p, pzErr);
3398 if( rc==SQLITE_OK ){
3399 int nQuery = sqlite3_expert_count(p);
3400 int i;
3401
3402 if( bVerbose ){
3403 const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
3404 raw_printf(out, "-- Candidates -----------------------------\n");
3405 raw_printf(out, "%s\n", zCand);
3406 }
3407 for(i=0; i<nQuery; i++){
3408 const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
3409 const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
3410 const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
3411 if( zIdx==0 ) zIdx = "(no new indexes)\n";
3412 if( bVerbose ){
3413 raw_printf(out, "-- Query %d --------------------------------\n",i+1);
3414 raw_printf(out, "%s\n\n", zSql);
3415 }
3416 raw_printf(out, "%s\n", zIdx);
3417 raw_printf(out, "%s\n", zEQP);
3418 }
3419 }
3420 }
3421 sqlite3_expert_destroy(p);
3422 pState->expert.pExpert = 0;
3423 return rc;
3424}
3425
dan6b046be2018-01-09 15:25:55 +00003426/*
3427** Implementation of ".expert" dot command.
3428*/
3429static int expertDotCommand(
3430 ShellState *pState, /* Current shell tool state */
3431 char **azArg, /* Array of arguments passed to dot command */
3432 int nArg /* Number of entries in azArg[] */
3433){
3434 int rc = SQLITE_OK;
3435 char *zErr = 0;
3436 int i;
3437 int iSample = 0;
3438
3439 assert( pState->expert.pExpert==0 );
3440 memset(&pState->expert, 0, sizeof(ExpertInfo));
3441
3442 for(i=1; rc==SQLITE_OK && i<nArg; i++){
3443 char *z = azArg[i];
3444 int n;
3445 if( z[0]=='-' && z[1]=='-' ) z++;
3446 n = strlen30(z);
3447 if( n>=2 && 0==strncmp(z, "-verbose", n) ){
3448 pState->expert.bVerbose = 1;
3449 }
3450 else if( n>=2 && 0==strncmp(z, "-sample", n) ){
3451 if( i==(nArg-1) ){
3452 raw_printf(stderr, "option requires an argument: %s\n", z);
3453 rc = SQLITE_ERROR;
3454 }else{
3455 iSample = (int)integerValue(azArg[++i]);
3456 if( iSample<0 || iSample>100 ){
3457 raw_printf(stderr, "value out of range: %s\n", azArg[i]);
3458 rc = SQLITE_ERROR;
3459 }
3460 }
3461 }
3462 else{
3463 raw_printf(stderr, "unknown option: %s\n", z);
3464 rc = SQLITE_ERROR;
3465 }
3466 }
3467
3468 if( rc==SQLITE_OK ){
3469 pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
3470 if( pState->expert.pExpert==0 ){
drhe0adf602021-12-16 14:26:16 +00003471 raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr ? zErr : "out of memory");
dan6b046be2018-01-09 15:25:55 +00003472 rc = SQLITE_ERROR;
3473 }else{
3474 sqlite3_expert_config(
3475 pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
3476 );
3477 }
3478 }
drhe0adf602021-12-16 14:26:16 +00003479 sqlite3_free(zErr);
dan6b046be2018-01-09 15:25:55 +00003480
3481 return rc;
3482}
3483#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
dan43efc182017-12-19 17:42:13 +00003484
3485/*
drh2ce15c32017-07-11 13:34:40 +00003486** Execute a statement or set of statements. Print
3487** any result rows/columns depending on the current mode
3488** set via the supplied callback.
3489**
3490** This is very similar to SQLite's built-in sqlite3_exec()
3491** function except it takes a slightly different callback
3492** and callback data argument.
3493*/
3494static int shell_exec(
drh2ce15c32017-07-11 13:34:40 +00003495 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003496 const char *zSql, /* SQL to be evaluated */
drh2ce15c32017-07-11 13:34:40 +00003497 char **pzErrMsg /* Error msg written here */
3498){
3499 sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
3500 int rc = SQLITE_OK; /* Return Code */
3501 int rc2;
3502 const char *zLeftover; /* Tail of unprocessed SQL */
drha10b9992018-03-09 15:24:33 +00003503 sqlite3 *db = pArg->db;
drh2ce15c32017-07-11 13:34:40 +00003504
3505 if( pzErrMsg ){
3506 *pzErrMsg = NULL;
3507 }
3508
dan6b046be2018-01-09 15:25:55 +00003509#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00003510 if( pArg->expert.pExpert ){
3511 rc = expertHandleSQL(pArg, zSql, pzErrMsg);
3512 return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
3513 }
dan6b046be2018-01-09 15:25:55 +00003514#endif
dan43efc182017-12-19 17:42:13 +00003515
drh2ce15c32017-07-11 13:34:40 +00003516 while( zSql[0] && (SQLITE_OK == rc) ){
3517 static const char *zStmtSql;
3518 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
3519 if( SQLITE_OK != rc ){
3520 if( pzErrMsg ){
larrybrf9a49b02021-10-26 16:57:09 +00003521 *pzErrMsg = save_err_msg(db, "in prepare, %s (%d)", rc);
drh2ce15c32017-07-11 13:34:40 +00003522 }
3523 }else{
3524 if( !pStmt ){
3525 /* this happens for a comment or white-space */
3526 zSql = zLeftover;
3527 while( IsSpace(zSql[0]) ) zSql++;
3528 continue;
3529 }
3530 zStmtSql = sqlite3_sql(pStmt);
3531 if( zStmtSql==0 ) zStmtSql = "";
3532 while( IsSpace(zStmtSql[0]) ) zStmtSql++;
3533
3534 /* save off the prepared statment handle and reset row count */
3535 if( pArg ){
3536 pArg->pStmt = pStmt;
3537 pArg->cnt = 0;
3538 }
3539
3540 /* echo the sql statement if echo on */
3541 if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
3542 utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
3543 }
3544
3545 /* Show the EXPLAIN QUERY PLAN if .eqp is on */
drh39c5c4a2019-03-06 14:53:27 +00003546 if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
drh2ce15c32017-07-11 13:34:40 +00003547 sqlite3_stmt *pExplain;
3548 char *zEQP;
drhada70452017-12-21 21:02:27 +00003549 int triggerEQP = 0;
drh2ce15c32017-07-11 13:34:40 +00003550 disable_debug_trace_modes();
drhada70452017-12-21 21:02:27 +00003551 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
3552 if( pArg->autoEQP>=AUTOEQP_trigger ){
3553 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
3554 }
drh2ce15c32017-07-11 13:34:40 +00003555 zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
drhe3e25652021-12-16 13:29:28 +00003556 shell_check_oom(zEQP);
drh2ce15c32017-07-11 13:34:40 +00003557 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3558 if( rc==SQLITE_OK ){
3559 while( sqlite3_step(pExplain)==SQLITE_ROW ){
drh4b5345c2018-04-24 13:07:40 +00003560 const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
drhe2ca99c2018-05-02 00:33:43 +00003561 int iEqpId = sqlite3_column_int(pExplain, 0);
3562 int iParentId = sqlite3_column_int(pExplain, 1);
drh7e088a62020-05-02 00:01:39 +00003563 if( zEQPLine==0 ) zEQPLine = "";
drh4b5345c2018-04-24 13:07:40 +00003564 if( zEQPLine[0]=='-' ) eqp_render(pArg);
drhe2ca99c2018-05-02 00:33:43 +00003565 eqp_append(pArg, iEqpId, iParentId, zEQPLine);
drh2ce15c32017-07-11 13:34:40 +00003566 }
drh4b5345c2018-04-24 13:07:40 +00003567 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003568 }
3569 sqlite3_finalize(pExplain);
3570 sqlite3_free(zEQP);
drhada70452017-12-21 21:02:27 +00003571 if( pArg->autoEQP>=AUTOEQP_full ){
drh2ce15c32017-07-11 13:34:40 +00003572 /* Also do an EXPLAIN for ".eqp full" mode */
3573 zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
drhe3e25652021-12-16 13:29:28 +00003574 shell_check_oom(zEQP);
drh2ce15c32017-07-11 13:34:40 +00003575 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3576 if( rc==SQLITE_OK ){
3577 pArg->cMode = MODE_Explain;
3578 explain_data_prepare(pArg, pExplain);
drha10b9992018-03-09 15:24:33 +00003579 exec_prepared_stmt(pArg, pExplain);
drh2ce15c32017-07-11 13:34:40 +00003580 explain_data_delete(pArg);
3581 }
3582 sqlite3_finalize(pExplain);
3583 sqlite3_free(zEQP);
3584 }
drh51efe092018-03-20 12:04:38 +00003585 if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
3586 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
3587 /* Reprepare pStmt before reactiving trace modes */
3588 sqlite3_finalize(pStmt);
3589 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
drh3c49eaf2018-06-07 15:23:43 +00003590 if( pArg ) pArg->pStmt = pStmt;
drh51efe092018-03-20 12:04:38 +00003591 }
drh2ce15c32017-07-11 13:34:40 +00003592 restore_debug_trace_modes();
3593 }
3594
3595 if( pArg ){
3596 pArg->cMode = pArg->mode;
drh4b5345c2018-04-24 13:07:40 +00003597 if( pArg->autoExplain ){
drh39c5c4a2019-03-06 14:53:27 +00003598 if( sqlite3_stmt_isexplain(pStmt)==1 ){
drh4b5345c2018-04-24 13:07:40 +00003599 pArg->cMode = MODE_Explain;
3600 }
drh39c5c4a2019-03-06 14:53:27 +00003601 if( sqlite3_stmt_isexplain(pStmt)==2 ){
drh4b5345c2018-04-24 13:07:40 +00003602 pArg->cMode = MODE_EQP;
3603 }
drh2ce15c32017-07-11 13:34:40 +00003604 }
3605
3606 /* If the shell is currently in ".explain" mode, gather the extra
3607 ** data required to add indents to the output.*/
3608 if( pArg->cMode==MODE_Explain ){
3609 explain_data_prepare(pArg, pStmt);
3610 }
3611 }
3612
drh8b738d02019-02-25 18:43:54 +00003613 bind_prepared_stmt(pArg, pStmt);
drha10b9992018-03-09 15:24:33 +00003614 exec_prepared_stmt(pArg, pStmt);
drh2ce15c32017-07-11 13:34:40 +00003615 explain_data_delete(pArg);
drh4b5345c2018-04-24 13:07:40 +00003616 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003617
3618 /* print usage stats if stats on */
3619 if( pArg && pArg->statsOn ){
3620 display_stats(db, pArg, 0);
3621 }
3622
3623 /* print loop-counters if required */
3624 if( pArg && pArg->scanstatsOn ){
3625 display_scanstats(db, pArg);
3626 }
3627
3628 /* Finalize the statement just executed. If this fails, save a
3629 ** copy of the error message. Otherwise, set zSql to point to the
3630 ** next statement to execute. */
3631 rc2 = sqlite3_finalize(pStmt);
3632 if( rc!=SQLITE_NOMEM ) rc = rc2;
3633 if( rc==SQLITE_OK ){
3634 zSql = zLeftover;
3635 while( IsSpace(zSql[0]) ) zSql++;
3636 }else if( pzErrMsg ){
larrybrf9a49b02021-10-26 16:57:09 +00003637 *pzErrMsg = save_err_msg(db, "stepping, %s (%d)", rc);
drh2ce15c32017-07-11 13:34:40 +00003638 }
3639
3640 /* clear saved stmt handle */
3641 if( pArg ){
3642 pArg->pStmt = NULL;
3643 }
3644 }
3645 } /* end while */
3646
3647 return rc;
3648}
3649
3650/*
3651** Release memory previously allocated by tableColumnList().
3652*/
3653static void freeColumnList(char **azCol){
3654 int i;
3655 for(i=1; azCol[i]; i++){
3656 sqlite3_free(azCol[i]);
3657 }
3658 /* azCol[0] is a static string */
3659 sqlite3_free(azCol);
3660}
3661
3662/*
3663** Return a list of pointers to strings which are the names of all
3664** columns in table zTab. The memory to hold the names is dynamically
3665** allocated and must be released by the caller using a subsequent call
3666** to freeColumnList().
3667**
3668** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
3669** value that needs to be preserved, then azCol[0] is filled in with the
3670** name of the rowid column.
3671**
3672** The first regular column in the table is azCol[1]. The list is terminated
3673** by an entry with azCol[i]==0.
3674*/
3675static char **tableColumnList(ShellState *p, const char *zTab){
3676 char **azCol = 0;
3677 sqlite3_stmt *pStmt;
3678 char *zSql;
3679 int nCol = 0;
3680 int nAlloc = 0;
3681 int nPK = 0; /* Number of PRIMARY KEY columns seen */
3682 int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
3683 int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
3684 int rc;
3685
3686 zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
drhe3e25652021-12-16 13:29:28 +00003687 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +00003688 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3689 sqlite3_free(zSql);
3690 if( rc ) return 0;
3691 while( sqlite3_step(pStmt)==SQLITE_ROW ){
3692 if( nCol>=nAlloc-2 ){
3693 nAlloc = nAlloc*2 + nCol + 10;
3694 azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
drhe3e25652021-12-16 13:29:28 +00003695 shell_check_oom(azCol);
drh2ce15c32017-07-11 13:34:40 +00003696 }
3697 azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
drhe3e25652021-12-16 13:29:28 +00003698 shell_check_oom(azCol[nCol]);
drh2ce15c32017-07-11 13:34:40 +00003699 if( sqlite3_column_int(pStmt, 5) ){
3700 nPK++;
3701 if( nPK==1
3702 && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
3703 "INTEGER")==0
3704 ){
3705 isIPK = 1;
3706 }else{
3707 isIPK = 0;
3708 }
3709 }
3710 }
3711 sqlite3_finalize(pStmt);
drh4c6cddc2017-10-12 10:28:30 +00003712 if( azCol==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00003713 azCol[0] = 0;
3714 azCol[nCol+1] = 0;
3715
3716 /* The decision of whether or not a rowid really needs to be preserved
3717 ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
3718 ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
3719 ** rowids on tables where the rowid is inaccessible because there are other
3720 ** columns in the table named "rowid", "_rowid_", and "oid".
3721 */
3722 if( preserveRowid && isIPK ){
3723 /* If a single PRIMARY KEY column with type INTEGER was seen, then it
3724 ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID
3725 ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
3726 ** ROWID aliases. To distinguish these cases, check to see if
3727 ** there is a "pk" entry in "PRAGMA index_list". There will be
3728 ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
3729 */
3730 zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
3731 " WHERE origin='pk'", zTab);
drhe3e25652021-12-16 13:29:28 +00003732 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +00003733 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3734 sqlite3_free(zSql);
3735 if( rc ){
3736 freeColumnList(azCol);
3737 return 0;
3738 }
3739 rc = sqlite3_step(pStmt);
3740 sqlite3_finalize(pStmt);
3741 preserveRowid = rc==SQLITE_ROW;
3742 }
3743 if( preserveRowid ){
3744 /* Only preserve the rowid if we can find a name to use for the
3745 ** rowid */
3746 static char *azRowid[] = { "rowid", "_rowid_", "oid" };
3747 int i, j;
3748 for(j=0; j<3; j++){
3749 for(i=1; i<=nCol; i++){
3750 if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
3751 }
3752 if( i>nCol ){
3753 /* At this point, we know that azRowid[j] is not the name of any
3754 ** ordinary column in the table. Verify that azRowid[j] is a valid
3755 ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
3756 ** tables will fail this last check */
3757 rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
3758 if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
3759 break;
3760 }
3761 }
3762 }
3763 return azCol;
3764}
3765
3766/*
3767** Toggle the reverse_unordered_selects setting.
3768*/
3769static void toggleSelectOrder(sqlite3 *db){
3770 sqlite3_stmt *pStmt = 0;
3771 int iSetting = 0;
3772 char zStmt[100];
3773 sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0);
3774 if( sqlite3_step(pStmt)==SQLITE_ROW ){
3775 iSetting = sqlite3_column_int(pStmt, 0);
3776 }
3777 sqlite3_finalize(pStmt);
3778 sqlite3_snprintf(sizeof(zStmt), zStmt,
3779 "PRAGMA reverse_unordered_selects(%d)", !iSetting);
3780 sqlite3_exec(db, zStmt, 0, 0, 0);
3781}
3782
3783/*
3784** This is a different callback routine used for dumping the database.
3785** Each row received by this callback consists of a table name,
3786** the table type ("index" or "table") and SQL to create the table.
3787** This routine should print text sufficient to recreate the table.
3788*/
3789static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
3790 int rc;
3791 const char *zTable;
3792 const char *zType;
3793 const char *zSql;
3794 ShellState *p = (ShellState *)pArg;
mistachkina00a0162020-10-18 18:35:34 +00003795 int dataOnly;
3796 int noSys;
drh2ce15c32017-07-11 13:34:40 +00003797
3798 UNUSED_PARAMETER(azNotUsed);
drhb3c45232017-08-28 14:33:27 +00003799 if( nArg!=3 || azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00003800 zTable = azArg[0];
3801 zType = azArg[1];
3802 zSql = azArg[2];
mistachkina00a0162020-10-18 18:35:34 +00003803 dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
3804 noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
drh2ce15c32017-07-11 13:34:40 +00003805
drhc1962192020-10-12 16:54:28 +00003806 if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
3807 if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
3808 }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
3809 if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00003810 }else if( strncmp(zTable, "sqlite_", 7)==0 ){
3811 return 0;
drhc1962192020-10-12 16:54:28 +00003812 }else if( dataOnly ){
3813 /* no-op */
drh2ce15c32017-07-11 13:34:40 +00003814 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
3815 char *zIns;
3816 if( !p->writableSchema ){
3817 raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
3818 p->writableSchema = 1;
3819 }
3820 zIns = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00003821 "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
drh2ce15c32017-07-11 13:34:40 +00003822 "VALUES('table','%q','%q',0,'%q');",
3823 zTable, zTable, zSql);
drhe3e25652021-12-16 13:29:28 +00003824 shell_check_oom(zIns);
drh2ce15c32017-07-11 13:34:40 +00003825 utf8_printf(p->out, "%s\n", zIns);
3826 sqlite3_free(zIns);
3827 return 0;
3828 }else{
3829 printSchemaLine(p->out, zSql, ";\n");
3830 }
3831
3832 if( strcmp(zType, "table")==0 ){
3833 ShellText sSelect;
3834 ShellText sTable;
3835 char **azCol;
3836 int i;
3837 char *savedDestTable;
3838 int savedMode;
3839
3840 azCol = tableColumnList(p, zTable);
3841 if( azCol==0 ){
3842 p->nErr++;
3843 return 0;
3844 }
3845
3846 /* Always quote the table name, even if it appears to be pure ascii,
3847 ** in case it is a keyword. Ex: INSERT INTO "table" ... */
3848 initText(&sTable);
3849 appendText(&sTable, zTable, quoteChar(zTable));
3850 /* If preserving the rowid, add a column list after the table name.
3851 ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
3852 ** instead of the usual "INSERT INTO tab VALUES(...)".
3853 */
3854 if( azCol[0] ){
3855 appendText(&sTable, "(", 0);
3856 appendText(&sTable, azCol[0], 0);
3857 for(i=1; azCol[i]; i++){
3858 appendText(&sTable, ",", 0);
3859 appendText(&sTable, azCol[i], quoteChar(azCol[i]));
3860 }
3861 appendText(&sTable, ")", 0);
3862 }
3863
3864 /* Build an appropriate SELECT statement */
3865 initText(&sSelect);
3866 appendText(&sSelect, "SELECT ", 0);
3867 if( azCol[0] ){
3868 appendText(&sSelect, azCol[0], 0);
3869 appendText(&sSelect, ",", 0);
3870 }
3871 for(i=1; azCol[i]; i++){
3872 appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
3873 if( azCol[i+1] ){
3874 appendText(&sSelect, ",", 0);
3875 }
3876 }
3877 freeColumnList(azCol);
3878 appendText(&sSelect, " FROM ", 0);
3879 appendText(&sSelect, zTable, quoteChar(zTable));
3880
3881 savedDestTable = p->zDestTable;
3882 savedMode = p->mode;
3883 p->zDestTable = sTable.z;
3884 p->mode = p->cMode = MODE_Insert;
drha10b9992018-03-09 15:24:33 +00003885 rc = shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00003886 if( (rc&0xff)==SQLITE_CORRUPT ){
3887 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
3888 toggleSelectOrder(p->db);
drha10b9992018-03-09 15:24:33 +00003889 shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00003890 toggleSelectOrder(p->db);
3891 }
3892 p->zDestTable = savedDestTable;
3893 p->mode = savedMode;
3894 freeText(&sTable);
3895 freeText(&sSelect);
3896 if( rc ) p->nErr++;
3897 }
3898 return 0;
3899}
3900
3901/*
3902** Run zQuery. Use dump_callback() as the callback routine so that
3903** the contents of the query are output as SQL statements.
3904**
3905** If we get a SQLITE_CORRUPT error, rerun the query after appending
3906** "ORDER BY rowid DESC" to the end.
3907*/
3908static int run_schema_dump_query(
3909 ShellState *p,
3910 const char *zQuery
3911){
3912 int rc;
3913 char *zErr = 0;
3914 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
3915 if( rc==SQLITE_CORRUPT ){
3916 char *zQ2;
3917 int len = strlen30(zQuery);
3918 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
3919 if( zErr ){
3920 utf8_printf(p->out, "/****** %s ******/\n", zErr);
3921 sqlite3_free(zErr);
3922 zErr = 0;
3923 }
3924 zQ2 = malloc( len+100 );
3925 if( zQ2==0 ) return rc;
3926 sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
3927 rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
3928 if( rc ){
3929 utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
3930 }else{
3931 rc = SQLITE_CORRUPT;
3932 }
3933 sqlite3_free(zErr);
3934 free(zQ2);
3935 }
3936 return rc;
3937}
3938
3939/*
drh98aa2ab2018-09-26 16:53:51 +00003940** Text of help messages.
3941**
3942** The help text for each individual command begins with a line that starts
3943** with ".". Subsequent lines are supplimental information.
3944**
3945** There must be two or more spaces between the end of the command and the
3946** start of the description of what that command does.
drh2ce15c32017-07-11 13:34:40 +00003947*/
drh98aa2ab2018-09-26 16:53:51 +00003948static const char *(azHelp[]) = {
drhe37c0e12018-01-06 19:19:50 +00003949#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drh98aa2ab2018-09-26 16:53:51 +00003950 ".archive ... Manage SQL archives",
3951 " Each command must have exactly one of the following options:",
3952 " -c, --create Create a new archive",
drhe2754c12019-08-26 12:50:01 +00003953 " -u, --update Add or update files with changed mtime",
3954 " -i, --insert Like -u but always add even if unchanged",
larrybr47061b92021-11-01 17:22:52 +00003955 " -r, --remove Remove files from archive",
drh98aa2ab2018-09-26 16:53:51 +00003956 " -t, --list List contents of archive",
3957 " -x, --extract Extract files from archive",
3958 " Optional arguments:",
3959 " -v, --verbose Print each filename as it is processed",
drhe2754c12019-08-26 12:50:01 +00003960 " -f FILE, --file FILE Use archive FILE (default is current db)",
3961 " -a FILE, --append FILE Open FILE using the apndvfs VFS",
3962 " -C DIR, --directory DIR Read/extract files from directory DIR",
larrybr8f09f4b2021-11-02 00:18:11 +00003963 " -g, --glob Use glob matching for names in archive",
drh98aa2ab2018-09-26 16:53:51 +00003964 " -n, --dryrun Show the SQL that would have occurred",
3965 " Examples:",
drhe2754c12019-08-26 12:50:01 +00003966 " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
3967 " .ar -tf ARCHIVE # List members of ARCHIVE",
3968 " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE",
drh98aa2ab2018-09-26 16:53:51 +00003969 " See also:",
larrybrbd0d62c2021-06-13 08:23:28 +00003970 " http://sqlite.org/cli.html#sqlite_archive_support",
drhe37c0e12018-01-06 19:19:50 +00003971#endif
drh2ce15c32017-07-11 13:34:40 +00003972#ifndef SQLITE_OMIT_AUTHORIZATION
drh98aa2ab2018-09-26 16:53:51 +00003973 ".auth ON|OFF Show authorizer callbacks",
drh2ce15c32017-07-11 13:34:40 +00003974#endif
drh98aa2ab2018-09-26 16:53:51 +00003975 ".backup ?DB? FILE Backup DB (default \"main\") to FILE",
3976 " --append Use the appendvfs",
drhe2754c12019-08-26 12:50:01 +00003977 " --async Write to FILE without journal and fsync()",
drh98aa2ab2018-09-26 16:53:51 +00003978 ".bail on|off Stop after hitting an error. Default OFF",
3979 ".binary on|off Turn binary output on or off. Default OFF",
3980 ".cd DIRECTORY Change the working directory to DIRECTORY",
3981 ".changes on|off Show number of rows changed by SQL",
3982 ".check GLOB Fail if output since .testcase does not match",
3983 ".clone NEWDB Clone data into NEWDB from the existing database",
drh37407122021-07-23 18:43:58 +00003984 ".connection [close] [#] Open or close an auxiliary database connection",
drh98aa2ab2018-09-26 16:53:51 +00003985 ".databases List names and files of attached databases",
3986 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
3987 ".dbinfo ?DB? Show status information about the database",
larrybr7bdbe592021-03-15 12:56:00 +00003988 ".dump ?OBJECTS? Render database content as SQL",
drheb7f2a02018-09-26 18:02:32 +00003989 " Options:",
drhc1962192020-10-12 16:54:28 +00003990 " --data-only Output only INSERT statements",
drheb7f2a02018-09-26 18:02:32 +00003991 " --newlines Allow unescaped newline characters in output",
drhc1962192020-10-12 16:54:28 +00003992 " --nosys Omit system tables (ex: \"sqlite_stat1\")",
3993 " --preserve-rowids Include ROWID values in the output",
larrybr7bdbe592021-03-15 12:56:00 +00003994 " OBJECTS is a LIKE pattern for tables, indexes, triggers or views to dump",
drh8e9297f2020-03-25 12:50:13 +00003995 " Additional LIKE patterns can be given in subsequent arguments",
drh98aa2ab2018-09-26 16:53:51 +00003996 ".echo on|off Turn command echo on or off",
drhb4e50392019-01-26 15:40:04 +00003997 ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
3998 " Other Modes:",
3999#ifdef SQLITE_DEBUG
4000 " test Show raw EXPLAIN QUERY PLAN output",
drhe2754c12019-08-26 12:50:01 +00004001 " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"",
drhb4e50392019-01-26 15:40:04 +00004002#endif
4003 " trigger Like \"full\" but also show trigger bytecode",
drhe2754c12019-08-26 12:50:01 +00004004 ".excel Display the output of next command in spreadsheet",
drh7a431002020-04-18 14:12:00 +00004005 " --bom Put a UTF8 byte-order mark on intermediate file",
drheb7f2a02018-09-26 18:02:32 +00004006 ".exit ?CODE? Exit this program with return-code CODE",
drhe2754c12019-08-26 12:50:01 +00004007 ".expert EXPERIMENTAL. Suggest indexes for queries",
drh978256f2019-11-02 00:00:14 +00004008 ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto",
drhd985f722019-06-05 14:29:53 +00004009 ".filectrl CMD ... Run various sqlite3_file_control() operations",
drh541ef2c2020-04-20 16:21:30 +00004010 " --schema SCHEMA Use SCHEMA instead of \"main\"",
4011 " --help Show CMD details",
drh98aa2ab2018-09-26 16:53:51 +00004012 ".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
4013 ".headers on|off Turn display of headers on or off",
4014 ".help ?-all? ?PATTERN? Show help text for PATTERN",
4015 ".import FILE TABLE Import data from FILE into TABLE",
drhccb37812020-03-09 15:39:39 +00004016 " Options:",
4017 " --ascii Use \\037 and \\036 as column and row separators",
4018 " --csv Use , and \\n as column and row separators",
4019 " --skip N Skip the first N rows of input",
4020 " -v \"Verbose\" - increase auxiliary output",
4021 " Notes:",
4022 " * If TABLE does not exist, it is created. The first row of input",
4023 " determines the column names.",
4024 " * If neither --csv or --ascii are used, the input mode is derived",
4025 " from the \".mode\" output mode",
4026 " * If FILE begins with \"|\" then it is a command that generates the",
4027 " input text.",
drh2ce15c32017-07-11 13:34:40 +00004028#ifndef SQLITE_OMIT_TEST_CONTROL
drh98aa2ab2018-09-26 16:53:51 +00004029 ".imposter INDEX TABLE Create imposter table TABLE on index INDEX",
drh2ce15c32017-07-11 13:34:40 +00004030#endif
drh98aa2ab2018-09-26 16:53:51 +00004031 ".indexes ?TABLE? Show names of indexes",
4032 " If TABLE is specified, only show indexes for",
4033 " tables matching TABLE using the LIKE operator.",
drh2ce15c32017-07-11 13:34:40 +00004034#ifdef SQLITE_ENABLE_IOTRACE
drh98aa2ab2018-09-26 16:53:51 +00004035 ".iotrace FILE Enable I/O diagnostic logging to FILE",
drh2ce15c32017-07-11 13:34:40 +00004036#endif
drh98aa2ab2018-09-26 16:53:51 +00004037 ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
4038 ".lint OPTIONS Report potential schema issues.",
4039 " Options:",
4040 " fkey-indexes Find missing foreign key indexes",
drh2ce15c32017-07-11 13:34:40 +00004041#ifndef SQLITE_OMIT_LOAD_EXTENSION
drh98aa2ab2018-09-26 16:53:51 +00004042 ".load FILE ?ENTRY? Load an extension library",
drh2ce15c32017-07-11 13:34:40 +00004043#endif
drh98aa2ab2018-09-26 16:53:51 +00004044 ".log FILE|off Turn logging on or off. FILE can be stderr/stdout",
4045 ".mode MODE ?TABLE? Set output mode",
4046 " MODE is one of:",
drh7da29a32020-05-29 19:17:20 +00004047 " ascii Columns/rows delimited by 0x1F and 0x1E",
drh0908e382020-06-04 18:05:39 +00004048 " box Tables using unicode box-drawing characters",
drh7da29a32020-05-29 19:17:20 +00004049 " csv Comma-separated values",
4050 " column Output in columns. (See .width)",
4051 " html HTML <table> code",
4052 " insert SQL insert statements for TABLE",
4053 " json Results in a JSON array",
4054 " line One value per line",
4055 " list Values delimited by \"|\"",
4056 " markdown Markdown table format",
4057 " quote Escape answers as for SQL",
4058 " table ASCII-art table",
4059 " tabs Tab-separated values",
4060 " tcl TCL list elements",
drhb97e2ad2021-08-26 18:31:39 +00004061 ".nonce STRING Disable safe mode for one command if the nonce matches",
drh98aa2ab2018-09-26 16:53:51 +00004062 ".nullvalue STRING Use STRING in place of NULL values",
drh7a431002020-04-18 14:12:00 +00004063 ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE",
drh98aa2ab2018-09-26 16:53:51 +00004064 " If FILE begins with '|' then open as a pipe",
drh7a431002020-04-18 14:12:00 +00004065 " --bom Put a UTF8 byte-order mark at the beginning",
4066 " -e Send output to the system text editor",
4067 " -x Send output as CSV to a spreadsheet (same as \".excel\")",
drh98aa2ab2018-09-26 16:53:51 +00004068 ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
4069 " Options:",
drh60f34ae2018-10-30 13:19:49 +00004070 " --append Use appendvfs to append database to the end of FILE",
drh8d889af2021-05-08 17:18:23 +00004071#ifndef SQLITE_OMIT_DESERIALIZE
drhd10c3ca2021-05-08 11:57:35 +00004072 " --deserialize Load into memory using sqlite3_deserialize()",
drhe2754c12019-08-26 12:50:01 +00004073 " --hexdb Load the output of \"dbtotxt\" as an in-memory db",
drh6ca64482019-01-22 16:06:20 +00004074 " --maxsize N Maximum size for --hexdb or --deserialized database",
drha751f392018-10-30 15:31:22 +00004075#endif
drh60f34ae2018-10-30 13:19:49 +00004076 " --new Initialize FILE to an empty database",
drh0933aad2019-11-18 17:46:38 +00004077 " --nofollow Do not follow symbolic links",
drh60f34ae2018-10-30 13:19:49 +00004078 " --readonly Open FILE readonly",
4079 " --zip FILE is a ZIP archive",
drh98aa2ab2018-09-26 16:53:51 +00004080 ".output ?FILE? Send output to FILE or stdout if FILE is omitted",
drh7a431002020-04-18 14:12:00 +00004081 " If FILE begins with '|' then open it as a pipe.",
4082 " Options:",
4083 " --bom Prefix output with a UTF8 byte-order mark",
4084 " -e Send output to the system text editor",
4085 " -x Send output as CSV to a spreadsheet",
drh9cb02642019-02-28 20:10:52 +00004086 ".parameter CMD ... Manage SQL parameter bindings",
4087 " clear Erase all bindings",
4088 " init Initialize the TEMP table that holds bindings",
4089 " list List the current parameter bindings",
4090 " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE",
drhe2754c12019-08-26 12:50:01 +00004091 " PARAMETER should start with one of: $ : @ ?",
drh9cb02642019-02-28 20:10:52 +00004092 " unset PARAMETER Remove PARAMETER from the binding table",
drh98aa2ab2018-09-26 16:53:51 +00004093 ".print STRING... Print literal STRING",
drh569b1d92019-02-05 20:51:41 +00004094#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh3f83f592019-02-04 14:53:18 +00004095 ".progress N Invoke progress handler after every N opcodes",
4096 " --limit N Interrupt after N progress callbacks",
4097 " --once Do no more than one progress interrupt",
4098 " --quiet|-q No output except at interrupts",
4099 " --reset Reset the count for each input and interrupt",
drh569b1d92019-02-05 20:51:41 +00004100#endif
drh98aa2ab2018-09-26 16:53:51 +00004101 ".prompt MAIN CONTINUE Replace the standard prompts",
4102 ".quit Exit this program",
4103 ".read FILE Read input from FILE",
dan1b162162019-04-27 20:15:15 +00004104#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan42ebb012019-04-27 18:47:03 +00004105 ".recover Recover as much data as possible from corrupt db.",
drhe2754c12019-08-26 12:50:01 +00004106 " --freelist-corrupt Assume the freelist is corrupt",
4107 " --recovery-db NAME Store recovery metadata in database file NAME",
4108 " --lost-and-found TABLE Alternative name for the lost-and-found table",
dan8cce6b82019-09-14 16:44:51 +00004109 " --no-rowids Do not attempt to recover rowid values",
4110 " that are not also INTEGER PRIMARY KEYs",
dan1b162162019-04-27 20:15:15 +00004111#endif
drh98aa2ab2018-09-26 16:53:51 +00004112 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
4113 ".save FILE Write in-memory database into FILE",
4114 ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
4115 ".schema ?PATTERN? Show the CREATE statements matching PATTERN",
drhbbb29ec2020-10-12 14:56:47 +00004116 " Options:",
4117 " --indent Try to pretty-print the schema",
4118 " --nosys Omit objects whose names start with \"sqlite_\"",
drheb7f2a02018-09-26 18:02:32 +00004119 ".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
4120 " Options:",
4121 " --init Create a new SELFTEST table",
4122 " -v Verbose output",
drh98aa2ab2018-09-26 16:53:51 +00004123 ".separator COL ?ROW? Change the column and row separators",
drh2ce15c32017-07-11 13:34:40 +00004124#if defined(SQLITE_ENABLE_SESSION)
drheb7f2a02018-09-26 18:02:32 +00004125 ".session ?NAME? CMD ... Create or control sessions",
4126 " Subcommands:",
4127 " attach TABLE Attach TABLE",
4128 " changeset FILE Write a changeset into FILE",
4129 " close Close one session",
4130 " enable ?BOOLEAN? Set or query the enable bit",
4131 " filter GLOB... Reject tables matching GLOBs",
4132 " indirect ?BOOLEAN? Mark or query the indirect status",
4133 " isempty Query whether the session is empty",
4134 " list List currently open session names",
4135 " open DB NAME Open a new session on DB",
4136 " patchset FILE Write a patchset into FILE",
4137 " If ?NAME? is omitted, the first defined session is used.",
drh2ce15c32017-07-11 13:34:40 +00004138#endif
drheb7f2a02018-09-26 18:02:32 +00004139 ".sha3sum ... Compute a SHA3 hash of database content",
4140 " Options:",
drh067b92b2020-06-19 15:24:12 +00004141 " --schema Also hash the sqlite_schema table",
drheb7f2a02018-09-26 18:02:32 +00004142 " --sha3-224 Use the sha3-224 algorithm",
drhe2754c12019-08-26 12:50:01 +00004143 " --sha3-256 Use the sha3-256 algorithm (default)",
drheb7f2a02018-09-26 18:02:32 +00004144 " --sha3-384 Use the sha3-384 algorithm",
4145 " --sha3-512 Use the sha3-512 algorithm",
4146 " Any other argument is a LIKE pattern for tables to hash",
drh04a28c32018-01-31 01:38:44 +00004147#ifndef SQLITE_NOHAVE_SYSTEM
drh98aa2ab2018-09-26 16:53:51 +00004148 ".shell CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004149#endif
drh98aa2ab2018-09-26 16:53:51 +00004150 ".show Show the current values for various settings",
drha6e6cf22021-01-09 19:10:04 +00004151 ".stats ?ARG? Show stats or turn stats on or off",
4152 " off Turn off automatic stat display",
4153 " on Turn on automatic stat display",
4154 " stmt Show statement stats",
4155 " vmstep Show the virtual machine step count only",
drh04a28c32018-01-31 01:38:44 +00004156#ifndef SQLITE_NOHAVE_SYSTEM
drh98aa2ab2018-09-26 16:53:51 +00004157 ".system CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004158#endif
drh98aa2ab2018-09-26 16:53:51 +00004159 ".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
4160 ".testcase NAME Begin redirecting output to 'testcase-out.txt'",
drhd985f722019-06-05 14:29:53 +00004161 ".testctrl CMD ... Run various sqlite3_test_control() operations",
4162 " Run \".testctrl\" with no arguments for details",
drh98aa2ab2018-09-26 16:53:51 +00004163 ".timeout MS Try opening locked tables for MS milliseconds",
4164 ".timer on|off Turn SQL timer on or off",
drh707821f2018-12-05 13:39:06 +00004165#ifndef SQLITE_OMIT_TRACE
4166 ".trace ?OPTIONS? Output each SQL statement as it is run",
4167 " FILE Send output to FILE",
4168 " stdout Send output to stdout",
4169 " stderr Send output to stderr",
4170 " off Disable tracing",
4171 " --expanded Expand query parameters",
4172#ifdef SQLITE_ENABLE_NORMALIZE
4173 " --normalized Normal the SQL statements",
4174#endif
4175 " --plain Show SQL as it is input",
4176 " --stmt Trace statement execution (SQLITE_TRACE_STMT)",
4177 " --profile Profile statements (SQLITE_TRACE_PROFILE)",
4178 " --row Trace each row (SQLITE_TRACE_ROW)",
4179 " --close Trace connection close (SQLITE_TRACE_CLOSE)",
4180#endif /* SQLITE_OMIT_TRACE */
drhcc5979d2019-08-16 22:58:29 +00004181#ifdef SQLITE_DEBUG
4182 ".unmodule NAME ... Unregister virtual table modules",
drh5df84282019-08-17 19:45:25 +00004183 " --allexcept Unregister everything except those named",
drhcc5979d2019-08-16 22:58:29 +00004184#endif
drh98aa2ab2018-09-26 16:53:51 +00004185 ".vfsinfo ?AUX? Information about the top-level VFS",
4186 ".vfslist List all available VFSes",
4187 ".vfsname ?AUX? Print the name of the VFS stack",
drh7da29a32020-05-29 19:17:20 +00004188 ".width NUM1 NUM2 ... Set minimum column widths for columnar output",
drh98aa2ab2018-09-26 16:53:51 +00004189 " Negative values right-justify",
4190};
4191
4192/*
4193** Output help text.
4194**
4195** zPattern describes the set of commands for which help text is provided.
4196** If zPattern is NULL, then show all commands, but only give a one-line
4197** description of each.
4198**
4199** Return the number of matches.
4200*/
4201static int showHelp(FILE *out, const char *zPattern){
drhe93f8262018-10-11 16:53:37 +00004202 int i = 0;
4203 int j = 0;
drh98aa2ab2018-09-26 16:53:51 +00004204 int n = 0;
4205 char *zPat;
drh488cddf2018-10-06 14:38:17 +00004206 if( zPattern==0
4207 || zPattern[0]=='0'
4208 || strcmp(zPattern,"-a")==0
4209 || strcmp(zPattern,"-all")==0
drh7a431002020-04-18 14:12:00 +00004210 || strcmp(zPattern,"--all")==0
drh488cddf2018-10-06 14:38:17 +00004211 ){
drh98aa2ab2018-09-26 16:53:51 +00004212 /* Show all commands, but only one line per command */
drh488cddf2018-10-06 14:38:17 +00004213 if( zPattern==0 ) zPattern = "";
drh98aa2ab2018-09-26 16:53:51 +00004214 for(i=0; i<ArraySize(azHelp); i++){
drh488cddf2018-10-06 14:38:17 +00004215 if( azHelp[i][0]=='.' || zPattern[0] ){
drh98aa2ab2018-09-26 16:53:51 +00004216 utf8_printf(out, "%s\n", azHelp[i]);
4217 n++;
4218 }
4219 }
4220 }else{
4221 /* Look for commands that for which zPattern is an exact prefix */
4222 zPat = sqlite3_mprintf(".%s*", zPattern);
drhe3e25652021-12-16 13:29:28 +00004223 shell_check_oom(zPat);
drh98aa2ab2018-09-26 16:53:51 +00004224 for(i=0; i<ArraySize(azHelp); i++){
4225 if( sqlite3_strglob(zPat, azHelp[i])==0 ){
4226 utf8_printf(out, "%s\n", azHelp[i]);
drheb7f2a02018-09-26 18:02:32 +00004227 j = i+1;
drh98aa2ab2018-09-26 16:53:51 +00004228 n++;
4229 }
4230 }
4231 sqlite3_free(zPat);
drheb7f2a02018-09-26 18:02:32 +00004232 if( n ){
4233 if( n==1 ){
4234 /* when zPattern is a prefix of exactly one command, then include the
4235 ** details of that command, which should begin at offset j */
4236 while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){
4237 utf8_printf(out, "%s\n", azHelp[j]);
4238 j++;
4239 }
4240 }
4241 return n;
4242 }
4243 /* Look for commands that contain zPattern anywhere. Show the complete
4244 ** text of all commands that match. */
drh98aa2ab2018-09-26 16:53:51 +00004245 zPat = sqlite3_mprintf("%%%s%%", zPattern);
drhe3e25652021-12-16 13:29:28 +00004246 shell_check_oom(zPat);
drh98aa2ab2018-09-26 16:53:51 +00004247 for(i=0; i<ArraySize(azHelp); i++){
4248 if( azHelp[i][0]=='.' ) j = i;
4249 if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
4250 utf8_printf(out, "%s\n", azHelp[j]);
4251 while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
4252 j++;
4253 utf8_printf(out, "%s\n", azHelp[j]);
4254 }
4255 i = j;
4256 n++;
4257 }
4258 }
4259 sqlite3_free(zPat);
4260 }
4261 return n;
4262}
drh2ce15c32017-07-11 13:34:40 +00004263
drh2ce15c32017-07-11 13:34:40 +00004264/* Forward reference */
drh60379d42018-12-13 18:30:01 +00004265static int process_input(ShellState *p);
drh2ce15c32017-07-11 13:34:40 +00004266
4267/*
4268** Read the content of file zName into memory obtained from sqlite3_malloc64()
4269** and return a pointer to the buffer. The caller is responsible for freeing
4270** the memory.
4271**
4272** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
4273** read.
4274**
4275** For convenience, a nul-terminator byte is always appended to the data read
4276** from the file before the buffer is returned. This byte is not included in
4277** the final value of (*pnByte), if applicable.
4278**
4279** NULL is returned if any error is encountered. The final value of *pnByte
4280** is undefined in this case.
4281*/
4282static char *readFile(const char *zName, int *pnByte){
4283 FILE *in = fopen(zName, "rb");
4284 long nIn;
4285 size_t nRead;
4286 char *pBuf;
4287 if( in==0 ) return 0;
4288 fseek(in, 0, SEEK_END);
4289 nIn = ftell(in);
4290 rewind(in);
4291 pBuf = sqlite3_malloc64( nIn+1 );
drh1dbb1472018-10-11 10:37:24 +00004292 if( pBuf==0 ){ fclose(in); return 0; }
drh2ce15c32017-07-11 13:34:40 +00004293 nRead = fread(pBuf, nIn, 1, in);
4294 fclose(in);
4295 if( nRead!=1 ){
4296 sqlite3_free(pBuf);
4297 return 0;
4298 }
4299 pBuf[nIn] = 0;
4300 if( pnByte ) *pnByte = nIn;
4301 return pBuf;
4302}
4303
4304#if defined(SQLITE_ENABLE_SESSION)
4305/*
4306** Close a single OpenSession object and release all of its associated
4307** resources.
4308*/
4309static void session_close(OpenSession *pSession){
4310 int i;
4311 sqlite3session_delete(pSession->p);
4312 sqlite3_free(pSession->zName);
4313 for(i=0; i<pSession->nFilter; i++){
4314 sqlite3_free(pSession->azFilter[i]);
4315 }
4316 sqlite3_free(pSession->azFilter);
4317 memset(pSession, 0, sizeof(OpenSession));
4318}
4319#endif
4320
4321/*
4322** Close all OpenSession objects and release all associated resources.
4323*/
4324#if defined(SQLITE_ENABLE_SESSION)
drh37407122021-07-23 18:43:58 +00004325static void session_close_all(ShellState *p, int i){
4326 int j;
4327 struct AuxDb *pAuxDb = i<0 ? p->pAuxDb : &p->aAuxDb[i];
4328 for(j=0; j<pAuxDb->nSession; j++){
4329 session_close(&pAuxDb->aSession[j]);
drh2ce15c32017-07-11 13:34:40 +00004330 }
drh37407122021-07-23 18:43:58 +00004331 pAuxDb->nSession = 0;
drh2ce15c32017-07-11 13:34:40 +00004332}
4333#else
drh37407122021-07-23 18:43:58 +00004334# define session_close_all(X,Y)
drh2ce15c32017-07-11 13:34:40 +00004335#endif
4336
4337/*
4338** Implementation of the xFilter function for an open session. Omit
4339** any tables named by ".session filter" but let all other table through.
4340*/
4341#if defined(SQLITE_ENABLE_SESSION)
4342static int session_filter(void *pCtx, const char *zTab){
4343 OpenSession *pSession = (OpenSession*)pCtx;
4344 int i;
4345 for(i=0; i<pSession->nFilter; i++){
4346 if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
4347 }
4348 return 1;
4349}
4350#endif
4351
4352/*
drh1fa6d9f2018-01-06 21:46:01 +00004353** Try to deduce the type of file for zName based on its content. Return
4354** one of the SHELL_OPEN_* constants.
drh1bf208c2018-03-09 21:54:01 +00004355**
4356** If the file does not exist or is empty but its name looks like a ZIP
4357** archive and the dfltZip flag is true, then assume it is a ZIP archive.
4358** Otherwise, assume an ordinary database regardless of the filename if
4359** the type cannot be determined from content.
drh1fa6d9f2018-01-06 21:46:01 +00004360*/
drhfc97c1c2018-05-14 00:41:12 +00004361int deduceDatabaseType(const char *zName, int dfltZip){
drh1fa6d9f2018-01-06 21:46:01 +00004362 FILE *f = fopen(zName, "rb");
4363 size_t n;
4364 int rc = SHELL_OPEN_UNSPEC;
4365 char zBuf[100];
drh1bf208c2018-03-09 21:54:01 +00004366 if( f==0 ){
drhbe4ccb22018-05-17 20:04:24 +00004367 if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
4368 return SHELL_OPEN_ZIPFILE;
4369 }else{
4370 return SHELL_OPEN_NORMAL;
4371 }
drh1bf208c2018-03-09 21:54:01 +00004372 }
drh2b3c4af2018-10-30 14:36:21 +00004373 n = fread(zBuf, 16, 1, f);
4374 if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
4375 fclose(f);
4376 return SHELL_OPEN_NORMAL;
4377 }
drh1fa6d9f2018-01-06 21:46:01 +00004378 fseek(f, -25, SEEK_END);
4379 n = fread(zBuf, 25, 1, f);
4380 if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
4381 rc = SHELL_OPEN_APPENDVFS;
4382 }else{
4383 fseek(f, -22, SEEK_END);
4384 n = fread(zBuf, 22, 1, f);
4385 if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
4386 && zBuf[3]==0x06 ){
4387 rc = SHELL_OPEN_ZIPFILE;
drh1bf208c2018-03-09 21:54:01 +00004388 }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
mistachkina3926f42018-05-14 12:23:04 +00004389 rc = SHELL_OPEN_ZIPFILE;
drh1fa6d9f2018-01-06 21:46:01 +00004390 }
4391 }
4392 fclose(f);
4393 return rc;
4394}
4395
drh8d889af2021-05-08 17:18:23 +00004396#ifndef SQLITE_OMIT_DESERIALIZE
drh33746482018-12-13 15:06:26 +00004397/*
4398** Reconstruct an in-memory database using the output from the "dbtotxt"
drh37407122021-07-23 18:43:58 +00004399** program. Read content from the file in p->aAuxDb[].zDbFilename.
4400** If p->aAuxDb[].zDbFilename is 0, then read from standard input.
drh33746482018-12-13 15:06:26 +00004401*/
4402static unsigned char *readHexDb(ShellState *p, int *pnData){
4403 unsigned char *a = 0;
drh2c8ee022018-12-13 18:59:30 +00004404 int nLine;
drh33746482018-12-13 15:06:26 +00004405 int n = 0;
4406 int pgsz = 0;
4407 int iOffset = 0;
4408 int j, k;
4409 int rc;
4410 FILE *in;
drh37407122021-07-23 18:43:58 +00004411 const char *zDbFilename = p->pAuxDb->zDbFilename;
drh3ea557e2019-04-23 15:30:58 +00004412 unsigned int x[16];
drh2c8ee022018-12-13 18:59:30 +00004413 char zLine[1000];
drh37407122021-07-23 18:43:58 +00004414 if( zDbFilename ){
4415 in = fopen(zDbFilename, "r");
drh33746482018-12-13 15:06:26 +00004416 if( in==0 ){
drh37407122021-07-23 18:43:58 +00004417 utf8_printf(stderr, "cannot open \"%s\" for reading\n", zDbFilename);
drh33746482018-12-13 15:06:26 +00004418 return 0;
4419 }
drh2c8ee022018-12-13 18:59:30 +00004420 nLine = 0;
drh33746482018-12-13 15:06:26 +00004421 }else{
drh60379d42018-12-13 18:30:01 +00004422 in = p->in;
drh2c8ee022018-12-13 18:59:30 +00004423 nLine = p->lineno;
drh5bf46442019-05-03 02:41:36 +00004424 if( in==0 ) in = stdin;
drh33746482018-12-13 15:06:26 +00004425 }
4426 *pnData = 0;
drh2c8ee022018-12-13 18:59:30 +00004427 nLine++;
drh33746482018-12-13 15:06:26 +00004428 if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
4429 rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
4430 if( rc!=2 ) goto readHexDb_error;
drh68feae52019-05-09 11:18:41 +00004431 if( n<0 ) goto readHexDb_error;
drh09ea1252019-07-17 15:05:16 +00004432 if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
4433 n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */
drh68feae52019-05-09 11:18:41 +00004434 a = sqlite3_malloc( n ? n : 1 );
drhe3e25652021-12-16 13:29:28 +00004435 shell_check_oom(a);
drh33746482018-12-13 15:06:26 +00004436 memset(a, 0, n);
4437 if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
4438 utf8_printf(stderr, "invalid pagesize\n");
4439 goto readHexDb_error;
4440 }
drh2c8ee022018-12-13 18:59:30 +00004441 for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
drh33746482018-12-13 15:06:26 +00004442 rc = sscanf(zLine, "| page %d offset %d", &j, &k);
4443 if( rc==2 ){
4444 iOffset = k;
4445 continue;
4446 }
4447 if( strncmp(zLine, "| end ", 6)==0 ){
4448 break;
4449 }
drh3ea557e2019-04-23 15:30:58 +00004450 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 +00004451 &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
4452 &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
4453 if( rc==17 ){
4454 k = iOffset+j;
drh82978ac2021-10-01 17:06:44 +00004455 if( k+16<=n && k>=0 ){
drh3ea557e2019-04-23 15:30:58 +00004456 int ii;
4457 for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
drh33746482018-12-13 15:06:26 +00004458 }
drh33746482018-12-13 15:06:26 +00004459 }
4460 }
4461 *pnData = n;
drh2c8ee022018-12-13 18:59:30 +00004462 if( in!=p->in ){
4463 fclose(in);
4464 }else{
4465 p->lineno = nLine;
4466 }
drh33746482018-12-13 15:06:26 +00004467 return a;
4468
4469readHexDb_error:
drh68feae52019-05-09 11:18:41 +00004470 if( in!=p->in ){
drh33746482018-12-13 15:06:26 +00004471 fclose(in);
4472 }else{
drh60379d42018-12-13 18:30:01 +00004473 while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
drh2c8ee022018-12-13 18:59:30 +00004474 nLine++;
drh33746482018-12-13 15:06:26 +00004475 if(strncmp(zLine, "| end ", 6)==0 ) break;
4476 }
drh2c8ee022018-12-13 18:59:30 +00004477 p->lineno = nLine;
drh33746482018-12-13 15:06:26 +00004478 }
4479 sqlite3_free(a);
4480 utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
4481 return 0;
4482}
drh8d889af2021-05-08 17:18:23 +00004483#endif /* SQLITE_OMIT_DESERIALIZE */
drh33746482018-12-13 15:06:26 +00004484
danb1825882019-04-23 20:48:32 +00004485/*
dan9c014f82019-04-25 19:23:15 +00004486** Scalar function "shell_int32". The first argument to this function
4487** must be a blob. The second a non-negative integer. This function
4488** reads and returns a 32-bit big-endian integer from byte
4489** offset (4*<arg2>) of the blob.
4490*/
4491static void shellInt32(
4492 sqlite3_context *context,
4493 int argc,
4494 sqlite3_value **argv
4495){
4496 const unsigned char *pBlob;
4497 int nBlob;
4498 int iInt;
drh9546c762019-05-10 17:50:33 +00004499
4500 UNUSED_PARAMETER(argc);
dan9c014f82019-04-25 19:23:15 +00004501 nBlob = sqlite3_value_bytes(argv[0]);
4502 pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
4503 iInt = sqlite3_value_int(argv[1]);
4504
4505 if( iInt>=0 && (iInt+1)*4<=nBlob ){
4506 const unsigned char *a = &pBlob[iInt*4];
4507 sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24)
4508 + ((sqlite3_int64)a[1]<<16)
4509 + ((sqlite3_int64)a[2]<< 8)
4510 + ((sqlite3_int64)a[3]<< 0);
4511 sqlite3_result_int64(context, iVal);
4512 }
4513}
4514
4515/*
drha2de66c2019-08-06 20:26:17 +00004516** Scalar function "shell_idquote(X)" returns string X quoted as an identifier,
4517** using "..." with internal double-quote characters doubled.
4518*/
4519static void shellIdQuote(
4520 sqlite3_context *context,
4521 int argc,
4522 sqlite3_value **argv
4523){
4524 const char *zName = (const char*)sqlite3_value_text(argv[0]);
drh51755a72019-08-08 19:40:29 +00004525 UNUSED_PARAMETER(argc);
drha2de66c2019-08-06 20:26:17 +00004526 if( zName ){
4527 char *z = sqlite3_mprintf("\"%w\"", zName);
4528 sqlite3_result_text(context, z, -1, sqlite3_free);
4529 }
4530}
4531
4532/*
drhddcfe922020-09-15 12:29:35 +00004533** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
4534*/
4535static void shellUSleepFunc(
4536 sqlite3_context *context,
drhd36f5882020-11-25 16:28:04 +00004537 int argcUnused,
drhddcfe922020-09-15 12:29:35 +00004538 sqlite3_value **argv
4539){
4540 int sleep = sqlite3_value_int(argv[0]);
drhd36f5882020-11-25 16:28:04 +00004541 (void)argcUnused;
drhddcfe922020-09-15 12:29:35 +00004542 sqlite3_sleep(sleep/1000);
4543 sqlite3_result_int(context, sleep);
4544}
4545
4546/*
danb1825882019-04-23 20:48:32 +00004547** Scalar function "shell_escape_crnl" used by the .recover command.
4548** The argument passed to this function is the output of built-in
4549** function quote(). If the first character of the input is "'",
4550** indicating that the value passed to quote() was a text value,
4551** then this function searches the input for "\n" and "\r" characters
4552** and adds a wrapper similar to the following:
4553**
4554** replace(replace(<input>, '\n', char(10), '\r', char(13));
4555**
4556** Or, if the first character of the input is not "'", then a copy
4557** of the input is returned.
4558*/
4559static void shellEscapeCrnl(
4560 sqlite3_context *context,
4561 int argc,
4562 sqlite3_value **argv
4563){
4564 const char *zText = (const char*)sqlite3_value_text(argv[0]);
drh9546c762019-05-10 17:50:33 +00004565 UNUSED_PARAMETER(argc);
drh621a5e02021-12-16 17:35:27 +00004566 if( zText && zText[0]=='\'' ){
danb1825882019-04-23 20:48:32 +00004567 int nText = sqlite3_value_bytes(argv[0]);
4568 int i;
4569 char zBuf1[20];
4570 char zBuf2[20];
4571 const char *zNL = 0;
4572 const char *zCR = 0;
4573 int nCR = 0;
4574 int nNL = 0;
4575
4576 for(i=0; zText[i]; i++){
4577 if( zNL==0 && zText[i]=='\n' ){
4578 zNL = unused_string(zText, "\\n", "\\012", zBuf1);
4579 nNL = (int)strlen(zNL);
4580 }
4581 if( zCR==0 && zText[i]=='\r' ){
4582 zCR = unused_string(zText, "\\r", "\\015", zBuf2);
4583 nCR = (int)strlen(zCR);
4584 }
4585 }
4586
4587 if( zNL || zCR ){
4588 int iOut = 0;
4589 i64 nMax = (nNL > nCR) ? nNL : nCR;
dan51f5ffa2019-04-29 11:41:46 +00004590 i64 nAlloc = nMax * nText + (nMax+64)*2;
danb1825882019-04-23 20:48:32 +00004591 char *zOut = (char*)sqlite3_malloc64(nAlloc);
4592 if( zOut==0 ){
4593 sqlite3_result_error_nomem(context);
4594 return;
4595 }
4596
4597 if( zNL && zCR ){
4598 memcpy(&zOut[iOut], "replace(replace(", 16);
4599 iOut += 16;
4600 }else{
4601 memcpy(&zOut[iOut], "replace(", 8);
4602 iOut += 8;
4603 }
4604 for(i=0; zText[i]; i++){
4605 if( zText[i]=='\n' ){
4606 memcpy(&zOut[iOut], zNL, nNL);
4607 iOut += nNL;
4608 }else if( zText[i]=='\r' ){
4609 memcpy(&zOut[iOut], zCR, nCR);
4610 iOut += nCR;
4611 }else{
4612 zOut[iOut] = zText[i];
4613 iOut++;
4614 }
4615 }
4616
4617 if( zNL ){
4618 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
4619 memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
4620 memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
4621 }
4622 if( zCR ){
4623 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
4624 memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
4625 memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
4626 }
4627
4628 sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
4629 sqlite3_free(zOut);
4630 return;
4631 }
4632 }
4633
4634 sqlite3_result_value(context, argv[0]);
4635}
4636
drhbe4ccb22018-05-17 20:04:24 +00004637/* Flags for open_db().
4638**
4639** The default behavior of open_db() is to exit(1) if the database fails to
4640** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
4641** but still returns without calling exit.
4642**
4643** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a
4644** ZIP archive if the file does not exist or is empty and its name matches
4645** the *.zip pattern.
4646*/
4647#define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */
4648#define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */
4649
drh1fa6d9f2018-01-06 21:46:01 +00004650/*
drh2ce15c32017-07-11 13:34:40 +00004651** Make sure the database is open. If it is not, then open it. If
4652** the database fails to open, print an error message and exit.
4653*/
drhbe4ccb22018-05-17 20:04:24 +00004654static void open_db(ShellState *p, int openFlags){
drh2ce15c32017-07-11 13:34:40 +00004655 if( p->db==0 ){
drh37407122021-07-23 18:43:58 +00004656 const char *zDbFilename = p->pAuxDb->zDbFilename;
drhf2072d12018-05-11 15:10:11 +00004657 if( p->openMode==SHELL_OPEN_UNSPEC ){
drh37407122021-07-23 18:43:58 +00004658 if( zDbFilename==0 || zDbFilename[0]==0 ){
drhf2072d12018-05-11 15:10:11 +00004659 p->openMode = SHELL_OPEN_NORMAL;
drhbe4ccb22018-05-17 20:04:24 +00004660 }else{
drh37407122021-07-23 18:43:58 +00004661 p->openMode = (u8)deduceDatabaseType(zDbFilename,
drhbe4ccb22018-05-17 20:04:24 +00004662 (openFlags & OPEN_DB_ZIPFILE)!=0);
drhf2072d12018-05-11 15:10:11 +00004663 }
drh1fa6d9f2018-01-06 21:46:01 +00004664 }
4665 switch( p->openMode ){
4666 case SHELL_OPEN_APPENDVFS: {
drh37407122021-07-23 18:43:58 +00004667 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004668 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
drh1fa6d9f2018-01-06 21:46:01 +00004669 break;
4670 }
drh33746482018-12-13 15:06:26 +00004671 case SHELL_OPEN_HEXDB:
drh60f34ae2018-10-30 13:19:49 +00004672 case SHELL_OPEN_DESERIALIZE: {
4673 sqlite3_open(0, &p->db);
4674 break;
4675 }
drh1fa6d9f2018-01-06 21:46:01 +00004676 case SHELL_OPEN_ZIPFILE: {
4677 sqlite3_open(":memory:", &p->db);
4678 break;
4679 }
drhee269a62018-02-14 23:27:43 +00004680 case SHELL_OPEN_READONLY: {
drh37407122021-07-23 18:43:58 +00004681 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004682 SQLITE_OPEN_READONLY|p->openFlags, 0);
drhee269a62018-02-14 23:27:43 +00004683 break;
4684 }
drh1fa6d9f2018-01-06 21:46:01 +00004685 case SHELL_OPEN_UNSPEC:
4686 case SHELL_OPEN_NORMAL: {
drh37407122021-07-23 18:43:58 +00004687 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004688 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
drh1fa6d9f2018-01-06 21:46:01 +00004689 break;
4690 }
4691 }
drh2ce15c32017-07-11 13:34:40 +00004692 globalDb = p->db;
4693 if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
4694 utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
drh37407122021-07-23 18:43:58 +00004695 zDbFilename, sqlite3_errmsg(p->db));
drhf25cc4f2019-01-04 14:29:21 +00004696 if( openFlags & OPEN_DB_KEEPALIVE ){
4697 sqlite3_open(":memory:", &p->db);
4698 return;
4699 }
drh2ce15c32017-07-11 13:34:40 +00004700 exit(1);
4701 }
4702#ifndef SQLITE_OMIT_LOAD_EXTENSION
4703 sqlite3_enable_load_extension(p->db, 1);
4704#endif
4705 sqlite3_fileio_init(p->db, 0, 0);
4706 sqlite3_shathree_init(p->db, 0, 0);
drh56eb09b2017-07-11 13:59:07 +00004707 sqlite3_completion_init(p->db, 0, 0);
drhf05dd032020-04-14 15:53:58 +00004708 sqlite3_uint_init(p->db, 0, 0);
drhbeb9def2020-06-22 19:12:23 +00004709 sqlite3_decimal_init(p->db, 0, 0);
drh64689902021-06-03 13:51:31 +00004710 sqlite3_regexp_init(p->db, 0, 0);
drh8cda77d2020-06-24 15:06:29 +00004711 sqlite3_ieee_init(p->db, 0, 0);
mistachkin72c38d82020-08-28 18:47:39 +00004712 sqlite3_series_init(p->db, 0, 0);
dan1b162162019-04-27 20:15:15 +00004713#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00004714 sqlite3_dbdata_init(p->db, 0, 0);
dan1b162162019-04-27 20:15:15 +00004715#endif
dan72afc3c2017-12-05 18:32:40 +00004716#ifdef SQLITE_HAVE_ZLIB
dan9ebfaad2017-12-26 20:39:58 +00004717 sqlite3_zipfile_init(p->db, 0, 0);
dand1b51d42017-12-16 19:11:26 +00004718 sqlite3_sqlar_init(p->db, 0, 0);
dan72afc3c2017-12-05 18:32:40 +00004719#endif
drhceba7922018-01-01 21:28:25 +00004720 sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
drh2ce15c32017-07-11 13:34:40 +00004721 shellAddSchemaName, 0, 0);
drh667a2a22018-01-02 00:04:37 +00004722 sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
4723 shellModuleSchema, 0, 0);
drh634c70f2018-01-10 16:50:18 +00004724 sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
4725 shellPutsFunc, 0, 0);
danb1825882019-04-23 20:48:32 +00004726 sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0,
4727 shellEscapeCrnl, 0, 0);
dan9c014f82019-04-25 19:23:15 +00004728 sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
4729 shellInt32, 0, 0);
drha2de66c2019-08-06 20:26:17 +00004730 sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
4731 shellIdQuote, 0, 0);
drhddcfe922020-09-15 12:29:35 +00004732 sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
4733 shellUSleepFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00004734#ifndef SQLITE_NOHAVE_SYSTEM
drh97913132018-01-11 00:04:00 +00004735 sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
4736 editFunc, 0, 0);
4737 sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
4738 editFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00004739#endif
drh1fa6d9f2018-01-06 21:46:01 +00004740 if( p->openMode==SHELL_OPEN_ZIPFILE ){
4741 char *zSql = sqlite3_mprintf(
drh37407122021-07-23 18:43:58 +00004742 "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename);
drhe3e25652021-12-16 13:29:28 +00004743 shell_check_oom(zSql);
drh1fa6d9f2018-01-06 21:46:01 +00004744 sqlite3_exec(p->db, zSql, 0, 0, 0);
4745 sqlite3_free(zSql);
drha751f392018-10-30 15:31:22 +00004746 }
drh8d889af2021-05-08 17:18:23 +00004747#ifndef SQLITE_OMIT_DESERIALIZE
drh33746482018-12-13 15:06:26 +00004748 else
4749 if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
mistachkin99490932018-12-17 22:19:57 +00004750 int rc;
drh60f34ae2018-10-30 13:19:49 +00004751 int nData = 0;
drh33746482018-12-13 15:06:26 +00004752 unsigned char *aData;
4753 if( p->openMode==SHELL_OPEN_DESERIALIZE ){
drh37407122021-07-23 18:43:58 +00004754 aData = (unsigned char*)readFile(zDbFilename, &nData);
drh33746482018-12-13 15:06:26 +00004755 }else{
4756 aData = readHexDb(p, &nData);
4757 if( aData==0 ){
drh33746482018-12-13 15:06:26 +00004758 return;
4759 }
4760 }
mistachkin99490932018-12-17 22:19:57 +00004761 rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
drh60f34ae2018-10-30 13:19:49 +00004762 SQLITE_DESERIALIZE_RESIZEABLE |
4763 SQLITE_DESERIALIZE_FREEONCLOSE);
4764 if( rc ){
4765 utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
4766 }
drh6ca64482019-01-22 16:06:20 +00004767 if( p->szMax>0 ){
4768 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
4769 }
drh1fa6d9f2018-01-06 21:46:01 +00004770 }
drha751f392018-10-30 15:31:22 +00004771#endif
drh2ce15c32017-07-11 13:34:40 +00004772 }
drhb97e2ad2021-08-26 18:31:39 +00004773 if( p->bSafeModePersist && p->db!=0 ){
4774 sqlite3_set_authorizer(p->db, safeModeAuth, p);
4775 }
drh2ce15c32017-07-11 13:34:40 +00004776}
4777
drh9e804032018-05-18 17:11:50 +00004778/*
4779** Attempt to close the databaes connection. Report errors.
4780*/
4781void close_db(sqlite3 *db){
4782 int rc = sqlite3_close(db);
4783 if( rc ){
4784 utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
4785 rc, sqlite3_errmsg(db));
4786 }
4787}
4788
drh56eb09b2017-07-11 13:59:07 +00004789#if HAVE_READLINE || HAVE_EDITLINE
4790/*
4791** Readline completion callbacks
4792*/
4793static char *readline_completion_generator(const char *text, int state){
4794 static sqlite3_stmt *pStmt = 0;
4795 char *zRet;
4796 if( state==0 ){
4797 char *zSql;
drh56eb09b2017-07-11 13:59:07 +00004798 sqlite3_finalize(pStmt);
4799 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
4800 " FROM completion(%Q) ORDER BY 1", text);
drhe3e25652021-12-16 13:29:28 +00004801 shell_check_oom(zSql);
drh56eb09b2017-07-11 13:59:07 +00004802 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
4803 sqlite3_free(zSql);
4804 }
4805 if( sqlite3_step(pStmt)==SQLITE_ROW ){
drh621a5e02021-12-16 17:35:27 +00004806 const char *z = (const char*)sqlite3_column_text(pStmt,0);
4807 zRet = z ? strdup(z) : 0;
drh56eb09b2017-07-11 13:59:07 +00004808 }else{
4809 sqlite3_finalize(pStmt);
4810 pStmt = 0;
4811 zRet = 0;
4812 }
4813 return zRet;
4814}
4815static char **readline_completion(const char *zText, int iStart, int iEnd){
4816 rl_attempted_completion_over = 1;
4817 return rl_completion_matches(zText, readline_completion_generator);
4818}
4819
4820#elif HAVE_LINENOISE
4821/*
4822** Linenoise completion callback
4823*/
4824static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
drhaf2770f2018-01-05 14:55:43 +00004825 int nLine = strlen30(zLine);
drh56eb09b2017-07-11 13:59:07 +00004826 int i, iStart;
4827 sqlite3_stmt *pStmt = 0;
4828 char *zSql;
4829 char zBuf[1000];
4830
4831 if( nLine>sizeof(zBuf)-30 ) return;
drh1615c372018-05-12 23:56:22 +00004832 if( zLine[0]=='.' || zLine[0]=='#') return;
drh56eb09b2017-07-11 13:59:07 +00004833 for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
4834 if( i==nLine-1 ) return;
4835 iStart = i+1;
4836 memcpy(zBuf, zLine, iStart);
4837 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
4838 " FROM completion(%Q,%Q) ORDER BY 1",
4839 &zLine[iStart], zLine);
drhe3e25652021-12-16 13:29:28 +00004840 shell_check_oom(zSql);
drh56eb09b2017-07-11 13:59:07 +00004841 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
4842 sqlite3_free(zSql);
4843 sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
4844 while( sqlite3_step(pStmt)==SQLITE_ROW ){
4845 const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
4846 int nCompletion = sqlite3_column_bytes(pStmt, 0);
drh621a5e02021-12-16 17:35:27 +00004847 if( iStart+nCompletion < sizeof(zBuf)-1 && zCompletion ){
drh56eb09b2017-07-11 13:59:07 +00004848 memcpy(zBuf+iStart, zCompletion, nCompletion+1);
4849 linenoiseAddCompletion(lc, zBuf);
4850 }
4851 }
4852 sqlite3_finalize(pStmt);
4853}
4854#endif
4855
drh2ce15c32017-07-11 13:34:40 +00004856/*
4857** Do C-language style dequoting.
4858**
4859** \a -> alarm
4860** \b -> backspace
4861** \t -> tab
4862** \n -> newline
4863** \v -> vertical tab
4864** \f -> form feed
4865** \r -> carriage return
4866** \s -> space
4867** \" -> "
4868** \' -> '
4869** \\ -> backslash
4870** \NNN -> ascii character NNN in octal
4871*/
4872static void resolve_backslashes(char *z){
4873 int i, j;
4874 char c;
4875 while( *z && *z!='\\' ) z++;
4876 for(i=j=0; (c = z[i])!=0; i++, j++){
4877 if( c=='\\' && z[i+1]!=0 ){
4878 c = z[++i];
4879 if( c=='a' ){
4880 c = '\a';
4881 }else if( c=='b' ){
4882 c = '\b';
4883 }else if( c=='t' ){
4884 c = '\t';
4885 }else if( c=='n' ){
4886 c = '\n';
4887 }else if( c=='v' ){
4888 c = '\v';
4889 }else if( c=='f' ){
4890 c = '\f';
4891 }else if( c=='r' ){
4892 c = '\r';
4893 }else if( c=='"' ){
4894 c = '"';
4895 }else if( c=='\'' ){
4896 c = '\'';
4897 }else if( c=='\\' ){
4898 c = '\\';
4899 }else if( c>='0' && c<='7' ){
4900 c -= '0';
4901 if( z[i+1]>='0' && z[i+1]<='7' ){
4902 i++;
4903 c = (c<<3) + z[i] - '0';
4904 if( z[i+1]>='0' && z[i+1]<='7' ){
4905 i++;
4906 c = (c<<3) + z[i] - '0';
4907 }
4908 }
4909 }
4910 }
4911 z[j] = c;
4912 }
4913 if( j<i ) z[j] = 0;
4914}
4915
4916/*
drh2ce15c32017-07-11 13:34:40 +00004917** Interpret zArg as either an integer or a boolean value. Return 1 or 0
4918** for TRUE and FALSE. Return the integer value if appropriate.
4919*/
4920static int booleanValue(const char *zArg){
4921 int i;
4922 if( zArg[0]=='0' && zArg[1]=='x' ){
4923 for(i=2; hexDigitValue(zArg[i])>=0; i++){}
4924 }else{
4925 for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
4926 }
4927 if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
4928 if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
4929 return 1;
4930 }
4931 if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
4932 return 0;
4933 }
4934 utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
4935 zArg);
4936 return 0;
4937}
4938
4939/*
4940** Set or clear a shell flag according to a boolean value.
4941*/
4942static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){
4943 if( booleanValue(zArg) ){
4944 ShellSetFlag(p, mFlag);
4945 }else{
4946 ShellClearFlag(p, mFlag);
4947 }
4948}
4949
4950/*
4951** Close an output file, assuming it is not stderr or stdout
4952*/
4953static void output_file_close(FILE *f){
4954 if( f && f!=stdout && f!=stderr ) fclose(f);
4955}
4956
4957/*
4958** Try to open an output file. The names "stdout" and "stderr" are
4959** recognized and do the right thing. NULL is returned if the output
4960** filename is "off".
4961*/
drha92a01a2018-01-10 22:15:37 +00004962static FILE *output_file_open(const char *zFile, int bTextMode){
drh2ce15c32017-07-11 13:34:40 +00004963 FILE *f;
4964 if( strcmp(zFile,"stdout")==0 ){
4965 f = stdout;
4966 }else if( strcmp(zFile, "stderr")==0 ){
4967 f = stderr;
4968 }else if( strcmp(zFile, "off")==0 ){
4969 f = 0;
4970 }else{
drha92a01a2018-01-10 22:15:37 +00004971 f = fopen(zFile, bTextMode ? "w" : "wb");
drh2ce15c32017-07-11 13:34:40 +00004972 if( f==0 ){
4973 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
4974 }
4975 }
4976 return f;
4977}
4978
drh707821f2018-12-05 13:39:06 +00004979#ifndef SQLITE_OMIT_TRACE
drh2ce15c32017-07-11 13:34:40 +00004980/*
4981** A routine for handling output from sqlite3_trace().
4982*/
4983static int sql_trace_callback(
drh707821f2018-12-05 13:39:06 +00004984 unsigned mType, /* The trace type */
4985 void *pArg, /* The ShellState pointer */
4986 void *pP, /* Usually a pointer to sqlite_stmt */
4987 void *pX /* Auxiliary output */
drh2ce15c32017-07-11 13:34:40 +00004988){
drh707821f2018-12-05 13:39:06 +00004989 ShellState *p = (ShellState*)pArg;
4990 sqlite3_stmt *pStmt;
4991 const char *zSql;
4992 int nSql;
4993 if( p->traceOut==0 ) return 0;
4994 if( mType==SQLITE_TRACE_CLOSE ){
4995 utf8_printf(p->traceOut, "-- closing database connection\n");
4996 return 0;
4997 }
4998 if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){
4999 zSql = (const char*)pX;
5000 }else{
5001 pStmt = (sqlite3_stmt*)pP;
5002 switch( p->eTraceType ){
5003 case SHELL_TRACE_EXPANDED: {
5004 zSql = sqlite3_expanded_sql(pStmt);
5005 break;
5006 }
5007#ifdef SQLITE_ENABLE_NORMALIZE
5008 case SHELL_TRACE_NORMALIZED: {
5009 zSql = sqlite3_normalized_sql(pStmt);
5010 break;
5011 }
5012#endif
5013 default: {
5014 zSql = sqlite3_sql(pStmt);
5015 break;
5016 }
5017 }
5018 }
5019 if( zSql==0 ) return 0;
5020 nSql = strlen30(zSql);
5021 while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
5022 switch( mType ){
5023 case SQLITE_TRACE_ROW:
5024 case SQLITE_TRACE_STMT: {
5025 utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql);
5026 break;
5027 }
5028 case SQLITE_TRACE_PROFILE: {
5029 sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
5030 utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec);
5031 break;
5032 }
drh2ce15c32017-07-11 13:34:40 +00005033 }
5034 return 0;
5035}
5036#endif
drh2ce15c32017-07-11 13:34:40 +00005037
5038/*
5039** A no-op routine that runs with the ".breakpoint" doc-command. This is
5040** a useful spot to set a debugger breakpoint.
5041*/
5042static void test_breakpoint(void){
5043 static int nCall = 0;
5044 nCall++;
5045}
5046
5047/*
5048** An object used to read a CSV and other files for import.
5049*/
5050typedef struct ImportCtx ImportCtx;
5051struct ImportCtx {
5052 const char *zFile; /* Name of the input file */
5053 FILE *in; /* Read the CSV text from this input stream */
drh97767842020-05-29 19:39:35 +00005054 int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */
drh2ce15c32017-07-11 13:34:40 +00005055 char *z; /* Accumulated text for a field */
5056 int n; /* Number of bytes in z */
5057 int nAlloc; /* Space allocated for z[] */
5058 int nLine; /* Current line number */
drhccb37812020-03-09 15:39:39 +00005059 int nRow; /* Number of rows imported */
5060 int nErr; /* Number of errors encountered */
drh2ce15c32017-07-11 13:34:40 +00005061 int bNotFirst; /* True if one or more bytes already read */
5062 int cTerm; /* Character that terminated the most recent field */
5063 int cColSep; /* The column separator character. (Usually ",") */
5064 int cRowSep; /* The row separator character. (Usually "\n") */
5065};
5066
drh97767842020-05-29 19:39:35 +00005067/* Clean up resourced used by an ImportCtx */
5068static void import_cleanup(ImportCtx *p){
drh42c2a042020-05-29 20:16:19 +00005069 if( p->in!=0 && p->xCloser!=0 ){
drh97767842020-05-29 19:39:35 +00005070 p->xCloser(p->in);
5071 p->in = 0;
5072 }
5073 sqlite3_free(p->z);
5074 p->z = 0;
5075}
5076
drh2ce15c32017-07-11 13:34:40 +00005077/* Append a single byte to z[] */
5078static void import_append_char(ImportCtx *p, int c){
5079 if( p->n+1>=p->nAlloc ){
5080 p->nAlloc += p->nAlloc + 100;
5081 p->z = sqlite3_realloc64(p->z, p->nAlloc);
drhe3e25652021-12-16 13:29:28 +00005082 shell_check_oom(p->z);
drh2ce15c32017-07-11 13:34:40 +00005083 }
5084 p->z[p->n++] = (char)c;
5085}
5086
5087/* Read a single field of CSV text. Compatible with rfc4180 and extended
5088** with the option of having a separator other than ",".
5089**
5090** + Input comes from p->in.
5091** + Store results in p->z of length p->n. Space to hold p->z comes
5092** from sqlite3_malloc64().
5093** + Use p->cSep as the column separator. The default is ",".
5094** + Use p->rSep as the row separator. The default is "\n".
5095** + Keep track of the line number in p->nLine.
5096** + Store the character that terminates the field in p->cTerm. Store
5097** EOF on end-of-file.
5098** + Report syntax errors on stderr
5099*/
5100static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
5101 int c;
5102 int cSep = p->cColSep;
5103 int rSep = p->cRowSep;
5104 p->n = 0;
5105 c = fgetc(p->in);
5106 if( c==EOF || seenInterrupt ){
5107 p->cTerm = EOF;
5108 return 0;
5109 }
5110 if( c=='"' ){
5111 int pc, ppc;
5112 int startLine = p->nLine;
5113 int cQuote = c;
5114 pc = ppc = 0;
5115 while( 1 ){
5116 c = fgetc(p->in);
5117 if( c==rSep ) p->nLine++;
5118 if( c==cQuote ){
5119 if( pc==cQuote ){
5120 pc = 0;
5121 continue;
5122 }
5123 }
5124 if( (c==cSep && pc==cQuote)
5125 || (c==rSep && pc==cQuote)
5126 || (c==rSep && pc=='\r' && ppc==cQuote)
5127 || (c==EOF && pc==cQuote)
5128 ){
5129 do{ p->n--; }while( p->z[p->n]!=cQuote );
5130 p->cTerm = c;
5131 break;
5132 }
5133 if( pc==cQuote && c!='\r' ){
5134 utf8_printf(stderr, "%s:%d: unescaped %c character\n",
5135 p->zFile, p->nLine, cQuote);
5136 }
5137 if( c==EOF ){
5138 utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
5139 p->zFile, startLine, cQuote);
5140 p->cTerm = c;
5141 break;
5142 }
5143 import_append_char(p, c);
5144 ppc = pc;
5145 pc = c;
5146 }
5147 }else{
5148 /* If this is the first field being parsed and it begins with the
5149 ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
5150 if( (c&0xff)==0xef && p->bNotFirst==0 ){
5151 import_append_char(p, c);
5152 c = fgetc(p->in);
5153 if( (c&0xff)==0xbb ){
5154 import_append_char(p, c);
5155 c = fgetc(p->in);
5156 if( (c&0xff)==0xbf ){
5157 p->bNotFirst = 1;
5158 p->n = 0;
5159 return csv_read_one_field(p);
5160 }
5161 }
5162 }
5163 while( c!=EOF && c!=cSep && c!=rSep ){
5164 import_append_char(p, c);
5165 c = fgetc(p->in);
5166 }
5167 if( c==rSep ){
5168 p->nLine++;
5169 if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
5170 }
5171 p->cTerm = c;
5172 }
5173 if( p->z ) p->z[p->n] = 0;
5174 p->bNotFirst = 1;
5175 return p->z;
5176}
5177
5178/* Read a single field of ASCII delimited text.
5179**
5180** + Input comes from p->in.
5181** + Store results in p->z of length p->n. Space to hold p->z comes
5182** from sqlite3_malloc64().
5183** + Use p->cSep as the column separator. The default is "\x1F".
5184** + Use p->rSep as the row separator. The default is "\x1E".
5185** + Keep track of the row number in p->nLine.
5186** + Store the character that terminates the field in p->cTerm. Store
5187** EOF on end-of-file.
5188** + Report syntax errors on stderr
5189*/
5190static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
5191 int c;
5192 int cSep = p->cColSep;
5193 int rSep = p->cRowSep;
5194 p->n = 0;
5195 c = fgetc(p->in);
5196 if( c==EOF || seenInterrupt ){
5197 p->cTerm = EOF;
5198 return 0;
5199 }
5200 while( c!=EOF && c!=cSep && c!=rSep ){
5201 import_append_char(p, c);
5202 c = fgetc(p->in);
5203 }
5204 if( c==rSep ){
5205 p->nLine++;
5206 }
5207 p->cTerm = c;
5208 if( p->z ) p->z[p->n] = 0;
5209 return p->z;
5210}
5211
5212/*
5213** Try to transfer data for table zTable. If an error is seen while
5214** moving forward, try to go backwards. The backwards movement won't
5215** work for WITHOUT ROWID tables.
5216*/
5217static void tryToCloneData(
5218 ShellState *p,
5219 sqlite3 *newDb,
5220 const char *zTable
5221){
5222 sqlite3_stmt *pQuery = 0;
5223 sqlite3_stmt *pInsert = 0;
5224 char *zQuery = 0;
5225 char *zInsert = 0;
5226 int rc;
5227 int i, j, n;
drhaf2770f2018-01-05 14:55:43 +00005228 int nTable = strlen30(zTable);
drh2ce15c32017-07-11 13:34:40 +00005229 int k = 0;
5230 int cnt = 0;
5231 const int spinRate = 10000;
5232
5233 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
drhe3e25652021-12-16 13:29:28 +00005234 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005235 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5236 if( rc ){
5237 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5238 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5239 zQuery);
5240 goto end_data_xfer;
5241 }
5242 n = sqlite3_column_count(pQuery);
5243 zInsert = sqlite3_malloc64(200 + nTable + n*3);
drhe3e25652021-12-16 13:29:28 +00005244 shell_check_oom(zInsert);
drh2ce15c32017-07-11 13:34:40 +00005245 sqlite3_snprintf(200+nTable,zInsert,
5246 "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
drhaf2770f2018-01-05 14:55:43 +00005247 i = strlen30(zInsert);
drh2ce15c32017-07-11 13:34:40 +00005248 for(j=1; j<n; j++){
5249 memcpy(zInsert+i, ",?", 2);
5250 i += 2;
5251 }
5252 memcpy(zInsert+i, ");", 3);
5253 rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
5254 if( rc ){
5255 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5256 sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
5257 zQuery);
5258 goto end_data_xfer;
5259 }
5260 for(k=0; k<2; k++){
5261 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5262 for(i=0; i<n; i++){
5263 switch( sqlite3_column_type(pQuery, i) ){
5264 case SQLITE_NULL: {
5265 sqlite3_bind_null(pInsert, i+1);
5266 break;
5267 }
5268 case SQLITE_INTEGER: {
5269 sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
5270 break;
5271 }
5272 case SQLITE_FLOAT: {
5273 sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
5274 break;
5275 }
5276 case SQLITE_TEXT: {
5277 sqlite3_bind_text(pInsert, i+1,
5278 (const char*)sqlite3_column_text(pQuery,i),
5279 -1, SQLITE_STATIC);
5280 break;
5281 }
5282 case SQLITE_BLOB: {
5283 sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
5284 sqlite3_column_bytes(pQuery,i),
5285 SQLITE_STATIC);
5286 break;
5287 }
5288 }
5289 } /* End for */
5290 rc = sqlite3_step(pInsert);
5291 if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
5292 utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
5293 sqlite3_errmsg(newDb));
5294 }
5295 sqlite3_reset(pInsert);
5296 cnt++;
5297 if( (cnt%spinRate)==0 ){
5298 printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
5299 fflush(stdout);
5300 }
5301 } /* End while */
5302 if( rc==SQLITE_DONE ) break;
5303 sqlite3_finalize(pQuery);
5304 sqlite3_free(zQuery);
5305 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
5306 zTable);
drhe3e25652021-12-16 13:29:28 +00005307 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005308 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5309 if( rc ){
5310 utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
5311 break;
5312 }
5313 } /* End for(k=0...) */
5314
5315end_data_xfer:
5316 sqlite3_finalize(pQuery);
5317 sqlite3_finalize(pInsert);
5318 sqlite3_free(zQuery);
5319 sqlite3_free(zInsert);
5320}
5321
5322
5323/*
5324** Try to transfer all rows of the schema that match zWhere. For
5325** each row, invoke xForEach() on the object defined by that row.
5326** If an error is encountered while moving forward through the
drh067b92b2020-06-19 15:24:12 +00005327** sqlite_schema table, try again moving backwards.
drh2ce15c32017-07-11 13:34:40 +00005328*/
5329static void tryToCloneSchema(
5330 ShellState *p,
5331 sqlite3 *newDb,
5332 const char *zWhere,
5333 void (*xForEach)(ShellState*,sqlite3*,const char*)
5334){
5335 sqlite3_stmt *pQuery = 0;
5336 char *zQuery = 0;
5337 int rc;
5338 const unsigned char *zName;
5339 const unsigned char *zSql;
5340 char *zErrMsg = 0;
5341
drh067b92b2020-06-19 15:24:12 +00005342 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005343 " WHERE %s", zWhere);
drhe3e25652021-12-16 13:29:28 +00005344 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005345 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5346 if( rc ){
5347 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5348 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5349 zQuery);
5350 goto end_schema_xfer;
5351 }
5352 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5353 zName = sqlite3_column_text(pQuery, 0);
5354 zSql = sqlite3_column_text(pQuery, 1);
drh621a5e02021-12-16 17:35:27 +00005355 if( zName==0 || zSql==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00005356 printf("%s... ", zName); fflush(stdout);
5357 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5358 if( zErrMsg ){
5359 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5360 sqlite3_free(zErrMsg);
5361 zErrMsg = 0;
5362 }
5363 if( xForEach ){
5364 xForEach(p, newDb, (const char*)zName);
5365 }
5366 printf("done\n");
5367 }
5368 if( rc!=SQLITE_DONE ){
5369 sqlite3_finalize(pQuery);
5370 sqlite3_free(zQuery);
drh067b92b2020-06-19 15:24:12 +00005371 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005372 " WHERE %s ORDER BY rowid DESC", zWhere);
drhe3e25652021-12-16 13:29:28 +00005373 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005374 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5375 if( rc ){
5376 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5377 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5378 zQuery);
5379 goto end_schema_xfer;
5380 }
drh76fc88f2021-10-02 16:39:16 +00005381 while( sqlite3_step(pQuery)==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00005382 zName = sqlite3_column_text(pQuery, 0);
5383 zSql = sqlite3_column_text(pQuery, 1);
drh621a5e02021-12-16 17:35:27 +00005384 if( zName==0 || zSql==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00005385 printf("%s... ", zName); fflush(stdout);
5386 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5387 if( zErrMsg ){
5388 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5389 sqlite3_free(zErrMsg);
5390 zErrMsg = 0;
5391 }
5392 if( xForEach ){
5393 xForEach(p, newDb, (const char*)zName);
5394 }
5395 printf("done\n");
5396 }
5397 }
5398end_schema_xfer:
5399 sqlite3_finalize(pQuery);
5400 sqlite3_free(zQuery);
5401}
5402
5403/*
5404** Open a new database file named "zNewDb". Try to recover as much information
5405** as possible out of the main database (which might be corrupt) and write it
5406** into zNewDb.
5407*/
5408static void tryToClone(ShellState *p, const char *zNewDb){
5409 int rc;
5410 sqlite3 *newDb = 0;
5411 if( access(zNewDb,0)==0 ){
5412 utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
5413 return;
5414 }
5415 rc = sqlite3_open(zNewDb, &newDb);
5416 if( rc ){
5417 utf8_printf(stderr, "Cannot create output database: %s\n",
5418 sqlite3_errmsg(newDb));
5419 }else{
5420 sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
5421 sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
5422 tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
5423 tryToCloneSchema(p, newDb, "type!='table'", 0);
5424 sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
5425 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
5426 }
drh9e804032018-05-18 17:11:50 +00005427 close_db(newDb);
drh2ce15c32017-07-11 13:34:40 +00005428}
5429
5430/*
drh13c20932018-01-10 21:41:55 +00005431** Change the output file back to stdout.
5432**
5433** If the p->doXdgOpen flag is set, that means the output was being
5434** redirected to a temporary file named by p->zTempFile. In that case,
5435** launch start/open/xdg-open on that temporary file.
drh2ce15c32017-07-11 13:34:40 +00005436*/
5437static void output_reset(ShellState *p){
5438 if( p->outfile[0]=='|' ){
5439#ifndef SQLITE_OMIT_POPEN
5440 pclose(p->out);
5441#endif
5442 }else{
5443 output_file_close(p->out);
drh04a28c32018-01-31 01:38:44 +00005444#ifndef SQLITE_NOHAVE_SYSTEM
drh13c20932018-01-10 21:41:55 +00005445 if( p->doXdgOpen ){
5446 const char *zXdgOpenCmd =
5447#if defined(_WIN32)
5448 "start";
5449#elif defined(__APPLE__)
5450 "open";
5451#else
5452 "xdg-open";
5453#endif
5454 char *zCmd;
5455 zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
drha92a01a2018-01-10 22:15:37 +00005456 if( system(zCmd) ){
5457 utf8_printf(stderr, "Failed: [%s]\n", zCmd);
drh1d9ea272020-04-17 23:46:54 +00005458 }else{
5459 /* Give the start/open/xdg-open command some time to get
5460 ** going before we continue, and potential delete the
5461 ** p->zTempFile data file out from under it */
5462 sqlite3_sleep(2000);
drha92a01a2018-01-10 22:15:37 +00005463 }
drh13c20932018-01-10 21:41:55 +00005464 sqlite3_free(zCmd);
drh3c484e82018-01-10 22:27:21 +00005465 outputModePop(p);
drh13c20932018-01-10 21:41:55 +00005466 p->doXdgOpen = 0;
5467 }
drh04a28c32018-01-31 01:38:44 +00005468#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
drh2ce15c32017-07-11 13:34:40 +00005469 }
5470 p->outfile[0] = 0;
5471 p->out = stdout;
5472}
5473
5474/*
5475** Run an SQL command and return the single integer result.
5476*/
5477static int db_int(ShellState *p, const char *zSql){
5478 sqlite3_stmt *pStmt;
5479 int res = 0;
5480 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
5481 if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
5482 res = sqlite3_column_int(pStmt,0);
5483 }
5484 sqlite3_finalize(pStmt);
5485 return res;
5486}
5487
5488/*
5489** Convert a 2-byte or 4-byte big-endian integer into a native integer
5490*/
5491static unsigned int get2byteInt(unsigned char *a){
5492 return (a[0]<<8) + a[1];
5493}
5494static unsigned int get4byteInt(unsigned char *a){
5495 return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
5496}
5497
5498/*
drh76c12062020-01-14 13:13:19 +00005499** Implementation of the ".dbinfo" command.
drh2ce15c32017-07-11 13:34:40 +00005500**
5501** Return 1 on error, 2 to exit, and 0 otherwise.
5502*/
5503static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
5504 static const struct { const char *zName; int ofst; } aField[] = {
5505 { "file change counter:", 24 },
5506 { "database page count:", 28 },
5507 { "freelist page count:", 36 },
5508 { "schema cookie:", 40 },
5509 { "schema format:", 44 },
5510 { "default cache size:", 48 },
5511 { "autovacuum top root:", 52 },
5512 { "incremental vacuum:", 64 },
5513 { "text encoding:", 56 },
5514 { "user version:", 60 },
5515 { "application id:", 68 },
5516 { "software version:", 96 },
5517 };
5518 static const struct { const char *zName; const char *zSql; } aQuery[] = {
5519 { "number of tables:",
5520 "SELECT count(*) FROM %s WHERE type='table'" },
5521 { "number of indexes:",
5522 "SELECT count(*) FROM %s WHERE type='index'" },
5523 { "number of triggers:",
5524 "SELECT count(*) FROM %s WHERE type='trigger'" },
5525 { "number of views:",
5526 "SELECT count(*) FROM %s WHERE type='view'" },
5527 { "schema size:",
5528 "SELECT total(length(sql)) FROM %s" },
5529 };
drh87c889c2019-03-20 18:22:51 +00005530 int i, rc;
drhea99a312018-07-18 19:09:07 +00005531 unsigned iDataVersion;
drh2ce15c32017-07-11 13:34:40 +00005532 char *zSchemaTab;
5533 char *zDb = nArg>=2 ? azArg[1] : "main";
drh512e6c32017-10-11 17:51:08 +00005534 sqlite3_stmt *pStmt = 0;
drh2ce15c32017-07-11 13:34:40 +00005535 unsigned char aHdr[100];
5536 open_db(p, 0);
5537 if( p->db==0 ) return 1;
drh87c889c2019-03-20 18:22:51 +00005538 rc = sqlite3_prepare_v2(p->db,
5539 "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
5540 -1, &pStmt, 0);
5541 if( rc ){
drh451f89a2020-04-28 23:09:56 +00005542 utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
drh87c889c2019-03-20 18:22:51 +00005543 sqlite3_finalize(pStmt);
5544 return 1;
5545 }
drh512e6c32017-10-11 17:51:08 +00005546 sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
5547 if( sqlite3_step(pStmt)==SQLITE_ROW
5548 && sqlite3_column_bytes(pStmt,0)>100
5549 ){
5550 memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
5551 sqlite3_finalize(pStmt);
5552 }else{
drh2ce15c32017-07-11 13:34:40 +00005553 raw_printf(stderr, "unable to read database header\n");
drh512e6c32017-10-11 17:51:08 +00005554 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00005555 return 1;
5556 }
5557 i = get2byteInt(aHdr+16);
5558 if( i==1 ) i = 65536;
5559 utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
5560 utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
5561 utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
5562 utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
5563 for(i=0; i<ArraySize(aField); i++){
5564 int ofst = aField[i].ofst;
5565 unsigned int val = get4byteInt(aHdr + ofst);
5566 utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
5567 switch( ofst ){
5568 case 56: {
5569 if( val==1 ) raw_printf(p->out, " (utf8)");
5570 if( val==2 ) raw_printf(p->out, " (utf16le)");
5571 if( val==3 ) raw_printf(p->out, " (utf16be)");
5572 }
5573 }
5574 raw_printf(p->out, "\n");
5575 }
5576 if( zDb==0 ){
drh067b92b2020-06-19 15:24:12 +00005577 zSchemaTab = sqlite3_mprintf("main.sqlite_schema");
drh2ce15c32017-07-11 13:34:40 +00005578 }else if( strcmp(zDb,"temp")==0 ){
drh067b92b2020-06-19 15:24:12 +00005579 zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
drh2ce15c32017-07-11 13:34:40 +00005580 }else{
drh067b92b2020-06-19 15:24:12 +00005581 zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
drh2ce15c32017-07-11 13:34:40 +00005582 }
5583 for(i=0; i<ArraySize(aQuery); i++){
5584 char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
5585 int val = db_int(p, zSql);
5586 sqlite3_free(zSql);
5587 utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
5588 }
5589 sqlite3_free(zSchemaTab);
drhea99a312018-07-18 19:09:07 +00005590 sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
5591 utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
drh2ce15c32017-07-11 13:34:40 +00005592 return 0;
5593}
5594
5595/*
5596** Print the current sqlite3_errmsg() value to stderr and return 1.
5597*/
5598static int shellDatabaseError(sqlite3 *db){
5599 const char *zErr = sqlite3_errmsg(db);
5600 utf8_printf(stderr, "Error: %s\n", zErr);
5601 return 1;
5602}
5603
5604/*
drh2ce15c32017-07-11 13:34:40 +00005605** Compare the pattern in zGlob[] against the text in z[]. Return TRUE
5606** if they match and FALSE (0) if they do not match.
5607**
5608** Globbing rules:
5609**
5610** '*' Matches any sequence of zero or more characters.
5611**
5612** '?' Matches exactly one character.
5613**
5614** [...] Matches one character from the enclosed list of
5615** characters.
5616**
5617** [^...] Matches one character not in the enclosed list.
5618**
5619** '#' Matches any sequence of one or more digits with an
5620** optional + or - sign in front
5621**
5622** ' ' Any span of whitespace matches any other span of
5623** whitespace.
5624**
5625** Extra whitespace at the end of z[] is ignored.
5626*/
5627static int testcase_glob(const char *zGlob, const char *z){
5628 int c, c2;
5629 int invert;
5630 int seen;
5631
5632 while( (c = (*(zGlob++)))!=0 ){
5633 if( IsSpace(c) ){
5634 if( !IsSpace(*z) ) return 0;
5635 while( IsSpace(*zGlob) ) zGlob++;
5636 while( IsSpace(*z) ) z++;
5637 }else if( c=='*' ){
5638 while( (c=(*(zGlob++))) == '*' || c=='?' ){
5639 if( c=='?' && (*(z++))==0 ) return 0;
5640 }
5641 if( c==0 ){
5642 return 1;
5643 }else if( c=='[' ){
5644 while( *z && testcase_glob(zGlob-1,z)==0 ){
5645 z++;
5646 }
5647 return (*z)!=0;
5648 }
5649 while( (c2 = (*(z++)))!=0 ){
5650 while( c2!=c ){
5651 c2 = *(z++);
5652 if( c2==0 ) return 0;
5653 }
5654 if( testcase_glob(zGlob,z) ) return 1;
5655 }
5656 return 0;
5657 }else if( c=='?' ){
5658 if( (*(z++))==0 ) return 0;
5659 }else if( c=='[' ){
5660 int prior_c = 0;
5661 seen = 0;
5662 invert = 0;
5663 c = *(z++);
5664 if( c==0 ) return 0;
5665 c2 = *(zGlob++);
5666 if( c2=='^' ){
5667 invert = 1;
5668 c2 = *(zGlob++);
5669 }
5670 if( c2==']' ){
5671 if( c==']' ) seen = 1;
5672 c2 = *(zGlob++);
5673 }
5674 while( c2 && c2!=']' ){
5675 if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
5676 c2 = *(zGlob++);
5677 if( c>=prior_c && c<=c2 ) seen = 1;
5678 prior_c = 0;
5679 }else{
5680 if( c==c2 ){
5681 seen = 1;
5682 }
5683 prior_c = c2;
5684 }
5685 c2 = *(zGlob++);
5686 }
5687 if( c2==0 || (seen ^ invert)==0 ) return 0;
5688 }else if( c=='#' ){
5689 if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++;
5690 if( !IsDigit(z[0]) ) return 0;
5691 z++;
5692 while( IsDigit(z[0]) ){ z++; }
5693 }else{
5694 if( c!=(*(z++)) ) return 0;
5695 }
5696 }
5697 while( IsSpace(*z) ){ z++; }
5698 return *z==0;
5699}
5700
5701
5702/*
5703** Compare the string as a command-line option with either one or two
5704** initial "-" characters.
5705*/
5706static int optionMatch(const char *zStr, const char *zOpt){
5707 if( zStr[0]!='-' ) return 0;
5708 zStr++;
5709 if( zStr[0]=='-' ) zStr++;
5710 return strcmp(zStr, zOpt)==0;
5711}
5712
5713/*
5714** Delete a file.
5715*/
5716int shellDeleteFile(const char *zFilename){
5717 int rc;
5718#ifdef _WIN32
5719 wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
5720 rc = _wunlink(z);
5721 sqlite3_free(z);
5722#else
5723 rc = unlink(zFilename);
5724#endif
5725 return rc;
5726}
5727
drh13c20932018-01-10 21:41:55 +00005728/*
5729** Try to delete the temporary file (if there is one) and free the
5730** memory used to hold the name of the temp file.
5731*/
5732static void clearTempFile(ShellState *p){
5733 if( p->zTempFile==0 ) return;
drh536c3452018-01-11 00:38:39 +00005734 if( p->doXdgOpen ) return;
drh13c20932018-01-10 21:41:55 +00005735 if( shellDeleteFile(p->zTempFile) ) return;
5736 sqlite3_free(p->zTempFile);
5737 p->zTempFile = 0;
5738}
5739
5740/*
5741** Create a new temp file name with the given suffix.
5742*/
5743static void newTempFile(ShellState *p, const char *zSuffix){
5744 clearTempFile(p);
5745 sqlite3_free(p->zTempFile);
5746 p->zTempFile = 0;
drh7f3bf8a2018-01-10 21:50:08 +00005747 if( p->db ){
5748 sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
5749 }
drh13c20932018-01-10 21:41:55 +00005750 if( p->zTempFile==0 ){
drh1d9ea272020-04-17 23:46:54 +00005751 /* If p->db is an in-memory database then the TEMPFILENAME file-control
5752 ** will not work and we will need to fallback to guessing */
5753 char *zTemp;
drh13c20932018-01-10 21:41:55 +00005754 sqlite3_uint64 r;
5755 sqlite3_randomness(sizeof(r), &r);
drh1d9ea272020-04-17 23:46:54 +00005756 zTemp = getenv("TEMP");
5757 if( zTemp==0 ) zTemp = getenv("TMP");
5758 if( zTemp==0 ){
5759#ifdef _WIN32
5760 zTemp = "\\tmp";
5761#else
5762 zTemp = "/tmp";
5763#endif
5764 }
5765 p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix);
drh13c20932018-01-10 21:41:55 +00005766 }else{
5767 p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
5768 }
drhe3e25652021-12-16 13:29:28 +00005769 shell_check_oom(p->zTempFile);
drh13c20932018-01-10 21:41:55 +00005770}
5771
drh2ce15c32017-07-11 13:34:40 +00005772
5773/*
5774** The implementation of SQL scalar function fkey_collate_clause(), used
5775** by the ".lint fkey-indexes" command. This scalar function is always
5776** called with four arguments - the parent table name, the parent column name,
5777** the child table name and the child column name.
5778**
5779** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
5780**
5781** If either of the named tables or columns do not exist, this function
5782** returns an empty string. An empty string is also returned if both tables
5783** and columns exist but have the same default collation sequence. Or,
5784** if both exist but the default collation sequences are different, this
5785** function returns the string " COLLATE <parent-collation>", where
5786** <parent-collation> is the default collation sequence of the parent column.
5787*/
5788static void shellFkeyCollateClause(
5789 sqlite3_context *pCtx,
5790 int nVal,
5791 sqlite3_value **apVal
5792){
5793 sqlite3 *db = sqlite3_context_db_handle(pCtx);
5794 const char *zParent;
5795 const char *zParentCol;
5796 const char *zParentSeq;
5797 const char *zChild;
5798 const char *zChildCol;
5799 const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */
5800 int rc;
5801
5802 assert( nVal==4 );
5803 zParent = (const char*)sqlite3_value_text(apVal[0]);
5804 zParentCol = (const char*)sqlite3_value_text(apVal[1]);
5805 zChild = (const char*)sqlite3_value_text(apVal[2]);
5806 zChildCol = (const char*)sqlite3_value_text(apVal[3]);
5807
5808 sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
5809 rc = sqlite3_table_column_metadata(
5810 db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0
5811 );
5812 if( rc==SQLITE_OK ){
5813 rc = sqlite3_table_column_metadata(
5814 db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0
5815 );
5816 }
5817
5818 if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){
5819 char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq);
5820 sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
5821 sqlite3_free(z);
5822 }
5823}
5824
5825
5826/*
5827** The implementation of dot-command ".lint fkey-indexes".
5828*/
5829static int lintFkeyIndexes(
5830 ShellState *pState, /* Current shell tool state */
5831 char **azArg, /* Array of arguments passed to dot command */
5832 int nArg /* Number of entries in azArg[] */
5833){
5834 sqlite3 *db = pState->db; /* Database handle to query "main" db of */
5835 FILE *out = pState->out; /* Stream to write non-error output to */
5836 int bVerbose = 0; /* If -verbose is present */
5837 int bGroupByParent = 0; /* If -groupbyparent is present */
5838 int i; /* To iterate through azArg[] */
5839 const char *zIndent = ""; /* How much to indent CREATE INDEX by */
5840 int rc; /* Return code */
5841 sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */
5842
5843 /*
5844 ** This SELECT statement returns one row for each foreign key constraint
5845 ** in the schema of the main database. The column values are:
5846 **
5847 ** 0. The text of an SQL statement similar to:
5848 **
danf9679312017-12-01 18:40:18 +00005849 ** "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?"
drh2ce15c32017-07-11 13:34:40 +00005850 **
danf9679312017-12-01 18:40:18 +00005851 ** This SELECT is similar to the one that the foreign keys implementation
5852 ** needs to run internally on child tables. If there is an index that can
drh2ce15c32017-07-11 13:34:40 +00005853 ** be used to optimize this query, then it can also be used by the FK
5854 ** implementation to optimize DELETE or UPDATE statements on the parent
5855 ** table.
5856 **
5857 ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by
5858 ** the EXPLAIN QUERY PLAN command matches this pattern, then the schema
5859 ** contains an index that can be used to optimize the query.
5860 **
5861 ** 2. Human readable text that describes the child table and columns. e.g.
5862 **
5863 ** "child_table(child_key1, child_key2)"
5864 **
5865 ** 3. Human readable text that describes the parent table and columns. e.g.
5866 **
5867 ** "parent_table(parent_key1, parent_key2)"
5868 **
5869 ** 4. A full CREATE INDEX statement for an index that could be used to
5870 ** optimize DELETE or UPDATE statements on the parent table. e.g.
5871 **
5872 ** "CREATE INDEX child_table_child_key ON child_table(child_key)"
5873 **
5874 ** 5. The name of the parent table.
5875 **
5876 ** These six values are used by the C logic below to generate the report.
5877 */
5878 const char *zSql =
5879 "SELECT "
danf9679312017-12-01 18:40:18 +00005880 " 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
drh2ce15c32017-07-11 13:34:40 +00005881 " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
5882 " || fkey_collate_clause("
5883 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
5884 ", "
drh82102332021-03-20 15:11:29 +00005885 " 'SEARCH ' || s.name || ' USING COVERING INDEX*('"
drh2ce15c32017-07-11 13:34:40 +00005886 " || group_concat('*=?', ' AND ') || ')'"
5887 ", "
5888 " s.name || '(' || group_concat(f.[from], ', ') || ')'"
5889 ", "
5890 " f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
5891 ", "
5892 " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
5893 " || ' ON ' || quote(s.name) || '('"
5894 " || group_concat(quote(f.[from]) ||"
5895 " fkey_collate_clause("
5896 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
5897 " || ');'"
5898 ", "
5899 " f.[table] "
drh067b92b2020-06-19 15:24:12 +00005900 "FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f "
drh2ce15c32017-07-11 13:34:40 +00005901 "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
5902 "GROUP BY s.name, f.id "
5903 "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
5904 ;
drh82102332021-03-20 15:11:29 +00005905 const char *zGlobIPK = "SEARCH * USING INTEGER PRIMARY KEY (rowid=?)";
drh2ce15c32017-07-11 13:34:40 +00005906
5907 for(i=2; i<nArg; i++){
drhaf2770f2018-01-05 14:55:43 +00005908 int n = strlen30(azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00005909 if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
5910 bVerbose = 1;
5911 }
5912 else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
5913 bGroupByParent = 1;
5914 zIndent = " ";
5915 }
5916 else{
5917 raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
5918 azArg[0], azArg[1]
5919 );
5920 return SQLITE_ERROR;
5921 }
5922 }
5923
5924 /* Register the fkey_collate_clause() SQL function */
5925 rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
5926 0, shellFkeyCollateClause, 0, 0
5927 );
5928
5929
5930 if( rc==SQLITE_OK ){
5931 rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
5932 }
5933 if( rc==SQLITE_OK ){
5934 sqlite3_bind_int(pSql, 1, bGroupByParent);
5935 }
5936
5937 if( rc==SQLITE_OK ){
5938 int rc2;
5939 char *zPrev = 0;
5940 while( SQLITE_ROW==sqlite3_step(pSql) ){
5941 int res = -1;
5942 sqlite3_stmt *pExplain = 0;
5943 const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
5944 const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
5945 const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
5946 const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
5947 const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
5948 const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
5949
drh621a5e02021-12-16 17:35:27 +00005950 if( zEQP==0 ) continue;
5951 if( zGlob==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00005952 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
5953 if( rc!=SQLITE_OK ) break;
5954 if( SQLITE_ROW==sqlite3_step(pExplain) ){
5955 const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
drh621a5e02021-12-16 17:35:27 +00005956 res = zPlan!=0 && ( 0==sqlite3_strglob(zGlob, zPlan)
5957 || 0==sqlite3_strglob(zGlobIPK, zPlan));
drh2ce15c32017-07-11 13:34:40 +00005958 }
5959 rc = sqlite3_finalize(pExplain);
5960 if( rc!=SQLITE_OK ) break;
5961
5962 if( res<0 ){
5963 raw_printf(stderr, "Error: internal error");
5964 break;
5965 }else{
5966 if( bGroupByParent
5967 && (bVerbose || res==0)
5968 && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
5969 ){
5970 raw_printf(out, "-- Parent table %s\n", zParent);
5971 sqlite3_free(zPrev);
5972 zPrev = sqlite3_mprintf("%s", zParent);
5973 }
5974
5975 if( res==0 ){
5976 raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
5977 }else if( bVerbose ){
5978 raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
5979 zIndent, zFrom, zTarget
5980 );
5981 }
5982 }
5983 }
5984 sqlite3_free(zPrev);
5985
5986 if( rc!=SQLITE_OK ){
5987 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
5988 }
5989
5990 rc2 = sqlite3_finalize(pSql);
5991 if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
5992 rc = rc2;
5993 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
5994 }
5995 }else{
5996 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
5997 }
5998
5999 return rc;
6000}
6001
6002/*
6003** Implementation of ".lint" dot command.
6004*/
6005static int lintDotCommand(
6006 ShellState *pState, /* Current shell tool state */
6007 char **azArg, /* Array of arguments passed to dot command */
6008 int nArg /* Number of entries in azArg[] */
6009){
6010 int n;
drhaf2770f2018-01-05 14:55:43 +00006011 n = (nArg>=2 ? strlen30(azArg[1]) : 0);
drh2ce15c32017-07-11 13:34:40 +00006012 if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
6013 return lintFkeyIndexes(pState, azArg, nArg);
6014
6015 usage:
6016 raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
6017 raw_printf(stderr, "Where sub-commands are:\n");
6018 raw_printf(stderr, " fkey-indexes\n");
6019 return SQLITE_ERROR;
6020}
6021
dan1b162162019-04-27 20:15:15 +00006022#if !defined SQLITE_OMIT_VIRTUALTABLE
danfd0245d2017-12-07 15:44:29 +00006023static void shellPrepare(
dand4b56e52017-12-12 20:04:59 +00006024 sqlite3 *db,
danfd0245d2017-12-07 15:44:29 +00006025 int *pRc,
6026 const char *zSql,
6027 sqlite3_stmt **ppStmt
6028){
6029 *ppStmt = 0;
6030 if( *pRc==SQLITE_OK ){
dand4b56e52017-12-12 20:04:59 +00006031 int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
danfd0245d2017-12-07 15:44:29 +00006032 if( rc!=SQLITE_OK ){
6033 raw_printf(stderr, "sql error: %s (%d)\n",
dand4b56e52017-12-12 20:04:59 +00006034 sqlite3_errmsg(db), sqlite3_errcode(db)
danfd0245d2017-12-07 15:44:29 +00006035 );
6036 *pRc = rc;
6037 }
6038 }
6039}
6040
drh9546c762019-05-10 17:50:33 +00006041/*
6042** Create a prepared statement using printf-style arguments for the SQL.
6043**
6044** This routine is could be marked "static". But it is not always used,
6045** depending on compile-time options. By omitting the "static", we avoid
6046** nuisance compiler warnings about "defined but not used".
6047*/
6048void shellPreparePrintf(
dan3f67ddf2017-12-13 20:04:53 +00006049 sqlite3 *db,
6050 int *pRc,
danac15e2d2017-12-14 19:15:07 +00006051 sqlite3_stmt **ppStmt,
6052 const char *zFmt,
6053 ...
dan3f67ddf2017-12-13 20:04:53 +00006054){
danac15e2d2017-12-14 19:15:07 +00006055 *ppStmt = 0;
6056 if( *pRc==SQLITE_OK ){
6057 va_list ap;
6058 char *z;
6059 va_start(ap, zFmt);
6060 z = sqlite3_vmprintf(zFmt, ap);
drh1dbb1472018-10-11 10:37:24 +00006061 va_end(ap);
dan3f67ddf2017-12-13 20:04:53 +00006062 if( z==0 ){
6063 *pRc = SQLITE_NOMEM;
6064 }else{
6065 shellPrepare(db, pRc, z, ppStmt);
6066 sqlite3_free(z);
6067 }
dan3f67ddf2017-12-13 20:04:53 +00006068 }
6069}
6070
drh9546c762019-05-10 17:50:33 +00006071/* Finalize the prepared statement created using shellPreparePrintf().
6072**
6073** This routine is could be marked "static". But it is not always used,
6074** depending on compile-time options. By omitting the "static", we avoid
6075** nuisance compiler warnings about "defined but not used".
6076*/
6077void shellFinalize(
danfd0245d2017-12-07 15:44:29 +00006078 int *pRc,
6079 sqlite3_stmt *pStmt
6080){
dan25c12182017-12-07 21:03:33 +00006081 if( pStmt ){
6082 sqlite3 *db = sqlite3_db_handle(pStmt);
6083 int rc = sqlite3_finalize(pStmt);
6084 if( *pRc==SQLITE_OK ){
6085 if( rc!=SQLITE_OK ){
6086 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
6087 }
6088 *pRc = rc;
6089 }
6090 }
danfd0245d2017-12-07 15:44:29 +00006091}
6092
drh9546c762019-05-10 17:50:33 +00006093/* Reset the prepared statement created using shellPreparePrintf().
6094**
6095** This routine is could be marked "static". But it is not always used,
6096** depending on compile-time options. By omitting the "static", we avoid
6097** nuisance compiler warnings about "defined but not used".
6098*/
6099void shellReset(
danfd0245d2017-12-07 15:44:29 +00006100 int *pRc,
6101 sqlite3_stmt *pStmt
6102){
6103 int rc = sqlite3_reset(pStmt);
dan5a78b812017-12-27 18:54:11 +00006104 if( *pRc==SQLITE_OK ){
6105 if( rc!=SQLITE_OK ){
6106 sqlite3 *db = sqlite3_db_handle(pStmt);
6107 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
6108 }
6109 *pRc = rc;
6110 }
danfd0245d2017-12-07 15:44:29 +00006111}
dan1b162162019-04-27 20:15:15 +00006112#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
6113
6114#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drhe2754c12019-08-26 12:50:01 +00006115/******************************************************************************
dan1b162162019-04-27 20:15:15 +00006116** The ".archive" or ".ar" command.
6117*/
drhe37c0e12018-01-06 19:19:50 +00006118/*
dan88be0202017-12-09 17:58:02 +00006119** Structure representing a single ".ar" command.
6120*/
6121typedef struct ArCommand ArCommand;
6122struct ArCommand {
drhb376b3d2018-01-10 13:11:51 +00006123 u8 eCmd; /* An AR_CMD_* value */
6124 u8 bVerbose; /* True if --verbose */
drha5676c42018-01-10 15:17:34 +00006125 u8 bZip; /* True if the archive is a ZIP */
drhb376b3d2018-01-10 13:11:51 +00006126 u8 bDryRun; /* True if --dry-run */
drha5676c42018-01-10 15:17:34 +00006127 u8 bAppend; /* True if --append */
larrybr8f09f4b2021-11-02 00:18:11 +00006128 u8 bGlob; /* True if --glob */
drhd0f9cdc2018-05-17 14:09:06 +00006129 u8 fromCmdLine; /* Run from -A instead of .archive */
drhb376b3d2018-01-10 13:11:51 +00006130 int nArg; /* Number of command arguments */
drha5676c42018-01-10 15:17:34 +00006131 char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
dan88be0202017-12-09 17:58:02 +00006132 const char *zFile; /* --file argument, or NULL */
6133 const char *zDir; /* --directory argument, or NULL */
dan88be0202017-12-09 17:58:02 +00006134 char **azArg; /* Array of command arguments */
drhb376b3d2018-01-10 13:11:51 +00006135 ShellState *p; /* Shell state */
6136 sqlite3 *db; /* Database containing the archive */
dan88be0202017-12-09 17:58:02 +00006137};
6138
6139/*
6140** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
6141*/
dan0d0547f2017-12-14 15:40:42 +00006142static int arUsage(FILE *f){
drh98aa2ab2018-09-26 16:53:51 +00006143 showHelp(f,"archive");
dan0d0547f2017-12-14 15:40:42 +00006144 return SQLITE_ERROR;
6145}
6146
6147/*
6148** Print an error message for the .ar command to stderr and return
6149** SQLITE_ERROR.
6150*/
drhd0f9cdc2018-05-17 14:09:06 +00006151static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
dan0d0547f2017-12-14 15:40:42 +00006152 va_list ap;
6153 char *z;
6154 va_start(ap, zFmt);
6155 z = sqlite3_vmprintf(zFmt, ap);
6156 va_end(ap);
drhd0f9cdc2018-05-17 14:09:06 +00006157 utf8_printf(stderr, "Error: %s\n", z);
6158 if( pAr->fromCmdLine ){
6159 utf8_printf(stderr, "Use \"-A\" for more help\n");
6160 }else{
6161 utf8_printf(stderr, "Use \".archive --help\" for more help\n");
6162 }
dan0d0547f2017-12-14 15:40:42 +00006163 sqlite3_free(z);
dan88be0202017-12-09 17:58:02 +00006164 return SQLITE_ERROR;
6165}
6166
6167/*
6168** Values for ArCommand.eCmd.
6169*/
dand4b56e52017-12-12 20:04:59 +00006170#define AR_CMD_CREATE 1
drhb17ea912019-03-25 14:24:19 +00006171#define AR_CMD_UPDATE 2
6172#define AR_CMD_INSERT 3
6173#define AR_CMD_EXTRACT 4
6174#define AR_CMD_LIST 5
6175#define AR_CMD_HELP 6
larrybr47061b92021-11-01 17:22:52 +00006176#define AR_CMD_REMOVE 7
dand4b56e52017-12-12 20:04:59 +00006177
6178/*
6179** Other (non-command) switches.
6180*/
larrybr47061b92021-11-01 17:22:52 +00006181#define AR_SWITCH_VERBOSE 8
6182#define AR_SWITCH_FILE 9
6183#define AR_SWITCH_DIRECTORY 10
6184#define AR_SWITCH_APPEND 11
larrybr719506f2021-11-01 22:33:20 +00006185#define AR_SWITCH_DRYRUN 12
larrybr8f09f4b2021-11-02 00:18:11 +00006186#define AR_SWITCH_GLOB 13
dand4b56e52017-12-12 20:04:59 +00006187
6188static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
6189 switch( eSwitch ){
6190 case AR_CMD_CREATE:
6191 case AR_CMD_EXTRACT:
6192 case AR_CMD_LIST:
larrybr47061b92021-11-01 17:22:52 +00006193 case AR_CMD_REMOVE:
dand4b56e52017-12-12 20:04:59 +00006194 case AR_CMD_UPDATE:
drhb17ea912019-03-25 14:24:19 +00006195 case AR_CMD_INSERT:
dan0d0547f2017-12-14 15:40:42 +00006196 case AR_CMD_HELP:
6197 if( pAr->eCmd ){
drhd0f9cdc2018-05-17 14:09:06 +00006198 return arErrorMsg(pAr, "multiple command options");
dan0d0547f2017-12-14 15:40:42 +00006199 }
dand4b56e52017-12-12 20:04:59 +00006200 pAr->eCmd = eSwitch;
6201 break;
6202
drhb376b3d2018-01-10 13:11:51 +00006203 case AR_SWITCH_DRYRUN:
6204 pAr->bDryRun = 1;
6205 break;
larrybr8f09f4b2021-11-02 00:18:11 +00006206 case AR_SWITCH_GLOB:
6207 pAr->bGlob = 1;
6208 break;
dand4b56e52017-12-12 20:04:59 +00006209 case AR_SWITCH_VERBOSE:
6210 pAr->bVerbose = 1;
6211 break;
drha5676c42018-01-10 15:17:34 +00006212 case AR_SWITCH_APPEND:
6213 pAr->bAppend = 1;
drhca7733b2018-01-10 18:09:20 +00006214 /* Fall thru into --file */
dand4b56e52017-12-12 20:04:59 +00006215 case AR_SWITCH_FILE:
6216 pAr->zFile = zArg;
6217 break;
6218 case AR_SWITCH_DIRECTORY:
6219 pAr->zDir = zArg;
6220 break;
6221 }
6222
6223 return SQLITE_OK;
6224}
dan88be0202017-12-09 17:58:02 +00006225
6226/*
6227** Parse the command line for an ".ar" command. The results are written into
6228** structure (*pAr). SQLITE_OK is returned if the command line is parsed
6229** successfully, otherwise an error message is written to stderr and
6230** SQLITE_ERROR returned.
6231*/
6232static int arParseCommand(
6233 char **azArg, /* Array of arguments passed to dot command */
6234 int nArg, /* Number of entries in azArg[] */
6235 ArCommand *pAr /* Populate this object */
6236){
dand4b56e52017-12-12 20:04:59 +00006237 struct ArSwitch {
dand4b56e52017-12-12 20:04:59 +00006238 const char *zLong;
drhb376b3d2018-01-10 13:11:51 +00006239 char cShort;
6240 u8 eSwitch;
6241 u8 bArg;
dand4b56e52017-12-12 20:04:59 +00006242 } aSwitch[] = {
drhb376b3d2018-01-10 13:11:51 +00006243 { "create", 'c', AR_CMD_CREATE, 0 },
6244 { "extract", 'x', AR_CMD_EXTRACT, 0 },
drhb17ea912019-03-25 14:24:19 +00006245 { "insert", 'i', AR_CMD_INSERT, 0 },
drhb376b3d2018-01-10 13:11:51 +00006246 { "list", 't', AR_CMD_LIST, 0 },
larrybr47061b92021-11-01 17:22:52 +00006247 { "remove", 'r', AR_CMD_REMOVE, 0 },
drhb376b3d2018-01-10 13:11:51 +00006248 { "update", 'u', AR_CMD_UPDATE, 0 },
6249 { "help", 'h', AR_CMD_HELP, 0 },
6250 { "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
6251 { "file", 'f', AR_SWITCH_FILE, 1 },
drhca7733b2018-01-10 18:09:20 +00006252 { "append", 'a', AR_SWITCH_APPEND, 1 },
drhb376b3d2018-01-10 13:11:51 +00006253 { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
drhb376b3d2018-01-10 13:11:51 +00006254 { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
larrybr8f09f4b2021-11-02 00:18:11 +00006255 { "glob", 'g', AR_SWITCH_GLOB, 0 },
dand4b56e52017-12-12 20:04:59 +00006256 };
6257 int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
6258 struct ArSwitch *pEnd = &aSwitch[nSwitch];
6259
dan88be0202017-12-09 17:58:02 +00006260 if( nArg<=1 ){
drh98aa2ab2018-09-26 16:53:51 +00006261 utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
dan0d0547f2017-12-14 15:40:42 +00006262 return arUsage(stderr);
dan88be0202017-12-09 17:58:02 +00006263 }else{
6264 char *z = azArg[1];
dan88be0202017-12-09 17:58:02 +00006265 if( z[0]!='-' ){
6266 /* Traditional style [tar] invocation */
6267 int i;
6268 int iArg = 2;
6269 for(i=0; z[i]; i++){
dand4b56e52017-12-12 20:04:59 +00006270 const char *zArg = 0;
6271 struct ArSwitch *pOpt;
6272 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6273 if( z[i]==pOpt->cShort ) break;
dan88be0202017-12-09 17:58:02 +00006274 }
dan0d0547f2017-12-14 15:40:42 +00006275 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006276 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006277 }
dand4b56e52017-12-12 20:04:59 +00006278 if( pOpt->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006279 if( iArg>=nArg ){
drhd0f9cdc2018-05-17 14:09:06 +00006280 return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
dan0d0547f2017-12-14 15:40:42 +00006281 }
dand4b56e52017-12-12 20:04:59 +00006282 zArg = azArg[iArg++];
6283 }
6284 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
dan88be0202017-12-09 17:58:02 +00006285 }
dan88be0202017-12-09 17:58:02 +00006286 pAr->nArg = nArg-iArg;
6287 if( pAr->nArg>0 ){
6288 pAr->azArg = &azArg[iArg];
6289 }
dand4b56e52017-12-12 20:04:59 +00006290 }else{
6291 /* Non-traditional invocation */
6292 int iArg;
6293 for(iArg=1; iArg<nArg; iArg++){
6294 int n;
6295 z = azArg[iArg];
6296 if( z[0]!='-' ){
6297 /* All remaining command line words are command arguments. */
6298 pAr->azArg = &azArg[iArg];
6299 pAr->nArg = nArg-iArg;
6300 break;
6301 }
drhaf2770f2018-01-05 14:55:43 +00006302 n = strlen30(z);
dand4b56e52017-12-12 20:04:59 +00006303
6304 if( z[1]!='-' ){
6305 int i;
6306 /* One or more short options */
6307 for(i=1; i<n; i++){
6308 const char *zArg = 0;
6309 struct ArSwitch *pOpt;
6310 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6311 if( z[i]==pOpt->cShort ) break;
6312 }
dan0d0547f2017-12-14 15:40:42 +00006313 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006314 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006315 }
dand4b56e52017-12-12 20:04:59 +00006316 if( pOpt->bArg ){
6317 if( i<(n-1) ){
6318 zArg = &z[i+1];
6319 i = n;
6320 }else{
dan0d0547f2017-12-14 15:40:42 +00006321 if( iArg>=(nArg-1) ){
drhe2754c12019-08-26 12:50:01 +00006322 return arErrorMsg(pAr, "option requires an argument: %c",
6323 z[i]);
dan0d0547f2017-12-14 15:40:42 +00006324 }
dand4b56e52017-12-12 20:04:59 +00006325 zArg = azArg[++iArg];
6326 }
6327 }
6328 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
6329 }
6330 }else if( z[2]=='\0' ){
6331 /* A -- option, indicating that all remaining command line words
6332 ** are command arguments. */
6333 pAr->azArg = &azArg[iArg+1];
6334 pAr->nArg = nArg-iArg-1;
6335 break;
6336 }else{
6337 /* A long option */
6338 const char *zArg = 0; /* Argument for option, if any */
6339 struct ArSwitch *pMatch = 0; /* Matching option */
6340 struct ArSwitch *pOpt; /* Iterator */
6341 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6342 const char *zLong = pOpt->zLong;
drhaf2770f2018-01-05 14:55:43 +00006343 if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
dand4b56e52017-12-12 20:04:59 +00006344 if( pMatch ){
drhd0f9cdc2018-05-17 14:09:06 +00006345 return arErrorMsg(pAr, "ambiguous option: %s",z);
dand4b56e52017-12-12 20:04:59 +00006346 }else{
6347 pMatch = pOpt;
6348 }
6349 }
6350 }
6351
6352 if( pMatch==0 ){
drhd0f9cdc2018-05-17 14:09:06 +00006353 return arErrorMsg(pAr, "unrecognized option: %s", z);
dand4b56e52017-12-12 20:04:59 +00006354 }
6355 if( pMatch->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006356 if( iArg>=(nArg-1) ){
drhd0f9cdc2018-05-17 14:09:06 +00006357 return arErrorMsg(pAr, "option requires an argument: %s", z);
dan0d0547f2017-12-14 15:40:42 +00006358 }
dand4b56e52017-12-12 20:04:59 +00006359 zArg = azArg[++iArg];
6360 }
6361 if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
6362 }
6363 }
dan88be0202017-12-09 17:58:02 +00006364 }
6365 }
6366
6367 return SQLITE_OK;
6368}
6369
6370/*
dan3f67ddf2017-12-13 20:04:53 +00006371** This function assumes that all arguments within the ArCommand.azArg[]
larrybr47061b92021-11-01 17:22:52 +00006372** array refer to archive members, as for the --extract, --list or --remove
larrybr8f09f4b2021-11-02 00:18:11 +00006373** commands. It checks that each of them are "present". If any specified
6374** file is not present in the archive, an error is printed to stderr and an
larrybr47061b92021-11-01 17:22:52 +00006375** error code returned. Otherwise, if all specified arguments are present
larrybr8f09f4b2021-11-02 00:18:11 +00006376** in the archive, SQLITE_OK is returned. Here, "present" means either an
6377** exact equality when pAr->bGlob is false or a "name GLOB pattern" match
drh0c0fb9c2021-11-02 10:54:39 +00006378** when pAr->bGlob is true.
dan3f67ddf2017-12-13 20:04:53 +00006379**
6380** This function strips any trailing '/' characters from each argument.
6381** This is consistent with the way the [tar] command seems to work on
6382** Linux.
6383*/
drhb376b3d2018-01-10 13:11:51 +00006384static int arCheckEntries(ArCommand *pAr){
dan3f67ddf2017-12-13 20:04:53 +00006385 int rc = SQLITE_OK;
6386 if( pAr->nArg ){
drhb376b3d2018-01-10 13:11:51 +00006387 int i, j;
dan3f67ddf2017-12-13 20:04:53 +00006388 sqlite3_stmt *pTest = 0;
larrybr8f09f4b2021-11-02 00:18:11 +00006389 const char *zSel = (pAr->bGlob)
6390 ? "SELECT name FROM %s WHERE glob($name,name)"
6391 : "SELECT name FROM %s WHERE name=$name";
dan3f67ddf2017-12-13 20:04:53 +00006392
larrybr8f09f4b2021-11-02 00:18:11 +00006393 shellPreparePrintf(pAr->db, &rc, &pTest, zSel, pAr->zSrcTable);
drhb376b3d2018-01-10 13:11:51 +00006394 j = sqlite3_bind_parameter_index(pTest, "$name");
dan3f67ddf2017-12-13 20:04:53 +00006395 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
6396 char *z = pAr->azArg[i];
drhaf2770f2018-01-05 14:55:43 +00006397 int n = strlen30(z);
dan3f67ddf2017-12-13 20:04:53 +00006398 int bOk = 0;
6399 while( n>0 && z[n-1]=='/' ) n--;
6400 z[n] = '\0';
drhb376b3d2018-01-10 13:11:51 +00006401 sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
dan3f67ddf2017-12-13 20:04:53 +00006402 if( SQLITE_ROW==sqlite3_step(pTest) ){
6403 bOk = 1;
6404 }
6405 shellReset(&rc, pTest);
6406 if( rc==SQLITE_OK && bOk==0 ){
drhb376b3d2018-01-10 13:11:51 +00006407 utf8_printf(stderr, "not found in archive: %s\n", z);
dan3f67ddf2017-12-13 20:04:53 +00006408 rc = SQLITE_ERROR;
6409 }
6410 }
6411 shellFinalize(&rc, pTest);
6412 }
dan3f67ddf2017-12-13 20:04:53 +00006413 return rc;
6414}
6415
6416/*
6417** Format a WHERE clause that can be used against the "sqlar" table to
6418** identify all archive members that match the command arguments held
6419** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
6420** The caller is responsible for eventually calling sqlite3_free() on
larrybr8f09f4b2021-11-02 00:18:11 +00006421** any non-NULL (*pzWhere) value. Here, "match" means strict equality
6422** when pAr->bGlob is false and GLOB match when pAr->bGlob is true.
dan3f67ddf2017-12-13 20:04:53 +00006423*/
6424static void arWhereClause(
6425 int *pRc,
larrybr8f09f4b2021-11-02 00:18:11 +00006426 ArCommand *pAr,
danac15e2d2017-12-14 19:15:07 +00006427 char **pzWhere /* OUT: New WHERE clause */
dan3f67ddf2017-12-13 20:04:53 +00006428){
6429 char *zWhere = 0;
larrybr8f09f4b2021-11-02 00:18:11 +00006430 const char *zSameOp = (pAr->bGlob)? "GLOB" : "=";
dan3f67ddf2017-12-13 20:04:53 +00006431 if( *pRc==SQLITE_OK ){
danac15e2d2017-12-14 19:15:07 +00006432 if( pAr->nArg==0 ){
6433 zWhere = sqlite3_mprintf("1");
6434 }else{
6435 int i;
6436 const char *zSep = "";
6437 for(i=0; i<pAr->nArg; i++){
6438 const char *z = pAr->azArg[i];
6439 zWhere = sqlite3_mprintf(
larrybr8f09f4b2021-11-02 00:18:11 +00006440 "%z%s name %s '%q' OR substr(name,1,%d) %s '%q/'",
6441 zWhere, zSep, zSameOp, z, strlen30(z)+1, zSameOp, z
drhb376b3d2018-01-10 13:11:51 +00006442 );
danac15e2d2017-12-14 19:15:07 +00006443 if( zWhere==0 ){
6444 *pRc = SQLITE_NOMEM;
6445 break;
6446 }
6447 zSep = " OR ";
dan3f67ddf2017-12-13 20:04:53 +00006448 }
dan3f67ddf2017-12-13 20:04:53 +00006449 }
6450 }
6451 *pzWhere = zWhere;
6452}
6453
6454/*
dan88be0202017-12-09 17:58:02 +00006455** Implementation of .ar "lisT" command.
6456*/
drhb376b3d2018-01-10 13:11:51 +00006457static int arListCommand(ArCommand *pAr){
danb5090e42017-12-27 21:13:21 +00006458 const char *zSql = "SELECT %s FROM %s WHERE %s";
danb5090e42017-12-27 21:13:21 +00006459 const char *azCols[] = {
6460 "name",
drh410cad92018-01-10 17:19:16 +00006461 "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
danb5090e42017-12-27 21:13:21 +00006462 };
dan5a78b812017-12-27 18:54:11 +00006463
dan3f67ddf2017-12-13 20:04:53 +00006464 char *zWhere = 0;
6465 sqlite3_stmt *pSql = 0;
6466 int rc;
6467
drhb376b3d2018-01-10 13:11:51 +00006468 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006469 arWhereClause(&rc, pAr, &zWhere);
6470
drhb376b3d2018-01-10 13:11:51 +00006471 shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
6472 pAr->zSrcTable, zWhere);
drhb376b3d2018-01-10 13:11:51 +00006473 if( pAr->bDryRun ){
6474 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
6475 }else{
6476 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
6477 if( pAr->bVerbose ){
drh410cad92018-01-10 17:19:16 +00006478 utf8_printf(pAr->p->out, "%s % 10d %s %s\n",
6479 sqlite3_column_text(pSql, 0),
drhb376b3d2018-01-10 13:11:51 +00006480 sqlite3_column_int(pSql, 1),
6481 sqlite3_column_text(pSql, 2),
6482 sqlite3_column_text(pSql, 3)
6483 );
6484 }else{
6485 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
6486 }
danb5090e42017-12-27 21:13:21 +00006487 }
dan3f67ddf2017-12-13 20:04:53 +00006488 }
dan5a78b812017-12-27 18:54:11 +00006489 shellFinalize(&rc, pSql);
drhd0f9cdc2018-05-17 14:09:06 +00006490 sqlite3_free(zWhere);
dan3f67ddf2017-12-13 20:04:53 +00006491 return rc;
dan88be0202017-12-09 17:58:02 +00006492}
6493
6494
danfd0245d2017-12-07 15:44:29 +00006495/*
larrybr47061b92021-11-01 17:22:52 +00006496** Implementation of .ar "Remove" command.
6497*/
6498static int arRemoveCommand(ArCommand *pAr){
larrybr7774fc02021-11-01 22:30:24 +00006499 int rc = 0;
larrybr47061b92021-11-01 17:22:52 +00006500 char *zSql = 0;
6501 char *zWhere = 0;
6502
6503 if( pAr->nArg ){
6504 /* Verify that args actually exist within the archive before proceeding.
6505 ** And formulate a WHERE clause to match them. */
6506 rc = arCheckEntries(pAr);
6507 arWhereClause(&rc, pAr, &zWhere);
6508 }
6509 if( rc==SQLITE_OK ){
6510 zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;",
6511 pAr->zSrcTable, zWhere);
6512 if( pAr->bDryRun ){
6513 utf8_printf(pAr->p->out, "%s\n", zSql);
6514 }else{
6515 char *zErr = 0;
6516 rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0);
6517 if( rc==SQLITE_OK ){
6518 rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
6519 if( rc!=SQLITE_OK ){
6520 sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
6521 }else{
6522 rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0);
6523 }
6524 }
6525 if( zErr ){
6526 utf8_printf(stdout, "ERROR: %s\n", zErr);
6527 sqlite3_free(zErr);
6528 }
6529 }
6530 }
6531 sqlite3_free(zWhere);
6532 sqlite3_free(zSql);
6533 return rc;
6534}
6535
6536/*
danfd0245d2017-12-07 15:44:29 +00006537** Implementation of .ar "eXtract" command.
6538*/
drhb376b3d2018-01-10 13:11:51 +00006539static int arExtractCommand(ArCommand *pAr){
dan25c12182017-12-07 21:03:33 +00006540 const char *zSql1 =
dand1b51d42017-12-16 19:11:26 +00006541 "SELECT "
drhb376b3d2018-01-10 13:11:51 +00006542 " ($dir || name),"
6543 " writefile(($dir || name), %s, mode, mtime) "
drh0cfd46a2018-06-06 01:18:01 +00006544 "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
6545 " AND name NOT GLOB '*..[/\\]*'";
dan5a78b812017-12-27 18:54:11 +00006546
6547 const char *azExtraArg[] = {
6548 "sqlar_uncompress(data, sz)",
dan7c15ac12018-01-08 19:59:59 +00006549 "data"
dan5a78b812017-12-27 18:54:11 +00006550 };
dan5a78b812017-12-27 18:54:11 +00006551
danfd0245d2017-12-07 15:44:29 +00006552 sqlite3_stmt *pSql = 0;
6553 int rc = SQLITE_OK;
dan2ad09492017-12-09 18:28:22 +00006554 char *zDir = 0;
dan3f67ddf2017-12-13 20:04:53 +00006555 char *zWhere = 0;
drhb376b3d2018-01-10 13:11:51 +00006556 int i, j;
dan2ad09492017-12-09 18:28:22 +00006557
dan3f67ddf2017-12-13 20:04:53 +00006558 /* If arguments are specified, check that they actually exist within
6559 ** the archive before proceeding. And formulate a WHERE clause to
6560 ** match them. */
drhb376b3d2018-01-10 13:11:51 +00006561 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006562 arWhereClause(&rc, pAr, &zWhere);
6563
6564 if( rc==SQLITE_OK ){
6565 if( pAr->zDir ){
6566 zDir = sqlite3_mprintf("%s/", pAr->zDir);
6567 }else{
6568 zDir = sqlite3_mprintf("");
6569 }
6570 if( zDir==0 ) rc = SQLITE_NOMEM;
dan2ad09492017-12-09 18:28:22 +00006571 }
danfd0245d2017-12-07 15:44:29 +00006572
drhb376b3d2018-01-10 13:11:51 +00006573 shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
6574 azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
dan5a78b812017-12-27 18:54:11 +00006575 );
6576
dan2ad09492017-12-09 18:28:22 +00006577 if( rc==SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00006578 j = sqlite3_bind_parameter_index(pSql, "$dir");
6579 sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
dan25c12182017-12-07 21:03:33 +00006580
danac15e2d2017-12-14 19:15:07 +00006581 /* Run the SELECT statement twice. The first time, writefile() is called
6582 ** for all archive members that should be extracted. The second time,
6583 ** only for the directories. This is because the timestamps for
6584 ** extracted directories must be reset after they are populated (as
6585 ** populating them changes the timestamp). */
6586 for(i=0; i<2; i++){
drhb376b3d2018-01-10 13:11:51 +00006587 j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
6588 sqlite3_bind_int(pSql, j, i);
6589 if( pAr->bDryRun ){
6590 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
6591 }else{
6592 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
6593 if( i==0 && pAr->bVerbose ){
6594 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
6595 }
danac15e2d2017-12-14 19:15:07 +00006596 }
6597 }
6598 shellReset(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00006599 }
danac15e2d2017-12-14 19:15:07 +00006600 shellFinalize(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00006601 }
dan25c12182017-12-07 21:03:33 +00006602
dan2ad09492017-12-09 18:28:22 +00006603 sqlite3_free(zDir);
dan3f67ddf2017-12-13 20:04:53 +00006604 sqlite3_free(zWhere);
danfd0245d2017-12-07 15:44:29 +00006605 return rc;
6606}
6607
drhb376b3d2018-01-10 13:11:51 +00006608/*
6609** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out.
6610*/
6611static int arExecSql(ArCommand *pAr, const char *zSql){
6612 int rc;
6613 if( pAr->bDryRun ){
6614 utf8_printf(pAr->p->out, "%s\n", zSql);
6615 rc = SQLITE_OK;
6616 }else{
drh410cad92018-01-10 17:19:16 +00006617 char *zErr = 0;
6618 rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
6619 if( zErr ){
6620 utf8_printf(stdout, "ERROR: %s\n", zErr);
6621 sqlite3_free(zErr);
6622 }
drhb376b3d2018-01-10 13:11:51 +00006623 }
6624 return rc;
6625}
6626
dan1ad3f612017-12-11 20:22:02 +00006627
danfd0245d2017-12-07 15:44:29 +00006628/*
drhb17ea912019-03-25 14:24:19 +00006629** Implementation of .ar "create", "insert", and "update" commands.
6630**
6631** create -> Create a new SQL archive
6632** insert -> Insert or reinsert all files listed
6633** update -> Insert files that have changed or that were not
6634** previously in the archive
danfd0245d2017-12-07 15:44:29 +00006635**
6636** Create the "sqlar" table in the database if it does not already exist.
6637** Then add each file in the azFile[] array to the archive. Directories
6638** are added recursively. If argument bVerbose is non-zero, a message is
6639** printed on stdout for each file archived.
dan06741a32017-12-13 20:17:18 +00006640**
6641** The create command is the same as update, except that it drops
drhb17ea912019-03-25 14:24:19 +00006642** any existing "sqlar" table before beginning. The "insert" command
6643** always overwrites every file named on the command-line, where as
6644** "update" only overwrites if the size or mtime or mode has changed.
danfd0245d2017-12-07 15:44:29 +00006645*/
drhb376b3d2018-01-10 13:11:51 +00006646static int arCreateOrUpdateCommand(
dan06741a32017-12-13 20:17:18 +00006647 ArCommand *pAr, /* Command arguments and options */
drhb17ea912019-03-25 14:24:19 +00006648 int bUpdate, /* true for a --create. */
6649 int bOnlyIfChanged /* Only update if file has changed */
danfd0245d2017-12-07 15:44:29 +00006650){
dand4b56e52017-12-12 20:04:59 +00006651 const char *zCreate =
drhafba1802018-01-06 15:49:57 +00006652 "CREATE TABLE IF NOT EXISTS sqlar(\n"
6653 " name TEXT PRIMARY KEY, -- name of the file\n"
6654 " mode INT, -- access permissions\n"
6655 " mtime INT, -- last modification time\n"
6656 " sz INT, -- original file size\n"
6657 " data BLOB -- compressed content\n"
6658 ")";
dand4b56e52017-12-12 20:04:59 +00006659 const char *zDrop = "DROP TABLE IF EXISTS sqlar";
drh1bf208c2018-03-09 21:54:01 +00006660 const char *zInsertFmt[2] = {
6661 "REPLACE INTO %s(name,mode,mtime,sz,data)\n"
drh634c70f2018-01-10 16:50:18 +00006662 " SELECT\n"
6663 " %s,\n"
6664 " mode,\n"
6665 " mtime,\n"
drh410cad92018-01-10 17:19:16 +00006666 " CASE substr(lsmode(mode),1,1)\n"
6667 " WHEN '-' THEN length(data)\n"
6668 " WHEN 'd' THEN 0\n"
drh634c70f2018-01-10 16:50:18 +00006669 " ELSE -1 END,\n"
drh69d2d352018-03-09 22:18:53 +00006670 " sqlar_compress(data)\n"
drhb17ea912019-03-25 14:24:19 +00006671 " FROM fsdir(%Q,%Q) AS disk\n"
6672 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
6673 ,
drh1bf208c2018-03-09 21:54:01 +00006674 "REPLACE INTO %s(name,mode,mtime,data)\n"
6675 " SELECT\n"
6676 " %s,\n"
6677 " mode,\n"
6678 " mtime,\n"
6679 " data\n"
drhb17ea912019-03-25 14:24:19 +00006680 " FROM fsdir(%Q,%Q) AS disk\n"
6681 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
drh1bf208c2018-03-09 21:54:01 +00006682 };
danfd0245d2017-12-07 15:44:29 +00006683 int i; /* For iterating through azFile[] */
6684 int rc; /* Return code */
drh1bf208c2018-03-09 21:54:01 +00006685 const char *zTab = 0; /* SQL table into which to insert */
6686 char *zSql;
6687 char zTemp[50];
drhb17ea912019-03-25 14:24:19 +00006688 char *zExists = 0;
danfd0245d2017-12-07 15:44:29 +00006689
drh1bf208c2018-03-09 21:54:01 +00006690 arExecSql(pAr, "PRAGMA page_size=512");
drhb376b3d2018-01-10 13:11:51 +00006691 rc = arExecSql(pAr, "SAVEPOINT ar;");
danfd0245d2017-12-07 15:44:29 +00006692 if( rc!=SQLITE_OK ) return rc;
drh1bf208c2018-03-09 21:54:01 +00006693 zTemp[0] = 0;
6694 if( pAr->bZip ){
6695 /* Initialize the zipfile virtual table, if necessary */
6696 if( pAr->zFile ){
6697 sqlite3_uint64 r;
6698 sqlite3_randomness(sizeof(r),&r);
6699 sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
6700 zTab = zTemp;
6701 zSql = sqlite3_mprintf(
6702 "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)",
6703 zTab, pAr->zFile
6704 );
6705 rc = arExecSql(pAr, zSql);
6706 sqlite3_free(zSql);
6707 }else{
6708 zTab = "zip";
6709 }
6710 }else{
6711 /* Initialize the table for an SQLAR */
6712 zTab = "sqlar";
6713 if( bUpdate==0 ){
6714 rc = arExecSql(pAr, zDrop);
6715 if( rc!=SQLITE_OK ) goto end_ar_transaction;
6716 }
6717 rc = arExecSql(pAr, zCreate);
dan06741a32017-12-13 20:17:18 +00006718 }
drhb17ea912019-03-25 14:24:19 +00006719 if( bOnlyIfChanged ){
6720 zExists = sqlite3_mprintf(
6721 " AND NOT EXISTS("
6722 "SELECT 1 FROM %s AS mem"
6723 " WHERE mem.name=disk.name"
6724 " AND mem.mtime=disk.mtime"
6725 " AND mem.mode=disk.mode)", zTab);
6726 }else{
6727 zExists = sqlite3_mprintf("");
6728 }
6729 if( zExists==0 ) rc = SQLITE_NOMEM;
dan88be0202017-12-09 17:58:02 +00006730 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
mistachkince2052b2018-03-23 00:31:53 +00006731 char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
drh634c70f2018-01-10 16:50:18 +00006732 pAr->bVerbose ? "shell_putsnl(name)" : "name",
drhb17ea912019-03-25 14:24:19 +00006733 pAr->azArg[i], pAr->zDir, zExists);
mistachkince2052b2018-03-23 00:31:53 +00006734 rc = arExecSql(pAr, zSql2);
6735 sqlite3_free(zSql2);
danfd0245d2017-12-07 15:44:29 +00006736 }
drh1bf208c2018-03-09 21:54:01 +00006737end_ar_transaction:
danfd0245d2017-12-07 15:44:29 +00006738 if( rc!=SQLITE_OK ){
drh2bd207f2019-01-11 17:19:59 +00006739 sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
danfd0245d2017-12-07 15:44:29 +00006740 }else{
drhb376b3d2018-01-10 13:11:51 +00006741 rc = arExecSql(pAr, "RELEASE ar;");
drh1bf208c2018-03-09 21:54:01 +00006742 if( pAr->bZip && pAr->zFile ){
6743 zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
6744 arExecSql(pAr, zSql);
6745 sqlite3_free(zSql);
6746 }
danfd0245d2017-12-07 15:44:29 +00006747 }
drhb17ea912019-03-25 14:24:19 +00006748 sqlite3_free(zExists);
danfd0245d2017-12-07 15:44:29 +00006749 return rc;
6750}
6751
6752/*
6753** Implementation of ".ar" dot command.
6754*/
6755static int arDotCommand(
drhe2754c12019-08-26 12:50:01 +00006756 ShellState *pState, /* Current shell tool state */
6757 int fromCmdLine, /* True if -A command-line option, not .ar cmd */
6758 char **azArg, /* Array of arguments passed to dot command */
6759 int nArg /* Number of entries in azArg[] */
danfd0245d2017-12-07 15:44:29 +00006760){
dan88be0202017-12-09 17:58:02 +00006761 ArCommand cmd;
6762 int rc;
drh34660642018-01-10 17:39:54 +00006763 memset(&cmd, 0, sizeof(cmd));
drhd0f9cdc2018-05-17 14:09:06 +00006764 cmd.fromCmdLine = fromCmdLine;
dan88be0202017-12-09 17:58:02 +00006765 rc = arParseCommand(azArg, nArg, &cmd);
6766 if( rc==SQLITE_OK ){
drha5676c42018-01-10 15:17:34 +00006767 int eDbType = SHELL_OPEN_UNSPEC;
drhb376b3d2018-01-10 13:11:51 +00006768 cmd.p = pState;
6769 cmd.db = pState->db;
drha5676c42018-01-10 15:17:34 +00006770 if( cmd.zFile ){
drh1bf208c2018-03-09 21:54:01 +00006771 eDbType = deduceDatabaseType(cmd.zFile, 1);
drha5676c42018-01-10 15:17:34 +00006772 }else{
6773 eDbType = pState->openMode;
6774 }
6775 if( eDbType==SHELL_OPEN_ZIPFILE ){
drh1bf208c2018-03-09 21:54:01 +00006776 if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){
6777 if( cmd.zFile==0 ){
6778 cmd.zSrcTable = sqlite3_mprintf("zip");
6779 }else{
6780 cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
6781 }
dan5a78b812017-12-27 18:54:11 +00006782 }
drha5676c42018-01-10 15:17:34 +00006783 cmd.bZip = 1;
dan5a78b812017-12-27 18:54:11 +00006784 }else if( cmd.zFile ){
dand4b56e52017-12-12 20:04:59 +00006785 int flags;
drha5676c42018-01-10 15:17:34 +00006786 if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
drhb17ea912019-03-25 14:24:19 +00006787 if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
larrybr47061b92021-11-01 17:22:52 +00006788 || cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){
dand4b56e52017-12-12 20:04:59 +00006789 flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
6790 }else{
6791 flags = SQLITE_OPEN_READONLY;
6792 }
drha82c95b2018-01-10 14:00:00 +00006793 cmd.db = 0;
drha5676c42018-01-10 15:17:34 +00006794 if( cmd.bDryRun ){
6795 utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
6796 eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
6797 }
6798 rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
6799 eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
dand4b56e52017-12-12 20:04:59 +00006800 if( rc!=SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00006801 utf8_printf(stderr, "cannot open file: %s (%s)\n",
6802 cmd.zFile, sqlite3_errmsg(cmd.db)
dand4b56e52017-12-12 20:04:59 +00006803 );
drha5676c42018-01-10 15:17:34 +00006804 goto end_ar_command;
dand4b56e52017-12-12 20:04:59 +00006805 }
drhb376b3d2018-01-10 13:11:51 +00006806 sqlite3_fileio_init(cmd.db, 0, 0);
drhb376b3d2018-01-10 13:11:51 +00006807 sqlite3_sqlar_init(cmd.db, 0, 0);
drh34660642018-01-10 17:39:54 +00006808 sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
6809 shellPutsFunc, 0, 0);
6810
dand4b56e52017-12-12 20:04:59 +00006811 }
drhd0f9cdc2018-05-17 14:09:06 +00006812 if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
drh634c70f2018-01-10 16:50:18 +00006813 if( cmd.eCmd!=AR_CMD_CREATE
6814 && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
6815 ){
drha5676c42018-01-10 15:17:34 +00006816 utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
6817 rc = SQLITE_ERROR;
6818 goto end_ar_command;
6819 }
6820 cmd.zSrcTable = sqlite3_mprintf("sqlar");
6821 }
dand4b56e52017-12-12 20:04:59 +00006822
dan88be0202017-12-09 17:58:02 +00006823 switch( cmd.eCmd ){
6824 case AR_CMD_CREATE:
drhb17ea912019-03-25 14:24:19 +00006825 rc = arCreateOrUpdateCommand(&cmd, 0, 0);
dan88be0202017-12-09 17:58:02 +00006826 break;
danfd0245d2017-12-07 15:44:29 +00006827
dan88be0202017-12-09 17:58:02 +00006828 case AR_CMD_EXTRACT:
drhb376b3d2018-01-10 13:11:51 +00006829 rc = arExtractCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00006830 break;
6831
6832 case AR_CMD_LIST:
drhb376b3d2018-01-10 13:11:51 +00006833 rc = arListCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00006834 break;
6835
dan0d0547f2017-12-14 15:40:42 +00006836 case AR_CMD_HELP:
6837 arUsage(pState->out);
6838 break;
6839
drhb17ea912019-03-25 14:24:19 +00006840 case AR_CMD_INSERT:
6841 rc = arCreateOrUpdateCommand(&cmd, 1, 0);
6842 break;
6843
larrybr47061b92021-11-01 17:22:52 +00006844 case AR_CMD_REMOVE:
6845 rc = arRemoveCommand(&cmd);
6846 break;
6847
dan88be0202017-12-09 17:58:02 +00006848 default:
6849 assert( cmd.eCmd==AR_CMD_UPDATE );
drhb17ea912019-03-25 14:24:19 +00006850 rc = arCreateOrUpdateCommand(&cmd, 1, 1);
dan88be0202017-12-09 17:58:02 +00006851 break;
danfd0245d2017-12-07 15:44:29 +00006852 }
6853 }
drha5676c42018-01-10 15:17:34 +00006854end_ar_command:
6855 if( cmd.db!=pState->db ){
drh9e804032018-05-18 17:11:50 +00006856 close_db(cmd.db);
drha5676c42018-01-10 15:17:34 +00006857 }
6858 sqlite3_free(cmd.zSrcTable);
danfd0245d2017-12-07 15:44:29 +00006859
dan88be0202017-12-09 17:58:02 +00006860 return rc;
danfd0245d2017-12-07 15:44:29 +00006861}
drhe37c0e12018-01-06 19:19:50 +00006862/* End of the ".archive" or ".ar" command logic
drhe2754c12019-08-26 12:50:01 +00006863*******************************************************************************/
drhe37c0e12018-01-06 19:19:50 +00006864#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
danfd0245d2017-12-07 15:44:29 +00006865
dan1b162162019-04-27 20:15:15 +00006866#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan42ebb012019-04-27 18:47:03 +00006867/*
6868** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
6869** Otherwise, the SQL statement or statements in zSql are executed using
6870** database connection db and the error code written to *pRc before
6871** this function returns.
6872*/
dan68cb86e2019-04-20 20:57:28 +00006873static void shellExec(sqlite3 *db, int *pRc, const char *zSql){
6874 int rc = *pRc;
6875 if( rc==SQLITE_OK ){
6876 char *zErr = 0;
6877 rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
6878 if( rc!=SQLITE_OK ){
6879 raw_printf(stderr, "SQL error: %s\n", zErr);
6880 }
drhf83d5012021-05-03 13:35:00 +00006881 sqlite3_free(zErr);
dan68cb86e2019-04-20 20:57:28 +00006882 *pRc = rc;
6883 }
6884}
6885
dan42ebb012019-04-27 18:47:03 +00006886/*
6887** Like shellExec(), except that zFmt is a printf() style format string.
6888*/
danc0b42432019-04-26 15:14:53 +00006889static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){
6890 char *z = 0;
6891 if( *pRc==SQLITE_OK ){
6892 va_list ap;
6893 va_start(ap, zFmt);
6894 z = sqlite3_vmprintf(zFmt, ap);
6895 va_end(ap);
6896 if( z==0 ){
6897 *pRc = SQLITE_NOMEM;
6898 }else{
6899 shellExec(db, pRc, z);
6900 }
6901 sqlite3_free(z);
6902 }
6903}
6904
dan42ebb012019-04-27 18:47:03 +00006905/*
6906** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
6907** Otherwise, an attempt is made to allocate, zero and return a pointer
6908** to a buffer nByte bytes in size. If an OOM error occurs, *pRc is set
6909** to SQLITE_NOMEM and NULL returned.
6910*/
dan68cb86e2019-04-20 20:57:28 +00006911static void *shellMalloc(int *pRc, sqlite3_int64 nByte){
6912 void *pRet = 0;
6913 if( *pRc==SQLITE_OK ){
6914 pRet = sqlite3_malloc64(nByte);
6915 if( pRet==0 ){
6916 *pRc = SQLITE_NOMEM;
6917 }else{
6918 memset(pRet, 0, nByte);
6919 }
6920 }
6921 return pRet;
6922}
6923
dan42ebb012019-04-27 18:47:03 +00006924/*
6925** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
6926** Otherwise, zFmt is treated as a printf() style string. The result of
6927** formatting it along with any trailing arguments is written into a
6928** buffer obtained from sqlite3_malloc(), and pointer to which is returned.
6929** It is the responsibility of the caller to eventually free this buffer
6930** using a call to sqlite3_free().
6931**
6932** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL
6933** pointer returned.
6934*/
dan68cb86e2019-04-20 20:57:28 +00006935static char *shellMPrintf(int *pRc, const char *zFmt, ...){
6936 char *z = 0;
6937 if( *pRc==SQLITE_OK ){
6938 va_list ap;
6939 va_start(ap, zFmt);
6940 z = sqlite3_vmprintf(zFmt, ap);
6941 va_end(ap);
6942 if( z==0 ){
6943 *pRc = SQLITE_NOMEM;
6944 }
6945 }
6946 return z;
6947}
6948
dan42ebb012019-04-27 18:47:03 +00006949/*
6950** When running the ".recover" command, each output table, and the special
6951** orphaned row table if it is required, is represented by an instance
6952** of the following struct.
6953*/
dan68cb86e2019-04-20 20:57:28 +00006954typedef struct RecoverTable RecoverTable;
6955struct RecoverTable {
dan42ebb012019-04-27 18:47:03 +00006956 char *zQuoted; /* Quoted version of table name */
dan68cb86e2019-04-20 20:57:28 +00006957 int nCol; /* Number of columns in table */
6958 char **azlCol; /* Array of column lists */
dan42ebb012019-04-27 18:47:03 +00006959 int iPk; /* Index of IPK column */
dan68cb86e2019-04-20 20:57:28 +00006960};
6961
6962/*
dan42ebb012019-04-27 18:47:03 +00006963** Free a RecoverTable object allocated by recoverFindTable() or
6964** recoverOrphanTable().
dan68cb86e2019-04-20 20:57:28 +00006965*/
6966static void recoverFreeTable(RecoverTable *pTab){
6967 if( pTab ){
dan68cb86e2019-04-20 20:57:28 +00006968 sqlite3_free(pTab->zQuoted);
dan68cb86e2019-04-20 20:57:28 +00006969 if( pTab->azlCol ){
6970 int i;
dan98c5ad32019-04-26 21:11:37 +00006971 for(i=0; i<=pTab->nCol; i++){
dan68cb86e2019-04-20 20:57:28 +00006972 sqlite3_free(pTab->azlCol[i]);
6973 }
6974 sqlite3_free(pTab->azlCol);
6975 }
6976 sqlite3_free(pTab);
6977 }
6978}
6979
dan42ebb012019-04-27 18:47:03 +00006980/*
6981** This function is a no-op if (*pRc) is not SQLITE_OK when it is called.
6982** Otherwise, it allocates and returns a RecoverTable object based on the
6983** final four arguments passed to this function. It is the responsibility
6984** of the caller to eventually free the returned object using
6985** recoverFreeTable().
6986*/
6987static RecoverTable *recoverNewTable(
danb40af492019-04-22 20:52:12 +00006988 int *pRc, /* IN/OUT: Error code */
danb40af492019-04-22 20:52:12 +00006989 const char *zName, /* Name of table */
6990 const char *zSql, /* CREATE TABLE statement */
6991 int bIntkey,
6992 int nCol
6993){
6994 sqlite3 *dbtmp = 0; /* sqlite3 handle for testing CREATE TABLE */
6995 int rc = *pRc;
dan98c5ad32019-04-26 21:11:37 +00006996 RecoverTable *pTab = 0;
danb40af492019-04-22 20:52:12 +00006997
dan98c5ad32019-04-26 21:11:37 +00006998 pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable));
danb40af492019-04-22 20:52:12 +00006999 if( rc==SQLITE_OK ){
7000 int nSqlCol = 0;
7001 int bSqlIntkey = 0;
7002 sqlite3_stmt *pStmt = 0;
dan98c5ad32019-04-26 21:11:37 +00007003
danb40af492019-04-22 20:52:12 +00007004 rc = sqlite3_open("", &dbtmp);
7005 if( rc==SQLITE_OK ){
drha2de66c2019-08-06 20:26:17 +00007006 sqlite3_create_function(dbtmp, "shell_idquote", 1, SQLITE_UTF8, 0,
7007 shellIdQuote, 0, 0);
7008 }
7009 if( rc==SQLITE_OK ){
dan38f9c712019-04-23 18:03:02 +00007010 rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
7011 }
7012 if( rc==SQLITE_OK ){
danb40af492019-04-22 20:52:12 +00007013 rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0);
7014 if( rc==SQLITE_ERROR ){
7015 rc = SQLITE_OK;
7016 goto finished;
7017 }
7018 }
7019 shellPreparePrintf(dbtmp, &rc, &pStmt,
7020 "SELECT count(*) FROM pragma_table_info(%Q)", zName
7021 );
7022 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7023 nSqlCol = sqlite3_column_int(pStmt, 0);
7024 }
7025 shellFinalize(&rc, pStmt);
7026
7027 if( rc!=SQLITE_OK || nSqlCol<nCol ){
7028 goto finished;
7029 }
7030
7031 shellPreparePrintf(dbtmp, &rc, &pStmt,
7032 "SELECT ("
7033 " SELECT substr(data,1,1)==X'0D' FROM sqlite_dbpage WHERE pgno=rootpage"
drh067b92b2020-06-19 15:24:12 +00007034 ") FROM sqlite_schema WHERE name = %Q", zName
danb40af492019-04-22 20:52:12 +00007035 );
7036 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7037 bSqlIntkey = sqlite3_column_int(pStmt, 0);
7038 }
7039 shellFinalize(&rc, pStmt);
7040
7041 if( bIntkey==bSqlIntkey ){
dan98c5ad32019-04-26 21:11:37 +00007042 int i;
danb40af492019-04-22 20:52:12 +00007043 const char *zPk = "_rowid_";
7044 sqlite3_stmt *pPkFinder = 0;
7045
danf57bea32019-04-27 15:35:45 +00007046 /* If this is an intkey table and there is an INTEGER PRIMARY KEY,
7047 ** set zPk to the name of the PK column, and pTab->iPk to the index
7048 ** of the column, where columns are 0-numbered from left to right.
7049 ** Or, if this is a WITHOUT ROWID table or if there is no IPK column,
7050 ** leave zPk as "_rowid_" and pTab->iPk at -2. */
dan98c5ad32019-04-26 21:11:37 +00007051 pTab->iPk = -2;
7052 if( bIntkey ){
7053 shellPreparePrintf(dbtmp, &rc, &pPkFinder,
danb40af492019-04-22 20:52:12 +00007054 "SELECT cid, name FROM pragma_table_info(%Q) "
7055 " WHERE pk=1 AND type='integer' COLLATE nocase"
dan98c5ad32019-04-26 21:11:37 +00007056 " AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
7057 , zName, zName
7058 );
7059 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){
7060 pTab->iPk = sqlite3_column_int(pPkFinder, 0);
7061 zPk = (const char*)sqlite3_column_text(pPkFinder, 1);
drh621a5e02021-12-16 17:35:27 +00007062 if( zPk==0 ){ zPk = "_"; /* Defensive. Should never happen */ }
dan98c5ad32019-04-26 21:11:37 +00007063 }
danb40af492019-04-22 20:52:12 +00007064 }
7065
drha2de66c2019-08-06 20:26:17 +00007066 pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName);
dan98c5ad32019-04-26 21:11:37 +00007067 pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
danb40af492019-04-22 20:52:12 +00007068 pTab->nCol = nSqlCol;
7069
dan98c5ad32019-04-26 21:11:37 +00007070 if( bIntkey ){
drha2de66c2019-08-06 20:26:17 +00007071 pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk);
danb40af492019-04-22 20:52:12 +00007072 }else{
dan98c5ad32019-04-26 21:11:37 +00007073 pTab->azlCol[0] = shellMPrintf(&rc, "");
danb40af492019-04-22 20:52:12 +00007074 }
dan98c5ad32019-04-26 21:11:37 +00007075 i = 1;
7076 shellPreparePrintf(dbtmp, &rc, &pStmt,
drha2de66c2019-08-06 20:26:17 +00007077 "SELECT %Q || group_concat(shell_idquote(name), ', ') "
danf57bea32019-04-27 15:35:45 +00007078 " FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
dan98c5ad32019-04-26 21:11:37 +00007079 "FROM pragma_table_info(%Q)",
danf57bea32019-04-27 15:35:45 +00007080 bIntkey ? ", " : "", pTab->iPk,
7081 bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ",
7082 zName
dan98c5ad32019-04-26 21:11:37 +00007083 );
7084 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7085 const char *zText = (const char*)sqlite3_column_text(pStmt, 0);
7086 pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText);
7087 i++;
7088 }
7089 shellFinalize(&rc, pStmt);
7090
danb40af492019-04-22 20:52:12 +00007091 shellFinalize(&rc, pPkFinder);
7092 }
7093 }
7094
7095 finished:
7096 sqlite3_close(dbtmp);
7097 *pRc = rc;
dan98779652019-05-09 14:15:19 +00007098 if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){
dan98c5ad32019-04-26 21:11:37 +00007099 recoverFreeTable(pTab);
7100 pTab = 0;
7101 }
7102 return pTab;
danb40af492019-04-22 20:52:12 +00007103}
7104
dan0aa01ee2019-04-27 19:36:49 +00007105/*
7106** This function is called to search the schema recovered from the
drh067b92b2020-06-19 15:24:12 +00007107** sqlite_schema table of the (possibly) corrupt database as part
dan0aa01ee2019-04-27 19:36:49 +00007108** of a ".recover" command. Specifically, for a table with root page
7109** iRoot and at least nCol columns. Additionally, if bIntkey is 0, the
7110** table must be a WITHOUT ROWID table, or if non-zero, not one of
7111** those.
7112**
7113** If a table is found, a (RecoverTable*) object is returned. Or, if
7114** no such table is found, but bIntkey is false and iRoot is the
7115** root page of an index in the recovered schema, then (*pbNoop) is
7116** set to true and NULL returned. Or, if there is no such table or
7117** index, NULL is returned and (*pbNoop) set to 0, indicating that
7118** the caller should write data to the orphans table.
7119*/
dan42ebb012019-04-27 18:47:03 +00007120static RecoverTable *recoverFindTable(
dan0aa01ee2019-04-27 19:36:49 +00007121 ShellState *pState, /* Shell state object */
7122 int *pRc, /* IN/OUT: Error code */
7123 int iRoot, /* Root page of table */
7124 int bIntkey, /* True for an intkey table */
7125 int nCol, /* Number of columns in table */
7126 int *pbNoop /* OUT: True if iRoot is root of index */
dan68cb86e2019-04-20 20:57:28 +00007127){
danb40af492019-04-22 20:52:12 +00007128 sqlite3_stmt *pStmt = 0;
dan68cb86e2019-04-20 20:57:28 +00007129 RecoverTable *pRet = 0;
danb40af492019-04-22 20:52:12 +00007130 int bNoop = 0;
7131 const char *zSql = 0;
7132 const char *zName = 0;
dan68cb86e2019-04-20 20:57:28 +00007133
danb40af492019-04-22 20:52:12 +00007134 /* Search the recovered schema for an object with root page iRoot. */
7135 shellPreparePrintf(pState->db, pRc, &pStmt,
7136 "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot
7137 );
7138 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7139 const char *zType = (const char*)sqlite3_column_text(pStmt, 0);
7140 if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){
7141 bNoop = 1;
7142 break;
7143 }
7144 if( sqlite3_stricmp(zType, "table")==0 ){
7145 zName = (const char*)sqlite3_column_text(pStmt, 1);
7146 zSql = (const char*)sqlite3_column_text(pStmt, 2);
drh621a5e02021-12-16 17:35:27 +00007147 if( zName!=0 && zSql!=0 ){
7148 pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol);
7149 break;
7150 }
danb40af492019-04-22 20:52:12 +00007151 }
7152 }
dan98c5ad32019-04-26 21:11:37 +00007153
danb40af492019-04-22 20:52:12 +00007154 shellFinalize(pRc, pStmt);
dan98c5ad32019-04-26 21:11:37 +00007155 *pbNoop = bNoop;
7156 return pRet;
7157}
danb40af492019-04-22 20:52:12 +00007158
dan0aa01ee2019-04-27 19:36:49 +00007159/*
7160** Return a RecoverTable object representing the orphans table.
7161*/
dan98c5ad32019-04-26 21:11:37 +00007162static RecoverTable *recoverOrphanTable(
dan0aa01ee2019-04-27 19:36:49 +00007163 ShellState *pState, /* Shell state object */
7164 int *pRc, /* IN/OUT: Error code */
7165 const char *zLostAndFound, /* Base name for orphans table */
7166 int nCol /* Number of user data columns */
dan98c5ad32019-04-26 21:11:37 +00007167){
7168 RecoverTable *pTab = 0;
7169 if( nCol>=0 && *pRc==SQLITE_OK ){
7170 int i;
dan42ebb012019-04-27 18:47:03 +00007171
7172 /* This block determines the name of the orphan table. The prefered
7173 ** name is zLostAndFound. But if that clashes with another name
7174 ** in the recovered schema, try zLostAndFound_0, zLostAndFound_1
7175 ** and so on until a non-clashing name is found. */
7176 int iTab = 0;
7177 char *zTab = shellMPrintf(pRc, "%s", zLostAndFound);
7178 sqlite3_stmt *pTest = 0;
7179 shellPrepare(pState->db, pRc,
7180 "SELECT 1 FROM recovery.schema WHERE name=?", &pTest
dan68cb86e2019-04-20 20:57:28 +00007181 );
dan42ebb012019-04-27 18:47:03 +00007182 if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
7183 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){
7184 shellReset(pRc, pTest);
7185 sqlite3_free(zTab);
7186 zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++);
7187 sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
dan68cb86e2019-04-20 20:57:28 +00007188 }
dan42ebb012019-04-27 18:47:03 +00007189 shellFinalize(pRc, pTest);
dan68cb86e2019-04-20 20:57:28 +00007190
dan98c5ad32019-04-26 21:11:37 +00007191 pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
7192 if( pTab ){
drha2de66c2019-08-06 20:26:17 +00007193 pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab);
dan98c5ad32019-04-26 21:11:37 +00007194 pTab->nCol = nCol;
7195 pTab->iPk = -2;
7196 if( nCol>0 ){
7197 pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1));
7198 if( pTab->azlCol ){
7199 pTab->azlCol[nCol] = shellMPrintf(pRc, "");
7200 for(i=nCol-1; i>=0; i--){
7201 pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]);
7202 }
7203 }
danb40af492019-04-22 20:52:12 +00007204 }
dan68cb86e2019-04-20 20:57:28 +00007205
dan42ebb012019-04-27 18:47:03 +00007206 if( *pRc!=SQLITE_OK ){
7207 recoverFreeTable(pTab);
7208 pTab = 0;
7209 }else{
7210 raw_printf(pState->out,
7211 "CREATE TABLE %s(rootpgno INTEGER, "
7212 "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted
7213 );
7214 for(i=0; i<nCol; i++){
7215 raw_printf(pState->out, ", c%d", i);
7216 }
7217 raw_printf(pState->out, ");\n");
7218 }
dan98c5ad32019-04-26 21:11:37 +00007219 }
dan42ebb012019-04-27 18:47:03 +00007220 sqlite3_free(zTab);
dan68cb86e2019-04-20 20:57:28 +00007221 }
dan98c5ad32019-04-26 21:11:37 +00007222 return pTab;
dan68cb86e2019-04-20 20:57:28 +00007223}
7224
7225/*
7226** This function is called to recover data from the database. A script
7227** to construct a new database containing all recovered data is output
7228** on stream pState->out.
7229*/
danb9b71db2019-04-25 16:20:40 +00007230static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
dan68cb86e2019-04-20 20:57:28 +00007231 int rc = SQLITE_OK;
7232 sqlite3_stmt *pLoop = 0; /* Loop through all root pages */
danefa363b2019-04-24 20:48:55 +00007233 sqlite3_stmt *pPages = 0; /* Loop through all pages in a group */
7234 sqlite3_stmt *pCells = 0; /* Loop through all cells in a page */
danc0b42432019-04-26 15:14:53 +00007235 const char *zRecoveryDb = ""; /* Name of "recovery" database */
dan42ebb012019-04-27 18:47:03 +00007236 const char *zLostAndFound = "lost_and_found";
dan9c014f82019-04-25 19:23:15 +00007237 int i;
dan98c5ad32019-04-26 21:11:37 +00007238 int nOrphan = -1;
7239 RecoverTable *pOrphan = 0;
dan9c014f82019-04-25 19:23:15 +00007240
7241 int bFreelist = 1; /* 0 if --freelist-corrupt is specified */
dan8cce6b82019-09-14 16:44:51 +00007242 int bRowids = 1; /* 0 if --no-rowids */
dan9c014f82019-04-25 19:23:15 +00007243 for(i=1; i<nArg; i++){
7244 char *z = azArg[i];
7245 int n;
7246 if( z[0]=='-' && z[1]=='-' ) z++;
drh4245e042019-06-13 13:52:46 +00007247 n = strlen30(z);
dan9c014f82019-04-25 19:23:15 +00007248 if( n<=17 && memcmp("-freelist-corrupt", z, n)==0 ){
7249 bFreelist = 0;
dan42ebb012019-04-27 18:47:03 +00007250 }else
danc0b42432019-04-26 15:14:53 +00007251 if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
7252 i++;
7253 zRecoveryDb = azArg[i];
dan42ebb012019-04-27 18:47:03 +00007254 }else
7255 if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
7256 i++;
7257 zLostAndFound = azArg[i];
dan8cce6b82019-09-14 16:44:51 +00007258 }else
7259 if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
7260 bRowids = 0;
danc0b42432019-04-26 15:14:53 +00007261 }
dan9c014f82019-04-25 19:23:15 +00007262 else{
drhe2754c12019-08-26 12:50:01 +00007263 utf8_printf(stderr, "unexpected option: %s\n", azArg[i]);
7264 showHelp(pState->out, azArg[0]);
dan9c014f82019-04-25 19:23:15 +00007265 return 1;
7266 }
7267 }
dan68cb86e2019-04-20 20:57:28 +00007268
danc0b42432019-04-26 15:14:53 +00007269 shellExecPrintf(pState->db, &rc,
dan68cb86e2019-04-20 20:57:28 +00007270 /* Attach an in-memory database named 'recovery'. Create an indexed
7271 ** cache of the sqlite_dbptr virtual table. */
dan01c08bc2019-07-24 19:20:30 +00007272 "PRAGMA writable_schema = on;"
danc0b42432019-04-26 15:14:53 +00007273 "ATTACH %Q AS recovery;"
7274 "DROP TABLE IF EXISTS recovery.dbptr;"
7275 "DROP TABLE IF EXISTS recovery.freelist;"
7276 "DROP TABLE IF EXISTS recovery.map;"
7277 "DROP TABLE IF EXISTS recovery.schema;"
danc0b42432019-04-26 15:14:53 +00007278 "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb
dan9c014f82019-04-25 19:23:15 +00007279 );
7280
7281 if( bFreelist ){
7282 shellExec(pState->db, &rc,
7283 "WITH trunk(pgno) AS ("
7284 " SELECT shell_int32("
7285 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x "
7286 " WHERE x>0"
7287 " UNION"
7288 " SELECT shell_int32("
7289 " (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x "
7290 " FROM trunk WHERE x>0"
7291 "),"
7292 "freelist(data, n, freepgno) AS ("
danf6099e92019-05-09 16:57:39 +00007293 " SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno "
dan9c014f82019-04-25 19:23:15 +00007294 " FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno"
7295 " UNION ALL"
7296 " SELECT data, n-1, shell_int32(data, 2+n) "
7297 " FROM freelist WHERE n>=0"
7298 ")"
7299 "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;"
7300 );
7301 }
7302
dan95063c22019-07-24 08:15:09 +00007303 /* If this is an auto-vacuum database, add all pointer-map pages to
7304 ** the freelist table. Do this regardless of whether or not
7305 ** --freelist-corrupt was specified. */
7306 shellExec(pState->db, &rc,
7307 "WITH ptrmap(pgno) AS ("
7308 " SELECT 2 WHERE shell_int32("
7309 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 13"
7310 " )"
7311 " UNION ALL "
7312 " SELECT pgno+1+(SELECT page_size FROM pragma_page_size)/5 AS pp "
7313 " FROM ptrmap WHERE pp<=(SELECT page_count FROM pragma_page_count)"
7314 ")"
7315 "REPLACE INTO recovery.freelist SELECT pgno FROM ptrmap"
7316 );
7317
dan9c014f82019-04-25 19:23:15 +00007318 shellExec(pState->db, &rc,
danca424382019-04-26 15:40:27 +00007319 "CREATE TABLE recovery.dbptr("
7320 " pgno, child, PRIMARY KEY(child, pgno)"
7321 ") WITHOUT ROWID;"
7322 "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) "
7323 " SELECT * FROM sqlite_dbptr"
7324 " WHERE pgno NOT IN freelist AND child NOT IN freelist;"
7325
7326 /* Delete any pointer to page 1. This ensures that page 1 is considered
7327 ** a root page, regardless of how corrupt the db is. */
7328 "DELETE FROM recovery.dbptr WHERE child = 1;"
7329
7330 /* Delete all pointers to any pages that have more than one pointer
7331 ** to them. Such pages will be treated as root pages when recovering
7332 ** data. */
7333 "DELETE FROM recovery.dbptr WHERE child IN ("
7334 " SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1"
7335 ");"
7336
dan68cb86e2019-04-20 20:57:28 +00007337 /* Create the "map" table that will (eventually) contain instructions
7338 ** for dealing with each page in the db that contains one or more
7339 ** records. */
danb40af492019-04-22 20:52:12 +00007340 "CREATE TABLE recovery.map("
7341 "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT"
7342 ");"
dan68cb86e2019-04-20 20:57:28 +00007343
7344 /* Populate table [map]. If there are circular loops of pages in the
7345 ** database, the following adds all pages in such a loop to the map
7346 ** as individual root pages. This could be handled better. */
7347 "WITH pages(i, maxlen) AS ("
danb9b71db2019-04-25 16:20:40 +00007348 " SELECT page_count, ("
7349 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count"
dan13b87672019-05-09 11:45:21 +00007350 " ) FROM pragma_page_count WHERE page_count>0"
dan68cb86e2019-04-20 20:57:28 +00007351 " UNION ALL"
danb40af492019-04-22 20:52:12 +00007352 " SELECT i-1, ("
7353 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1"
7354 " ) FROM pages WHERE i>=2"
dan68cb86e2019-04-20 20:57:28 +00007355 ")"
danb40af492019-04-22 20:52:12 +00007356 "INSERT INTO recovery.map(pgno, maxlen, intkey, root) "
7357 " SELECT i, maxlen, NULL, ("
dan68cb86e2019-04-20 20:57:28 +00007358 " WITH p(orig, pgno, parent) AS ("
7359 " SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)"
dan39e04f82019-05-09 18:33:32 +00007360 " UNION "
dan68cb86e2019-04-20 20:57:28 +00007361 " SELECT i, p.parent, "
7362 " (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p"
7363 " )"
7364 " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
7365 ") "
dand790c9a2019-08-26 14:57:58 +00007366 "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;"
danb40af492019-04-22 20:52:12 +00007367 "UPDATE recovery.map AS o SET intkey = ("
7368 " SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
7369 ");"
dan68cb86e2019-04-20 20:57:28 +00007370
7371 /* Extract data from page 1 and any linked pages into table
drh067b92b2020-06-19 15:24:12 +00007372 ** recovery.schema. With the same schema as an sqlite_schema table. */
dan68cb86e2019-04-20 20:57:28 +00007373 "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
7374 "INSERT INTO recovery.schema SELECT "
7375 " max(CASE WHEN field=0 THEN value ELSE NULL END),"
7376 " max(CASE WHEN field=1 THEN value ELSE NULL END),"
7377 " max(CASE WHEN field=2 THEN value ELSE NULL END),"
7378 " max(CASE WHEN field=3 THEN value ELSE NULL END),"
7379 " max(CASE WHEN field=4 THEN value ELSE NULL END)"
7380 "FROM sqlite_dbdata WHERE pgno IN ("
7381 " SELECT pgno FROM recovery.map WHERE root=1"
7382 ")"
7383 "GROUP BY pgno, cell;"
dan98c5ad32019-04-26 21:11:37 +00007384 "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);"
dan68cb86e2019-04-20 20:57:28 +00007385 );
7386
danb40af492019-04-22 20:52:12 +00007387 /* Open a transaction, then print out all non-virtual, non-"sqlite_%"
7388 ** CREATE TABLE statements that extracted from the existing schema. */
7389 if( rc==SQLITE_OK ){
7390 sqlite3_stmt *pStmt = 0;
danf3210572019-08-06 18:40:36 +00007391 /* ".recover" might output content in an order which causes immediate
7392 ** foreign key constraints to be violated. So disable foreign-key
7393 ** constraint enforcement to prevent problems when running the output
7394 ** script. */
7395 raw_printf(pState->out, "PRAGMA foreign_keys=OFF;\n");
danb40af492019-04-22 20:52:12 +00007396 raw_printf(pState->out, "BEGIN;\n");
dan38f9c712019-04-23 18:03:02 +00007397 raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
7398 shellPrepare(pState->db, &rc,
danb40af492019-04-22 20:52:12 +00007399 "SELECT sql FROM recovery.schema "
dan38f9c712019-04-23 18:03:02 +00007400 "WHERE type='table' AND sql LIKE 'create table%'", &pStmt
danb40af492019-04-22 20:52:12 +00007401 );
7402 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7403 const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0);
dan38f9c712019-04-23 18:03:02 +00007404 raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n",
7405 &zCreateTable[12]
7406 );
danb40af492019-04-22 20:52:12 +00007407 }
7408 shellFinalize(&rc, pStmt);
7409 }
7410
dan98c5ad32019-04-26 21:11:37 +00007411 /* Figure out if an orphan table will be required. And if so, how many
7412 ** user columns it should contain */
7413 shellPrepare(pState->db, &rc,
dan98779652019-05-09 14:15:19 +00007414 "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1"
dan98c5ad32019-04-26 21:11:37 +00007415 , &pLoop
7416 );
7417 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
7418 nOrphan = sqlite3_column_int(pLoop, 0);
7419 }
7420 shellFinalize(&rc, pLoop);
7421 pLoop = 0;
dan98c5ad32019-04-26 21:11:37 +00007422
danefa363b2019-04-24 20:48:55 +00007423 shellPrepare(pState->db, &rc,
7424 "SELECT pgno FROM recovery.map WHERE root=?", &pPages
7425 );
dan8cce6b82019-09-14 16:44:51 +00007426
danefa363b2019-04-24 20:48:55 +00007427 shellPrepare(pState->db, &rc,
dan8cce6b82019-09-14 16:44:51 +00007428 "SELECT max(field), group_concat(shell_escape_crnl(quote"
7429 "(case when (? AND field<0) then NULL else value end)"
7430 "), ', ')"
dan9443dbc2019-07-24 20:10:27 +00007431 ", min(field) "
danefa363b2019-04-24 20:48:55 +00007432 "FROM sqlite_dbdata WHERE pgno = ? AND field != ?"
7433 "GROUP BY cell", &pCells
7434 );
7435
dan68cb86e2019-04-20 20:57:28 +00007436 /* Loop through each root page. */
danb40af492019-04-22 20:52:12 +00007437 shellPrepare(pState->db, &rc,
7438 "SELECT root, intkey, max(maxlen) FROM recovery.map"
dan38f9c712019-04-23 18:03:02 +00007439 " WHERE root>1 GROUP BY root, intkey ORDER BY root=("
7440 " SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'"
7441 ")", &pLoop
danb40af492019-04-22 20:52:12 +00007442 );
dan68cb86e2019-04-20 20:57:28 +00007443 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
7444 int iRoot = sqlite3_column_int(pLoop, 0);
danb40af492019-04-22 20:52:12 +00007445 int bIntkey = sqlite3_column_int(pLoop, 1);
7446 int nCol = sqlite3_column_int(pLoop, 2);
dan98c5ad32019-04-26 21:11:37 +00007447 int bNoop = 0;
dan68cb86e2019-04-20 20:57:28 +00007448 RecoverTable *pTab;
7449
dan9443dbc2019-07-24 20:10:27 +00007450 assert( bIntkey==0 || bIntkey==1 );
dan42ebb012019-04-27 18:47:03 +00007451 pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);
dan98c5ad32019-04-26 21:11:37 +00007452 if( bNoop || rc ) continue;
dan98779652019-05-09 14:15:19 +00007453 if( pTab==0 ){
7454 if( pOrphan==0 ){
7455 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
7456 }
7457 pTab = pOrphan;
7458 if( pTab==0 ) break;
7459 }
dan98c5ad32019-04-26 21:11:37 +00007460
drha2de66c2019-08-06 20:26:17 +00007461 if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){
dan98c5ad32019-04-26 21:11:37 +00007462 raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
7463 }
7464 sqlite3_bind_int(pPages, 1, iRoot);
dan8cce6b82019-09-14 16:44:51 +00007465 if( bRowids==0 && pTab->iPk<0 ){
7466 sqlite3_bind_int(pCells, 1, 1);
7467 }else{
7468 sqlite3_bind_int(pCells, 1, 0);
7469 }
7470 sqlite3_bind_int(pCells, 3, pTab->iPk);
dan98c5ad32019-04-26 21:11:37 +00007471
7472 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){
7473 int iPgno = sqlite3_column_int(pPages, 0);
dan8cce6b82019-09-14 16:44:51 +00007474 sqlite3_bind_int(pCells, 2, iPgno);
dan98c5ad32019-04-26 21:11:37 +00007475 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){
7476 int nField = sqlite3_column_int(pCells, 0);
dan9443dbc2019-07-24 20:10:27 +00007477 int iMin = sqlite3_column_int(pCells, 2);
dan98c5ad32019-04-26 21:11:37 +00007478 const char *zVal = (const char*)sqlite3_column_text(pCells, 1);
7479
dan9443dbc2019-07-24 20:10:27 +00007480 RecoverTable *pTab2 = pTab;
7481 if( pTab!=pOrphan && (iMin<0)!=bIntkey ){
7482 if( pOrphan==0 ){
7483 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
7484 }
7485 pTab2 = pOrphan;
7486 if( pTab2==0 ) break;
7487 }
7488
dan98c5ad32019-04-26 21:11:37 +00007489 nField = nField+1;
dan9443dbc2019-07-24 20:10:27 +00007490 if( pTab2==pOrphan ){
dan98c5ad32019-04-26 21:11:37 +00007491 raw_printf(pState->out,
7492 "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",
dan9443dbc2019-07-24 20:10:27 +00007493 pTab2->zQuoted, iRoot, iPgno, nField,
7494 iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField]
dan98c5ad32019-04-26 21:11:37 +00007495 );
7496 }else{
danefa363b2019-04-24 20:48:55 +00007497 raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n",
dan9443dbc2019-07-24 20:10:27 +00007498 pTab2->zQuoted, pTab2->azlCol[nField], zVal
danefa363b2019-04-24 20:48:55 +00007499 );
7500 }
dan68cb86e2019-04-20 20:57:28 +00007501 }
dan98c5ad32019-04-26 21:11:37 +00007502 shellReset(&rc, pCells);
dan68cb86e2019-04-20 20:57:28 +00007503 }
dan98c5ad32019-04-26 21:11:37 +00007504 shellReset(&rc, pPages);
7505 if( pTab!=pOrphan ) recoverFreeTable(pTab);
dan68cb86e2019-04-20 20:57:28 +00007506 }
7507 shellFinalize(&rc, pLoop);
danefa363b2019-04-24 20:48:55 +00007508 shellFinalize(&rc, pPages);
7509 shellFinalize(&rc, pCells);
dan98c5ad32019-04-26 21:11:37 +00007510 recoverFreeTable(pOrphan);
dan68cb86e2019-04-20 20:57:28 +00007511
dan38f9c712019-04-23 18:03:02 +00007512 /* The rest of the schema */
danb40af492019-04-22 20:52:12 +00007513 if( rc==SQLITE_OK ){
dan38f9c712019-04-23 18:03:02 +00007514 sqlite3_stmt *pStmt = 0;
7515 shellPrepare(pState->db, &rc,
7516 "SELECT sql, name FROM recovery.schema "
danb1825882019-04-23 20:48:32 +00007517 "WHERE sql NOT LIKE 'create table%'", &pStmt
dan38f9c712019-04-23 18:03:02 +00007518 );
7519 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7520 const char *zSql = (const char*)sqlite3_column_text(pStmt, 0);
7521 if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){
7522 const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
7523 char *zPrint = shellMPrintf(&rc,
drh067b92b2020-06-19 15:24:12 +00007524 "INSERT INTO sqlite_schema VALUES('table', %Q, %Q, 0, %Q)",
dan38f9c712019-04-23 18:03:02 +00007525 zName, zName, zSql
7526 );
7527 raw_printf(pState->out, "%s;\n", zPrint);
7528 sqlite3_free(zPrint);
7529 }else{
7530 raw_printf(pState->out, "%s;\n", zSql);
7531 }
7532 }
7533 shellFinalize(&rc, pStmt);
7534 }
7535
7536 if( rc==SQLITE_OK ){
7537 raw_printf(pState->out, "PRAGMA writable_schema = off;\n");
danb40af492019-04-22 20:52:12 +00007538 raw_printf(pState->out, "COMMIT;\n");
7539 }
dan68cb86e2019-04-20 20:57:28 +00007540 sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
7541 return rc;
7542}
dan1b162162019-04-27 20:15:15 +00007543#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
dan68cb86e2019-04-20 20:57:28 +00007544
drh2ce15c32017-07-11 13:34:40 +00007545/*
7546** If an input line begins with "." then invoke this routine to
7547** process that line.
7548**
7549** Return 1 on error, 2 to exit, and 0 otherwise.
7550*/
7551static int do_meta_command(char *zLine, ShellState *p){
7552 int h = 1;
7553 int nArg = 0;
7554 int n, c;
7555 int rc = 0;
drh5df84282019-08-17 19:45:25 +00007556 char *azArg[52];
drh2ce15c32017-07-11 13:34:40 +00007557
dan6b046be2018-01-09 15:25:55 +00007558#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00007559 if( p->expert.pExpert ){
7560 expertFinish(p, 1, 0);
7561 }
dan6b046be2018-01-09 15:25:55 +00007562#endif
dan43efc182017-12-19 17:42:13 +00007563
drh2ce15c32017-07-11 13:34:40 +00007564 /* Parse the input line into tokens.
7565 */
drh5df84282019-08-17 19:45:25 +00007566 while( zLine[h] && nArg<ArraySize(azArg)-1 ){
drh2ce15c32017-07-11 13:34:40 +00007567 while( IsSpace(zLine[h]) ){ h++; }
7568 if( zLine[h]==0 ) break;
7569 if( zLine[h]=='\'' || zLine[h]=='"' ){
7570 int delim = zLine[h++];
7571 azArg[nArg++] = &zLine[h];
7572 while( zLine[h] && zLine[h]!=delim ){
7573 if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
7574 h++;
7575 }
7576 if( zLine[h]==delim ){
7577 zLine[h++] = 0;
7578 }
7579 if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
7580 }else{
7581 azArg[nArg++] = &zLine[h];
7582 while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
7583 if( zLine[h] ) zLine[h++] = 0;
7584 resolve_backslashes(azArg[nArg-1]);
7585 }
7586 }
drh5df84282019-08-17 19:45:25 +00007587 azArg[nArg] = 0;
drh2ce15c32017-07-11 13:34:40 +00007588
7589 /* Process the input line.
7590 */
7591 if( nArg==0 ) return 0; /* no tokens, no error */
7592 n = strlen30(azArg[0]);
7593 c = azArg[0][0];
drh13c20932018-01-10 21:41:55 +00007594 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +00007595
7596#ifndef SQLITE_OMIT_AUTHORIZATION
7597 if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
7598 if( nArg!=2 ){
7599 raw_printf(stderr, "Usage: .auth ON|OFF\n");
7600 rc = 1;
7601 goto meta_command_exit;
7602 }
7603 open_db(p, 0);
7604 if( booleanValue(azArg[1]) ){
7605 sqlite3_set_authorizer(p->db, shellAuth, p);
drhb97e2ad2021-08-26 18:31:39 +00007606 }else if( p->bSafeModePersist ){
7607 sqlite3_set_authorizer(p->db, safeModeAuth, p);
drh2ce15c32017-07-11 13:34:40 +00007608 }else{
7609 sqlite3_set_authorizer(p->db, 0, 0);
7610 }
7611 }else
7612#endif
7613
drhe37c0e12018-01-06 19:19:50 +00007614#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
7615 if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
danfd0245d2017-12-07 15:44:29 +00007616 open_db(p, 0);
drhb97e2ad2021-08-26 18:31:39 +00007617 failIfSafeMode(p, "cannot run .archive in safe mode");
drhd0f9cdc2018-05-17 14:09:06 +00007618 rc = arDotCommand(p, 0, azArg, nArg);
danfd0245d2017-12-07 15:44:29 +00007619 }else
7620#endif
7621
drh2ce15c32017-07-11 13:34:40 +00007622 if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
7623 || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
7624 ){
7625 const char *zDestFile = 0;
7626 const char *zDb = 0;
7627 sqlite3 *pDest;
7628 sqlite3_backup *pBackup;
7629 int j;
drha50bffb2018-12-08 01:09:14 +00007630 int bAsync = 0;
drh69ed38a2018-05-14 00:23:08 +00007631 const char *zVfs = 0;
drhb97e2ad2021-08-26 18:31:39 +00007632 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00007633 for(j=1; j<nArg; j++){
7634 const char *z = azArg[j];
7635 if( z[0]=='-' ){
drh69ed38a2018-05-14 00:23:08 +00007636 if( z[1]=='-' ) z++;
7637 if( strcmp(z, "-append")==0 ){
7638 zVfs = "apndvfs";
7639 }else
drha50bffb2018-12-08 01:09:14 +00007640 if( strcmp(z, "-async")==0 ){
7641 bAsync = 1;
7642 }else
drh2ce15c32017-07-11 13:34:40 +00007643 {
7644 utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
7645 return 1;
7646 }
7647 }else if( zDestFile==0 ){
7648 zDestFile = azArg[j];
7649 }else if( zDb==0 ){
7650 zDb = zDestFile;
7651 zDestFile = azArg[j];
7652 }else{
drha50bffb2018-12-08 01:09:14 +00007653 raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
drh2ce15c32017-07-11 13:34:40 +00007654 return 1;
7655 }
7656 }
7657 if( zDestFile==0 ){
7658 raw_printf(stderr, "missing FILENAME argument on .backup\n");
7659 return 1;
7660 }
7661 if( zDb==0 ) zDb = "main";
drh69ed38a2018-05-14 00:23:08 +00007662 rc = sqlite3_open_v2(zDestFile, &pDest,
7663 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
drh2ce15c32017-07-11 13:34:40 +00007664 if( rc!=SQLITE_OK ){
7665 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
drh9e804032018-05-18 17:11:50 +00007666 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007667 return 1;
7668 }
drha50bffb2018-12-08 01:09:14 +00007669 if( bAsync ){
7670 sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
7671 0, 0, 0);
7672 }
drh2ce15c32017-07-11 13:34:40 +00007673 open_db(p, 0);
7674 pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
7675 if( pBackup==0 ){
7676 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
drh9e804032018-05-18 17:11:50 +00007677 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007678 return 1;
7679 }
7680 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
7681 sqlite3_backup_finish(pBackup);
7682 if( rc==SQLITE_DONE ){
7683 rc = 0;
7684 }else{
7685 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
7686 rc = 1;
7687 }
drh9e804032018-05-18 17:11:50 +00007688 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007689 }else
7690
7691 if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
7692 if( nArg==2 ){
7693 bail_on_error = booleanValue(azArg[1]);
7694 }else{
7695 raw_printf(stderr, "Usage: .bail on|off\n");
7696 rc = 1;
7697 }
7698 }else
7699
7700 if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
7701 if( nArg==2 ){
7702 if( booleanValue(azArg[1]) ){
7703 setBinaryMode(p->out, 1);
7704 }else{
7705 setTextMode(p->out, 1);
7706 }
7707 }else{
7708 raw_printf(stderr, "Usage: .binary on|off\n");
7709 rc = 1;
7710 }
7711 }else
7712
drh37407122021-07-23 18:43:58 +00007713 /* The undocumented ".breakpoint" command causes a call to the no-op
7714 ** routine named test_breakpoint().
7715 */
7716 if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
7717 test_breakpoint();
7718 }else
7719
drh2ce15c32017-07-11 13:34:40 +00007720 if( c=='c' && strcmp(azArg[0],"cd")==0 ){
drhb97e2ad2021-08-26 18:31:39 +00007721 failIfSafeMode(p, "cannot run .cd in safe mode");
drh2ce15c32017-07-11 13:34:40 +00007722 if( nArg==2 ){
7723#if defined(_WIN32) || defined(WIN32)
7724 wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
7725 rc = !SetCurrentDirectoryW(z);
7726 sqlite3_free(z);
7727#else
7728 rc = chdir(azArg[1]);
7729#endif
7730 if( rc ){
7731 utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
7732 rc = 1;
7733 }
7734 }else{
7735 raw_printf(stderr, "Usage: .cd DIRECTORY\n");
7736 rc = 1;
7737 }
7738 }else
7739
drh2ce15c32017-07-11 13:34:40 +00007740 if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
7741 if( nArg==2 ){
7742 setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
7743 }else{
7744 raw_printf(stderr, "Usage: .changes on|off\n");
7745 rc = 1;
7746 }
7747 }else
7748
7749 /* Cancel output redirection, if it is currently set (by .testcase)
7750 ** Then read the content of the testcase-out.txt file and compare against
7751 ** azArg[1]. If there are differences, report an error and exit.
7752 */
7753 if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
7754 char *zRes = 0;
7755 output_reset(p);
7756 if( nArg!=2 ){
7757 raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
7758 rc = 2;
7759 }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
7760 raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
7761 rc = 2;
7762 }else if( testcase_glob(azArg[1],zRes)==0 ){
7763 utf8_printf(stderr,
7764 "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
7765 p->zTestcase, azArg[1], zRes);
drhf30d3452017-10-17 13:44:46 +00007766 rc = 1;
drh2ce15c32017-07-11 13:34:40 +00007767 }else{
7768 utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
7769 p->nCheck++;
7770 }
7771 sqlite3_free(zRes);
7772 }else
7773
7774 if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
drhb97e2ad2021-08-26 18:31:39 +00007775 failIfSafeMode(p, "cannot run .clone in safe mode");
drh2ce15c32017-07-11 13:34:40 +00007776 if( nArg==2 ){
7777 tryToClone(p, azArg[1]);
7778 }else{
7779 raw_printf(stderr, "Usage: .clone FILENAME\n");
7780 rc = 1;
7781 }
7782 }else
7783
drh37407122021-07-23 18:43:58 +00007784 if( c=='c' && strncmp(azArg[0], "connection", n)==0 ){
7785 if( nArg==1 ){
7786 /* List available connections */
7787 int i;
7788 for(i=0; i<ArraySize(p->aAuxDb); i++){
7789 const char *zFile = p->aAuxDb[i].zDbFilename;
7790 if( p->aAuxDb[i].db==0 && p->pAuxDb!=&p->aAuxDb[i] ){
7791 zFile = "(not open)";
7792 }else if( zFile==0 ){
7793 zFile = "(memory)";
7794 }else if( zFile[0]==0 ){
7795 zFile = "(temporary-file)";
7796 }
7797 if( p->pAuxDb == &p->aAuxDb[i] ){
7798 utf8_printf(stdout, "ACTIVE %d: %s\n", i, zFile);
7799 }else if( p->aAuxDb[i].db!=0 ){
7800 utf8_printf(stdout, " %d: %s\n", i, zFile);
7801 }
7802 }
7803 }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){
7804 int i = azArg[1][0] - '0';
7805 if( p->pAuxDb != &p->aAuxDb[i] && i>=0 && i<ArraySize(p->aAuxDb) ){
7806 p->pAuxDb->db = p->db;
7807 p->pAuxDb = &p->aAuxDb[i];
7808 globalDb = p->db = p->pAuxDb->db;
7809 p->pAuxDb->db = 0;
7810 }
7811 }else if( nArg==3 && strcmp(azArg[1], "close")==0
7812 && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){
7813 int i = azArg[2][0] - '0';
7814 if( i<0 || i>=ArraySize(p->aAuxDb) ){
7815 /* No-op */
7816 }else if( p->pAuxDb == &p->aAuxDb[i] ){
7817 raw_printf(stderr, "cannot close the active database connection\n");
7818 rc = 1;
7819 }else if( p->aAuxDb[i].db ){
7820 session_close_all(p, i);
7821 close_db(p->aAuxDb[i].db);
7822 p->aAuxDb[i].db = 0;
7823 }
7824 }else{
7825 raw_printf(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n");
7826 rc = 1;
7827 }
7828 }else
7829
drh2ce15c32017-07-11 13:34:40 +00007830 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
drh60081a02020-08-26 19:07:18 +00007831 char **azName = 0;
7832 int nName = 0;
7833 sqlite3_stmt *pStmt;
drh60081a02020-08-26 19:07:18 +00007834 int i;
drh2ce15c32017-07-11 13:34:40 +00007835 open_db(p, 0);
drh60081a02020-08-26 19:07:18 +00007836 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
7837 if( rc ){
7838 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh2ce15c32017-07-11 13:34:40 +00007839 rc = 1;
drh60081a02020-08-26 19:07:18 +00007840 }else{
7841 while( sqlite3_step(pStmt)==SQLITE_ROW ){
7842 const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
7843 const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
drh621a5e02021-12-16 17:35:27 +00007844 if( zSchema==0 || zFile==0 ) continue;
drh60081a02020-08-26 19:07:18 +00007845 azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
drhe3e25652021-12-16 13:29:28 +00007846 shell_check_oom(azName);
drh60081a02020-08-26 19:07:18 +00007847 azName[nName*2] = strdup(zSchema);
7848 azName[nName*2+1] = strdup(zFile);
7849 nName++;
7850 }
drh2ce15c32017-07-11 13:34:40 +00007851 }
drh60081a02020-08-26 19:07:18 +00007852 sqlite3_finalize(pStmt);
7853 for(i=0; i<nName; i++){
7854 int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
7855 int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
7856 const char *z = azName[i*2+1];
7857 utf8_printf(p->out, "%s: %s %s%s\n",
7858 azName[i*2],
7859 z && z[0] ? z : "\"\"",
7860 bRdonly ? "r/o" : "r/w",
7861 eTxn==SQLITE_TXN_NONE ? "" :
7862 eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
7863 free(azName[i*2]);
7864 free(azName[i*2+1]);
7865 }
7866 sqlite3_free(azName);
drh2ce15c32017-07-11 13:34:40 +00007867 }else
7868
drh7df01192018-04-28 12:43:16 +00007869 if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
drheb7f2a02018-09-26 18:02:32 +00007870 static const struct DbConfigChoices {
7871 const char *zName;
7872 int op;
7873 } aDbConfig[] = {
drhb945bcd2019-12-31 22:52:10 +00007874 { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
7875 { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL },
7876 { "dqs_dml", SQLITE_DBCONFIG_DQS_DML },
drh0a6873b2019-06-14 21:25:25 +00007877 { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
drhb945bcd2019-12-31 22:52:10 +00007878 { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
drh0a6873b2019-06-14 21:25:25 +00007879 { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
drh11d88e62019-08-15 21:27:20 +00007880 { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
drh0a6873b2019-06-14 21:25:25 +00007881 { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
drhb945bcd2019-12-31 22:52:10 +00007882 { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
7883 { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
drh0a6873b2019-06-14 21:25:25 +00007884 { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
7885 { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
drh0a6873b2019-06-14 21:25:25 +00007886 { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
drhb945bcd2019-12-31 22:52:10 +00007887 { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
drhb77da372020-01-07 16:09:11 +00007888 { "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA },
dan07312a62019-06-21 14:05:27 +00007889 { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA },
drh7df01192018-04-28 12:43:16 +00007890 };
7891 int ii, v;
7892 open_db(p, 0);
7893 for(ii=0; ii<ArraySize(aDbConfig); ii++){
7894 if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
7895 if( nArg>=3 ){
7896 sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
7897 }
7898 sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
drhb945bcd2019-12-31 22:52:10 +00007899 utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
drh7df01192018-04-28 12:43:16 +00007900 if( nArg>1 ) break;
7901 }
7902 if( nArg>1 && ii==ArraySize(aDbConfig) ){
7903 utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
7904 utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
7905 }
7906 }else
7907
7908 if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00007909 rc = shell_dbinfo_command(p, nArg, azArg);
7910 }else
7911
dan1b162162019-04-27 20:15:15 +00007912#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00007913 if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){
7914 open_db(p, 0);
danb9b71db2019-04-25 16:20:40 +00007915 rc = recoverDatabaseCmd(p, nArg, azArg);
dan68cb86e2019-04-20 20:57:28 +00007916 }else
dan1b162162019-04-27 20:15:15 +00007917#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
dan68cb86e2019-04-20 20:57:28 +00007918
drh2ce15c32017-07-11 13:34:40 +00007919 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
drh8e9297f2020-03-25 12:50:13 +00007920 char *zLike = 0;
7921 char *zSql;
drh2ce15c32017-07-11 13:34:40 +00007922 int i;
7923 int savedShowHeader = p->showHeader;
drhf213b332018-07-05 17:35:46 +00007924 int savedShellFlags = p->shellFlgs;
drhc1962192020-10-12 16:54:28 +00007925 ShellClearFlag(p,
7926 SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
7927 |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
drh2ce15c32017-07-11 13:34:40 +00007928 for(i=1; i<nArg; i++){
7929 if( azArg[i][0]=='-' ){
7930 const char *z = azArg[i]+1;
7931 if( z[0]=='-' ) z++;
7932 if( strcmp(z,"preserve-rowids")==0 ){
7933#ifdef SQLITE_OMIT_VIRTUALTABLE
7934 raw_printf(stderr, "The --preserve-rowids option is not compatible"
7935 " with SQLITE_OMIT_VIRTUALTABLE\n");
7936 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00007937 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00007938 goto meta_command_exit;
7939#else
7940 ShellSetFlag(p, SHFLG_PreserveRowid);
7941#endif
7942 }else
7943 if( strcmp(z,"newlines")==0 ){
7944 ShellSetFlag(p, SHFLG_Newlines);
7945 }else
drhc1962192020-10-12 16:54:28 +00007946 if( strcmp(z,"data-only")==0 ){
7947 ShellSetFlag(p, SHFLG_DumpDataOnly);
7948 }else
7949 if( strcmp(z,"nosys")==0 ){
7950 ShellSetFlag(p, SHFLG_DumpNoSys);
7951 }else
drh2ce15c32017-07-11 13:34:40 +00007952 {
7953 raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
7954 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00007955 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00007956 goto meta_command_exit;
7957 }
drh2ce15c32017-07-11 13:34:40 +00007958 }else{
dan78a9d752021-05-25 11:39:14 +00007959 /* azArg[i] contains a LIKE pattern. This ".dump" request should
7960 ** only dump data for tables for which either the table name matches
7961 ** the LIKE pattern, or the table appears to be a shadow table of
7962 ** a virtual table for which the name matches the LIKE pattern.
7963 */
7964 char *zExpr = sqlite3_mprintf(
7965 "name LIKE %Q ESCAPE '\\' OR EXISTS ("
7966 " SELECT 1 FROM sqlite_schema WHERE "
7967 " name LIKE %Q ESCAPE '\\' AND"
7968 " sql LIKE 'CREATE VIRTUAL TABLE%%' AND"
7969 " substr(o.name, 1, length(name)+1) == (name||'_')"
7970 ")", azArg[i], azArg[i]
7971 );
7972
7973 if( zLike ){
7974 zLike = sqlite3_mprintf("%z OR %z", zLike, zExpr);
7975 }else{
7976 zLike = zExpr;
7977 }
drh2ce15c32017-07-11 13:34:40 +00007978 }
7979 }
dan68cb86e2019-04-20 20:57:28 +00007980
drh2ce15c32017-07-11 13:34:40 +00007981 open_db(p, 0);
dan68cb86e2019-04-20 20:57:28 +00007982
drhc1962192020-10-12 16:54:28 +00007983 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
7984 /* When playing back a "dump", the content might appear in an order
7985 ** which causes immediate foreign key constraints to be violated.
7986 ** So disable foreign-key constraint enforcement to prevent problems. */
7987 raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
7988 raw_printf(p->out, "BEGIN TRANSACTION;\n");
7989 }
drh2ce15c32017-07-11 13:34:40 +00007990 p->writableSchema = 0;
7991 p->showHeader = 0;
7992 /* Set writable_schema=ON since doing so forces SQLite to initialize
drh067b92b2020-06-19 15:24:12 +00007993 ** as much of the schema as it can even if the sqlite_schema table is
drh2ce15c32017-07-11 13:34:40 +00007994 ** corrupt. */
7995 sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
7996 p->nErr = 0;
drh8e9297f2020-03-25 12:50:13 +00007997 if( zLike==0 ) zLike = sqlite3_mprintf("true");
7998 zSql = sqlite3_mprintf(
dan78a9d752021-05-25 11:39:14 +00007999 "SELECT name, type, sql FROM sqlite_schema AS o "
drh8e9297f2020-03-25 12:50:13 +00008000 "WHERE (%s) AND type=='table'"
8001 " AND sql NOT NULL"
8002 " ORDER BY tbl_name='sqlite_sequence', rowid",
8003 zLike
8004 );
8005 run_schema_dump_query(p,zSql);
8006 sqlite3_free(zSql);
drhc1962192020-10-12 16:54:28 +00008007 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
8008 zSql = sqlite3_mprintf(
dan78a9d752021-05-25 11:39:14 +00008009 "SELECT sql FROM sqlite_schema AS o "
drhc1962192020-10-12 16:54:28 +00008010 "WHERE (%s) AND sql NOT NULL"
8011 " AND type IN ('index','trigger','view')",
8012 zLike
8013 );
8014 run_table_dump_query(p, zSql);
8015 sqlite3_free(zSql);
8016 }
drh8e9297f2020-03-25 12:50:13 +00008017 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00008018 if( p->writableSchema ){
8019 raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
8020 p->writableSchema = 0;
8021 }
8022 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
8023 sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
drhc1962192020-10-12 16:54:28 +00008024 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
8025 raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
8026 }
drh2ce15c32017-07-11 13:34:40 +00008027 p->showHeader = savedShowHeader;
drhf213b332018-07-05 17:35:46 +00008028 p->shellFlgs = savedShellFlags;
drh2ce15c32017-07-11 13:34:40 +00008029 }else
8030
8031 if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
8032 if( nArg==2 ){
8033 setOrClearFlag(p, SHFLG_Echo, azArg[1]);
8034 }else{
8035 raw_printf(stderr, "Usage: .echo on|off\n");
8036 rc = 1;
8037 }
8038 }else
8039
8040 if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
8041 if( nArg==2 ){
drhe2ca99c2018-05-02 00:33:43 +00008042 p->autoEQPtest = 0;
drhb4e50392019-01-26 15:40:04 +00008043 if( p->autoEQPtrace ){
8044 if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
8045 p->autoEQPtrace = 0;
8046 }
drh2ce15c32017-07-11 13:34:40 +00008047 if( strcmp(azArg[1],"full")==0 ){
drhada70452017-12-21 21:02:27 +00008048 p->autoEQP = AUTOEQP_full;
8049 }else if( strcmp(azArg[1],"trigger")==0 ){
8050 p->autoEQP = AUTOEQP_trigger;
drhb4e50392019-01-26 15:40:04 +00008051#ifdef SQLITE_DEBUG
drhe2ca99c2018-05-02 00:33:43 +00008052 }else if( strcmp(azArg[1],"test")==0 ){
8053 p->autoEQP = AUTOEQP_on;
8054 p->autoEQPtest = 1;
drhb4e50392019-01-26 15:40:04 +00008055 }else if( strcmp(azArg[1],"trace")==0 ){
8056 p->autoEQP = AUTOEQP_full;
8057 p->autoEQPtrace = 1;
8058 open_db(p, 0);
drh067b92b2020-06-19 15:24:12 +00008059 sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0);
drhb4e50392019-01-26 15:40:04 +00008060 sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
8061#endif
drh2ce15c32017-07-11 13:34:40 +00008062 }else{
mistachkinb71aa092018-01-23 00:05:18 +00008063 p->autoEQP = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00008064 }
8065 }else{
drhb4e50392019-01-26 15:40:04 +00008066 raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
drh2ce15c32017-07-11 13:34:40 +00008067 rc = 1;
8068 }
8069 }else
8070
8071 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
8072 if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
8073 rc = 2;
8074 }else
8075
8076 /* The ".explain" command is automatic now. It is largely pointless. It
8077 ** retained purely for backwards compatibility */
8078 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
8079 int val = 1;
8080 if( nArg>=2 ){
8081 if( strcmp(azArg[1],"auto")==0 ){
8082 val = 99;
8083 }else{
8084 val = booleanValue(azArg[1]);
8085 }
8086 }
8087 if( val==1 && p->mode!=MODE_Explain ){
8088 p->normalMode = p->mode;
8089 p->mode = MODE_Explain;
8090 p->autoExplain = 0;
8091 }else if( val==0 ){
8092 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
8093 p->autoExplain = 0;
8094 }else if( val==99 ){
8095 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
8096 p->autoExplain = 1;
8097 }
8098 }else
8099
dan6b046be2018-01-09 15:25:55 +00008100#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00008101 if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
drhfe463172021-12-16 17:57:21 +00008102 if( p->bSafeMode ){
8103 raw_printf(stderr,
8104 "Cannot run experimental commands such as \"%s\" in safe mode\n",
8105 azArg[0]);
8106 rc = 1;
8107 }else{
8108 open_db(p, 0);
8109 expertDotCommand(p, azArg, nArg);
8110 }
dan43efc182017-12-19 17:42:13 +00008111 }else
dan6b046be2018-01-09 15:25:55 +00008112#endif
dan43efc182017-12-19 17:42:13 +00008113
drhd985f722019-06-05 14:29:53 +00008114 if( c=='f' && strncmp(azArg[0], "filectrl", n)==0 ){
8115 static const struct {
8116 const char *zCtrlName; /* Name of a test-control option */
8117 int ctrlCode; /* Integer code for that option */
8118 const char *zUsage; /* Usage notes */
8119 } aCtrl[] = {
drhd985f722019-06-05 14:29:53 +00008120 { "chunk_size", SQLITE_FCNTL_CHUNK_SIZE, "SIZE" },
drh18a4bbd2020-12-17 15:17:42 +00008121 { "data_version", SQLITE_FCNTL_DATA_VERSION, "" },
drhd985f722019-06-05 14:29:53 +00008122 { "has_moved", SQLITE_FCNTL_HAS_MOVED, "" },
8123 { "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" },
drh18a4bbd2020-12-17 15:17:42 +00008124 { "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" },
8125 /* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/
8126 { "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" },
drh541ef2c2020-04-20 16:21:30 +00008127 { "reserve_bytes", SQLITE_FCNTL_RESERVE_BYTES, "[N]" },
drh18a4bbd2020-12-17 15:17:42 +00008128 { "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" },
8129 { "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" },
8130 /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/
drhd985f722019-06-05 14:29:53 +00008131 };
8132 int filectrl = -1;
8133 int iCtrl = -1;
drh4245e042019-06-13 13:52:46 +00008134 sqlite3_int64 iRes = 0; /* Integer result to display if rc2==1 */
8135 int isOk = 0; /* 0: usage 1: %lld 2: no-result */
drhd985f722019-06-05 14:29:53 +00008136 int n2, i;
8137 const char *zCmd = 0;
drh541ef2c2020-04-20 16:21:30 +00008138 const char *zSchema = 0;
drhd985f722019-06-05 14:29:53 +00008139
8140 open_db(p, 0);
8141 zCmd = nArg>=2 ? azArg[1] : "help";
8142
drh541ef2c2020-04-20 16:21:30 +00008143 if( zCmd[0]=='-'
8144 && (strcmp(zCmd,"--schema")==0 || strcmp(zCmd,"-schema")==0)
8145 && nArg>=4
8146 ){
8147 zSchema = azArg[2];
8148 for(i=3; i<nArg; i++) azArg[i-2] = azArg[i];
8149 nArg -= 2;
8150 zCmd = azArg[1];
8151 }
8152
drhd985f722019-06-05 14:29:53 +00008153 /* The argument can optionally begin with "-" or "--" */
8154 if( zCmd[0]=='-' && zCmd[1] ){
8155 zCmd++;
8156 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
8157 }
8158
8159 /* --help lists all file-controls */
8160 if( strcmp(zCmd,"help")==0 ){
8161 utf8_printf(p->out, "Available file-controls:\n");
8162 for(i=0; i<ArraySize(aCtrl); i++){
8163 utf8_printf(p->out, " .filectrl %s %s\n",
8164 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
8165 }
8166 rc = 1;
8167 goto meta_command_exit;
8168 }
8169
8170 /* convert filectrl text option to value. allow any unique prefix
8171 ** of the option name, or a numerical value. */
8172 n2 = strlen30(zCmd);
8173 for(i=0; i<ArraySize(aCtrl); i++){
8174 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
8175 if( filectrl<0 ){
8176 filectrl = aCtrl[i].ctrlCode;
8177 iCtrl = i;
8178 }else{
8179 utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n"
8180 "Use \".filectrl --help\" for help\n", zCmd);
8181 rc = 1;
8182 goto meta_command_exit;
8183 }
8184 }
8185 }
8186 if( filectrl<0 ){
8187 utf8_printf(stderr,"Error: unknown file-control: %s\n"
8188 "Use \".filectrl --help\" for help\n", zCmd);
8189 }else{
8190 switch(filectrl){
8191 case SQLITE_FCNTL_SIZE_LIMIT: {
8192 if( nArg!=2 && nArg!=3 ) break;
8193 iRes = nArg==3 ? integerValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00008194 sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
drhd985f722019-06-05 14:29:53 +00008195 isOk = 1;
8196 break;
8197 }
8198 case SQLITE_FCNTL_LOCK_TIMEOUT:
8199 case SQLITE_FCNTL_CHUNK_SIZE: {
8200 int x;
8201 if( nArg!=3 ) break;
8202 x = (int)integerValue(azArg[2]);
drh541ef2c2020-04-20 16:21:30 +00008203 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008204 isOk = 2;
8205 break;
8206 }
8207 case SQLITE_FCNTL_PERSIST_WAL:
8208 case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
8209 int x;
8210 if( nArg!=2 && nArg!=3 ) break;
8211 x = nArg==3 ? booleanValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00008212 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008213 iRes = x;
8214 isOk = 1;
8215 break;
8216 }
drh18a4bbd2020-12-17 15:17:42 +00008217 case SQLITE_FCNTL_DATA_VERSION:
drhd985f722019-06-05 14:29:53 +00008218 case SQLITE_FCNTL_HAS_MOVED: {
8219 int x;
8220 if( nArg!=2 ) break;
drh541ef2c2020-04-20 16:21:30 +00008221 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008222 iRes = x;
8223 isOk = 1;
8224 break;
8225 }
8226 case SQLITE_FCNTL_TEMPFILENAME: {
8227 char *z = 0;
8228 if( nArg!=2 ) break;
drh541ef2c2020-04-20 16:21:30 +00008229 sqlite3_file_control(p->db, zSchema, filectrl, &z);
drhd985f722019-06-05 14:29:53 +00008230 if( z ){
8231 utf8_printf(p->out, "%s\n", z);
8232 sqlite3_free(z);
8233 }
8234 isOk = 2;
8235 break;
8236 }
drh541ef2c2020-04-20 16:21:30 +00008237 case SQLITE_FCNTL_RESERVE_BYTES: {
8238 int x;
8239 if( nArg>=3 ){
8240 x = atoi(azArg[2]);
8241 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8242 }
8243 x = -1;
8244 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8245 utf8_printf(p->out,"%d\n", x);
8246 isOk = 2;
8247 break;
8248 }
drhd985f722019-06-05 14:29:53 +00008249 }
8250 }
8251 if( isOk==0 && iCtrl>=0 ){
8252 utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
8253 rc = 1;
8254 }else if( isOk==1 ){
drhe2500762019-06-13 14:07:41 +00008255 char zBuf[100];
8256 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
8257 raw_printf(p->out, "%s\n", zBuf);
drhd985f722019-06-05 14:29:53 +00008258 }
8259 }else
8260
drh2ce15c32017-07-11 13:34:40 +00008261 if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
8262 ShellState data;
drh2ce15c32017-07-11 13:34:40 +00008263 int doStats = 0;
8264 memcpy(&data, p, sizeof(data));
8265 data.showHeader = 0;
8266 data.cMode = data.mode = MODE_Semi;
8267 if( nArg==2 && optionMatch(azArg[1], "indent") ){
8268 data.cMode = data.mode = MODE_Pretty;
8269 nArg = 1;
8270 }
8271 if( nArg!=1 ){
8272 raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
8273 rc = 1;
8274 goto meta_command_exit;
8275 }
8276 open_db(p, 0);
8277 rc = sqlite3_exec(p->db,
8278 "SELECT sql FROM"
8279 " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
drh067b92b2020-06-19 15:24:12 +00008280 " FROM sqlite_schema UNION ALL"
8281 " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
drh2ce15c32017-07-11 13:34:40 +00008282 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
drh69935c02021-06-25 11:14:10 +00008283 "ORDER BY x",
drhf83d5012021-05-03 13:35:00 +00008284 callback, &data, 0
drh2ce15c32017-07-11 13:34:40 +00008285 );
8286 if( rc==SQLITE_OK ){
8287 sqlite3_stmt *pStmt;
8288 rc = sqlite3_prepare_v2(p->db,
drh067b92b2020-06-19 15:24:12 +00008289 "SELECT rowid FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00008290 " WHERE name GLOB 'sqlite_stat[134]'",
8291 -1, &pStmt, 0);
8292 doStats = sqlite3_step(pStmt)==SQLITE_ROW;
8293 sqlite3_finalize(pStmt);
8294 }
8295 if( doStats==0 ){
8296 raw_printf(p->out, "/* No STAT tables available */\n");
8297 }else{
drh067b92b2020-06-19 15:24:12 +00008298 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00008299 data.cMode = data.mode = MODE_Insert;
8300 data.zDestTable = "sqlite_stat1";
drhf83d5012021-05-03 13:35:00 +00008301 shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
drh2ce15c32017-07-11 13:34:40 +00008302 data.zDestTable = "sqlite_stat4";
drhf83d5012021-05-03 13:35:00 +00008303 shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
drh067b92b2020-06-19 15:24:12 +00008304 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00008305 }
8306 }else
8307
8308 if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
8309 if( nArg==2 ){
8310 p->showHeader = booleanValue(azArg[1]);
drhc0605082020-06-05 00:54:27 +00008311 p->shellFlgs |= SHFLG_HeaderSet;
drh2ce15c32017-07-11 13:34:40 +00008312 }else{
8313 raw_printf(stderr, "Usage: .headers on|off\n");
8314 rc = 1;
8315 }
8316 }else
8317
8318 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
drh98aa2ab2018-09-26 16:53:51 +00008319 if( nArg>=2 ){
drhe93f8262018-10-11 16:53:37 +00008320 n = showHelp(p->out, azArg[1]);
drh98aa2ab2018-09-26 16:53:51 +00008321 if( n==0 ){
8322 utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
8323 }
8324 }else{
8325 showHelp(p->out, 0);
8326 }
drh2ce15c32017-07-11 13:34:40 +00008327 }else
8328
8329 if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
drhccb37812020-03-09 15:39:39 +00008330 char *zTable = 0; /* Insert data into this table */
8331 char *zFile = 0; /* Name of file to extra content from */
drh2ce15c32017-07-11 13:34:40 +00008332 sqlite3_stmt *pStmt = NULL; /* A statement */
8333 int nCol; /* Number of columns in the table */
8334 int nByte; /* Number of bytes in an SQL string */
8335 int i, j; /* Loop counters */
8336 int needCommit; /* True to COMMIT or ROLLBACK at end */
8337 int nSep; /* Number of bytes in p->colSeparator[] */
8338 char *zSql; /* An SQL statement */
8339 ImportCtx sCtx; /* Reader context */
8340 char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
drhccb37812020-03-09 15:39:39 +00008341 int eVerbose = 0; /* Larger for more console output */
8342 int nSkip = 0; /* Initial lines to skip */
8343 int useOutputMode = 1; /* Use output mode to determine separators */
drh2ce15c32017-07-11 13:34:40 +00008344
drhb97e2ad2021-08-26 18:31:39 +00008345 failIfSafeMode(p, "cannot run .import in safe mode");
drhccb37812020-03-09 15:39:39 +00008346 memset(&sCtx, 0, sizeof(sCtx));
larrybr6ac9a5c2021-10-28 19:49:23 +00008347 sCtx.z = sqlite3_malloc64(120);
8348 if( sCtx.z==0 ){
8349 import_cleanup(&sCtx);
8350 shell_out_of_memory();
8351 }
drhccb37812020-03-09 15:39:39 +00008352 if( p->mode==MODE_Ascii ){
8353 xRead = ascii_read_one_field;
8354 }else{
8355 xRead = csv_read_one_field;
8356 }
8357 for(i=1; i<nArg; i++){
8358 char *z = azArg[i];
8359 if( z[0]=='-' && z[1]=='-' ) z++;
8360 if( z[0]!='-' ){
8361 if( zFile==0 ){
8362 zFile = z;
8363 }else if( zTable==0 ){
8364 zTable = z;
8365 }else{
8366 utf8_printf(p->out, "ERROR: extra argument: \"%s\". Usage:\n", z);
8367 showHelp(p->out, "import");
8368 rc = 1;
8369 goto meta_command_exit;
8370 }
8371 }else if( strcmp(z,"-v")==0 ){
8372 eVerbose++;
8373 }else if( strcmp(z,"-skip")==0 && i<nArg-1 ){
8374 nSkip = integerValue(azArg[++i]);
8375 }else if( strcmp(z,"-ascii")==0 ){
8376 sCtx.cColSep = SEP_Unit[0];
8377 sCtx.cRowSep = SEP_Record[0];
8378 xRead = ascii_read_one_field;
8379 useOutputMode = 0;
8380 }else if( strcmp(z,"-csv")==0 ){
8381 sCtx.cColSep = ',';
8382 sCtx.cRowSep = '\n';
8383 xRead = csv_read_one_field;
8384 useOutputMode = 0;
8385 }else{
8386 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", z);
8387 showHelp(p->out, "import");
8388 rc = 1;
8389 goto meta_command_exit;
8390 }
8391 }
8392 if( zTable==0 ){
8393 utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
8394 zFile==0 ? "FILE" : "TABLE");
8395 showHelp(p->out, "import");
8396 rc = 1;
drh2ce15c32017-07-11 13:34:40 +00008397 goto meta_command_exit;
8398 }
drh2ce15c32017-07-11 13:34:40 +00008399 seenInterrupt = 0;
drh2ce15c32017-07-11 13:34:40 +00008400 open_db(p, 0);
drhccb37812020-03-09 15:39:39 +00008401 if( useOutputMode ){
8402 /* If neither the --csv or --ascii options are specified, then set
8403 ** the column and row separator characters from the output mode. */
8404 nSep = strlen30(p->colSeparator);
8405 if( nSep==0 ){
8406 raw_printf(stderr,
8407 "Error: non-null column separator required for import\n");
8408 rc = 1;
8409 goto meta_command_exit;
8410 }
8411 if( nSep>1 ){
8412 raw_printf(stderr,
8413 "Error: multi-character column separators not allowed"
8414 " for import\n");
8415 rc = 1;
8416 goto meta_command_exit;
8417 }
drh2ce15c32017-07-11 13:34:40 +00008418 nSep = strlen30(p->rowSeparator);
drhccb37812020-03-09 15:39:39 +00008419 if( nSep==0 ){
8420 raw_printf(stderr,
8421 "Error: non-null row separator required for import\n");
8422 rc = 1;
8423 goto meta_command_exit;
8424 }
8425 if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator,SEP_CrLf)==0 ){
8426 /* When importing CSV (only), if the row separator is set to the
8427 ** default output row separator, change it to the default input
8428 ** row separator. This avoids having to maintain different input
8429 ** and output row separators. */
8430 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8431 nSep = strlen30(p->rowSeparator);
8432 }
8433 if( nSep>1 ){
8434 raw_printf(stderr, "Error: multi-character row separators not allowed"
8435 " for import\n");
8436 rc = 1;
8437 goto meta_command_exit;
8438 }
8439 sCtx.cColSep = p->colSeparator[0];
8440 sCtx.cRowSep = p->rowSeparator[0];
drh2ce15c32017-07-11 13:34:40 +00008441 }
8442 sCtx.zFile = zFile;
8443 sCtx.nLine = 1;
8444 if( sCtx.zFile[0]=='|' ){
8445#ifdef SQLITE_OMIT_POPEN
8446 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
drhccb37812020-03-09 15:39:39 +00008447 rc = 1;
8448 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008449#else
8450 sCtx.in = popen(sCtx.zFile+1, "r");
8451 sCtx.zFile = "<pipe>";
drh97767842020-05-29 19:39:35 +00008452 sCtx.xCloser = pclose;
drh2ce15c32017-07-11 13:34:40 +00008453#endif
8454 }else{
8455 sCtx.in = fopen(sCtx.zFile, "rb");
drh97767842020-05-29 19:39:35 +00008456 sCtx.xCloser = fclose;
drh2ce15c32017-07-11 13:34:40 +00008457 }
drh2ce15c32017-07-11 13:34:40 +00008458 if( sCtx.in==0 ){
8459 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
drhccb37812020-03-09 15:39:39 +00008460 rc = 1;
dan07ed9c12021-11-02 14:01:41 +00008461 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008462 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008463 }
drhccb37812020-03-09 15:39:39 +00008464 if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
8465 char zSep[2];
8466 zSep[1] = 0;
8467 zSep[0] = sCtx.cColSep;
8468 utf8_printf(p->out, "Column separator ");
8469 output_c_string(p->out, zSep);
8470 utf8_printf(p->out, ", row separator ");
8471 zSep[0] = sCtx.cRowSep;
8472 output_c_string(p->out, zSep);
8473 utf8_printf(p->out, "\n");
8474 }
8475 while( (nSkip--)>0 ){
8476 while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
drhccb37812020-03-09 15:39:39 +00008477 }
drhc6712642020-10-12 17:57:29 +00008478 zSql = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
drh2ce15c32017-07-11 13:34:40 +00008479 if( zSql==0 ){
drh97767842020-05-29 19:39:35 +00008480 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00008481 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00008482 }
8483 nByte = strlen30(zSql);
8484 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8485 import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
8486 if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
drhc6712642020-10-12 17:57:29 +00008487 char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"", zTable);
drh2ce15c32017-07-11 13:34:40 +00008488 char cSep = '(';
8489 while( xRead(&sCtx) ){
8490 zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z);
8491 cSep = ',';
8492 if( sCtx.cTerm!=sCtx.cColSep ) break;
8493 }
8494 if( cSep=='(' ){
8495 sqlite3_free(zCreate);
drh97767842020-05-29 19:39:35 +00008496 import_cleanup(&sCtx);
drh2ce15c32017-07-11 13:34:40 +00008497 utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
drhccb37812020-03-09 15:39:39 +00008498 rc = 1;
8499 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008500 }
8501 zCreate = sqlite3_mprintf("%z\n)", zCreate);
drhccb37812020-03-09 15:39:39 +00008502 if( eVerbose>=1 ){
8503 utf8_printf(p->out, "%s\n", zCreate);
8504 }
drh2ce15c32017-07-11 13:34:40 +00008505 rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
8506 sqlite3_free(zCreate);
8507 if( rc ){
drhc6712642020-10-12 17:57:29 +00008508 utf8_printf(stderr, "CREATE TABLE \"%s\"(...) failed: %s\n", zTable,
drh2ce15c32017-07-11 13:34:40 +00008509 sqlite3_errmsg(p->db));
drh97767842020-05-29 19:39:35 +00008510 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008511 rc = 1;
8512 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008513 }
8514 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8515 }
8516 sqlite3_free(zSql);
8517 if( rc ){
8518 if (pStmt) sqlite3_finalize(pStmt);
8519 utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
drh97767842020-05-29 19:39:35 +00008520 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008521 rc = 1;
8522 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008523 }
8524 nCol = sqlite3_column_count(pStmt);
8525 sqlite3_finalize(pStmt);
8526 pStmt = 0;
8527 if( nCol==0 ) return 0; /* no columns, no error */
8528 zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
8529 if( zSql==0 ){
drh97767842020-05-29 19:39:35 +00008530 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00008531 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00008532 }
8533 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
8534 j = strlen30(zSql);
8535 for(i=1; i<nCol; i++){
8536 zSql[j++] = ',';
8537 zSql[j++] = '?';
8538 }
8539 zSql[j++] = ')';
8540 zSql[j] = 0;
drhccb37812020-03-09 15:39:39 +00008541 if( eVerbose>=2 ){
8542 utf8_printf(p->out, "Insert using: %s\n", zSql);
8543 }
drh2ce15c32017-07-11 13:34:40 +00008544 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8545 sqlite3_free(zSql);
8546 if( rc ){
8547 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
8548 if (pStmt) sqlite3_finalize(pStmt);
drh97767842020-05-29 19:39:35 +00008549 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008550 rc = 1;
8551 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008552 }
8553 needCommit = sqlite3_get_autocommit(p->db);
8554 if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
8555 do{
8556 int startLine = sCtx.nLine;
8557 for(i=0; i<nCol; i++){
8558 char *z = xRead(&sCtx);
8559 /*
8560 ** Did we reach end-of-file before finding any columns?
8561 ** If so, stop instead of NULL filling the remaining columns.
8562 */
8563 if( z==0 && i==0 ) break;
8564 /*
8565 ** Did we reach end-of-file OR end-of-line before finding any
8566 ** columns in ASCII mode? If so, stop instead of NULL filling
8567 ** the remaining columns.
8568 */
8569 if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
8570 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
8571 if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
8572 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
8573 "filling the rest with NULL\n",
8574 sCtx.zFile, startLine, nCol, i+1);
8575 i += 2;
8576 while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
8577 }
8578 }
8579 if( sCtx.cTerm==sCtx.cColSep ){
8580 do{
8581 xRead(&sCtx);
8582 i++;
8583 }while( sCtx.cTerm==sCtx.cColSep );
8584 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
8585 "extras ignored\n",
8586 sCtx.zFile, startLine, nCol, i);
8587 }
8588 if( i>=nCol ){
8589 sqlite3_step(pStmt);
8590 rc = sqlite3_reset(pStmt);
8591 if( rc!=SQLITE_OK ){
8592 utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
8593 startLine, sqlite3_errmsg(p->db));
drhccb37812020-03-09 15:39:39 +00008594 sCtx.nErr++;
8595 }else{
8596 sCtx.nRow++;
drh2ce15c32017-07-11 13:34:40 +00008597 }
8598 }
8599 }while( sCtx.cTerm!=EOF );
8600
drh97767842020-05-29 19:39:35 +00008601 import_cleanup(&sCtx);
drh2ce15c32017-07-11 13:34:40 +00008602 sqlite3_finalize(pStmt);
8603 if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
drhccb37812020-03-09 15:39:39 +00008604 if( eVerbose>0 ){
8605 utf8_printf(p->out,
8606 "Added %d rows with %d errors using %d lines of input\n",
8607 sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
8608 }
drh2ce15c32017-07-11 13:34:40 +00008609 }else
8610
8611#ifndef SQLITE_UNTESTABLE
8612 if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
8613 char *zSql;
8614 char *zCollist = 0;
8615 sqlite3_stmt *pStmt;
8616 int tnum = 0;
drh491c5be2019-10-18 15:58:50 +00008617 int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */
8618 int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
drh2ce15c32017-07-11 13:34:40 +00008619 int i;
drh48d219a2018-04-23 18:38:48 +00008620 if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
8621 utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
8622 " .imposter off\n");
drh491c5be2019-10-18 15:58:50 +00008623 /* Also allowed, but not documented:
8624 **
8625 ** .imposter TABLE IMPOSTER
8626 **
8627 ** where TABLE is a WITHOUT ROWID table. In that case, the
8628 ** imposter is another WITHOUT ROWID table with the columns in
8629 ** storage order. */
drh2ce15c32017-07-11 13:34:40 +00008630 rc = 1;
8631 goto meta_command_exit;
8632 }
8633 open_db(p, 0);
drh48d219a2018-04-23 18:38:48 +00008634 if( nArg==2 ){
8635 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
8636 goto meta_command_exit;
8637 }
drh491c5be2019-10-18 15:58:50 +00008638 zSql = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00008639 "SELECT rootpage, 0 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00008640 " WHERE name='%q' AND type='index'"
8641 "UNION ALL "
drh067b92b2020-06-19 15:24:12 +00008642 "SELECT rootpage, 1 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00008643 " WHERE name='%q' AND type='table'"
8644 " AND sql LIKE '%%without%%rowid%%'",
8645 azArg[1], azArg[1]
8646 );
drh2ce15c32017-07-11 13:34:40 +00008647 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8648 sqlite3_free(zSql);
8649 if( sqlite3_step(pStmt)==SQLITE_ROW ){
8650 tnum = sqlite3_column_int(pStmt, 0);
drh491c5be2019-10-18 15:58:50 +00008651 isWO = sqlite3_column_int(pStmt, 1);
drh2ce15c32017-07-11 13:34:40 +00008652 }
8653 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00008654 zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
8655 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8656 sqlite3_free(zSql);
8657 i = 0;
drhe85e1da2021-10-01 21:01:07 +00008658 while( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00008659 char zLabel[20];
8660 const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
8661 i++;
8662 if( zCol==0 ){
8663 if( sqlite3_column_int(pStmt,1)==-1 ){
8664 zCol = "_ROWID_";
8665 }else{
8666 sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
8667 zCol = zLabel;
8668 }
8669 }
drh491c5be2019-10-18 15:58:50 +00008670 if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){
8671 lenPK = (int)strlen(zCollist);
8672 }
drh2ce15c32017-07-11 13:34:40 +00008673 if( zCollist==0 ){
8674 zCollist = sqlite3_mprintf("\"%w\"", zCol);
8675 }else{
8676 zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
8677 }
8678 }
8679 sqlite3_finalize(pStmt);
drh491c5be2019-10-18 15:58:50 +00008680 if( i==0 || tnum==0 ){
8681 utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
8682 rc = 1;
8683 sqlite3_free(zCollist);
8684 goto meta_command_exit;
8685 }
8686 if( lenPK==0 ) lenPK = 100000;
drh2ce15c32017-07-11 13:34:40 +00008687 zSql = sqlite3_mprintf(
drh491c5be2019-10-18 15:58:50 +00008688 "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
8689 azArg[2], zCollist, lenPK, zCollist);
drh2ce15c32017-07-11 13:34:40 +00008690 sqlite3_free(zCollist);
8691 rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
8692 if( rc==SQLITE_OK ){
8693 rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
8694 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
8695 if( rc ){
8696 utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
8697 }else{
8698 utf8_printf(stdout, "%s;\n", zSql);
8699 raw_printf(stdout,
drh491c5be2019-10-18 15:58:50 +00008700 "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
8701 azArg[1], isWO ? "table" : "index"
drh2ce15c32017-07-11 13:34:40 +00008702 );
8703 }
8704 }else{
8705 raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
8706 rc = 1;
8707 }
8708 sqlite3_free(zSql);
8709 }else
8710#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
8711
8712#ifdef SQLITE_ENABLE_IOTRACE
8713 if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
8714 SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
8715 if( iotrace && iotrace!=stdout ) fclose(iotrace);
8716 iotrace = 0;
8717 if( nArg<2 ){
8718 sqlite3IoTrace = 0;
8719 }else if( strcmp(azArg[1], "-")==0 ){
8720 sqlite3IoTrace = iotracePrintf;
8721 iotrace = stdout;
8722 }else{
8723 iotrace = fopen(azArg[1], "w");
8724 if( iotrace==0 ){
8725 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
8726 sqlite3IoTrace = 0;
8727 rc = 1;
8728 }else{
8729 sqlite3IoTrace = iotracePrintf;
8730 }
8731 }
8732 }else
8733#endif
8734
8735 if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
8736 static const struct {
8737 const char *zLimitName; /* Name of a limit */
8738 int limitCode; /* Integer code for that limit */
8739 } aLimit[] = {
8740 { "length", SQLITE_LIMIT_LENGTH },
8741 { "sql_length", SQLITE_LIMIT_SQL_LENGTH },
8742 { "column", SQLITE_LIMIT_COLUMN },
8743 { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
8744 { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
8745 { "vdbe_op", SQLITE_LIMIT_VDBE_OP },
8746 { "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
8747 { "attached", SQLITE_LIMIT_ATTACHED },
8748 { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
8749 { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER },
8750 { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
8751 { "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
8752 };
8753 int i, n2;
8754 open_db(p, 0);
8755 if( nArg==1 ){
8756 for(i=0; i<ArraySize(aLimit); i++){
8757 printf("%20s %d\n", aLimit[i].zLimitName,
8758 sqlite3_limit(p->db, aLimit[i].limitCode, -1));
8759 }
8760 }else if( nArg>3 ){
8761 raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
8762 rc = 1;
8763 goto meta_command_exit;
8764 }else{
8765 int iLimit = -1;
8766 n2 = strlen30(azArg[1]);
8767 for(i=0; i<ArraySize(aLimit); i++){
8768 if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
8769 if( iLimit<0 ){
8770 iLimit = i;
8771 }else{
8772 utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
8773 rc = 1;
8774 goto meta_command_exit;
8775 }
8776 }
8777 }
8778 if( iLimit<0 ){
8779 utf8_printf(stderr, "unknown limit: \"%s\"\n"
8780 "enter \".limits\" with no arguments for a list.\n",
8781 azArg[1]);
8782 rc = 1;
8783 goto meta_command_exit;
8784 }
8785 if( nArg==3 ){
8786 sqlite3_limit(p->db, aLimit[iLimit].limitCode,
8787 (int)integerValue(azArg[2]));
8788 }
8789 printf("%20s %d\n", aLimit[iLimit].zLimitName,
8790 sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
8791 }
8792 }else
8793
8794 if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
8795 open_db(p, 0);
8796 lintDotCommand(p, azArg, nArg);
8797 }else
8798
8799#ifndef SQLITE_OMIT_LOAD_EXTENSION
8800 if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
8801 const char *zFile, *zProc;
8802 char *zErrMsg = 0;
drhb97e2ad2021-08-26 18:31:39 +00008803 failIfSafeMode(p, "cannot run .load in safe mode");
drh2ce15c32017-07-11 13:34:40 +00008804 if( nArg<2 ){
8805 raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
8806 rc = 1;
8807 goto meta_command_exit;
8808 }
8809 zFile = azArg[1];
8810 zProc = nArg>=3 ? azArg[2] : 0;
8811 open_db(p, 0);
8812 rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
8813 if( rc!=SQLITE_OK ){
8814 utf8_printf(stderr, "Error: %s\n", zErrMsg);
8815 sqlite3_free(zErrMsg);
8816 rc = 1;
8817 }
8818 }else
8819#endif
8820
8821 if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
drhb97e2ad2021-08-26 18:31:39 +00008822 failIfSafeMode(p, "cannot run .log in safe mode");
drh2ce15c32017-07-11 13:34:40 +00008823 if( nArg!=2 ){
8824 raw_printf(stderr, "Usage: .log FILENAME\n");
8825 rc = 1;
8826 }else{
8827 const char *zFile = azArg[1];
8828 output_file_close(p->pLog);
drha92a01a2018-01-10 22:15:37 +00008829 p->pLog = output_file_open(zFile, 0);
drh2ce15c32017-07-11 13:34:40 +00008830 }
8831 }else
8832
8833 if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
8834 const char *zMode = nArg>=2 ? azArg[1] : "";
drhaf2770f2018-01-05 14:55:43 +00008835 int n2 = strlen30(zMode);
drh2ce15c32017-07-11 13:34:40 +00008836 int c2 = zMode[0];
8837 if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){
8838 p->mode = MODE_Line;
8839 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8840 }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
8841 p->mode = MODE_Column;
drhc0605082020-06-05 00:54:27 +00008842 if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){
8843 p->showHeader = 1;
8844 }
drh2ce15c32017-07-11 13:34:40 +00008845 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8846 }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
8847 p->mode = MODE_List;
8848 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
8849 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8850 }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){
8851 p->mode = MODE_Html;
8852 }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
8853 p->mode = MODE_Tcl;
8854 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
8855 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8856 }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
8857 p->mode = MODE_Csv;
8858 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
8859 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
8860 }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
8861 p->mode = MODE_List;
8862 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
8863 }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
8864 p->mode = MODE_Insert;
8865 set_table_name(p, nArg>=3 ? azArg[2] : "table");
8866 }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
8867 p->mode = MODE_Quote;
drhc6835732020-05-28 20:37:17 +00008868 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
8869 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +00008870 }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
8871 p->mode = MODE_Ascii;
8872 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
8873 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
drh30c54a02020-05-28 23:49:50 +00008874 }else if( c2=='m' && strncmp(azArg[1],"markdown",n2)==0 ){
8875 p->mode = MODE_Markdown;
8876 }else if( c2=='t' && strncmp(azArg[1],"table",n2)==0 ){
8877 p->mode = MODE_Table;
drh0908e382020-06-04 18:05:39 +00008878 }else if( c2=='b' && strncmp(azArg[1],"box",n2)==0 ){
8879 p->mode = MODE_Box;
drh5d88be82021-12-09 16:17:43 +00008880 }else if( c2=='c' && strncmp(azArg[1],"count",n2)==0 ){
8881 p->mode = MODE_Count;
8882 }else if( c2=='o' && strncmp(azArg[1],"off",n2)==0 ){
8883 p->mode = MODE_Off;
drh30c54a02020-05-28 23:49:50 +00008884 }else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){
8885 p->mode = MODE_Json;
drh2ce15c32017-07-11 13:34:40 +00008886 }else if( nArg==1 ){
8887 raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
8888 }else{
8889 raw_printf(stderr, "Error: mode should be one of: "
drh0908e382020-06-04 18:05:39 +00008890 "ascii box column csv html insert json line list markdown "
drh30c54a02020-05-28 23:49:50 +00008891 "quote table tabs tcl\n");
drh2ce15c32017-07-11 13:34:40 +00008892 rc = 1;
8893 }
8894 p->cMode = p->mode;
8895 }else
8896
drhb97e2ad2021-08-26 18:31:39 +00008897 if( c=='n' && strcmp(azArg[0], "nonce")==0 ){
8898 if( nArg!=2 ){
8899 raw_printf(stderr, "Usage: .nonce NONCE\n");
8900 rc = 1;
8901 }else if( p->zNonce==0 || strcmp(azArg[1],p->zNonce)!=0 ){
drhfe463172021-12-16 17:57:21 +00008902 raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n",
8903 p->lineno, azArg[1]);
drhb97e2ad2021-08-26 18:31:39 +00008904 exit(1);
drhe85e1da2021-10-01 21:01:07 +00008905 }else{
8906 p->bSafeMode = 0;
8907 return 0; /* Return immediately to bypass the safe mode reset
8908 ** at the end of this procedure */
drhb97e2ad2021-08-26 18:31:39 +00008909 }
drhb97e2ad2021-08-26 18:31:39 +00008910 }else
8911
drh2ce15c32017-07-11 13:34:40 +00008912 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
8913 if( nArg==2 ){
8914 sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
8915 "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
8916 }else{
8917 raw_printf(stderr, "Usage: .nullvalue STRING\n");
8918 rc = 1;
8919 }
8920 }else
8921
8922 if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
drh61fd4b92021-12-16 14:59:25 +00008923 const char *zFN = 0; /* Pointer to constant filename */
drhf30bbce2020-12-02 18:27:48 +00008924 char *zNewFilename = 0; /* Name of the database file to open */
8925 int iName = 1; /* Index in azArg[] of the filename */
8926 int newFlag = 0; /* True to delete file before opening */
dan1872c5b2021-12-02 14:16:30 +00008927 int openMode = SHELL_OPEN_UNSPEC;
8928
drh2ce15c32017-07-11 13:34:40 +00008929 /* Check for command-line arguments */
drhf30bbce2020-12-02 18:27:48 +00008930 for(iName=1; iName<nArg; iName++){
drh2ce15c32017-07-11 13:34:40 +00008931 const char *z = azArg[iName];
8932 if( optionMatch(z,"new") ){
8933 newFlag = 1;
drh3baed312018-03-08 18:14:41 +00008934#ifdef SQLITE_HAVE_ZLIB
drh1fa6d9f2018-01-06 21:46:01 +00008935 }else if( optionMatch(z, "zip") ){
dan1872c5b2021-12-02 14:16:30 +00008936 openMode = SHELL_OPEN_ZIPFILE;
drh1fa6d9f2018-01-06 21:46:01 +00008937#endif
8938 }else if( optionMatch(z, "append") ){
dan1872c5b2021-12-02 14:16:30 +00008939 openMode = SHELL_OPEN_APPENDVFS;
drhee269a62018-02-14 23:27:43 +00008940 }else if( optionMatch(z, "readonly") ){
dan1872c5b2021-12-02 14:16:30 +00008941 openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +00008942 }else if( optionMatch(z, "nofollow") ){
8943 p->openFlags |= SQLITE_OPEN_NOFOLLOW;
drh8d889af2021-05-08 17:18:23 +00008944#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +00008945 }else if( optionMatch(z, "deserialize") ){
dan1872c5b2021-12-02 14:16:30 +00008946 openMode = SHELL_OPEN_DESERIALIZE;
drh33746482018-12-13 15:06:26 +00008947 }else if( optionMatch(z, "hexdb") ){
dan1872c5b2021-12-02 14:16:30 +00008948 openMode = SHELL_OPEN_HEXDB;
drh6ca64482019-01-22 16:06:20 +00008949 }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
8950 p->szMax = integerValue(azArg[++iName]);
drh8d889af2021-05-08 17:18:23 +00008951#endif /* SQLITE_OMIT_DESERIALIZE */
drh2ce15c32017-07-11 13:34:40 +00008952 }else if( z[0]=='-' ){
8953 utf8_printf(stderr, "unknown option: %s\n", z);
8954 rc = 1;
8955 goto meta_command_exit;
drh61fd4b92021-12-16 14:59:25 +00008956 }else if( zFN ){
drhf30bbce2020-12-02 18:27:48 +00008957 utf8_printf(stderr, "extra argument: \"%s\"\n", z);
8958 rc = 1;
8959 goto meta_command_exit;
8960 }else{
drh61fd4b92021-12-16 14:59:25 +00008961 zFN = z;
drh2ce15c32017-07-11 13:34:40 +00008962 }
8963 }
dan1872c5b2021-12-02 14:16:30 +00008964
8965 /* Close the existing database */
8966 session_close_all(p, -1);
8967 close_db(p->db);
8968 p->db = 0;
8969 p->pAuxDb->zDbFilename = 0;
8970 sqlite3_free(p->pAuxDb->zFreeOnClose);
8971 p->pAuxDb->zFreeOnClose = 0;
8972 p->openMode = openMode;
8973 p->openFlags = 0;
8974 p->szMax = 0;
8975
drh2ce15c32017-07-11 13:34:40 +00008976 /* If a filename is specified, try to open it first */
drh61fd4b92021-12-16 14:59:25 +00008977 if( zFN || p->openMode==SHELL_OPEN_HEXDB ){
drhb97e2ad2021-08-26 18:31:39 +00008978 if( newFlag && !p->bSafeMode ) shellDeleteFile(zNewFilename);
8979 if( p->bSafeMode
8980 && p->openMode!=SHELL_OPEN_HEXDB
8981 && zNewFilename
8982 && strcmp(zNewFilename,":memory:")!=0
8983 ){
8984 failIfSafeMode(p, "cannot open disk-based database files in safe mode");
8985 }
drh61fd4b92021-12-16 14:59:25 +00008986 if( zFN ){
8987 zNewFilename = sqlite3_mprintf("%s", zFN);
8988 shell_check_oom(zNewFilename);
8989 }else{
8990 zNewFilename = 0;
8991 }
drh37407122021-07-23 18:43:58 +00008992 p->pAuxDb->zDbFilename = zNewFilename;
drhbe4ccb22018-05-17 20:04:24 +00008993 open_db(p, OPEN_DB_KEEPALIVE);
drh2ce15c32017-07-11 13:34:40 +00008994 if( p->db==0 ){
8995 utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
8996 sqlite3_free(zNewFilename);
8997 }else{
drh37407122021-07-23 18:43:58 +00008998 p->pAuxDb->zFreeOnClose = zNewFilename;
drh2ce15c32017-07-11 13:34:40 +00008999 }
9000 }
9001 if( p->db==0 ){
9002 /* As a fall-back open a TEMP database */
drh37407122021-07-23 18:43:58 +00009003 p->pAuxDb->zDbFilename = 0;
drh2ce15c32017-07-11 13:34:40 +00009004 open_db(p, 0);
9005 }
9006 }else
9007
drh13c20932018-01-10 21:41:55 +00009008 if( (c=='o'
9009 && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
9010 || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
drh2ce15c32017-07-11 13:34:40 +00009011 ){
drh4b0229a2021-02-17 13:19:22 +00009012 char *zFile = 0;
drha92a01a2018-01-10 22:15:37 +00009013 int bTxtMode = 0;
drh7a431002020-04-18 14:12:00 +00009014 int i;
9015 int eMode = 0;
9016 int bBOM = 0;
drh5415ab42020-04-23 20:45:46 +00009017 int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */
drh7a431002020-04-18 14:12:00 +00009018
drhb97e2ad2021-08-26 18:31:39 +00009019 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh7a431002020-04-18 14:12:00 +00009020 if( c=='e' ){
9021 eMode = 'x';
9022 bOnce = 2;
9023 }else if( strncmp(azArg[0],"once",n)==0 ){
9024 bOnce = 1;
drh13c20932018-01-10 21:41:55 +00009025 }
drh7a431002020-04-18 14:12:00 +00009026 for(i=1; i<nArg; i++){
9027 char *z = azArg[i];
9028 if( z[0]=='-' ){
9029 if( z[1]=='-' ) z++;
9030 if( strcmp(z,"-bom")==0 ){
9031 bBOM = 1;
9032 }else if( c!='e' && strcmp(z,"-x")==0 ){
9033 eMode = 'x'; /* spreadsheet */
9034 }else if( c!='e' && strcmp(z,"-e")==0 ){
9035 eMode = 'e'; /* text editor */
9036 }else{
9037 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n",
9038 azArg[i]);
9039 showHelp(p->out, azArg[0]);
9040 rc = 1;
9041 goto meta_command_exit;
9042 }
drh4b0229a2021-02-17 13:19:22 +00009043 }else if( zFile==0 && eMode!='e' && eMode!='x' ){
9044 zFile = sqlite3_mprintf("%s", z);
drhe3e25652021-12-16 13:29:28 +00009045 if( zFile && zFile[0]=='|' ){
drh4b0229a2021-02-17 13:19:22 +00009046 while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]);
9047 break;
9048 }
drh7a431002020-04-18 14:12:00 +00009049 }else{
9050 utf8_printf(p->out,"ERROR: extra parameter: \"%s\". Usage:\n",
9051 azArg[i]);
9052 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00009053 rc = 1;
drh4b0229a2021-02-17 13:19:22 +00009054 sqlite3_free(zFile);
drh2ce15c32017-07-11 13:34:40 +00009055 goto meta_command_exit;
9056 }
drh7a431002020-04-18 14:12:00 +00009057 }
drhe3e25652021-12-16 13:29:28 +00009058 if( zFile==0 ){
9059 zFile = sqlite3_mprintf("stdout");
9060 }
drh7a431002020-04-18 14:12:00 +00009061 if( bOnce ){
drh2ce15c32017-07-11 13:34:40 +00009062 p->outCount = 2;
9063 }else{
9064 p->outCount = 0;
9065 }
9066 output_reset(p);
drh04a28c32018-01-31 01:38:44 +00009067#ifndef SQLITE_NOHAVE_SYSTEM
drh7a431002020-04-18 14:12:00 +00009068 if( eMode=='e' || eMode=='x' ){
drh3c484e82018-01-10 22:27:21 +00009069 p->doXdgOpen = 1;
9070 outputModePush(p);
drh7a431002020-04-18 14:12:00 +00009071 if( eMode=='x' ){
9072 /* spreadsheet mode. Output as CSV. */
drh13c20932018-01-10 21:41:55 +00009073 newTempFile(p, "csv");
drh7a431002020-04-18 14:12:00 +00009074 ShellClearFlag(p, SHFLG_Echo);
drh13c20932018-01-10 21:41:55 +00009075 p->mode = MODE_Csv;
9076 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
9077 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
9078 }else{
drh7a431002020-04-18 14:12:00 +00009079 /* text editor mode */
drh13c20932018-01-10 21:41:55 +00009080 newTempFile(p, "txt");
drha92a01a2018-01-10 22:15:37 +00009081 bTxtMode = 1;
drh13c20932018-01-10 21:41:55 +00009082 }
drh4b0229a2021-02-17 13:19:22 +00009083 sqlite3_free(zFile);
9084 zFile = sqlite3_mprintf("%s", p->zTempFile);
drh13c20932018-01-10 21:41:55 +00009085 }
drh04a28c32018-01-31 01:38:44 +00009086#endif /* SQLITE_NOHAVE_SYSTEM */
drhe3e25652021-12-16 13:29:28 +00009087 shell_check_oom(zFile);
drh2ce15c32017-07-11 13:34:40 +00009088 if( zFile[0]=='|' ){
9089#ifdef SQLITE_OMIT_POPEN
9090 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
9091 rc = 1;
9092 p->out = stdout;
9093#else
9094 p->out = popen(zFile + 1, "w");
9095 if( p->out==0 ){
9096 utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
9097 p->out = stdout;
9098 rc = 1;
9099 }else{
drh7a431002020-04-18 14:12:00 +00009100 if( bBOM ) fprintf(p->out,"\357\273\277");
drh2ce15c32017-07-11 13:34:40 +00009101 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
9102 }
9103#endif
9104 }else{
drha92a01a2018-01-10 22:15:37 +00009105 p->out = output_file_open(zFile, bTxtMode);
drh2ce15c32017-07-11 13:34:40 +00009106 if( p->out==0 ){
9107 if( strcmp(zFile,"off")!=0 ){
9108 utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
9109 }
9110 p->out = stdout;
9111 rc = 1;
9112 } else {
drh7a431002020-04-18 14:12:00 +00009113 if( bBOM ) fprintf(p->out,"\357\273\277");
drh2ce15c32017-07-11 13:34:40 +00009114 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
9115 }
9116 }
drh4b0229a2021-02-17 13:19:22 +00009117 sqlite3_free(zFile);
drh2ce15c32017-07-11 13:34:40 +00009118 }else
9119
drh9cb02642019-02-28 20:10:52 +00009120 if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
9121 open_db(p,0);
9122 if( nArg<=1 ) goto parameter_syntax_error;
9123
9124 /* .parameter clear
9125 ** Clear all bind parameters by dropping the TEMP table that holds them.
9126 */
9127 if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
drh65c29fd2019-03-25 21:56:26 +00009128 sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
drh9cb02642019-02-28 20:10:52 +00009129 0, 0, 0);
9130 }else
9131
9132 /* .parameter list
9133 ** List all bind parameters.
9134 */
9135 if( nArg==2 && strcmp(azArg[1],"list")==0 ){
9136 sqlite3_stmt *pStmt = 0;
9137 int rx;
9138 int len = 0;
9139 rx = sqlite3_prepare_v2(p->db,
9140 "SELECT max(length(key)) "
drh65c29fd2019-03-25 21:56:26 +00009141 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drh9cb02642019-02-28 20:10:52 +00009142 if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
9143 len = sqlite3_column_int(pStmt, 0);
9144 if( len>40 ) len = 40;
9145 }
9146 sqlite3_finalize(pStmt);
9147 pStmt = 0;
9148 if( len ){
9149 rx = sqlite3_prepare_v2(p->db,
9150 "SELECT key, quote(value) "
drh65c29fd2019-03-25 21:56:26 +00009151 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drhe85e1da2021-10-01 21:01:07 +00009152 while( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
drh9cb02642019-02-28 20:10:52 +00009153 utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
9154 sqlite3_column_text(pStmt,1));
9155 }
9156 sqlite3_finalize(pStmt);
9157 }
9158 }else
9159
9160 /* .parameter init
9161 ** Make sure the TEMP table used to hold bind parameters exists.
9162 ** Create it if necessary.
9163 */
9164 if( nArg==2 && strcmp(azArg[1],"init")==0 ){
9165 bind_table_init(p);
9166 }else
9167
9168 /* .parameter set NAME VALUE
9169 ** Set or reset a bind parameter. NAME should be the full parameter
9170 ** name exactly as it appears in the query. (ex: $abc, @def). The
9171 ** VALUE can be in either SQL literal notation, or if not it will be
9172 ** understood to be a text string.
9173 */
9174 if( nArg==4 && strcmp(azArg[1],"set")==0 ){
9175 int rx;
9176 char *zSql;
9177 sqlite3_stmt *pStmt;
9178 const char *zKey = azArg[2];
9179 const char *zValue = azArg[3];
9180 bind_table_init(p);
9181 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009182 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00009183 "VALUES(%Q,%s);", zKey, zValue);
drhe3e25652021-12-16 13:29:28 +00009184 shell_check_oom(zSql);
drh9cb02642019-02-28 20:10:52 +00009185 pStmt = 0;
9186 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9187 sqlite3_free(zSql);
9188 if( rx!=SQLITE_OK ){
9189 sqlite3_finalize(pStmt);
9190 pStmt = 0;
9191 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009192 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00009193 "VALUES(%Q,%Q);", zKey, zValue);
drhe3e25652021-12-16 13:29:28 +00009194 shell_check_oom(zSql);
drh9cb02642019-02-28 20:10:52 +00009195 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9196 sqlite3_free(zSql);
9197 if( rx!=SQLITE_OK ){
9198 utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
9199 sqlite3_finalize(pStmt);
9200 pStmt = 0;
9201 rc = 1;
9202 }
9203 }
9204 sqlite3_step(pStmt);
9205 sqlite3_finalize(pStmt);
9206 }else
9207
9208 /* .parameter unset NAME
9209 ** Remove the NAME binding from the parameter binding table, if it
9210 ** exists.
9211 */
9212 if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
9213 char *zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009214 "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
drhe3e25652021-12-16 13:29:28 +00009215 shell_check_oom(zSql);
drh9cb02642019-02-28 20:10:52 +00009216 sqlite3_exec(p->db, zSql, 0, 0, 0);
9217 sqlite3_free(zSql);
9218 }else
9219 /* If no command name matches, show a syntax error */
9220 parameter_syntax_error:
9221 showHelp(p->out, "parameter");
9222 }else
9223
drh2ce15c32017-07-11 13:34:40 +00009224 if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
9225 int i;
9226 for(i=1; i<nArg; i++){
9227 if( i>1 ) raw_printf(p->out, " ");
9228 utf8_printf(p->out, "%s", azArg[i]);
9229 }
9230 raw_printf(p->out, "\n");
9231 }else
9232
drh569b1d92019-02-05 20:51:41 +00009233#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh3f83f592019-02-04 14:53:18 +00009234 if( c=='p' && n>=3 && strncmp(azArg[0], "progress", n)==0 ){
9235 int i;
drhfc4eeef2019-02-05 19:48:46 +00009236 int nn = 0;
drh3f83f592019-02-04 14:53:18 +00009237 p->flgProgress = 0;
9238 p->mxProgress = 0;
9239 p->nProgress = 0;
9240 for(i=1; i<nArg; i++){
9241 const char *z = azArg[i];
9242 if( z[0]=='-' ){
9243 z++;
9244 if( z[0]=='-' ) z++;
9245 if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009246 p->flgProgress |= SHELL_PROGRESS_QUIET;
drh3f83f592019-02-04 14:53:18 +00009247 continue;
9248 }
9249 if( strcmp(z,"reset")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009250 p->flgProgress |= SHELL_PROGRESS_RESET;
drh3f83f592019-02-04 14:53:18 +00009251 continue;
9252 }
9253 if( strcmp(z,"once")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009254 p->flgProgress |= SHELL_PROGRESS_ONCE;
drh3f83f592019-02-04 14:53:18 +00009255 continue;
9256 }
9257 if( strcmp(z,"limit")==0 ){
9258 if( i+1>=nArg ){
9259 utf8_printf(stderr, "Error: missing argument on --limit\n");
9260 rc = 1;
9261 goto meta_command_exit;
9262 }else{
9263 p->mxProgress = (int)integerValue(azArg[++i]);
9264 }
9265 continue;
9266 }
9267 utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
9268 rc = 1;
9269 goto meta_command_exit;
9270 }else{
drhfc4eeef2019-02-05 19:48:46 +00009271 nn = (int)integerValue(z);
drh3f83f592019-02-04 14:53:18 +00009272 }
9273 }
9274 open_db(p, 0);
drhfc4eeef2019-02-05 19:48:46 +00009275 sqlite3_progress_handler(p->db, nn, progress_handler, p);
drh3f83f592019-02-04 14:53:18 +00009276 }else
drh569b1d92019-02-05 20:51:41 +00009277#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
drh3f83f592019-02-04 14:53:18 +00009278
drh2ce15c32017-07-11 13:34:40 +00009279 if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
9280 if( nArg >= 2) {
9281 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
9282 }
9283 if( nArg >= 3) {
9284 strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
9285 }
9286 }else
9287
9288 if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
9289 rc = 2;
9290 }else
9291
9292 if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
drh60379d42018-12-13 18:30:01 +00009293 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +00009294 int savedLineno = p->lineno;
drhb97e2ad2021-08-26 18:31:39 +00009295 failIfSafeMode(p, "cannot run .read in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009296 if( nArg!=2 ){
9297 raw_printf(stderr, "Usage: .read FILE\n");
9298 rc = 1;
9299 goto meta_command_exit;
9300 }
drh30497f42020-08-26 10:50:48 +00009301 if( azArg[1][0]=='|' ){
drh9d59e3b2021-03-12 01:49:08 +00009302#ifdef SQLITE_OMIT_POPEN
9303 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
9304 rc = 1;
9305 p->out = stdout;
9306#else
drh30497f42020-08-26 10:50:48 +00009307 p->in = popen(azArg[1]+1, "r");
9308 if( p->in==0 ){
9309 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
9310 rc = 1;
9311 }else{
9312 rc = process_input(p);
9313 pclose(p->in);
9314 }
drh9d59e3b2021-03-12 01:49:08 +00009315#endif
larrybrd96bcc72021-09-17 21:12:47 +00009316 }else if( (p->in = openChrSource(azArg[1]))==0 ){
drh2ce15c32017-07-11 13:34:40 +00009317 utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
9318 rc = 1;
9319 }else{
drh60379d42018-12-13 18:30:01 +00009320 rc = process_input(p);
9321 fclose(p->in);
drh2ce15c32017-07-11 13:34:40 +00009322 }
drh60379d42018-12-13 18:30:01 +00009323 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +00009324 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +00009325 }else
9326
9327 if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
9328 const char *zSrcFile;
9329 const char *zDb;
9330 sqlite3 *pSrc;
9331 sqlite3_backup *pBackup;
9332 int nTimeout = 0;
9333
drhb97e2ad2021-08-26 18:31:39 +00009334 failIfSafeMode(p, "cannot run .restore in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009335 if( nArg==2 ){
9336 zSrcFile = azArg[1];
9337 zDb = "main";
9338 }else if( nArg==3 ){
9339 zSrcFile = azArg[2];
9340 zDb = azArg[1];
9341 }else{
9342 raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
9343 rc = 1;
9344 goto meta_command_exit;
9345 }
9346 rc = sqlite3_open(zSrcFile, &pSrc);
9347 if( rc!=SQLITE_OK ){
9348 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
drh9e804032018-05-18 17:11:50 +00009349 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009350 return 1;
9351 }
9352 open_db(p, 0);
9353 pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
9354 if( pBackup==0 ){
9355 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh9e804032018-05-18 17:11:50 +00009356 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009357 return 1;
9358 }
9359 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
9360 || rc==SQLITE_BUSY ){
9361 if( rc==SQLITE_BUSY ){
9362 if( nTimeout++ >= 3 ) break;
9363 sqlite3_sleep(100);
9364 }
9365 }
9366 sqlite3_backup_finish(pBackup);
9367 if( rc==SQLITE_DONE ){
9368 rc = 0;
9369 }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
9370 raw_printf(stderr, "Error: source database is busy\n");
9371 rc = 1;
9372 }else{
9373 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9374 rc = 1;
9375 }
drh9e804032018-05-18 17:11:50 +00009376 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009377 }else
9378
drh2ce15c32017-07-11 13:34:40 +00009379 if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
9380 if( nArg==2 ){
mistachkinb71aa092018-01-23 00:05:18 +00009381 p->scanstatsOn = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00009382#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
9383 raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
9384#endif
9385 }else{
9386 raw_printf(stderr, "Usage: .scanstats on|off\n");
9387 rc = 1;
9388 }
9389 }else
9390
9391 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
9392 ShellText sSelect;
9393 ShellState data;
9394 char *zErrMsg = 0;
drh667a2a22018-01-02 00:04:37 +00009395 const char *zDiv = "(";
drhceba7922018-01-01 21:28:25 +00009396 const char *zName = 0;
drh2ce15c32017-07-11 13:34:40 +00009397 int iSchema = 0;
drhceba7922018-01-01 21:28:25 +00009398 int bDebug = 0;
drhbbb29ec2020-10-12 14:56:47 +00009399 int bNoSystemTabs = 0;
drhceba7922018-01-01 21:28:25 +00009400 int ii;
drh2ce15c32017-07-11 13:34:40 +00009401
9402 open_db(p, 0);
9403 memcpy(&data, p, sizeof(data));
9404 data.showHeader = 0;
9405 data.cMode = data.mode = MODE_Semi;
9406 initText(&sSelect);
drhceba7922018-01-01 21:28:25 +00009407 for(ii=1; ii<nArg; ii++){
9408 if( optionMatch(azArg[ii],"indent") ){
9409 data.cMode = data.mode = MODE_Pretty;
9410 }else if( optionMatch(azArg[ii],"debug") ){
9411 bDebug = 1;
drhbbb29ec2020-10-12 14:56:47 +00009412 }else if( optionMatch(azArg[ii],"nosys") ){
9413 bNoSystemTabs = 1;
9414 }else if( azArg[ii][0]=='-' ){
9415 utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
9416 rc = 1;
9417 goto meta_command_exit;
drhceba7922018-01-01 21:28:25 +00009418 }else if( zName==0 ){
9419 zName = azArg[ii];
drh2ce15c32017-07-11 13:34:40 +00009420 }else{
drhbbb29ec2020-10-12 14:56:47 +00009421 raw_printf(stderr, "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
drhceba7922018-01-01 21:28:25 +00009422 rc = 1;
9423 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00009424 }
drh2ce15c32017-07-11 13:34:40 +00009425 }
drhceba7922018-01-01 21:28:25 +00009426 if( zName!=0 ){
drh067b92b2020-06-19 15:24:12 +00009427 int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0
drh346a70c2020-06-15 20:27:35 +00009428 || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
9429 || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
9430 || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
drh067b92b2020-06-19 15:24:12 +00009431 if( isSchema ){
drh2ce15c32017-07-11 13:34:40 +00009432 char *new_argv[2], *new_colv[2];
drhc22b7162018-01-01 20:11:23 +00009433 new_argv[0] = sqlite3_mprintf(
9434 "CREATE TABLE %s (\n"
drh2ce15c32017-07-11 13:34:40 +00009435 " type text,\n"
9436 " name text,\n"
9437 " tbl_name text,\n"
9438 " rootpage integer,\n"
9439 " sql text\n"
drh346a70c2020-06-15 20:27:35 +00009440 ")", zName);
drhe3e25652021-12-16 13:29:28 +00009441 shell_check_oom(new_argv[0]);
drh2ce15c32017-07-11 13:34:40 +00009442 new_argv[1] = 0;
9443 new_colv[0] = "sql";
9444 new_colv[1] = 0;
9445 callback(&data, 1, new_argv, new_colv);
drhc22b7162018-01-01 20:11:23 +00009446 sqlite3_free(new_argv[0]);
drh2ce15c32017-07-11 13:34:40 +00009447 }
drh2ce15c32017-07-11 13:34:40 +00009448 }
9449 if( zDiv ){
9450 sqlite3_stmt *pStmt = 0;
9451 rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
9452 -1, &pStmt, 0);
9453 if( rc ){
9454 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9455 sqlite3_finalize(pStmt);
9456 rc = 1;
9457 goto meta_command_exit;
9458 }
9459 appendText(&sSelect, "SELECT sql FROM", 0);
9460 iSchema = 0;
9461 while( sqlite3_step(pStmt)==SQLITE_ROW ){
9462 const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
9463 char zScNum[30];
9464 sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
9465 appendText(&sSelect, zDiv, 0);
9466 zDiv = " UNION ALL ";
drhceba7922018-01-01 21:28:25 +00009467 appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
9468 if( sqlite3_stricmp(zDb, "main")!=0 ){
drhea38f4f2019-07-13 17:21:47 +00009469 appendText(&sSelect, zDb, '\'');
drh2ce15c32017-07-11 13:34:40 +00009470 }else{
drhceba7922018-01-01 21:28:25 +00009471 appendText(&sSelect, "NULL", 0);
drh2ce15c32017-07-11 13:34:40 +00009472 }
drhceba7922018-01-01 21:28:25 +00009473 appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0);
9474 appendText(&sSelect, zScNum, 0);
9475 appendText(&sSelect, " AS snum, ", 0);
9476 appendText(&sSelect, zDb, '\'');
9477 appendText(&sSelect, " AS sname FROM ", 0);
drhea38f4f2019-07-13 17:21:47 +00009478 appendText(&sSelect, zDb, quoteChar(zDb));
drh067b92b2020-06-19 15:24:12 +00009479 appendText(&sSelect, ".sqlite_schema", 0);
drh2ce15c32017-07-11 13:34:40 +00009480 }
9481 sqlite3_finalize(pStmt);
drhcc3f3d12019-08-17 15:27:58 +00009482#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
drh667a2a22018-01-02 00:04:37 +00009483 if( zName ){
9484 appendText(&sSelect,
9485 " UNION ALL SELECT shell_module_schema(name),"
drhe2754c12019-08-26 12:50:01 +00009486 " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
9487 0);
drh667a2a22018-01-02 00:04:37 +00009488 }
drhcde7b772018-01-02 12:50:40 +00009489#endif
drh2ce15c32017-07-11 13:34:40 +00009490 appendText(&sSelect, ") WHERE ", 0);
drhceba7922018-01-01 21:28:25 +00009491 if( zName ){
9492 char *zQarg = sqlite3_mprintf("%Q", zName);
drhe3e25652021-12-16 13:29:28 +00009493 shell_check_oom(zQarg);
mistachkin9d107262018-03-23 14:24:34 +00009494 int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
9495 strchr(zName, '[') != 0;
drhceba7922018-01-01 21:28:25 +00009496 if( strchr(zName, '.') ){
drh2ce15c32017-07-11 13:34:40 +00009497 appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
9498 }else{
9499 appendText(&sSelect, "lower(tbl_name)", 0);
9500 }
mistachkin9d107262018-03-23 14:24:34 +00009501 appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0);
drh2ce15c32017-07-11 13:34:40 +00009502 appendText(&sSelect, zQarg, 0);
mistachkin9d107262018-03-23 14:24:34 +00009503 if( !bGlob ){
9504 appendText(&sSelect, " ESCAPE '\\' ", 0);
9505 }
drh2ce15c32017-07-11 13:34:40 +00009506 appendText(&sSelect, " AND ", 0);
9507 sqlite3_free(zQarg);
9508 }
drhbbb29ec2020-10-12 14:56:47 +00009509 if( bNoSystemTabs ){
9510 appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
9511 }
9512 appendText(&sSelect, "sql IS NOT NULL"
drh2ce15c32017-07-11 13:34:40 +00009513 " ORDER BY snum, rowid", 0);
drhceba7922018-01-01 21:28:25 +00009514 if( bDebug ){
9515 utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
9516 }else{
9517 rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
9518 }
drh2ce15c32017-07-11 13:34:40 +00009519 freeText(&sSelect);
9520 }
9521 if( zErrMsg ){
9522 utf8_printf(stderr,"Error: %s\n", zErrMsg);
9523 sqlite3_free(zErrMsg);
9524 rc = 1;
9525 }else if( rc != SQLITE_OK ){
9526 raw_printf(stderr,"Error: querying schema information\n");
9527 rc = 1;
9528 }else{
9529 rc = 0;
9530 }
9531 }else
9532
drh2ce15c32017-07-11 13:34:40 +00009533 if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
drhfda8e492020-12-04 16:04:45 +00009534 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
drhc0622a42020-12-04 01:17:57 +00009535 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
drh2ce15c32017-07-11 13:34:40 +00009536 }else
drh2ce15c32017-07-11 13:34:40 +00009537
9538#if defined(SQLITE_ENABLE_SESSION)
9539 if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
drh37407122021-07-23 18:43:58 +00009540 struct AuxDb *pAuxDb = p->pAuxDb;
9541 OpenSession *pSession = &pAuxDb->aSession[0];
drh2ce15c32017-07-11 13:34:40 +00009542 char **azCmd = &azArg[1];
9543 int iSes = 0;
9544 int nCmd = nArg - 1;
9545 int i;
9546 if( nArg<=1 ) goto session_syntax_error;
9547 open_db(p, 0);
9548 if( nArg>=3 ){
drh37407122021-07-23 18:43:58 +00009549 for(iSes=0; iSes<pAuxDb->nSession; iSes++){
9550 if( strcmp(pAuxDb->aSession[iSes].zName, azArg[1])==0 ) break;
drh2ce15c32017-07-11 13:34:40 +00009551 }
drh37407122021-07-23 18:43:58 +00009552 if( iSes<pAuxDb->nSession ){
9553 pSession = &pAuxDb->aSession[iSes];
drh2ce15c32017-07-11 13:34:40 +00009554 azCmd++;
9555 nCmd--;
9556 }else{
drh37407122021-07-23 18:43:58 +00009557 pSession = &pAuxDb->aSession[0];
drh2ce15c32017-07-11 13:34:40 +00009558 iSes = 0;
9559 }
9560 }
9561
9562 /* .session attach TABLE
9563 ** Invoke the sqlite3session_attach() interface to attach a particular
9564 ** table so that it is never filtered.
9565 */
9566 if( strcmp(azCmd[0],"attach")==0 ){
9567 if( nCmd!=2 ) goto session_syntax_error;
9568 if( pSession->p==0 ){
9569 session_not_open:
9570 raw_printf(stderr, "ERROR: No sessions are open\n");
9571 }else{
9572 rc = sqlite3session_attach(pSession->p, azCmd[1]);
9573 if( rc ){
9574 raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
9575 rc = 0;
9576 }
9577 }
9578 }else
9579
9580 /* .session changeset FILE
9581 ** .session patchset FILE
9582 ** Write a changeset or patchset into a file. The file is overwritten.
9583 */
9584 if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
9585 FILE *out = 0;
drhb97e2ad2021-08-26 18:31:39 +00009586 failIfSafeMode(p, "cannot run \".session %s\" in safe mode", azCmd[0]);
drh2ce15c32017-07-11 13:34:40 +00009587 if( nCmd!=2 ) goto session_syntax_error;
9588 if( pSession->p==0 ) goto session_not_open;
9589 out = fopen(azCmd[1], "wb");
9590 if( out==0 ){
drhe2754c12019-08-26 12:50:01 +00009591 utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
9592 azCmd[1]);
drh2ce15c32017-07-11 13:34:40 +00009593 }else{
9594 int szChng;
9595 void *pChng;
9596 if( azCmd[0][0]=='c' ){
9597 rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
9598 }else{
9599 rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
9600 }
9601 if( rc ){
9602 printf("Error: error code %d\n", rc);
9603 rc = 0;
9604 }
9605 if( pChng
9606 && fwrite(pChng, szChng, 1, out)!=1 ){
9607 raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
9608 szChng);
9609 }
9610 sqlite3_free(pChng);
9611 fclose(out);
9612 }
9613 }else
9614
9615 /* .session close
9616 ** Close the identified session
9617 */
9618 if( strcmp(azCmd[0], "close")==0 ){
9619 if( nCmd!=1 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009620 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009621 session_close(pSession);
drh37407122021-07-23 18:43:58 +00009622 pAuxDb->aSession[iSes] = pAuxDb->aSession[--pAuxDb->nSession];
drh2ce15c32017-07-11 13:34:40 +00009623 }
9624 }else
9625
9626 /* .session enable ?BOOLEAN?
9627 ** Query or set the enable flag
9628 */
9629 if( strcmp(azCmd[0], "enable")==0 ){
9630 int ii;
9631 if( nCmd>2 ) goto session_syntax_error;
9632 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
drh37407122021-07-23 18:43:58 +00009633 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009634 ii = sqlite3session_enable(pSession->p, ii);
9635 utf8_printf(p->out, "session %s enable flag = %d\n",
9636 pSession->zName, ii);
9637 }
9638 }else
9639
9640 /* .session filter GLOB ....
9641 ** Set a list of GLOB patterns of table names to be excluded.
9642 */
9643 if( strcmp(azCmd[0], "filter")==0 ){
9644 int ii, nByte;
9645 if( nCmd<2 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009646 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009647 for(ii=0; ii<pSession->nFilter; ii++){
9648 sqlite3_free(pSession->azFilter[ii]);
9649 }
9650 sqlite3_free(pSession->azFilter);
9651 nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
9652 pSession->azFilter = sqlite3_malloc( nByte );
9653 if( pSession->azFilter==0 ){
9654 raw_printf(stderr, "Error: out or memory\n");
9655 exit(1);
9656 }
9657 for(ii=1; ii<nCmd; ii++){
drhe3e25652021-12-16 13:29:28 +00009658 char *x = pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
9659 shell_check_oom(x);
drh2ce15c32017-07-11 13:34:40 +00009660 }
9661 pSession->nFilter = ii-1;
9662 }
9663 }else
9664
9665 /* .session indirect ?BOOLEAN?
9666 ** Query or set the indirect flag
9667 */
9668 if( strcmp(azCmd[0], "indirect")==0 ){
9669 int ii;
9670 if( nCmd>2 ) goto session_syntax_error;
9671 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
drh37407122021-07-23 18:43:58 +00009672 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009673 ii = sqlite3session_indirect(pSession->p, ii);
9674 utf8_printf(p->out, "session %s indirect flag = %d\n",
9675 pSession->zName, ii);
9676 }
9677 }else
9678
9679 /* .session isempty
9680 ** Determine if the session is empty
9681 */
9682 if( strcmp(azCmd[0], "isempty")==0 ){
9683 int ii;
9684 if( nCmd!=1 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009685 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009686 ii = sqlite3session_isempty(pSession->p);
9687 utf8_printf(p->out, "session %s isempty flag = %d\n",
9688 pSession->zName, ii);
9689 }
9690 }else
9691
9692 /* .session list
9693 ** List all currently open sessions
9694 */
9695 if( strcmp(azCmd[0],"list")==0 ){
drh37407122021-07-23 18:43:58 +00009696 for(i=0; i<pAuxDb->nSession; i++){
9697 utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName);
drh2ce15c32017-07-11 13:34:40 +00009698 }
9699 }else
9700
9701 /* .session open DB NAME
9702 ** Open a new session called NAME on the attached database DB.
9703 ** DB is normally "main".
9704 */
9705 if( strcmp(azCmd[0],"open")==0 ){
9706 char *zName;
9707 if( nCmd!=3 ) goto session_syntax_error;
9708 zName = azCmd[2];
9709 if( zName[0]==0 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009710 for(i=0; i<pAuxDb->nSession; i++){
9711 if( strcmp(pAuxDb->aSession[i].zName,zName)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009712 utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
9713 goto meta_command_exit;
9714 }
9715 }
drh37407122021-07-23 18:43:58 +00009716 if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){
9717 raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession));
drh2ce15c32017-07-11 13:34:40 +00009718 goto meta_command_exit;
9719 }
drh37407122021-07-23 18:43:58 +00009720 pSession = &pAuxDb->aSession[pAuxDb->nSession];
drh2ce15c32017-07-11 13:34:40 +00009721 rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
9722 if( rc ){
9723 raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
9724 rc = 0;
9725 goto meta_command_exit;
9726 }
9727 pSession->nFilter = 0;
9728 sqlite3session_table_filter(pSession->p, session_filter, pSession);
drh37407122021-07-23 18:43:58 +00009729 pAuxDb->nSession++;
drh2ce15c32017-07-11 13:34:40 +00009730 pSession->zName = sqlite3_mprintf("%s", zName);
drhe3e25652021-12-16 13:29:28 +00009731 shell_check_oom(pSession->zName);
drh2ce15c32017-07-11 13:34:40 +00009732 }else
9733 /* If no command name matches, show a syntax error */
9734 session_syntax_error:
drheb7f2a02018-09-26 18:02:32 +00009735 showHelp(p->out, "session");
drh2ce15c32017-07-11 13:34:40 +00009736 }else
9737#endif
9738
9739#ifdef SQLITE_DEBUG
9740 /* Undocumented commands for internal testing. Subject to change
9741 ** without notice. */
9742 if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
9743 if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
9744 int i, v;
9745 for(i=1; i<nArg; i++){
9746 v = booleanValue(azArg[i]);
9747 utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
9748 }
9749 }
9750 if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
9751 int i; sqlite3_int64 v;
9752 for(i=1; i<nArg; i++){
9753 char zBuf[200];
9754 v = integerValue(azArg[i]);
9755 sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
9756 utf8_printf(p->out, "%s", zBuf);
9757 }
9758 }
9759 }else
9760#endif
9761
9762 if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){
9763 int bIsInit = 0; /* True to initialize the SELFTEST table */
9764 int bVerbose = 0; /* Verbose output */
9765 int bSelftestExists; /* True if SELFTEST already exists */
9766 int i, k; /* Loop counters */
9767 int nTest = 0; /* Number of tests runs */
9768 int nErr = 0; /* Number of errors seen */
9769 ShellText str; /* Answer for a query */
9770 sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
9771
9772 open_db(p,0);
9773 for(i=1; i<nArg; i++){
9774 const char *z = azArg[i];
9775 if( z[0]=='-' && z[1]=='-' ) z++;
9776 if( strcmp(z,"-init")==0 ){
9777 bIsInit = 1;
9778 }else
9779 if( strcmp(z,"-v")==0 ){
9780 bVerbose++;
9781 }else
9782 {
9783 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
9784 azArg[i], azArg[0]);
9785 raw_printf(stderr, "Should be one of: --init -v\n");
9786 rc = 1;
9787 goto meta_command_exit;
9788 }
9789 }
9790 if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
9791 != SQLITE_OK ){
9792 bSelftestExists = 0;
9793 }else{
9794 bSelftestExists = 1;
9795 }
9796 if( bIsInit ){
9797 createSelftestTable(p);
9798 bSelftestExists = 1;
9799 }
9800 initText(&str);
9801 appendText(&str, "x", 0);
9802 for(k=bSelftestExists; k>=0; k--){
9803 if( k==1 ){
9804 rc = sqlite3_prepare_v2(p->db,
9805 "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
9806 -1, &pStmt, 0);
9807 }else{
9808 rc = sqlite3_prepare_v2(p->db,
9809 "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
9810 " (1,'run','PRAGMA integrity_check','ok')",
9811 -1, &pStmt, 0);
9812 }
9813 if( rc ){
9814 raw_printf(stderr, "Error querying the selftest table\n");
9815 rc = 1;
9816 sqlite3_finalize(pStmt);
9817 goto meta_command_exit;
9818 }
9819 for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
9820 int tno = sqlite3_column_int(pStmt, 0);
9821 const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
9822 const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
9823 const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
9824
drh621a5e02021-12-16 17:35:27 +00009825 if( zOp==0 ) continue;
9826 if( zSql==0 ) continue;
9827 if( zAns==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00009828 k = 0;
9829 if( bVerbose>0 ){
drh2ce15c32017-07-11 13:34:40 +00009830 printf("%d: %s %s\n", tno, zOp, zSql);
drh2ce15c32017-07-11 13:34:40 +00009831 }
9832 if( strcmp(zOp,"memo")==0 ){
9833 utf8_printf(p->out, "%s\n", zSql);
9834 }else
9835 if( strcmp(zOp,"run")==0 ){
9836 char *zErrMsg = 0;
9837 str.n = 0;
9838 str.z[0] = 0;
9839 rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
9840 nTest++;
9841 if( bVerbose ){
9842 utf8_printf(p->out, "Result: %s\n", str.z);
9843 }
9844 if( rc || zErrMsg ){
9845 nErr++;
9846 rc = 1;
9847 utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
9848 sqlite3_free(zErrMsg);
9849 }else if( strcmp(zAns,str.z)!=0 ){
9850 nErr++;
9851 rc = 1;
9852 utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
9853 utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z);
9854 }
9855 }else
9856 {
9857 utf8_printf(stderr,
9858 "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
9859 rc = 1;
9860 break;
9861 }
9862 } /* End loop over rows of content from SELFTEST */
9863 sqlite3_finalize(pStmt);
9864 } /* End loop over k */
9865 freeText(&str);
9866 utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
9867 }else
9868
9869 if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
9870 if( nArg<2 || nArg>3 ){
9871 raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
9872 rc = 1;
9873 }
9874 if( nArg>=2 ){
9875 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
9876 "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
9877 }
9878 if( nArg>=3 ){
9879 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator,
9880 "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]);
9881 }
9882 }else
9883
9884 if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){
9885 const char *zLike = 0; /* Which table to checksum. 0 means everything */
9886 int i; /* Loop counter */
9887 int bSchema = 0; /* Also hash the schema */
9888 int bSeparate = 0; /* Hash each table separately */
9889 int iSize = 224; /* Hash algorithm to use */
9890 int bDebug = 0; /* Only show the query that would have run */
9891 sqlite3_stmt *pStmt; /* For querying tables names */
9892 char *zSql; /* SQL to be run */
9893 char *zSep; /* Separator */
9894 ShellText sSql; /* Complete SQL for the query to run the hash */
9895 ShellText sQuery; /* Set of queries used to read all content */
9896 open_db(p, 0);
9897 for(i=1; i<nArg; i++){
9898 const char *z = azArg[i];
9899 if( z[0]=='-' ){
9900 z++;
9901 if( z[0]=='-' ) z++;
9902 if( strcmp(z,"schema")==0 ){
9903 bSchema = 1;
9904 }else
9905 if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
9906 || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
9907 ){
9908 iSize = atoi(&z[5]);
9909 }else
9910 if( strcmp(z,"debug")==0 ){
9911 bDebug = 1;
9912 }else
9913 {
9914 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
9915 azArg[i], azArg[0]);
drhe2754c12019-08-26 12:50:01 +00009916 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00009917 rc = 1;
9918 goto meta_command_exit;
9919 }
9920 }else if( zLike ){
9921 raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
9922 rc = 1;
9923 goto meta_command_exit;
9924 }else{
9925 zLike = z;
9926 bSeparate = 1;
drhcedfecf2018-03-23 12:59:10 +00009927 if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1;
drh2ce15c32017-07-11 13:34:40 +00009928 }
9929 }
9930 if( bSchema ){
drh067b92b2020-06-19 15:24:12 +00009931 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00009932 " WHERE type='table' AND coalesce(rootpage,0)>1"
drh067b92b2020-06-19 15:24:12 +00009933 " UNION ALL SELECT 'sqlite_schema'"
drh2ce15c32017-07-11 13:34:40 +00009934 " ORDER BY 1 collate nocase";
9935 }else{
drh067b92b2020-06-19 15:24:12 +00009936 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00009937 " WHERE type='table' AND coalesce(rootpage,0)>1"
9938 " AND name NOT LIKE 'sqlite_%'"
9939 " ORDER BY 1 collate nocase";
9940 }
9941 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9942 initText(&sQuery);
9943 initText(&sSql);
9944 appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
9945 zSep = "VALUES(";
9946 while( SQLITE_ROW==sqlite3_step(pStmt) ){
9947 const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
drh621a5e02021-12-16 17:35:27 +00009948 if( zTab==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00009949 if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
9950 if( strncmp(zTab, "sqlite_",7)!=0 ){
9951 appendText(&sQuery,"SELECT * FROM ", 0);
9952 appendText(&sQuery,zTab,'"');
9953 appendText(&sQuery," NOT INDEXED;", 0);
drh067b92b2020-06-19 15:24:12 +00009954 }else if( strcmp(zTab, "sqlite_schema")==0 ){
9955 appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00009956 " ORDER BY name;", 0);
9957 }else if( strcmp(zTab, "sqlite_sequence")==0 ){
9958 appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
9959 " ORDER BY name;", 0);
9960 }else if( strcmp(zTab, "sqlite_stat1")==0 ){
9961 appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
9962 " ORDER BY tbl,idx;", 0);
drh175b8f02019-08-08 15:24:17 +00009963 }else if( strcmp(zTab, "sqlite_stat4")==0 ){
drh2ce15c32017-07-11 13:34:40 +00009964 appendText(&sQuery, "SELECT * FROM ", 0);
9965 appendText(&sQuery, zTab, 0);
9966 appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
9967 }
9968 appendText(&sSql, zSep, 0);
9969 appendText(&sSql, sQuery.z, '\'');
9970 sQuery.n = 0;
9971 appendText(&sSql, ",", 0);
9972 appendText(&sSql, zTab, '\'');
9973 zSep = "),(";
9974 }
9975 sqlite3_finalize(pStmt);
9976 if( bSeparate ){
9977 zSql = sqlite3_mprintf(
9978 "%s))"
9979 " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
9980 " FROM [sha3sum$query]",
9981 sSql.z, iSize);
9982 }else{
9983 zSql = sqlite3_mprintf(
9984 "%s))"
9985 " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
9986 " FROM [sha3sum$query]",
9987 sSql.z, iSize);
9988 }
drhe3e25652021-12-16 13:29:28 +00009989 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +00009990 freeText(&sQuery);
9991 freeText(&sSql);
9992 if( bDebug ){
9993 utf8_printf(p->out, "%s\n", zSql);
9994 }else{
drha10b9992018-03-09 15:24:33 +00009995 shell_exec(p, zSql, 0);
drh2ce15c32017-07-11 13:34:40 +00009996 }
9997 sqlite3_free(zSql);
9998 }else
9999
drh04a28c32018-01-31 01:38:44 +000010000#ifndef SQLITE_NOHAVE_SYSTEM
drh2ce15c32017-07-11 13:34:40 +000010001 if( c=='s'
10002 && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
10003 ){
10004 char *zCmd;
10005 int i, x;
drhb97e2ad2021-08-26 18:31:39 +000010006 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh2ce15c32017-07-11 13:34:40 +000010007 if( nArg<2 ){
10008 raw_printf(stderr, "Usage: .system COMMAND\n");
10009 rc = 1;
10010 goto meta_command_exit;
10011 }
10012 zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
drhe3e25652021-12-16 13:29:28 +000010013 for(i=2; i<nArg && zCmd!=0; i++){
drh2ce15c32017-07-11 13:34:40 +000010014 zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
10015 zCmd, azArg[i]);
10016 }
drhe3e25652021-12-16 13:29:28 +000010017 x = zCmd!=0 ? system(zCmd) : 1;
drh2ce15c32017-07-11 13:34:40 +000010018 sqlite3_free(zCmd);
10019 if( x ) raw_printf(stderr, "System command returns %d\n", x);
10020 }else
drh04a28c32018-01-31 01:38:44 +000010021#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
drh2ce15c32017-07-11 13:34:40 +000010022
10023 if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
drhada70452017-12-21 21:02:27 +000010024 static const char *azBool[] = { "off", "on", "trigger", "full"};
drha6e6cf22021-01-09 19:10:04 +000010025 const char *zOut;
drh2ce15c32017-07-11 13:34:40 +000010026 int i;
10027 if( nArg!=1 ){
10028 raw_printf(stderr, "Usage: .show\n");
10029 rc = 1;
10030 goto meta_command_exit;
10031 }
10032 utf8_printf(p->out, "%12.12s: %s\n","echo",
10033 azBool[ShellHasFlag(p, SHFLG_Echo)]);
10034 utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
10035 utf8_printf(p->out, "%12.12s: %s\n","explain",
10036 p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
10037 utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
10038 utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
10039 utf8_printf(p->out, "%12.12s: ", "nullvalue");
10040 output_c_string(p->out, p->nullValue);
10041 raw_printf(p->out, "\n");
10042 utf8_printf(p->out,"%12.12s: %s\n","output",
10043 strlen30(p->outfile) ? p->outfile : "stdout");
10044 utf8_printf(p->out,"%12.12s: ", "colseparator");
10045 output_c_string(p->out, p->colSeparator);
10046 raw_printf(p->out, "\n");
10047 utf8_printf(p->out,"%12.12s: ", "rowseparator");
10048 output_c_string(p->out, p->rowSeparator);
10049 raw_printf(p->out, "\n");
drha6e6cf22021-01-09 19:10:04 +000010050 switch( p->statsOn ){
10051 case 0: zOut = "off"; break;
10052 default: zOut = "on"; break;
10053 case 2: zOut = "stmt"; break;
10054 case 3: zOut = "vmstep"; break;
10055 }
10056 utf8_printf(p->out, "%12.12s: %s\n","stats", zOut);
drh2ce15c32017-07-11 13:34:40 +000010057 utf8_printf(p->out, "%12.12s: ", "width");
drh0285d982020-05-29 14:38:43 +000010058 for (i=0;i<p->nWidth;i++) {
drh2ce15c32017-07-11 13:34:40 +000010059 raw_printf(p->out, "%d ", p->colWidth[i]);
10060 }
10061 raw_printf(p->out, "\n");
10062 utf8_printf(p->out, "%12.12s: %s\n", "filename",
drh37407122021-07-23 18:43:58 +000010063 p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : "");
drh2ce15c32017-07-11 13:34:40 +000010064 }else
10065
10066 if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
10067 if( nArg==2 ){
drha6e6cf22021-01-09 19:10:04 +000010068 if( strcmp(azArg[1],"stmt")==0 ){
10069 p->statsOn = 2;
10070 }else if( strcmp(azArg[1],"vmstep")==0 ){
10071 p->statsOn = 3;
10072 }else{
10073 p->statsOn = (u8)booleanValue(azArg[1]);
10074 }
drh2ce15c32017-07-11 13:34:40 +000010075 }else if( nArg==1 ){
10076 display_stats(p->db, p, 0);
10077 }else{
drha6e6cf22021-01-09 19:10:04 +000010078 raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n");
drh2ce15c32017-07-11 13:34:40 +000010079 rc = 1;
10080 }
10081 }else
10082
10083 if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0)
10084 || (c=='i' && (strncmp(azArg[0], "indices", n)==0
10085 || strncmp(azArg[0], "indexes", n)==0) )
10086 ){
10087 sqlite3_stmt *pStmt;
10088 char **azResult;
10089 int nRow, nAlloc;
10090 int ii;
10091 ShellText s;
10092 initText(&s);
10093 open_db(p, 0);
10094 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
drh9e804032018-05-18 17:11:50 +000010095 if( rc ){
10096 sqlite3_finalize(pStmt);
10097 return shellDatabaseError(p->db);
10098 }
drh2ce15c32017-07-11 13:34:40 +000010099
10100 if( nArg>2 && c=='i' ){
10101 /* It is an historical accident that the .indexes command shows an error
10102 ** when called with the wrong number of arguments whereas the .tables
10103 ** command does not. */
10104 raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
10105 rc = 1;
drh9e804032018-05-18 17:11:50 +000010106 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +000010107 goto meta_command_exit;
10108 }
10109 for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
10110 const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
10111 if( zDbName==0 ) continue;
10112 if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0);
10113 if( sqlite3_stricmp(zDbName, "main")==0 ){
10114 appendText(&s, "SELECT name FROM ", 0);
10115 }else{
10116 appendText(&s, "SELECT ", 0);
10117 appendText(&s, zDbName, '\'');
10118 appendText(&s, "||'.'||name FROM ", 0);
10119 }
10120 appendText(&s, zDbName, '"');
drh067b92b2020-06-19 15:24:12 +000010121 appendText(&s, ".sqlite_schema ", 0);
drh2ce15c32017-07-11 13:34:40 +000010122 if( c=='t' ){
10123 appendText(&s," WHERE type IN ('table','view')"
10124 " AND name NOT LIKE 'sqlite_%'"
10125 " AND name LIKE ?1", 0);
10126 }else{
10127 appendText(&s," WHERE type='index'"
10128 " AND tbl_name LIKE ?1", 0);
10129 }
10130 }
10131 rc = sqlite3_finalize(pStmt);
drhe85e1da2021-10-01 21:01:07 +000010132 if( rc==SQLITE_OK ){
10133 appendText(&s, " ORDER BY 1", 0);
10134 rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
10135 }
drh2ce15c32017-07-11 13:34:40 +000010136 freeText(&s);
10137 if( rc ) return shellDatabaseError(p->db);
10138
10139 /* Run the SQL statement prepared by the above block. Store the results
10140 ** as an array of nul-terminated strings in azResult[]. */
10141 nRow = nAlloc = 0;
10142 azResult = 0;
10143 if( nArg>1 ){
10144 sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
10145 }else{
10146 sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
10147 }
10148 while( sqlite3_step(pStmt)==SQLITE_ROW ){
10149 if( nRow>=nAlloc ){
10150 char **azNew;
10151 int n2 = nAlloc*2 + 10;
10152 azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
drhe3e25652021-12-16 13:29:28 +000010153 shell_check_oom(azNew);
drh2ce15c32017-07-11 13:34:40 +000010154 nAlloc = n2;
10155 azResult = azNew;
10156 }
10157 azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
drhe3e25652021-12-16 13:29:28 +000010158 shell_check_oom(azResult[nRow]);
drh2ce15c32017-07-11 13:34:40 +000010159 nRow++;
10160 }
10161 if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
10162 rc = shellDatabaseError(p->db);
10163 }
10164
10165 /* Pretty-print the contents of array azResult[] to the output */
10166 if( rc==0 && nRow>0 ){
10167 int len, maxlen = 0;
10168 int i, j;
10169 int nPrintCol, nPrintRow;
10170 for(i=0; i<nRow; i++){
10171 len = strlen30(azResult[i]);
10172 if( len>maxlen ) maxlen = len;
10173 }
10174 nPrintCol = 80/(maxlen+2);
10175 if( nPrintCol<1 ) nPrintCol = 1;
10176 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
10177 for(i=0; i<nPrintRow; i++){
10178 for(j=i; j<nRow; j+=nPrintRow){
10179 char *zSp = j<nPrintRow ? "" : " ";
10180 utf8_printf(p->out, "%s%-*s", zSp, maxlen,
10181 azResult[j] ? azResult[j]:"");
10182 }
10183 raw_printf(p->out, "\n");
10184 }
10185 }
10186
10187 for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
10188 sqlite3_free(azResult);
10189 }else
10190
10191 /* Begin redirecting output to the file "testcase-out.txt" */
10192 if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
10193 output_reset(p);
drha92a01a2018-01-10 22:15:37 +000010194 p->out = output_file_open("testcase-out.txt", 0);
drh2ce15c32017-07-11 13:34:40 +000010195 if( p->out==0 ){
10196 raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
10197 }
10198 if( nArg>=2 ){
10199 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
10200 }else{
10201 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
10202 }
10203 }else
10204
10205#ifndef SQLITE_UNTESTABLE
drh35f51a42017-11-15 17:07:22 +000010206 if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010207 static const struct {
10208 const char *zCtrlName; /* Name of a test-control option */
10209 int ctrlCode; /* Integer code for that option */
drh38ed1ce2021-12-06 15:24:36 +000010210 int unSafe; /* Not valid for --safe mode */
drhef302e82017-11-15 19:14:08 +000010211 const char *zUsage; /* Usage notes */
drh2ce15c32017-07-11 13:34:40 +000010212 } aCtrl[] = {
drh38ed1ce2021-12-06 15:24:36 +000010213 { "always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" },
10214 { "assert", SQLITE_TESTCTRL_ASSERT, 1, "BOOLEAN" },
10215 /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, "" },*/
10216 /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "" },*/
10217 { "byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" },
10218 { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" },
10219 /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"" },*/
10220 { "imposter", SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"},
10221 { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,"" },
10222 { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN" },
10223 { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" },
10224 { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" },
drh0d9de992017-12-26 18:04:23 +000010225#ifdef YYCOVERAGE
drh38ed1ce2021-12-06 15:24:36 +000010226 { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE,0,"" },
drh0d9de992017-12-26 18:04:23 +000010227#endif
drh38ed1ce2021-12-06 15:24:36 +000010228 { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET " },
10229 { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" },
10230 { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" },
10231 { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" },
10232 { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" },
10233 { "sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" },
10234 { "tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" },
drh2ce15c32017-07-11 13:34:40 +000010235 };
10236 int testctrl = -1;
drhef302e82017-11-15 19:14:08 +000010237 int iCtrl = -1;
10238 int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */
10239 int isOk = 0;
drh2ce15c32017-07-11 13:34:40 +000010240 int i, n2;
mistachkinc6bc15a2017-11-21 21:14:32 +000010241 const char *zCmd = 0;
10242
drh2ce15c32017-07-11 13:34:40 +000010243 open_db(p, 0);
mistachkinc6bc15a2017-11-21 21:14:32 +000010244 zCmd = nArg>=2 ? azArg[1] : "help";
drh35f51a42017-11-15 17:07:22 +000010245
10246 /* The argument can optionally begin with "-" or "--" */
10247 if( zCmd[0]=='-' && zCmd[1] ){
10248 zCmd++;
10249 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
10250 }
10251
10252 /* --help lists all test-controls */
10253 if( strcmp(zCmd,"help")==0 ){
10254 utf8_printf(p->out, "Available test-controls:\n");
10255 for(i=0; i<ArraySize(aCtrl); i++){
drhef302e82017-11-15 19:14:08 +000010256 utf8_printf(p->out, " .testctrl %s %s\n",
10257 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
drh35f51a42017-11-15 17:07:22 +000010258 }
10259 rc = 1;
10260 goto meta_command_exit;
10261 }
drh2ce15c32017-07-11 13:34:40 +000010262
10263 /* convert testctrl text option to value. allow any unique prefix
10264 ** of the option name, or a numerical value. */
drh35f51a42017-11-15 17:07:22 +000010265 n2 = strlen30(zCmd);
drh2ce15c32017-07-11 13:34:40 +000010266 for(i=0; i<ArraySize(aCtrl); i++){
drh35f51a42017-11-15 17:07:22 +000010267 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010268 if( testctrl<0 ){
10269 testctrl = aCtrl[i].ctrlCode;
drhef302e82017-11-15 19:14:08 +000010270 iCtrl = i;
drh2ce15c32017-07-11 13:34:40 +000010271 }else{
drh35f51a42017-11-15 17:07:22 +000010272 utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
10273 "Use \".testctrl --help\" for help\n", zCmd);
10274 rc = 1;
10275 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +000010276 }
10277 }
10278 }
drhef302e82017-11-15 19:14:08 +000010279 if( testctrl<0 ){
drh35f51a42017-11-15 17:07:22 +000010280 utf8_printf(stderr,"Error: unknown test-control: %s\n"
10281 "Use \".testctrl --help\" for help\n", zCmd);
drh38ed1ce2021-12-06 15:24:36 +000010282 }else if( aCtrl[iCtrl].unSafe && p->bSafeMode ){
10283 utf8_printf(stderr,
10284 "line %d: \".testctrl %s\" may not be used in safe mode\n",
10285 p->lineno, aCtrl[iCtrl].zCtrlName);
10286 exit(1);
drh2ce15c32017-07-11 13:34:40 +000010287 }else{
10288 switch(testctrl){
10289
10290 /* sqlite3_test_control(int, db, int) */
10291 case SQLITE_TESTCTRL_OPTIMIZATIONS:
drh2ce15c32017-07-11 13:34:40 +000010292 if( nArg==3 ){
drhaf7b7652021-01-13 19:28:17 +000010293 unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
drh2ce15c32017-07-11 13:34:40 +000010294 rc2 = sqlite3_test_control(testctrl, p->db, opt);
drhef302e82017-11-15 19:14:08 +000010295 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010296 }
10297 break;
10298
10299 /* sqlite3_test_control(int) */
10300 case SQLITE_TESTCTRL_PRNG_SAVE:
10301 case SQLITE_TESTCTRL_PRNG_RESTORE:
drh2ce15c32017-07-11 13:34:40 +000010302 case SQLITE_TESTCTRL_BYTEORDER:
10303 if( nArg==2 ){
10304 rc2 = sqlite3_test_control(testctrl);
drhef302e82017-11-15 19:14:08 +000010305 isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
drh2ce15c32017-07-11 13:34:40 +000010306 }
10307 break;
10308
10309 /* sqlite3_test_control(int, uint) */
10310 case SQLITE_TESTCTRL_PENDING_BYTE:
10311 if( nArg==3 ){
10312 unsigned int opt = (unsigned int)integerValue(azArg[2]);
10313 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010314 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010315 }
10316 break;
10317
drh2e6d83b2019-08-03 01:39:20 +000010318 /* sqlite3_test_control(int, int, sqlite3*) */
10319 case SQLITE_TESTCTRL_PRNG_SEED:
10320 if( nArg==3 || nArg==4 ){
drh51755a72019-08-08 19:40:29 +000010321 int ii = (int)integerValue(azArg[2]);
drh2e6d83b2019-08-03 01:39:20 +000010322 sqlite3 *db;
drh41428a92019-08-12 16:25:11 +000010323 if( ii==0 && strcmp(azArg[2],"random")==0 ){
10324 sqlite3_randomness(sizeof(ii),&ii);
10325 printf("-- random seed: %d\n", ii);
10326 }
drh2e6d83b2019-08-03 01:39:20 +000010327 if( nArg==3 ){
10328 db = 0;
10329 }else{
10330 db = p->db;
10331 /* Make sure the schema has been loaded */
10332 sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);
10333 }
drh51755a72019-08-08 19:40:29 +000010334 rc2 = sqlite3_test_control(testctrl, ii, db);
drh2e6d83b2019-08-03 01:39:20 +000010335 isOk = 3;
10336 }
10337 break;
10338
drh2ce15c32017-07-11 13:34:40 +000010339 /* sqlite3_test_control(int, int) */
10340 case SQLITE_TESTCTRL_ASSERT:
10341 case SQLITE_TESTCTRL_ALWAYS:
drhef302e82017-11-15 19:14:08 +000010342 if( nArg==3 ){
10343 int opt = booleanValue(azArg[2]);
10344 rc2 = sqlite3_test_control(testctrl, opt);
10345 isOk = 1;
10346 }
10347 break;
10348
10349 /* sqlite3_test_control(int, int) */
10350 case SQLITE_TESTCTRL_LOCALTIME_FAULT:
drh2ce15c32017-07-11 13:34:40 +000010351 case SQLITE_TESTCTRL_NEVER_CORRUPT:
10352 if( nArg==3 ){
10353 int opt = booleanValue(azArg[2]);
10354 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010355 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010356 }
10357 break;
10358
drh171c50e2020-01-01 15:43:30 +000010359 /* sqlite3_test_control(sqlite3*) */
10360 case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
10361 rc2 = sqlite3_test_control(testctrl, p->db);
drh2a83c102020-01-01 23:02:35 +000010362 isOk = 3;
drh171c50e2020-01-01 15:43:30 +000010363 break;
10364
drh2ce15c32017-07-11 13:34:40 +000010365 case SQLITE_TESTCTRL_IMPOSTER:
10366 if( nArg==5 ){
10367 rc2 = sqlite3_test_control(testctrl, p->db,
10368 azArg[2],
10369 integerValue(azArg[3]),
10370 integerValue(azArg[4]));
drhef302e82017-11-15 19:14:08 +000010371 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010372 }
10373 break;
drh0d9de992017-12-26 18:04:23 +000010374
drh37ccfcf2020-08-31 18:49:04 +000010375 case SQLITE_TESTCTRL_SEEK_COUNT: {
10376 u64 x = 0;
10377 rc2 = sqlite3_test_control(testctrl, p->db, &x);
10378 utf8_printf(p->out, "%llu\n", x);
10379 isOk = 3;
10380 break;
10381 }
10382
drh0d9de992017-12-26 18:04:23 +000010383#ifdef YYCOVERAGE
drhf3c12562021-06-04 13:16:46 +000010384 case SQLITE_TESTCTRL_PARSER_COVERAGE: {
drh0d9de992017-12-26 18:04:23 +000010385 if( nArg==2 ){
10386 sqlite3_test_control(testctrl, p->out);
10387 isOk = 3;
10388 }
drhf3c12562021-06-04 13:16:46 +000010389 break;
10390 }
10391#endif
10392#ifdef SQLITE_DEBUG
10393 case SQLITE_TESTCTRL_TUNE: {
10394 if( nArg==4 ){
10395 int id = (int)integerValue(azArg[2]);
drh2d26cfc2021-06-04 13:40:26 +000010396 int val = (int)integerValue(azArg[3]);
10397 sqlite3_test_control(testctrl, id, &val);
10398 isOk = 3;
10399 }else if( nArg==3 ){
10400 int id = (int)integerValue(azArg[2]);
10401 sqlite3_test_control(testctrl, -id, &rc2);
10402 isOk = 1;
10403 }else if( nArg==2 ){
10404 int id = 1;
10405 while(1){
10406 int val = 0;
10407 rc2 = sqlite3_test_control(testctrl, -id, &val);
10408 if( rc2!=SQLITE_OK ) break;
10409 if( id>1 ) utf8_printf(p->out, " ");
10410 utf8_printf(p->out, "%d: %d", id, val);
10411 id++;
10412 }
10413 if( id>1 ) utf8_printf(p->out, "\n");
drhf3c12562021-06-04 13:16:46 +000010414 isOk = 3;
10415 }
10416 break;
10417 }
drh0d9de992017-12-26 18:04:23 +000010418#endif
dan779e9902021-07-28 18:13:28 +000010419 case SQLITE_TESTCTRL_SORTER_MMAP:
10420 if( nArg==3 ){
10421 int opt = (unsigned int)integerValue(azArg[2]);
10422 rc2 = sqlite3_test_control(testctrl, p->db, opt);
10423 isOk = 3;
10424 }
10425 break;
drh2ce15c32017-07-11 13:34:40 +000010426 }
10427 }
drhef302e82017-11-15 19:14:08 +000010428 if( isOk==0 && iCtrl>=0 ){
drhe2754c12019-08-26 12:50:01 +000010429 utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
drhef302e82017-11-15 19:14:08 +000010430 rc = 1;
10431 }else if( isOk==1 ){
10432 raw_printf(p->out, "%d\n", rc2);
10433 }else if( isOk==2 ){
10434 raw_printf(p->out, "0x%08x\n", rc2);
10435 }
drh2ce15c32017-07-11 13:34:40 +000010436 }else
10437#endif /* !defined(SQLITE_UNTESTABLE) */
10438
10439 if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
10440 open_db(p, 0);
10441 sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
10442 }else
10443
10444 if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
10445 if( nArg==2 ){
10446 enableTimer = booleanValue(azArg[1]);
10447 if( enableTimer && !HAS_TIMER ){
10448 raw_printf(stderr, "Error: timer not available on this system.\n");
10449 enableTimer = 0;
10450 }
10451 }else{
10452 raw_printf(stderr, "Usage: .timer on|off\n");
10453 rc = 1;
10454 }
10455 }else
10456
drh707821f2018-12-05 13:39:06 +000010457#ifndef SQLITE_OMIT_TRACE
drh2ce15c32017-07-11 13:34:40 +000010458 if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
drh707821f2018-12-05 13:39:06 +000010459 int mType = 0;
10460 int jj;
drh2ce15c32017-07-11 13:34:40 +000010461 open_db(p, 0);
drh707821f2018-12-05 13:39:06 +000010462 for(jj=1; jj<nArg; jj++){
10463 const char *z = azArg[jj];
10464 if( z[0]=='-' ){
10465 if( optionMatch(z, "expanded") ){
10466 p->eTraceType = SHELL_TRACE_EXPANDED;
10467 }
10468#ifdef SQLITE_ENABLE_NORMALIZE
10469 else if( optionMatch(z, "normalized") ){
10470 p->eTraceType = SHELL_TRACE_NORMALIZED;
10471 }
10472#endif
10473 else if( optionMatch(z, "plain") ){
10474 p->eTraceType = SHELL_TRACE_PLAIN;
10475 }
10476 else if( optionMatch(z, "profile") ){
10477 mType |= SQLITE_TRACE_PROFILE;
10478 }
10479 else if( optionMatch(z, "row") ){
10480 mType |= SQLITE_TRACE_ROW;
10481 }
10482 else if( optionMatch(z, "stmt") ){
10483 mType |= SQLITE_TRACE_STMT;
10484 }
10485 else if( optionMatch(z, "close") ){
10486 mType |= SQLITE_TRACE_CLOSE;
10487 }
10488 else {
10489 raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
10490 rc = 1;
10491 goto meta_command_exit;
10492 }
10493 }else{
10494 output_file_close(p->traceOut);
10495 p->traceOut = output_file_open(azArg[1], 0);
10496 }
drh2ce15c32017-07-11 13:34:40 +000010497 }
drh2ce15c32017-07-11 13:34:40 +000010498 if( p->traceOut==0 ){
10499 sqlite3_trace_v2(p->db, 0, 0, 0);
10500 }else{
drh707821f2018-12-05 13:39:06 +000010501 if( mType==0 ) mType = SQLITE_TRACE_STMT;
10502 sqlite3_trace_v2(p->db, mType, sql_trace_callback, p);
drh2ce15c32017-07-11 13:34:40 +000010503 }
drh2ce15c32017-07-11 13:34:40 +000010504 }else
drh707821f2018-12-05 13:39:06 +000010505#endif /* !defined(SQLITE_OMIT_TRACE) */
drh2ce15c32017-07-11 13:34:40 +000010506
drhe2b7a762019-10-02 00:25:08 +000010507#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhcc5979d2019-08-16 22:58:29 +000010508 if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){
10509 int ii;
drh8c754a32019-08-19 20:35:30 +000010510 int lenOpt;
drh5df84282019-08-17 19:45:25 +000010511 char *zOpt;
drhcc5979d2019-08-16 22:58:29 +000010512 if( nArg<2 ){
drh5df84282019-08-17 19:45:25 +000010513 raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
drhcc5979d2019-08-16 22:58:29 +000010514 rc = 1;
10515 goto meta_command_exit;
10516 }
10517 open_db(p, 0);
drh5df84282019-08-17 19:45:25 +000010518 zOpt = azArg[1];
10519 if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
drh8c754a32019-08-19 20:35:30 +000010520 lenOpt = (int)strlen(zOpt);
10521 if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){
drh5df84282019-08-17 19:45:25 +000010522 assert( azArg[nArg]==0 );
drh8c754a32019-08-19 20:35:30 +000010523 sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0);
drh5df84282019-08-17 19:45:25 +000010524 }else{
10525 for(ii=1; ii<nArg; ii++){
10526 sqlite3_create_module(p->db, azArg[ii], 0, 0);
10527 }
drhcc5979d2019-08-16 22:58:29 +000010528 }
10529 }else
10530#endif
10531
drh2ce15c32017-07-11 13:34:40 +000010532#if SQLITE_USER_AUTHENTICATION
10533 if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
10534 if( nArg<2 ){
10535 raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
10536 rc = 1;
10537 goto meta_command_exit;
10538 }
10539 open_db(p, 0);
10540 if( strcmp(azArg[1],"login")==0 ){
10541 if( nArg!=4 ){
10542 raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
10543 rc = 1;
10544 goto meta_command_exit;
10545 }
drhe2754c12019-08-26 12:50:01 +000010546 rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
10547 strlen30(azArg[3]));
drh2ce15c32017-07-11 13:34:40 +000010548 if( rc ){
10549 utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
10550 rc = 1;
10551 }
10552 }else if( strcmp(azArg[1],"add")==0 ){
10553 if( nArg!=5 ){
10554 raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
10555 rc = 1;
10556 goto meta_command_exit;
10557 }
drhaf2770f2018-01-05 14:55:43 +000010558 rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000010559 booleanValue(azArg[4]));
10560 if( rc ){
10561 raw_printf(stderr, "User-Add failed: %d\n", rc);
10562 rc = 1;
10563 }
10564 }else if( strcmp(azArg[1],"edit")==0 ){
10565 if( nArg!=5 ){
10566 raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
10567 rc = 1;
10568 goto meta_command_exit;
10569 }
drhaf2770f2018-01-05 14:55:43 +000010570 rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000010571 booleanValue(azArg[4]));
10572 if( rc ){
10573 raw_printf(stderr, "User-Edit failed: %d\n", rc);
10574 rc = 1;
10575 }
10576 }else if( strcmp(azArg[1],"delete")==0 ){
10577 if( nArg!=3 ){
10578 raw_printf(stderr, "Usage: .user delete USER\n");
10579 rc = 1;
10580 goto meta_command_exit;
10581 }
10582 rc = sqlite3_user_delete(p->db, azArg[2]);
10583 if( rc ){
10584 raw_printf(stderr, "User-Delete failed: %d\n", rc);
10585 rc = 1;
10586 }
10587 }else{
10588 raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
10589 rc = 1;
10590 goto meta_command_exit;
10591 }
10592 }else
10593#endif /* SQLITE_USER_AUTHENTICATION */
10594
10595 if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
10596 utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
10597 sqlite3_libversion(), sqlite3_sourceid());
drh0ed2fd82018-01-16 20:05:27 +000010598#if SQLITE_HAVE_ZLIB
10599 utf8_printf(p->out, "zlib version %s\n", zlibVersion());
10600#endif
10601#define CTIMEOPT_VAL_(opt) #opt
10602#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
10603#if defined(__clang__) && defined(__clang_major__)
10604 utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
10605 CTIMEOPT_VAL(__clang_minor__) "."
10606 CTIMEOPT_VAL(__clang_patchlevel__) "\n");
10607#elif defined(_MSC_VER)
10608 utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n");
10609#elif defined(__GNUC__) && defined(__VERSION__)
10610 utf8_printf(p->out, "gcc-" __VERSION__ "\n");
10611#endif
drh2ce15c32017-07-11 13:34:40 +000010612 }else
10613
10614 if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
10615 const char *zDbName = nArg==2 ? azArg[1] : "main";
10616 sqlite3_vfs *pVfs = 0;
10617 if( p->db ){
10618 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
10619 if( pVfs ){
10620 utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
10621 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
10622 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
10623 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
10624 }
10625 }
10626 }else
10627
10628 if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){
10629 sqlite3_vfs *pVfs;
10630 sqlite3_vfs *pCurrent = 0;
10631 if( p->db ){
10632 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
10633 }
10634 for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
10635 utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName,
10636 pVfs==pCurrent ? " <--- CURRENT" : "");
10637 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
10638 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
10639 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
10640 if( pVfs->pNext ){
10641 raw_printf(p->out, "-----------------------------------\n");
10642 }
10643 }
10644 }else
10645
10646 if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
10647 const char *zDbName = nArg==2 ? azArg[1] : "main";
10648 char *zVfsName = 0;
10649 if( p->db ){
10650 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
10651 if( zVfsName ){
10652 utf8_printf(p->out, "%s\n", zVfsName);
10653 sqlite3_free(zVfsName);
10654 }
10655 }
10656 }else
10657
drh2ce15c32017-07-11 13:34:40 +000010658 if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
drhc0622a42020-12-04 01:17:57 +000010659 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
10660 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x);
drh2ce15c32017-07-11 13:34:40 +000010661 }else
drh2ce15c32017-07-11 13:34:40 +000010662
10663 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
10664 int j;
10665 assert( nArg<=ArraySize(azArg) );
drh0285d982020-05-29 14:38:43 +000010666 p->nWidth = nArg-1;
drh76fc88f2021-10-02 16:39:16 +000010667 p->colWidth = realloc(p->colWidth, (p->nWidth+1)*sizeof(int)*2);
drh0285d982020-05-29 14:38:43 +000010668 if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory();
10669 if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
10670 for(j=1; j<nArg; j++){
drh2ce15c32017-07-11 13:34:40 +000010671 p->colWidth[j-1] = (int)integerValue(azArg[j]);
10672 }
10673 }else
10674
10675 {
10676 utf8_printf(stderr, "Error: unknown command or invalid arguments: "
10677 " \"%s\". Enter \".help\" for help\n", azArg[0]);
10678 rc = 1;
10679 }
10680
10681meta_command_exit:
10682 if( p->outCount ){
10683 p->outCount--;
10684 if( p->outCount==0 ) output_reset(p);
10685 }
drhb97e2ad2021-08-26 18:31:39 +000010686 p->bSafeMode = p->bSafeModePersist;
drh2ce15c32017-07-11 13:34:40 +000010687 return rc;
10688}
10689
larrybr8bc4cbc2021-09-10 00:58:46 +000010690/* Line scan result and intermediate states (supporting scan resumption)
drh2ce15c32017-07-11 13:34:40 +000010691*/
drh68911c22021-09-22 14:26:22 +000010692#ifndef CHAR_BIT
10693# define CHAR_BIT 8
10694#endif
larrybr8bc4cbc2021-09-10 00:58:46 +000010695typedef enum {
larrybr7e009842021-09-18 21:35:22 +000010696 QSS_HasDark = 1<<CHAR_BIT, QSS_EndingSemi = 2<<CHAR_BIT,
10697 QSS_CharMask = (1<<CHAR_BIT)-1, QSS_ScanMask = 3<<CHAR_BIT,
larrybra96bbe92021-09-10 19:45:22 +000010698 QSS_Start = 0
larrybr8bc4cbc2021-09-10 00:58:46 +000010699} QuickScanState;
larrybr7e009842021-09-18 21:35:22 +000010700#define QSS_SETV(qss, newst) ((newst) | ((qss) & QSS_ScanMask))
10701#define QSS_INPLAIN(qss) (((qss)&QSS_CharMask)==QSS_Start)
10702#define QSS_PLAINWHITE(qss) (((qss)&~QSS_EndingSemi)==QSS_Start)
larrybra96bbe92021-09-10 19:45:22 +000010703#define QSS_PLAINDARK(qss) (((qss)&~QSS_EndingSemi)==QSS_HasDark)
larrybr7e009842021-09-18 21:35:22 +000010704#define QSS_SEMITERM(qss) (((qss)&~QSS_HasDark)==QSS_EndingSemi)
drh2ce15c32017-07-11 13:34:40 +000010705
10706/*
larrybr8bc4cbc2021-09-10 00:58:46 +000010707** Scan line for classification to guide shell's handling.
10708** The scan is resumable for subsequent lines when prior
10709** return values are passed as the 2nd argument.
drh2ce15c32017-07-11 13:34:40 +000010710*/
larrybr8bc4cbc2021-09-10 00:58:46 +000010711static QuickScanState quickscan(char *zLine, QuickScanState qss){
10712 char cin;
larrybr7e009842021-09-18 21:35:22 +000010713 char cWait = (char)qss; /* intentional narrowing loss */
10714 if( cWait==0 ){
10715 PlainScan:
drhe85e1da2021-10-01 21:01:07 +000010716 assert( cWait==0 );
drhfd7abcd2021-09-22 13:43:16 +000010717 while( (cin = *zLine++)!=0 ){
larrybr8bc4cbc2021-09-10 00:58:46 +000010718 if( IsSpace(cin) )
10719 continue;
10720 switch (cin){
10721 case '-':
larrybr7e009842021-09-18 21:35:22 +000010722 if( *zLine!='-' )
10723 break;
10724 while((cin = *++zLine)!=0 )
10725 if( cin=='\n')
10726 goto PlainScan;
10727 return qss;
larrybr8bc4cbc2021-09-10 00:58:46 +000010728 case ';':
larrybra96bbe92021-09-10 19:45:22 +000010729 qss |= QSS_EndingSemi;
10730 continue;
larrybr8bc4cbc2021-09-10 00:58:46 +000010731 case '/':
10732 if( *zLine=='*' ){
10733 ++zLine;
larrybr7e009842021-09-18 21:35:22 +000010734 cWait = '*';
10735 qss = QSS_SETV(qss, cWait);
10736 goto TermScan;
larrybr8bc4cbc2021-09-10 00:58:46 +000010737 }
10738 break;
larrybra96bbe92021-09-10 19:45:22 +000010739 case '[':
10740 cin = ']';
10741 /* fall thru */
10742 case '`': case '\'': case '"':
larrybr7e009842021-09-18 21:35:22 +000010743 cWait = cin;
10744 qss = QSS_HasDark | cWait;
10745 goto TermScan;
larrybr8bc4cbc2021-09-10 00:58:46 +000010746 default:
10747 break;
10748 }
larrybr7e009842021-09-18 21:35:22 +000010749 qss = (qss & ~QSS_EndingSemi) | QSS_HasDark;
drh2ce15c32017-07-11 13:34:40 +000010750 }
larrybr7e009842021-09-18 21:35:22 +000010751 }else{
10752 TermScan:
drhfd7abcd2021-09-22 13:43:16 +000010753 while( (cin = *zLine++)!=0 ){
larrybr7e009842021-09-18 21:35:22 +000010754 if( cin==cWait ){
10755 switch( cWait ){
10756 case '*':
10757 if( *zLine != '/' )
10758 continue;
10759 ++zLine;
10760 cWait = 0;
10761 qss = QSS_SETV(qss, 0);
10762 goto PlainScan;
10763 case '`': case '\'': case '"':
10764 if(*zLine==cWait){
larrybr8d463ce2021-09-11 02:42:04 +000010765 ++zLine;
larrybr7e009842021-09-18 21:35:22 +000010766 continue;
10767 }
10768 /* fall thru */
10769 case ']':
10770 cWait = 0;
10771 qss = QSS_SETV(qss, 0);
10772 goto PlainScan;
10773 default: assert(0);
larrybr8bc4cbc2021-09-10 00:58:46 +000010774 }
10775 }
10776 }
drh2ce15c32017-07-11 13:34:40 +000010777 }
larrybr8bc4cbc2021-09-10 00:58:46 +000010778 return qss;
drh2ce15c32017-07-11 13:34:40 +000010779}
10780
10781/*
10782** Return TRUE if the line typed in is an SQL command terminator other
10783** than a semi-colon. The SQL Server style "go" command is understood
10784** as is the Oracle "/".
10785*/
larrybr8bc4cbc2021-09-10 00:58:46 +000010786static int line_is_command_terminator(char *zLine){
drh2ce15c32017-07-11 13:34:40 +000010787 while( IsSpace(zLine[0]) ){ zLine++; };
larrybr8bc4cbc2021-09-10 00:58:46 +000010788 if( zLine[0]=='/' )
10789 zLine += 1; /* Oracle */
10790 else if ( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o' )
10791 zLine += 2; /* SQL Server */
10792 else
10793 return 0;
larrybra96bbe92021-09-10 19:45:22 +000010794 return quickscan(zLine,QSS_Start)==QSS_Start;
drh2ce15c32017-07-11 13:34:40 +000010795}
10796
10797/*
drh56f17742018-01-24 01:58:49 +000010798** We need a default sqlite3_complete() implementation to use in case
10799** the shell is compiled with SQLITE_OMIT_COMPLETE. The default assumes
10800** any arbitrary text is a complete SQL statement. This is not very
10801** user-friendly, but it does seem to work.
10802*/
10803#ifdef SQLITE_OMIT_COMPLETE
danc86b23b2018-11-16 14:36:42 +000010804#define sqlite3_complete(x) 1
drh56f17742018-01-24 01:58:49 +000010805#endif
10806
10807/*
drh2ce15c32017-07-11 13:34:40 +000010808** Return true if zSql is a complete SQL statement. Return false if it
10809** ends in the middle of a string literal or C-style comment.
10810*/
10811static int line_is_complete(char *zSql, int nSql){
10812 int rc;
10813 if( zSql==0 ) return 1;
10814 zSql[nSql] = ';';
10815 zSql[nSql+1] = 0;
10816 rc = sqlite3_complete(zSql);
10817 zSql[nSql] = 0;
10818 return rc;
10819}
10820
10821/*
drhfc29a862018-05-11 19:11:18 +000010822** Run a single line of SQL. Return the number of errors.
drh2ce15c32017-07-11 13:34:40 +000010823*/
10824static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
10825 int rc;
10826 char *zErrMsg = 0;
10827
10828 open_db(p, 0);
10829 if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
drhfc4eeef2019-02-05 19:48:46 +000010830 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
drh2ce15c32017-07-11 13:34:40 +000010831 BEGIN_TIMER;
drha10b9992018-03-09 15:24:33 +000010832 rc = shell_exec(p, zSql, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000010833 END_TIMER;
10834 if( rc || zErrMsg ){
10835 char zPrefix[100];
10836 if( in!=0 || !stdin_is_interactive ){
10837 sqlite3_snprintf(sizeof(zPrefix), zPrefix,
10838 "Error: near line %d:", startline);
10839 }else{
10840 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
10841 }
10842 if( zErrMsg!=0 ){
10843 utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
10844 sqlite3_free(zErrMsg);
10845 zErrMsg = 0;
10846 }else{
10847 utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
10848 }
10849 return 1;
10850 }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
drh6d9f0342021-09-22 10:28:50 +000010851 char zLineBuf[2000];
10852 sqlite3_snprintf(sizeof(zLineBuf), zLineBuf,
10853 "changes: %lld total_changes: %lld",
larrybr10496f72021-06-23 16:07:20 +000010854 sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
drh6d9f0342021-09-22 10:28:50 +000010855 raw_printf(p->out, "%s\n", zLineBuf);
drh2ce15c32017-07-11 13:34:40 +000010856 }
10857 return 0;
10858}
10859
10860
10861/*
10862** Read input from *in and process it. If *in==0 then input
10863** is interactive - the user is typing it it. Otherwise, input
10864** is coming from a file or device. A prompt is issued and history
10865** is saved only if input is interactive. An interrupt signal will
10866** cause this routine to exit immediately, unless input is interactive.
10867**
10868** Return the number of errors.
10869*/
drh60379d42018-12-13 18:30:01 +000010870static int process_input(ShellState *p){
drh2ce15c32017-07-11 13:34:40 +000010871 char *zLine = 0; /* A single input line */
10872 char *zSql = 0; /* Accumulated SQL text */
10873 int nLine; /* Length of current line */
10874 int nSql = 0; /* Bytes of zSql[] used */
10875 int nAlloc = 0; /* Allocated zSql[] space */
drh2ce15c32017-07-11 13:34:40 +000010876 int rc; /* Error code */
10877 int errCnt = 0; /* Number of errors seen */
drh2ce15c32017-07-11 13:34:40 +000010878 int startline = 0; /* Line number for start of current input */
larrybr7e009842021-09-18 21:35:22 +000010879 QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */
drh2ce15c32017-07-11 13:34:40 +000010880
drh2c8ee022018-12-13 18:59:30 +000010881 p->lineno = 0;
drh60379d42018-12-13 18:30:01 +000010882 while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
drh2ce15c32017-07-11 13:34:40 +000010883 fflush(p->out);
drh60379d42018-12-13 18:30:01 +000010884 zLine = one_input_line(p->in, zLine, nSql>0);
drh2ce15c32017-07-11 13:34:40 +000010885 if( zLine==0 ){
10886 /* End of input */
drh60379d42018-12-13 18:30:01 +000010887 if( p->in==0 && stdin_is_interactive ) printf("\n");
drh2ce15c32017-07-11 13:34:40 +000010888 break;
10889 }
10890 if( seenInterrupt ){
drh60379d42018-12-13 18:30:01 +000010891 if( p->in!=0 ) break;
drh2ce15c32017-07-11 13:34:40 +000010892 seenInterrupt = 0;
10893 }
drh2c8ee022018-12-13 18:59:30 +000010894 p->lineno++;
larrybr7e009842021-09-18 21:35:22 +000010895 if( QSS_INPLAIN(qss)
larrybr8bc4cbc2021-09-10 00:58:46 +000010896 && line_is_command_terminator(zLine)
10897 && line_is_complete(zSql, nSql) ){
10898 memcpy(zLine,";",2);
10899 }
10900 qss = quickscan(zLine, qss);
10901 if( QSS_PLAINWHITE(qss) && nSql==0 ){
10902 if( ShellHasFlag(p, SHFLG_Echo) )
10903 printf("%s\n", zLine);
larrybrd797d6b2021-10-03 22:03:59 +000010904 /* Just swallow single-line whitespace */
10905 qss = QSS_Start;
larrybr8bc4cbc2021-09-10 00:58:46 +000010906 continue;
drh2ce15c32017-07-11 13:34:40 +000010907 }
drh1615c372018-05-12 23:56:22 +000010908 if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
drh2ce15c32017-07-11 13:34:40 +000010909 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
drh1615c372018-05-12 23:56:22 +000010910 if( zLine[0]=='.' ){
10911 rc = do_meta_command(zLine, p);
10912 if( rc==2 ){ /* exit requested */
10913 break;
10914 }else if( rc ){
10915 errCnt++;
10916 }
drh2ce15c32017-07-11 13:34:40 +000010917 }
larrybr81012162021-10-02 15:34:52 +000010918 qss = QSS_Start;
drh2ce15c32017-07-11 13:34:40 +000010919 continue;
10920 }
larrybrd797d6b2021-10-03 22:03:59 +000010921 /* No single-line dispositions remain; accumulate line(s). */
drh2ce15c32017-07-11 13:34:40 +000010922 nLine = strlen30(zLine);
10923 if( nSql+nLine+2>=nAlloc ){
larrybr31bffb42021-09-08 21:49:03 +000010924 /* Grow buffer by half-again increments when big. */
10925 nAlloc = nSql+(nSql>>1)+nLine+100;
drh2ce15c32017-07-11 13:34:40 +000010926 zSql = realloc(zSql, nAlloc);
drhe3e25652021-12-16 13:29:28 +000010927 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +000010928 }
drh2ce15c32017-07-11 13:34:40 +000010929 if( nSql==0 ){
10930 int i;
10931 for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
10932 assert( nAlloc>0 && zSql!=0 );
10933 memcpy(zSql, zLine+i, nLine+1-i);
drh2c8ee022018-12-13 18:59:30 +000010934 startline = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000010935 nSql = nLine-i;
10936 }else{
10937 zSql[nSql++] = '\n';
10938 memcpy(zSql+nSql, zLine, nLine+1);
10939 nSql += nLine;
10940 }
larrybra96bbe92021-09-10 19:45:22 +000010941 if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){
drh60379d42018-12-13 18:30:01 +000010942 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000010943 nSql = 0;
10944 if( p->outCount ){
10945 output_reset(p);
10946 p->outCount = 0;
drh13c20932018-01-10 21:41:55 +000010947 }else{
10948 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +000010949 }
drhb97e2ad2021-08-26 18:31:39 +000010950 p->bSafeMode = p->bSafeModePersist;
larrybrd797d6b2021-10-03 22:03:59 +000010951 qss = QSS_Start;
larrybr8bc4cbc2021-09-10 00:58:46 +000010952 }else if( nSql && QSS_PLAINWHITE(qss) ){
drh2ce15c32017-07-11 13:34:40 +000010953 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
10954 nSql = 0;
larrybrd797d6b2021-10-03 22:03:59 +000010955 qss = QSS_Start;
drh2ce15c32017-07-11 13:34:40 +000010956 }
10957 }
larrybr8bc4cbc2021-09-10 00:58:46 +000010958 if( nSql && QSS_PLAINDARK(qss) ){
drh60379d42018-12-13 18:30:01 +000010959 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000010960 }
10961 free(zSql);
10962 free(zLine);
10963 return errCnt>0;
10964}
10965
10966/*
10967** Return a pathname which is the user's home directory. A
10968** 0 return indicates an error of some kind.
10969*/
10970static char *find_home_dir(int clearFlag){
10971 static char *home_dir = NULL;
10972 if( clearFlag ){
10973 free(home_dir);
10974 home_dir = 0;
10975 return 0;
10976 }
10977 if( home_dir ) return home_dir;
10978
10979#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
10980 && !defined(__RTP__) && !defined(_WRS_KERNEL)
10981 {
10982 struct passwd *pwent;
10983 uid_t uid = getuid();
10984 if( (pwent=getpwuid(uid)) != NULL) {
10985 home_dir = pwent->pw_dir;
10986 }
10987 }
10988#endif
10989
10990#if defined(_WIN32_WCE)
10991 /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
10992 */
10993 home_dir = "/";
10994#else
10995
10996#if defined(_WIN32) || defined(WIN32)
10997 if (!home_dir) {
10998 home_dir = getenv("USERPROFILE");
10999 }
11000#endif
11001
11002 if (!home_dir) {
11003 home_dir = getenv("HOME");
11004 }
11005
11006#if defined(_WIN32) || defined(WIN32)
11007 if (!home_dir) {
11008 char *zDrive, *zPath;
11009 int n;
11010 zDrive = getenv("HOMEDRIVE");
11011 zPath = getenv("HOMEPATH");
11012 if( zDrive && zPath ){
11013 n = strlen30(zDrive) + strlen30(zPath) + 1;
11014 home_dir = malloc( n );
11015 if( home_dir==0 ) return 0;
11016 sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
11017 return home_dir;
11018 }
11019 home_dir = "c:\\";
11020 }
11021#endif
11022
11023#endif /* !_WIN32_WCE */
11024
11025 if( home_dir ){
11026 int n = strlen30(home_dir) + 1;
11027 char *z = malloc( n );
11028 if( z ) memcpy(z, home_dir, n);
11029 home_dir = z;
11030 }
11031
11032 return home_dir;
11033}
11034
11035/*
11036** Read input from the file given by sqliterc_override. Or if that
11037** parameter is NULL, take input from ~/.sqliterc
11038**
11039** Returns the number of errors.
11040*/
11041static void process_sqliterc(
11042 ShellState *p, /* Configuration data */
11043 const char *sqliterc_override /* Name of config file. NULL to use default */
11044){
11045 char *home_dir = NULL;
11046 const char *sqliterc = sqliterc_override;
11047 char *zBuf = 0;
drh60379d42018-12-13 18:30:01 +000011048 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +000011049 int savedLineno = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000011050
11051 if (sqliterc == NULL) {
11052 home_dir = find_home_dir(0);
11053 if( home_dir==0 ){
11054 raw_printf(stderr, "-- warning: cannot find home directory;"
11055 " cannot read ~/.sqliterc\n");
11056 return;
11057 }
drh2ce15c32017-07-11 13:34:40 +000011058 zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
drhe3e25652021-12-16 13:29:28 +000011059 shell_check_oom(zBuf);
drh2ce15c32017-07-11 13:34:40 +000011060 sqliterc = zBuf;
11061 }
drh60379d42018-12-13 18:30:01 +000011062 p->in = fopen(sqliterc,"rb");
11063 if( p->in ){
drh2ce15c32017-07-11 13:34:40 +000011064 if( stdin_is_interactive ){
11065 utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
11066 }
drhb7c46aa2020-11-25 13:59:47 +000011067 if( process_input(p) && bail_on_error ) exit(1);
drh60379d42018-12-13 18:30:01 +000011068 fclose(p->in);
drhb7c46aa2020-11-25 13:59:47 +000011069 }else if( sqliterc_override!=0 ){
11070 utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
11071 if( bail_on_error ) exit(1);
drh2ce15c32017-07-11 13:34:40 +000011072 }
drh60379d42018-12-13 18:30:01 +000011073 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +000011074 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +000011075 sqlite3_free(zBuf);
11076}
11077
11078/*
11079** Show available command line options
11080*/
11081static const char zOptions[] =
drhda57d962018-03-05 19:34:05 +000011082#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhad7fd5d2018-03-05 20:21:50 +000011083 " -A ARGS... run \".archive ARGS\" and exit\n"
drhda57d962018-03-05 19:34:05 +000011084#endif
drh3baed312018-03-08 18:14:41 +000011085 " -append append the database to the end of the file\n"
drh2ce15c32017-07-11 13:34:40 +000011086 " -ascii set output mode to 'ascii'\n"
11087 " -bail stop after hitting an error\n"
11088 " -batch force batch I/O\n"
drh0908e382020-06-04 18:05:39 +000011089 " -box set output mode to 'box'\n"
drh2ce15c32017-07-11 13:34:40 +000011090 " -column set output mode to 'column'\n"
11091 " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
11092 " -csv set output mode to 'csv'\n"
drh8d889af2021-05-08 17:18:23 +000011093#if !defined(SQLITE_OMIT_DESERIALIZE)
drh6ca64482019-01-22 16:06:20 +000011094 " -deserialize open the database using sqlite3_deserialize()\n"
11095#endif
drh2ce15c32017-07-11 13:34:40 +000011096 " -echo print commands before execution\n"
11097 " -init FILENAME read/process named file\n"
11098 " -[no]header turn headers on or off\n"
11099#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
11100 " -heap SIZE Size of heap for memsys3 or memsys5\n"
11101#endif
11102 " -help show this message\n"
11103 " -html set output mode to HTML\n"
11104 " -interactive force interactive I/O\n"
drh30c54a02020-05-28 23:49:50 +000011105 " -json set output mode to 'json'\n"
drh2ce15c32017-07-11 13:34:40 +000011106 " -line set output mode to 'line'\n"
11107 " -list set output mode to 'list'\n"
11108 " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
drh30c54a02020-05-28 23:49:50 +000011109 " -markdown set output mode to 'markdown'\n"
drh8d889af2021-05-08 17:18:23 +000011110#if !defined(SQLITE_OMIT_DESERIALIZE)
drh6ca64482019-01-22 16:06:20 +000011111 " -maxsize N maximum size for a --deserialize database\n"
11112#endif
drhaf482572019-02-04 19:52:39 +000011113 " -memtrace trace all memory allocations and deallocations\n"
drh2ce15c32017-07-11 13:34:40 +000011114 " -mmap N default mmap size set to N\n"
11115#ifdef SQLITE_ENABLE_MULTIPLEX
11116 " -multiplex enable the multiplexor VFS\n"
11117#endif
11118 " -newline SEP set output row separator. Default: '\\n'\n"
drh0933aad2019-11-18 17:46:38 +000011119 " -nofollow refuse to open symbolic links to database files\n"
drhb97e2ad2021-08-26 18:31:39 +000011120 " -nonce STRING set the safe-mode escape nonce\n"
drh2ce15c32017-07-11 13:34:40 +000011121 " -nullvalue TEXT set text string for NULL values. Default ''\n"
11122 " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
11123 " -quote set output mode to 'quote'\n"
drhee269a62018-02-14 23:27:43 +000011124 " -readonly open the database read-only\n"
drhb97e2ad2021-08-26 18:31:39 +000011125 " -safe enable safe-mode\n"
drh2ce15c32017-07-11 13:34:40 +000011126 " -separator SEP set output column separator. Default: '|'\n"
drha90d84f2018-04-18 15:21:13 +000011127#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11128 " -sorterref SIZE sorter references threshold size\n"
11129#endif
drh2ce15c32017-07-11 13:34:40 +000011130 " -stats print memory stats before each finalize\n"
drh30c54a02020-05-28 23:49:50 +000011131 " -table set output mode to 'table'\n"
drh2fa78182020-10-31 18:58:37 +000011132 " -tabs set output mode to 'tabs'\n"
drh2ce15c32017-07-11 13:34:40 +000011133 " -version show SQLite version\n"
11134 " -vfs NAME use NAME as the default VFS\n"
11135#ifdef SQLITE_ENABLE_VFSTRACE
11136 " -vfstrace enable tracing of all VFS calls\n"
11137#endif
drh3baed312018-03-08 18:14:41 +000011138#ifdef SQLITE_HAVE_ZLIB
11139 " -zip open the file as a ZIP Archive\n"
11140#endif
drh2ce15c32017-07-11 13:34:40 +000011141;
11142static void usage(int showDetail){
11143 utf8_printf(stderr,
11144 "Usage: %s [OPTIONS] FILENAME [SQL]\n"
11145 "FILENAME is the name of an SQLite database. A new database is created\n"
11146 "if the file does not previously exist.\n", Argv0);
11147 if( showDetail ){
11148 utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
11149 }else{
11150 raw_printf(stderr, "Use the -help option for additional information\n");
11151 }
11152 exit(1);
11153}
11154
11155/*
drhe7df8922018-04-18 10:44:58 +000011156** Internal check: Verify that the SQLite is uninitialized. Print a
11157** error message if it is initialized.
11158*/
11159static void verify_uninitialized(void){
11160 if( sqlite3_config(-1)==SQLITE_MISUSE ){
drh8e02a182018-05-30 07:24:41 +000011161 utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
drhe7df8922018-04-18 10:44:58 +000011162 " initialization.\n");
11163 }
11164}
11165
11166/*
drh2ce15c32017-07-11 13:34:40 +000011167** Initialize the state information in data
11168*/
11169static void main_init(ShellState *data) {
11170 memset(data, 0, sizeof(*data));
11171 data->normalMode = data->cMode = data->mode = MODE_List;
11172 data->autoExplain = 1;
drh37407122021-07-23 18:43:58 +000011173 data->pAuxDb = &data->aAuxDb[0];
drh2ce15c32017-07-11 13:34:40 +000011174 memcpy(data->colSeparator,SEP_Column, 2);
11175 memcpy(data->rowSeparator,SEP_Row, 2);
11176 data->showHeader = 0;
11177 data->shellFlgs = SHFLG_Lookaside;
drhe7df8922018-04-18 10:44:58 +000011178 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000011179 sqlite3_config(SQLITE_CONFIG_URI, 1);
11180 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
11181 sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
11182 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
11183 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
11184}
11185
11186/*
11187** Output text to the console in a font that attracts extra attention.
11188*/
11189#ifdef _WIN32
11190static void printBold(const char *zText){
mistachkin43e86272020-04-09 15:31:22 +000011191#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000011192 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
11193 CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
11194 GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
11195 SetConsoleTextAttribute(out,
11196 FOREGROUND_RED|FOREGROUND_INTENSITY
11197 );
mistachkin43e86272020-04-09 15:31:22 +000011198#endif
drh2ce15c32017-07-11 13:34:40 +000011199 printf("%s", zText);
mistachkin43e86272020-04-09 15:31:22 +000011200#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000011201 SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
mistachkin43e86272020-04-09 15:31:22 +000011202#endif
drh2ce15c32017-07-11 13:34:40 +000011203}
11204#else
11205static void printBold(const char *zText){
11206 printf("\033[1m%s\033[0m", zText);
11207}
11208#endif
11209
11210/*
11211** Get the argument to an --option. Throw an error and die if no argument
11212** is available.
11213*/
11214static char *cmdline_option_value(int argc, char **argv, int i){
11215 if( i==argc ){
11216 utf8_printf(stderr, "%s: Error: missing argument to %s\n",
11217 argv[0], argv[argc-1]);
11218 exit(1);
11219 }
11220 return argv[i];
11221}
11222
11223#ifndef SQLITE_SHELL_IS_UTF8
dan39b6bd52021-03-04 18:31:07 +000011224# if (defined(_WIN32) || defined(WIN32)) \
11225 && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
drh2ce15c32017-07-11 13:34:40 +000011226# define SQLITE_SHELL_IS_UTF8 (0)
11227# else
11228# define SQLITE_SHELL_IS_UTF8 (1)
11229# endif
11230#endif
11231
11232#if SQLITE_SHELL_IS_UTF8
11233int SQLITE_CDECL main(int argc, char **argv){
11234#else
11235int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
11236 char **argv;
11237#endif
11238 char *zErrMsg = 0;
11239 ShellState data;
11240 const char *zInitFile = 0;
11241 int i;
11242 int rc = 0;
11243 int warnInmemoryDb = 0;
11244 int readStdin = 1;
11245 int nCmd = 0;
11246 char **azCmd = 0;
dan16a47422018-04-18 09:16:11 +000011247 const char *zVfs = 0; /* Value of -vfs command-line option */
drh1f22f622018-05-17 13:29:14 +000011248#if !SQLITE_SHELL_IS_UTF8
11249 char **argvToFree = 0;
11250 int argcToFree = 0;
11251#endif
drh2ce15c32017-07-11 13:34:40 +000011252
11253 setBinaryMode(stdin, 0);
11254 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
11255 stdin_is_interactive = isatty(0);
11256 stdout_is_console = isatty(1);
11257
mistachkin1e8487d2018-07-22 06:25:35 +000011258#if !defined(_WIN32_WCE)
11259 if( getenv("SQLITE_DEBUG_BREAK") ){
11260 if( isatty(0) && isatty(2) ){
11261 fprintf(stderr,
11262 "attach debugger to process %d and press any key to continue.\n",
11263 GETPID());
11264 fgetc(stdin);
11265 }else{
11266#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +000011267#if SQLITE_OS_WINRT
11268 __debugbreak();
11269#else
mistachkin1e8487d2018-07-22 06:25:35 +000011270 DebugBreak();
mistachkin43e86272020-04-09 15:31:22 +000011271#endif
mistachkin1e8487d2018-07-22 06:25:35 +000011272#elif defined(SIGTRAP)
11273 raise(SIGTRAP);
11274#endif
11275 }
11276 }
11277#endif
11278
drh2ce15c32017-07-11 13:34:40 +000011279#if USE_SYSTEM_SQLITE+0!=1
drhb3c45232017-08-28 14:33:27 +000011280 if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
drh2ce15c32017-07-11 13:34:40 +000011281 utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
11282 sqlite3_sourceid(), SQLITE_SOURCE_ID);
11283 exit(1);
11284 }
11285#endif
11286 main_init(&data);
drh501ea052018-02-15 01:03:37 +000011287
11288 /* On Windows, we must translate command-line arguments into UTF-8.
11289 ** The SQLite memory allocator subsystem has to be enabled in order to
11290 ** do this. But we want to run an sqlite3_shutdown() afterwards so that
11291 ** subsequent sqlite3_config() calls will work. So copy all results into
11292 ** memory that does not come from the SQLite memory allocator.
11293 */
drh4b18c1d2018-02-04 20:33:13 +000011294#if !SQLITE_SHELL_IS_UTF8
drh501ea052018-02-15 01:03:37 +000011295 sqlite3_initialize();
drh1f22f622018-05-17 13:29:14 +000011296 argvToFree = malloc(sizeof(argv[0])*argc*2);
drhe3e25652021-12-16 13:29:28 +000011297 shell_check_oom(argvToFree);
drh1f22f622018-05-17 13:29:14 +000011298 argcToFree = argc;
11299 argv = argvToFree + argc;
drh2ce15c32017-07-11 13:34:40 +000011300 for(i=0; i<argc; i++){
drh501ea052018-02-15 01:03:37 +000011301 char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
11302 int n;
drhe3e25652021-12-16 13:29:28 +000011303 shell_check_oom(z);
drh501ea052018-02-15 01:03:37 +000011304 n = (int)strlen(z);
11305 argv[i] = malloc( n+1 );
drhe3e25652021-12-16 13:29:28 +000011306 shell_check_oom(argv[i]);
drh501ea052018-02-15 01:03:37 +000011307 memcpy(argv[i], z, n+1);
drh1f22f622018-05-17 13:29:14 +000011308 argvToFree[i] = argv[i];
drh501ea052018-02-15 01:03:37 +000011309 sqlite3_free(z);
drh2ce15c32017-07-11 13:34:40 +000011310 }
drh501ea052018-02-15 01:03:37 +000011311 sqlite3_shutdown();
drh2ce15c32017-07-11 13:34:40 +000011312#endif
drh501ea052018-02-15 01:03:37 +000011313
drh2ce15c32017-07-11 13:34:40 +000011314 assert( argc>=1 && argv && argv[0] );
11315 Argv0 = argv[0];
11316
11317 /* Make sure we have a valid signal handler early, before anything
11318 ** else is done.
11319 */
11320#ifdef SIGINT
11321 signal(SIGINT, interrupt_handler);
mistachkinb4bab902017-10-27 17:09:44 +000011322#elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
11323 SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
drh2ce15c32017-07-11 13:34:40 +000011324#endif
11325
11326#ifdef SQLITE_SHELL_DBNAME_PROC
11327 {
11328 /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
11329 ** of a C-function that will provide the name of the database file. Use
11330 ** this compile-time option to embed this shell program in larger
11331 ** applications. */
11332 extern void SQLITE_SHELL_DBNAME_PROC(const char**);
drh37407122021-07-23 18:43:58 +000011333 SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename);
drh2ce15c32017-07-11 13:34:40 +000011334 warnInmemoryDb = 0;
11335 }
11336#endif
11337
11338 /* Do an initial pass through the command-line argument to locate
11339 ** the name of the database file, the name of the initialization file,
11340 ** the size of the alternative malloc heap,
11341 ** and the first command to execute.
11342 */
drhe7df8922018-04-18 10:44:58 +000011343 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000011344 for(i=1; i<argc; i++){
11345 char *z;
11346 z = argv[i];
11347 if( z[0]!='-' ){
drh37407122021-07-23 18:43:58 +000011348 if( data.aAuxDb->zDbFilename==0 ){
11349 data.aAuxDb->zDbFilename = z;
drh2ce15c32017-07-11 13:34:40 +000011350 }else{
11351 /* Excesss arguments are interpreted as SQL (or dot-commands) and
11352 ** mean that nothing is read from stdin */
11353 readStdin = 0;
11354 nCmd++;
11355 azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
drhe3e25652021-12-16 13:29:28 +000011356 shell_check_oom(azCmd);
drh2ce15c32017-07-11 13:34:40 +000011357 azCmd[nCmd-1] = z;
11358 }
11359 }
11360 if( z[1]=='-' ) z++;
11361 if( strcmp(z,"-separator")==0
11362 || strcmp(z,"-nullvalue")==0
11363 || strcmp(z,"-newline")==0
11364 || strcmp(z,"-cmd")==0
11365 ){
11366 (void)cmdline_option_value(argc, argv, ++i);
11367 }else if( strcmp(z,"-init")==0 ){
11368 zInitFile = cmdline_option_value(argc, argv, ++i);
11369 }else if( strcmp(z,"-batch")==0 ){
11370 /* Need to check for batch mode here to so we can avoid printing
11371 ** informational messages (like from process_sqliterc) before
11372 ** we do the actual processing of arguments later in a second pass.
11373 */
11374 stdin_is_interactive = 0;
11375 }else if( strcmp(z,"-heap")==0 ){
11376#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
11377 const char *zSize;
11378 sqlite3_int64 szHeap;
11379
11380 zSize = cmdline_option_value(argc, argv, ++i);
11381 szHeap = integerValue(zSize);
11382 if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
11383 sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
11384#else
11385 (void)cmdline_option_value(argc, argv, ++i);
11386#endif
drh2ce15c32017-07-11 13:34:40 +000011387 }else if( strcmp(z,"-pagecache")==0 ){
drhf573b4f2020-09-28 13:34:05 +000011388 sqlite3_int64 n, sz;
11389 sz = integerValue(cmdline_option_value(argc,argv,++i));
drh2ce15c32017-07-11 13:34:40 +000011390 if( sz>70000 ) sz = 70000;
11391 if( sz<0 ) sz = 0;
drhf573b4f2020-09-28 13:34:05 +000011392 n = integerValue(cmdline_option_value(argc,argv,++i));
11393 if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
11394 n = 0xffffffffffffLL/sz;
11395 }
drh2ce15c32017-07-11 13:34:40 +000011396 sqlite3_config(SQLITE_CONFIG_PAGECACHE,
11397 (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
11398 data.shellFlgs |= SHFLG_Pagecache;
11399 }else if( strcmp(z,"-lookaside")==0 ){
11400 int n, sz;
11401 sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
11402 if( sz<0 ) sz = 0;
11403 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
11404 if( n<0 ) n = 0;
11405 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
11406 if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
drhaf6d1af2021-08-09 17:37:58 +000011407 }else if( strcmp(z,"-threadsafe")==0 ){
drh9d16fb12021-08-09 17:45:00 +000011408 int n;
11409 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
11410 switch( n ){
drhaf6d1af2021-08-09 17:37:58 +000011411 case 0: sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); break;
11412 case 2: sqlite3_config(SQLITE_CONFIG_MULTITHREAD); break;
11413 default: sqlite3_config(SQLITE_CONFIG_SERIALIZED); break;
11414 }
drh2ce15c32017-07-11 13:34:40 +000011415#ifdef SQLITE_ENABLE_VFSTRACE
11416 }else if( strcmp(z,"-vfstrace")==0 ){
11417 extern int vfstrace_register(
11418 const char *zTraceName,
11419 const char *zOldVfsName,
11420 int (*xOut)(const char*,void*),
11421 void *pOutArg,
11422 int makeDefault
11423 );
11424 vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
11425#endif
11426#ifdef SQLITE_ENABLE_MULTIPLEX
11427 }else if( strcmp(z,"-multiplex")==0 ){
11428 extern int sqlite3_multiple_initialize(const char*,int);
11429 sqlite3_multiplex_initialize(0, 1);
11430#endif
11431 }else if( strcmp(z,"-mmap")==0 ){
11432 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
11433 sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
drha90d84f2018-04-18 15:21:13 +000011434#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11435 }else if( strcmp(z,"-sorterref")==0 ){
11436 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
11437 sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz);
11438#endif
drh2ce15c32017-07-11 13:34:40 +000011439 }else if( strcmp(z,"-vfs")==0 ){
dan16a47422018-04-18 09:16:11 +000011440 zVfs = cmdline_option_value(argc, argv, ++i);
drh3baed312018-03-08 18:14:41 +000011441#ifdef SQLITE_HAVE_ZLIB
drh8682e122018-01-07 20:38:10 +000011442 }else if( strcmp(z,"-zip")==0 ){
11443 data.openMode = SHELL_OPEN_ZIPFILE;
11444#endif
11445 }else if( strcmp(z,"-append")==0 ){
11446 data.openMode = SHELL_OPEN_APPENDVFS;
drh8d889af2021-05-08 17:18:23 +000011447#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +000011448 }else if( strcmp(z,"-deserialize")==0 ){
11449 data.openMode = SHELL_OPEN_DESERIALIZE;
drh6ca64482019-01-22 16:06:20 +000011450 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
11451 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000011452#endif
drhee269a62018-02-14 23:27:43 +000011453 }else if( strcmp(z,"-readonly")==0 ){
11454 data.openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +000011455 }else if( strcmp(z,"-nofollow")==0 ){
11456 data.openFlags = SQLITE_OPEN_NOFOLLOW;
drhda57d962018-03-05 19:34:05 +000011457#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drh93b77312018-03-05 20:20:22 +000011458 }else if( strncmp(z, "-A",2)==0 ){
drhda57d962018-03-05 19:34:05 +000011459 /* All remaining command-line arguments are passed to the ".archive"
11460 ** command, so ignore them */
11461 break;
11462#endif
drh50b910a2019-01-21 14:55:03 +000011463 }else if( strcmp(z, "-memtrace")==0 ){
11464 sqlite3MemTraceActivate(stderr);
drhb7c46aa2020-11-25 13:59:47 +000011465 }else if( strcmp(z,"-bail")==0 ){
11466 bail_on_error = 1;
drhb97e2ad2021-08-26 18:31:39 +000011467 }else if( strcmp(z,"-nonce")==0 ){
11468 free(data.zNonce);
11469 data.zNonce = strdup(argv[++i]);
11470 }else if( strcmp(z,"-safe")==0 ){
11471 /* no-op - catch this on the second pass */
drh2ce15c32017-07-11 13:34:40 +000011472 }
11473 }
drhe7df8922018-04-18 10:44:58 +000011474 verify_uninitialized();
11475
dan16a47422018-04-18 09:16:11 +000011476
drhd11b8f62018-04-25 13:27:07 +000011477#ifdef SQLITE_SHELL_INIT_PROC
11478 {
11479 /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name
11480 ** of a C-function that will perform initialization actions on SQLite that
11481 ** occur just before or after sqlite3_initialize(). Use this compile-time
11482 ** option to embed this shell program in larger applications. */
11483 extern void SQLITE_SHELL_INIT_PROC(void);
11484 SQLITE_SHELL_INIT_PROC();
11485 }
11486#else
dan16a47422018-04-18 09:16:11 +000011487 /* All the sqlite3_config() calls have now been made. So it is safe
11488 ** to call sqlite3_initialize() and process any command line -vfs option. */
11489 sqlite3_initialize();
drhd11b8f62018-04-25 13:27:07 +000011490#endif
11491
dan16a47422018-04-18 09:16:11 +000011492 if( zVfs ){
11493 sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
11494 if( pVfs ){
11495 sqlite3_vfs_register(pVfs, 1);
11496 }else{
11497 utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
11498 exit(1);
11499 }
11500 }
11501
drh37407122021-07-23 18:43:58 +000011502 if( data.pAuxDb->zDbFilename==0 ){
drh2ce15c32017-07-11 13:34:40 +000011503#ifndef SQLITE_OMIT_MEMORYDB
drh37407122021-07-23 18:43:58 +000011504 data.pAuxDb->zDbFilename = ":memory:";
drh2ce15c32017-07-11 13:34:40 +000011505 warnInmemoryDb = argc==1;
11506#else
11507 utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
11508 return 1;
11509#endif
11510 }
11511 data.out = stdout;
drh8682e122018-01-07 20:38:10 +000011512 sqlite3_appendvfs_init(0,0,0);
drh2ce15c32017-07-11 13:34:40 +000011513
11514 /* Go ahead and open the database file if it already exists. If the
11515 ** file does not exist, delay opening it. This prevents empty database
11516 ** files from being created if a user mistypes the database name argument
11517 ** to the sqlite command-line tool.
11518 */
drh37407122021-07-23 18:43:58 +000011519 if( access(data.pAuxDb->zDbFilename, 0)==0 ){
drh2ce15c32017-07-11 13:34:40 +000011520 open_db(&data, 0);
11521 }
11522
11523 /* Process the initialization file if there is one. If no -init option
11524 ** is given on the command line, look for a file named ~/.sqliterc and
11525 ** try to process it.
11526 */
11527 process_sqliterc(&data,zInitFile);
11528
11529 /* Make a second pass through the command-line argument and set
11530 ** options. This second pass is delayed until after the initialization
11531 ** file is processed so that the command-line arguments will override
11532 ** settings in the initialization file.
11533 */
11534 for(i=1; i<argc; i++){
11535 char *z = argv[i];
11536 if( z[0]!='-' ) continue;
11537 if( z[1]=='-' ){ z++; }
11538 if( strcmp(z,"-init")==0 ){
11539 i++;
11540 }else if( strcmp(z,"-html")==0 ){
11541 data.mode = MODE_Html;
11542 }else if( strcmp(z,"-list")==0 ){
11543 data.mode = MODE_List;
11544 }else if( strcmp(z,"-quote")==0 ){
11545 data.mode = MODE_Quote;
drh9191c702020-08-17 09:11:21 +000011546 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma);
11547 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +000011548 }else if( strcmp(z,"-line")==0 ){
11549 data.mode = MODE_Line;
11550 }else if( strcmp(z,"-column")==0 ){
11551 data.mode = MODE_Column;
drh30c54a02020-05-28 23:49:50 +000011552 }else if( strcmp(z,"-json")==0 ){
11553 data.mode = MODE_Json;
11554 }else if( strcmp(z,"-markdown")==0 ){
11555 data.mode = MODE_Markdown;
11556 }else if( strcmp(z,"-table")==0 ){
11557 data.mode = MODE_Table;
drh0908e382020-06-04 18:05:39 +000011558 }else if( strcmp(z,"-box")==0 ){
11559 data.mode = MODE_Box;
drh2ce15c32017-07-11 13:34:40 +000011560 }else if( strcmp(z,"-csv")==0 ){
11561 data.mode = MODE_Csv;
11562 memcpy(data.colSeparator,",",2);
drh3baed312018-03-08 18:14:41 +000011563#ifdef SQLITE_HAVE_ZLIB
drh1fa6d9f2018-01-06 21:46:01 +000011564 }else if( strcmp(z,"-zip")==0 ){
11565 data.openMode = SHELL_OPEN_ZIPFILE;
11566#endif
11567 }else if( strcmp(z,"-append")==0 ){
11568 data.openMode = SHELL_OPEN_APPENDVFS;
drh8d889af2021-05-08 17:18:23 +000011569#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +000011570 }else if( strcmp(z,"-deserialize")==0 ){
11571 data.openMode = SHELL_OPEN_DESERIALIZE;
drh6ca64482019-01-22 16:06:20 +000011572 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
11573 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000011574#endif
drh4aafe592018-03-23 16:08:30 +000011575 }else if( strcmp(z,"-readonly")==0 ){
11576 data.openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +000011577 }else if( strcmp(z,"-nofollow")==0 ){
11578 data.openFlags |= SQLITE_OPEN_NOFOLLOW;
drh2ce15c32017-07-11 13:34:40 +000011579 }else if( strcmp(z,"-ascii")==0 ){
11580 data.mode = MODE_Ascii;
drh2fa78182020-10-31 18:58:37 +000011581 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit);
11582 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record);
11583 }else if( strcmp(z,"-tabs")==0 ){
11584 data.mode = MODE_List;
11585 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Tab);
11586 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +000011587 }else if( strcmp(z,"-separator")==0 ){
11588 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
11589 "%s",cmdline_option_value(argc,argv,++i));
11590 }else if( strcmp(z,"-newline")==0 ){
11591 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
11592 "%s",cmdline_option_value(argc,argv,++i));
11593 }else if( strcmp(z,"-nullvalue")==0 ){
11594 sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
11595 "%s",cmdline_option_value(argc,argv,++i));
11596 }else if( strcmp(z,"-header")==0 ){
11597 data.showHeader = 1;
larrybrae509122021-09-10 01:45:20 +000011598 ShellSetFlag(&data, SHFLG_HeaderSet);
11599 }else if( strcmp(z,"-noheader")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011600 data.showHeader = 0;
larrybrae509122021-09-10 01:45:20 +000011601 ShellSetFlag(&data, SHFLG_HeaderSet);
drh2ce15c32017-07-11 13:34:40 +000011602 }else if( strcmp(z,"-echo")==0 ){
11603 ShellSetFlag(&data, SHFLG_Echo);
11604 }else if( strcmp(z,"-eqp")==0 ){
drhada70452017-12-21 21:02:27 +000011605 data.autoEQP = AUTOEQP_on;
drh2ce15c32017-07-11 13:34:40 +000011606 }else if( strcmp(z,"-eqpfull")==0 ){
drhada70452017-12-21 21:02:27 +000011607 data.autoEQP = AUTOEQP_full;
drh2ce15c32017-07-11 13:34:40 +000011608 }else if( strcmp(z,"-stats")==0 ){
11609 data.statsOn = 1;
11610 }else if( strcmp(z,"-scanstats")==0 ){
11611 data.scanstatsOn = 1;
11612 }else if( strcmp(z,"-backslash")==0 ){
11613 /* Undocumented command-line option: -backslash
11614 ** Causes C-style backslash escapes to be evaluated in SQL statements
11615 ** prior to sending the SQL into SQLite. Useful for injecting
11616 ** crazy bytes in the middle of SQL statements for testing and debugging.
11617 */
11618 ShellSetFlag(&data, SHFLG_Backslash);
11619 }else if( strcmp(z,"-bail")==0 ){
drhb7c46aa2020-11-25 13:59:47 +000011620 /* No-op. The bail_on_error flag should already be set. */
drh2ce15c32017-07-11 13:34:40 +000011621 }else if( strcmp(z,"-version")==0 ){
11622 printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
11623 return 0;
11624 }else if( strcmp(z,"-interactive")==0 ){
11625 stdin_is_interactive = 1;
11626 }else if( strcmp(z,"-batch")==0 ){
11627 stdin_is_interactive = 0;
11628 }else if( strcmp(z,"-heap")==0 ){
11629 i++;
drh2ce15c32017-07-11 13:34:40 +000011630 }else if( strcmp(z,"-pagecache")==0 ){
11631 i+=2;
11632 }else if( strcmp(z,"-lookaside")==0 ){
11633 i+=2;
drhaf6d1af2021-08-09 17:37:58 +000011634 }else if( strcmp(z,"-threadsafe")==0 ){
11635 i+=2;
drhb97e2ad2021-08-26 18:31:39 +000011636 }else if( strcmp(z,"-nonce")==0 ){
11637 i += 2;
drh2ce15c32017-07-11 13:34:40 +000011638 }else if( strcmp(z,"-mmap")==0 ){
11639 i++;
drh50b910a2019-01-21 14:55:03 +000011640 }else if( strcmp(z,"-memtrace")==0 ){
11641 i++;
drha90d84f2018-04-18 15:21:13 +000011642#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11643 }else if( strcmp(z,"-sorterref")==0 ){
11644 i++;
11645#endif
drh2ce15c32017-07-11 13:34:40 +000011646 }else if( strcmp(z,"-vfs")==0 ){
11647 i++;
11648#ifdef SQLITE_ENABLE_VFSTRACE
11649 }else if( strcmp(z,"-vfstrace")==0 ){
11650 i++;
11651#endif
11652#ifdef SQLITE_ENABLE_MULTIPLEX
11653 }else if( strcmp(z,"-multiplex")==0 ){
11654 i++;
11655#endif
11656 }else if( strcmp(z,"-help")==0 ){
11657 usage(1);
11658 }else if( strcmp(z,"-cmd")==0 ){
11659 /* Run commands that follow -cmd first and separately from commands
11660 ** that simply appear on the command-line. This seems goofy. It would
11661 ** be better if all commands ran in the order that they appear. But
11662 ** we retain the goofy behavior for historical compatibility. */
11663 if( i==argc-1 ) break;
11664 z = cmdline_option_value(argc,argv,++i);
11665 if( z[0]=='.' ){
11666 rc = do_meta_command(z, &data);
11667 if( rc && bail_on_error ) return rc==2 ? 0 : rc;
11668 }else{
11669 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000011670 rc = shell_exec(&data, z, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000011671 if( zErrMsg!=0 ){
11672 utf8_printf(stderr,"Error: %s\n", zErrMsg);
11673 if( bail_on_error ) return rc!=0 ? rc : 1;
11674 }else if( rc!=0 ){
11675 utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
11676 if( bail_on_error ) return rc;
11677 }
11678 }
drhda57d962018-03-05 19:34:05 +000011679#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drh93b77312018-03-05 20:20:22 +000011680 }else if( strncmp(z, "-A", 2)==0 ){
drhda57d962018-03-05 19:34:05 +000011681 if( nCmd>0 ){
11682 utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
11683 " with \"%s\"\n", z);
11684 return 1;
11685 }
drhbe4ccb22018-05-17 20:04:24 +000011686 open_db(&data, OPEN_DB_ZIPFILE);
drh93b77312018-03-05 20:20:22 +000011687 if( z[2] ){
11688 argv[i] = &z[2];
drhd0f9cdc2018-05-17 14:09:06 +000011689 arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
drh93b77312018-03-05 20:20:22 +000011690 }else{
drhd0f9cdc2018-05-17 14:09:06 +000011691 arDotCommand(&data, 1, argv+i, argc-i);
drh93b77312018-03-05 20:20:22 +000011692 }
drhda57d962018-03-05 19:34:05 +000011693 readStdin = 0;
11694 break;
11695#endif
drhb97e2ad2021-08-26 18:31:39 +000011696 }else if( strcmp(z,"-safe")==0 ){
11697 data.bSafeMode = data.bSafeModePersist = 1;
drh2ce15c32017-07-11 13:34:40 +000011698 }else{
11699 utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
11700 raw_printf(stderr,"Use -help for a list of options.\n");
11701 return 1;
11702 }
11703 data.cMode = data.mode;
11704 }
11705
11706 if( !readStdin ){
11707 /* Run all arguments that do not begin with '-' as if they were separate
11708 ** command-line inputs, except for the argToSkip argument which contains
11709 ** the database filename.
11710 */
11711 for(i=0; i<nCmd; i++){
11712 if( azCmd[i][0]=='.' ){
11713 rc = do_meta_command(azCmd[i], &data);
danaff1a572020-11-17 21:09:56 +000011714 if( rc ){
11715 free(azCmd);
11716 return rc==2 ? 0 : rc;
11717 }
drh2ce15c32017-07-11 13:34:40 +000011718 }else{
11719 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000011720 rc = shell_exec(&data, azCmd[i], &zErrMsg);
danaff1a572020-11-17 21:09:56 +000011721 if( zErrMsg || rc ){
11722 if( zErrMsg!=0 ){
11723 utf8_printf(stderr,"Error: %s\n", zErrMsg);
11724 }else{
11725 utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
11726 }
11727 sqlite3_free(zErrMsg);
11728 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000011729 return rc!=0 ? rc : 1;
drh2ce15c32017-07-11 13:34:40 +000011730 }
11731 }
11732 }
drh2ce15c32017-07-11 13:34:40 +000011733 }else{
11734 /* Run commands received from standard input
11735 */
11736 if( stdin_is_interactive ){
11737 char *zHome;
drha9e4be32018-10-10 18:56:40 +000011738 char *zHistory;
drh2ce15c32017-07-11 13:34:40 +000011739 int nHistory;
11740 printf(
11741 "SQLite version %s %.19s\n" /*extra-version-info*/
11742 "Enter \".help\" for usage hints.\n",
11743 sqlite3_libversion(), sqlite3_sourceid()
11744 );
11745 if( warnInmemoryDb ){
11746 printf("Connected to a ");
11747 printBold("transient in-memory database");
11748 printf(".\nUse \".open FILENAME\" to reopen on a "
11749 "persistent database.\n");
11750 }
drha9e4be32018-10-10 18:56:40 +000011751 zHistory = getenv("SQLITE_HISTORY");
11752 if( zHistory ){
11753 zHistory = strdup(zHistory);
11754 }else if( (zHome = find_home_dir(0))!=0 ){
drh2ce15c32017-07-11 13:34:40 +000011755 nHistory = strlen30(zHome) + 20;
11756 if( (zHistory = malloc(nHistory))!=0 ){
11757 sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
11758 }
11759 }
11760 if( zHistory ){ shell_read_history(zHistory); }
drh56eb09b2017-07-11 13:59:07 +000011761#if HAVE_READLINE || HAVE_EDITLINE
11762 rl_attempted_completion_function = readline_completion;
11763#elif HAVE_LINENOISE
11764 linenoiseSetCompletionCallback(linenoise_completion);
11765#endif
drh60379d42018-12-13 18:30:01 +000011766 data.in = 0;
11767 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000011768 if( zHistory ){
drh5a75dd82017-07-18 20:59:40 +000011769 shell_stifle_history(2000);
drh2ce15c32017-07-11 13:34:40 +000011770 shell_write_history(zHistory);
11771 free(zHistory);
11772 }
11773 }else{
drh60379d42018-12-13 18:30:01 +000011774 data.in = stdin;
11775 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000011776 }
11777 }
danaff1a572020-11-17 21:09:56 +000011778 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000011779 set_table_name(&data, 0);
11780 if( data.db ){
drh37407122021-07-23 18:43:58 +000011781 session_close_all(&data, -1);
drh9e804032018-05-18 17:11:50 +000011782 close_db(data.db);
drh2ce15c32017-07-11 13:34:40 +000011783 }
drh37407122021-07-23 18:43:58 +000011784 for(i=0; i<ArraySize(data.aAuxDb); i++){
11785 sqlite3_free(data.aAuxDb[i].zFreeOnClose);
11786 if( data.aAuxDb[i].db ){
11787 session_close_all(&data, i);
11788 close_db(data.aAuxDb[i].db);
11789 }
11790 }
drh2ce15c32017-07-11 13:34:40 +000011791 find_home_dir(1);
drh536c3452018-01-11 00:38:39 +000011792 output_reset(&data);
11793 data.doXdgOpen = 0;
drh13c20932018-01-10 21:41:55 +000011794 clearTempFile(&data);
drh2ce15c32017-07-11 13:34:40 +000011795#if !SQLITE_SHELL_IS_UTF8
drh1f22f622018-05-17 13:29:14 +000011796 for(i=0; i<argcToFree; i++) free(argvToFree[i]);
11797 free(argvToFree);
drh2ce15c32017-07-11 13:34:40 +000011798#endif
drh0285d982020-05-29 14:38:43 +000011799 free(data.colWidth);
drhb97e2ad2021-08-26 18:31:39 +000011800 free(data.zNonce);
drh9e804032018-05-18 17:11:50 +000011801 /* Clear the global data structure so that valgrind will detect memory
11802 ** leaks */
11803 memset(&data, 0, sizeof(data));
drh2ce15c32017-07-11 13:34:40 +000011804 return rc;
11805}