blob: 3d15cc1f892920d00cff7117c30e6dd3730fad68 [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
drhf62641e2021-12-24 20:22:13 +00002522/*
2523** Maybe construct two lines of text that point out the position of a
2524** syntax error. Return a pointer to the text, in memory obtained from
2525** sqlite3_malloc(). Or, if the most recent error does not involve a
2526** specific token that we can point to, return an empty string.
2527**
2528** In all cases, the memory returned is obtained from sqlite3_malloc64()
2529** and should be released by the caller invoking sqlite3_free().
2530*/
2531static char *shell_error_context(const char *zSql, sqlite3 *db){
2532 int iOffset;
2533 size_t len;
2534 char *zCode;
2535 char *zMsg;
2536 int i;
2537 if( db==0
2538 || zSql==0
2539 || (iOffset = sqlite3_error_offset(db))<0
2540 ){
2541 return sqlite3_mprintf("");
2542 }
2543 while( iOffset>50 ){
2544 iOffset--;
2545 zSql++;
2546 while( (zSql[0]&0xc0)==0x80 ){ zSql++; iOffset--; }
2547 }
2548 len = strlen(zSql);
2549 if( len>78 ){
2550 len = 78;
2551 while( (zSql[len]&0xc0)==0x80 ) len--;
2552 }
2553 zCode = sqlite3_mprintf("%.*s", len, zSql);
2554 for(i=0; zCode[i]; i++){ if( IsSpace(zSql[i]) ) zCode[i] = ' '; }
2555 if( iOffset<25 ){
2556 zMsg = sqlite3_mprintf("\n %z\n %*s^--- error here", zCode, iOffset, "");
2557 }else{
2558 zMsg = sqlite3_mprintf("\n %z\n %*serror here ---^", zCode, iOffset-14, "");
2559 }
2560 return zMsg;
2561}
2562
drh2ce15c32017-07-11 13:34:40 +00002563
2564/*
2565** Execute a query statement that will generate SQL output. Print
2566** the result columns, comma-separated, on a line and then add a
2567** semicolon terminator to the end of that line.
2568**
2569** If the number of columns is 1 and that column contains text "--"
2570** then write the semicolon on a separate line. That way, if a
2571** "--" comment occurs at the end of the statement, the comment
2572** won't consume the semicolon terminator.
2573*/
2574static int run_table_dump_query(
2575 ShellState *p, /* Query context */
drh8e9297f2020-03-25 12:50:13 +00002576 const char *zSelect /* SELECT statement to extract content */
drh2ce15c32017-07-11 13:34:40 +00002577){
2578 sqlite3_stmt *pSelect;
2579 int rc;
2580 int nResult;
2581 int i;
2582 const char *z;
2583 rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
2584 if( rc!=SQLITE_OK || !pSelect ){
drhf62641e2021-12-24 20:22:13 +00002585 char *zContext = shell_error_context(zSelect, p->db);
2586 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n%s", rc,
2587 sqlite3_errmsg(p->db), zContext);
2588 sqlite3_free(zContext);
drh2ce15c32017-07-11 13:34:40 +00002589 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
2590 return rc;
2591 }
2592 rc = sqlite3_step(pSelect);
2593 nResult = sqlite3_column_count(pSelect);
2594 while( rc==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00002595 z = (const char*)sqlite3_column_text(pSelect, 0);
2596 utf8_printf(p->out, "%s", z);
2597 for(i=1; i<nResult; i++){
2598 utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
2599 }
2600 if( z==0 ) z = "";
2601 while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
2602 if( z[0] ){
2603 raw_printf(p->out, "\n;\n");
2604 }else{
2605 raw_printf(p->out, ";\n");
2606 }
2607 rc = sqlite3_step(pSelect);
2608 }
2609 rc = sqlite3_finalize(pSelect);
2610 if( rc!=SQLITE_OK ){
2611 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
2612 sqlite3_errmsg(p->db));
2613 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
2614 }
2615 return rc;
2616}
2617
2618/*
larrybrf9a49b02021-10-26 16:57:09 +00002619** Allocate space and save off string indicating current error.
drh2ce15c32017-07-11 13:34:40 +00002620*/
2621static char *save_err_msg(
larrybrf9a49b02021-10-26 16:57:09 +00002622 sqlite3 *db, /* Database to query */
2623 const char *zWhen, /* Qualifier (format) wrapper */
drhf62641e2021-12-24 20:22:13 +00002624 int rc, /* Error code returned from API */
2625 const char *zSql /* SQL string, or NULL */
drh2ce15c32017-07-11 13:34:40 +00002626){
drhe3e25652021-12-16 13:29:28 +00002627 char *zErr;
drhf62641e2021-12-24 20:22:13 +00002628 char *zContext;
2629 if( zWhen==0 ) zWhen = "%s (%d)%s";
2630 zContext = shell_error_context(zSql, db);
2631 zErr = sqlite3_mprintf(zWhen, sqlite3_errmsg(db), rc, zContext);
drhe3e25652021-12-16 13:29:28 +00002632 shell_check_oom(zErr);
drhf62641e2021-12-24 20:22:13 +00002633 sqlite3_free(zContext);
drhe3e25652021-12-16 13:29:28 +00002634 return zErr;
drh2ce15c32017-07-11 13:34:40 +00002635}
2636
2637#ifdef __linux__
2638/*
2639** Attempt to display I/O stats on Linux using /proc/PID/io
2640*/
2641static void displayLinuxIoStats(FILE *out){
2642 FILE *in;
2643 char z[200];
2644 sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
2645 in = fopen(z, "rb");
2646 if( in==0 ) return;
2647 while( fgets(z, sizeof(z), in)!=0 ){
2648 static const struct {
2649 const char *zPattern;
2650 const char *zDesc;
2651 } aTrans[] = {
2652 { "rchar: ", "Bytes received by read():" },
2653 { "wchar: ", "Bytes sent to write():" },
2654 { "syscr: ", "Read() system calls:" },
2655 { "syscw: ", "Write() system calls:" },
2656 { "read_bytes: ", "Bytes read from storage:" },
2657 { "write_bytes: ", "Bytes written to storage:" },
2658 { "cancelled_write_bytes: ", "Cancelled write bytes:" },
2659 };
2660 int i;
2661 for(i=0; i<ArraySize(aTrans); i++){
drhaf2770f2018-01-05 14:55:43 +00002662 int n = strlen30(aTrans[i].zPattern);
drh2ce15c32017-07-11 13:34:40 +00002663 if( strncmp(aTrans[i].zPattern, z, n)==0 ){
2664 utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
2665 break;
2666 }
2667 }
2668 }
2669 fclose(in);
2670}
2671#endif
2672
2673/*
2674** Display a single line of status using 64-bit values.
2675*/
2676static void displayStatLine(
2677 ShellState *p, /* The shell context */
2678 char *zLabel, /* Label for this one line */
2679 char *zFormat, /* Format for the result */
2680 int iStatusCtrl, /* Which status to display */
2681 int bReset /* True to reset the stats */
2682){
2683 sqlite3_int64 iCur = -1;
2684 sqlite3_int64 iHiwtr = -1;
2685 int i, nPercent;
2686 char zLine[200];
2687 sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset);
2688 for(i=0, nPercent=0; zFormat[i]; i++){
2689 if( zFormat[i]=='%' ) nPercent++;
2690 }
2691 if( nPercent>1 ){
2692 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr);
2693 }else{
2694 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
2695 }
2696 raw_printf(p->out, "%-36s %s\n", zLabel, zLine);
2697}
2698
2699/*
2700** Display memory stats.
2701*/
2702static int display_stats(
2703 sqlite3 *db, /* Database to query */
2704 ShellState *pArg, /* Pointer to ShellState */
2705 int bReset /* True to reset the stats */
2706){
2707 int iCur;
2708 int iHiwtr;
drh393344f2018-03-09 16:37:05 +00002709 FILE *out;
2710 if( pArg==0 || pArg->out==0 ) return 0;
2711 out = pArg->out;
drh2ce15c32017-07-11 13:34:40 +00002712
drha6e6cf22021-01-09 19:10:04 +00002713 if( pArg->pStmt && pArg->statsOn==2 ){
drh393344f2018-03-09 16:37:05 +00002714 int nCol, i, x;
2715 sqlite3_stmt *pStmt = pArg->pStmt;
2716 char z[100];
2717 nCol = sqlite3_column_count(pStmt);
2718 raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
2719 for(i=0; i<nCol; i++){
2720 sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
2721 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
drh929cce82018-03-17 16:26:36 +00002722#ifndef SQLITE_OMIT_DECLTYPE
drh393344f2018-03-09 16:37:05 +00002723 sqlite3_snprintf(30, z+x, "declared type:");
2724 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
drh929cce82018-03-17 16:26:36 +00002725#endif
2726#ifdef SQLITE_ENABLE_COLUMN_METADATA
drh393344f2018-03-09 16:37:05 +00002727 sqlite3_snprintf(30, z+x, "database name:");
2728 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
2729 sqlite3_snprintf(30, z+x, "table name:");
2730 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
2731 sqlite3_snprintf(30, z+x, "origin name:");
2732 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
drh929cce82018-03-17 16:26:36 +00002733#endif
drh2ce15c32017-07-11 13:34:40 +00002734 }
drh929cce82018-03-17 16:26:36 +00002735 }
drh2ce15c32017-07-11 13:34:40 +00002736
drha6e6cf22021-01-09 19:10:04 +00002737 if( pArg->statsOn==3 ){
2738 if( pArg->pStmt ){
2739 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
2740 raw_printf(pArg->out, "VM-steps: %d\n", iCur);
2741 }
2742 return 0;
2743 }
2744
drh393344f2018-03-09 16:37:05 +00002745 displayStatLine(pArg, "Memory Used:",
2746 "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
2747 displayStatLine(pArg, "Number of Outstanding Allocations:",
2748 "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
2749 if( pArg->shellFlgs & SHFLG_Pagecache ){
2750 displayStatLine(pArg, "Number of Pcache Pages Used:",
2751 "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
2752 }
2753 displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
2754 "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
2755 displayStatLine(pArg, "Largest Allocation:",
2756 "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
2757 displayStatLine(pArg, "Largest Pcache Allocation:",
2758 "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
2759#ifdef YYTRACKMAXSTACKDEPTH
2760 displayStatLine(pArg, "Deepest Parser Stack:",
2761 "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
2762#endif
2763
2764 if( db ){
drh2ce15c32017-07-11 13:34:40 +00002765 if( pArg->shellFlgs & SHFLG_Lookaside ){
2766 iHiwtr = iCur = -1;
2767 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
2768 &iCur, &iHiwtr, bReset);
2769 raw_printf(pArg->out,
2770 "Lookaside Slots Used: %d (max %d)\n",
2771 iCur, iHiwtr);
2772 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
2773 &iCur, &iHiwtr, bReset);
2774 raw_printf(pArg->out, "Successful lookaside attempts: %d\n",
2775 iHiwtr);
2776 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
2777 &iCur, &iHiwtr, bReset);
2778 raw_printf(pArg->out, "Lookaside failures due to size: %d\n",
2779 iHiwtr);
2780 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
2781 &iCur, &iHiwtr, bReset);
2782 raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n",
2783 iHiwtr);
2784 }
2785 iHiwtr = iCur = -1;
2786 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
2787 raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n",
2788 iCur);
2789 iHiwtr = iCur = -1;
2790 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
2791 raw_printf(pArg->out, "Page cache hits: %d\n", iCur);
2792 iHiwtr = iCur = -1;
2793 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
2794 raw_printf(pArg->out, "Page cache misses: %d\n", iCur);
2795 iHiwtr = iCur = -1;
2796 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
2797 raw_printf(pArg->out, "Page cache writes: %d\n", iCur);
2798 iHiwtr = iCur = -1;
drhffc78a42018-03-14 14:53:50 +00002799 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
2800 raw_printf(pArg->out, "Page cache spills: %d\n", iCur);
2801 iHiwtr = iCur = -1;
drh2ce15c32017-07-11 13:34:40 +00002802 sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
2803 raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n",
2804 iCur);
2805 iHiwtr = iCur = -1;
2806 sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
2807 raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
2808 iCur);
2809 }
2810
drh393344f2018-03-09 16:37:05 +00002811 if( pArg->pStmt ){
drh23d41e62021-12-06 21:45:31 +00002812 int iHit, iMiss;
drh2ce15c32017-07-11 13:34:40 +00002813 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
2814 bReset);
2815 raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
2816 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
2817 raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
2818 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
2819 raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
drh23d41e62021-12-06 21:45:31 +00002820 iHit = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_HIT, bReset);
2821 iMiss = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_MISS, bReset);
2822 if( iHit || iMiss ){
2823 raw_printf(pArg->out, "Bloom filter bypass taken: %d/%d\n",
2824 iHit, iHit+iMiss);
2825 }
drh2ce15c32017-07-11 13:34:40 +00002826 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
2827 raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
drhe2754c12019-08-26 12:50:01 +00002828 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
drh393344f2018-03-09 16:37:05 +00002829 raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
2830 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
2831 raw_printf(pArg->out, "Number of times run: %d\n", iCur);
2832 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
2833 raw_printf(pArg->out, "Memory used by prepared stmt: %d\n", iCur);
drh2ce15c32017-07-11 13:34:40 +00002834 }
2835
2836#ifdef __linux__
2837 displayLinuxIoStats(pArg->out);
2838#endif
2839
2840 /* Do not remove this machine readable comment: extra-stats-output-here */
2841
2842 return 0;
2843}
2844
2845/*
2846** Display scan stats.
2847*/
2848static void display_scanstats(
2849 sqlite3 *db, /* Database to query */
2850 ShellState *pArg /* Pointer to ShellState */
2851){
2852#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
2853 UNUSED_PARAMETER(db);
2854 UNUSED_PARAMETER(pArg);
2855#else
2856 int i, k, n, mx;
2857 raw_printf(pArg->out, "-------- scanstats --------\n");
2858 mx = 0;
2859 for(k=0; k<=mx; k++){
2860 double rEstLoop = 1.0;
2861 for(i=n=0; 1; i++){
2862 sqlite3_stmt *p = pArg->pStmt;
2863 sqlite3_int64 nLoop, nVisit;
2864 double rEst;
2865 int iSid;
2866 const char *zExplain;
2867 if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){
2868 break;
2869 }
2870 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
2871 if( iSid>mx ) mx = iSid;
2872 if( iSid!=k ) continue;
2873 if( n==0 ){
2874 rEstLoop = (double)nLoop;
2875 if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k);
2876 }
2877 n++;
2878 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
2879 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
2880 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
2881 utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
2882 rEstLoop *= rEst;
2883 raw_printf(pArg->out,
2884 " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
2885 nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
2886 );
2887 }
2888 }
2889 raw_printf(pArg->out, "---------------------------\n");
2890#endif
2891}
2892
2893/*
2894** Parameter azArray points to a zero-terminated array of strings. zStr
2895** points to a single nul-terminated string. Return non-zero if zStr
2896** is equal, according to strcmp(), to any of the strings in the array.
2897** Otherwise, return zero.
2898*/
2899static int str_in_array(const char *zStr, const char **azArray){
2900 int i;
2901 for(i=0; azArray[i]; i++){
2902 if( 0==strcmp(zStr, azArray[i]) ) return 1;
2903 }
2904 return 0;
2905}
2906
2907/*
2908** If compiled statement pSql appears to be an EXPLAIN statement, allocate
2909** and populate the ShellState.aiIndent[] array with the number of
2910** spaces each opcode should be indented before it is output.
2911**
2912** The indenting rules are:
2913**
2914** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
2915** all opcodes that occur between the p2 jump destination and the opcode
2916** itself by 2 spaces.
2917**
2918** * For each "Goto", if the jump destination is earlier in the program
2919** and ends on one of:
2920** Yield SeekGt SeekLt RowSetRead Rewind
2921** or if the P1 parameter is one instead of zero,
2922** then indent all opcodes between the earlier instruction
2923** and "Goto" by 2 spaces.
2924*/
2925static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
2926 const char *zSql; /* The text of the SQL statement */
2927 const char *z; /* Used to check if this is an EXPLAIN */
2928 int *abYield = 0; /* True if op is an OP_Yield */
2929 int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
2930 int iOp; /* Index of operation in p->aiIndent[] */
2931
drhf1949b62018-06-07 17:32:59 +00002932 const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
drh2ce15c32017-07-11 13:34:40 +00002933 const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
2934 "Rewind", 0 };
2935 const char *azGoto[] = { "Goto", 0 };
2936
2937 /* Try to figure out if this is really an EXPLAIN statement. If this
2938 ** cannot be verified, return early. */
2939 if( sqlite3_column_count(pSql)!=8 ){
2940 p->cMode = p->mode;
2941 return;
2942 }
2943 zSql = sqlite3_sql(pSql);
2944 if( zSql==0 ) return;
2945 for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
2946 if( sqlite3_strnicmp(z, "explain", 7) ){
2947 p->cMode = p->mode;
2948 return;
2949 }
2950
2951 for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
2952 int i;
2953 int iAddr = sqlite3_column_int(pSql, 0);
2954 const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
2955
2956 /* Set p2 to the P2 field of the current opcode. Then, assuming that
2957 ** p2 is an instruction address, set variable p2op to the index of that
2958 ** instruction in the aiIndent[] array. p2 and p2op may be different if
2959 ** the current instruction is part of a sub-program generated by an
2960 ** SQL trigger or foreign key. */
2961 int p2 = sqlite3_column_int(pSql, 3);
2962 int p2op = (p2 + (iOp-iAddr));
2963
2964 /* Grow the p->aiIndent array as required */
2965 if( iOp>=nAlloc ){
2966 if( iOp==0 ){
2967 /* Do further verfication that this is explain output. Abort if
2968 ** it is not */
2969 static const char *explainCols[] = {
2970 "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" };
2971 int jj;
2972 for(jj=0; jj<ArraySize(explainCols); jj++){
2973 if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
2974 p->cMode = p->mode;
2975 sqlite3_reset(pSql);
2976 return;
2977 }
2978 }
2979 }
2980 nAlloc += 100;
2981 p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
drhe3e25652021-12-16 13:29:28 +00002982 shell_check_oom(p->aiIndent);
drh2ce15c32017-07-11 13:34:40 +00002983 abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
drhe3e25652021-12-16 13:29:28 +00002984 shell_check_oom(abYield);
drh2ce15c32017-07-11 13:34:40 +00002985 }
2986 abYield[iOp] = str_in_array(zOp, azYield);
2987 p->aiIndent[iOp] = 0;
2988 p->nIndent = iOp+1;
2989
2990 if( str_in_array(zOp, azNext) ){
2991 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
2992 }
2993 if( str_in_array(zOp, azGoto) && p2op<p->nIndent
2994 && (abYield[p2op] || sqlite3_column_int(pSql, 2))
2995 ){
2996 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
2997 }
2998 }
2999
3000 p->iIndent = 0;
3001 sqlite3_free(abYield);
3002 sqlite3_reset(pSql);
3003}
3004
3005/*
3006** Free the array allocated by explain_data_prepare().
3007*/
3008static void explain_data_delete(ShellState *p){
3009 sqlite3_free(p->aiIndent);
3010 p->aiIndent = 0;
3011 p->nIndent = 0;
3012 p->iIndent = 0;
3013}
3014
3015/*
3016** Disable and restore .wheretrace and .selecttrace settings.
3017*/
drhc0622a42020-12-04 01:17:57 +00003018static unsigned int savedSelectTrace;
3019static unsigned int savedWhereTrace;
drh2ce15c32017-07-11 13:34:40 +00003020static void disable_debug_trace_modes(void){
drh0a2fb792020-12-04 16:58:20 +00003021 unsigned int zero = 0;
drhc0622a42020-12-04 01:17:57 +00003022 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace);
drh0a2fb792020-12-04 16:58:20 +00003023 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero);
drhc0622a42020-12-04 01:17:57 +00003024 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace);
drh0a2fb792020-12-04 16:58:20 +00003025 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero);
drh2ce15c32017-07-11 13:34:40 +00003026}
3027static void restore_debug_trace_modes(void){
drhc0622a42020-12-04 01:17:57 +00003028 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &savedSelectTrace);
3029 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &savedWhereTrace);
drh2ce15c32017-07-11 13:34:40 +00003030}
3031
drh9cb02642019-02-28 20:10:52 +00003032/* Create the TEMP table used to store parameter bindings */
3033static void bind_table_init(ShellState *p){
drh346f4e22019-03-25 21:35:41 +00003034 int wrSchema = 0;
drh4b86e202020-01-19 20:37:26 +00003035 int defensiveMode = 0;
3036 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
3037 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
drh346f4e22019-03-25 21:35:41 +00003038 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
3039 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
drh9cb02642019-02-28 20:10:52 +00003040 sqlite3_exec(p->db,
drh65c29fd2019-03-25 21:56:26 +00003041 "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
drh9cb02642019-02-28 20:10:52 +00003042 " key TEXT PRIMARY KEY,\n"
larrybrdabada62021-04-04 12:52:58 +00003043 " value\n"
drh9cb02642019-02-28 20:10:52 +00003044 ") WITHOUT ROWID;",
3045 0, 0, 0);
drh346f4e22019-03-25 21:35:41 +00003046 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
drh4b86e202020-01-19 20:37:26 +00003047 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0);
drh9cb02642019-02-28 20:10:52 +00003048}
3049
drh8b738d02019-02-25 18:43:54 +00003050/*
3051** Bind parameters on a prepared statement.
3052**
3053** Parameter bindings are taken from a TEMP table of the form:
3054**
drh1cb02632019-03-25 22:05:22 +00003055** CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
drh8b738d02019-02-25 18:43:54 +00003056** WITHOUT ROWID;
3057**
drh91654b22020-04-02 13:21:10 +00003058** No bindings occur if this table does not exist. The name of the table
3059** begins with "sqlite_" so that it will not collide with ordinary application
3060** tables. The table must be in the TEMP schema.
drh8b738d02019-02-25 18:43:54 +00003061*/
3062static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
3063 int nVar;
3064 int i;
3065 int rc;
3066 sqlite3_stmt *pQ = 0;
3067
3068 nVar = sqlite3_bind_parameter_count(pStmt);
3069 if( nVar==0 ) return; /* Nothing to do */
drh65c29fd2019-03-25 21:56:26 +00003070 if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters",
drh8b738d02019-02-25 18:43:54 +00003071 "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
3072 return; /* Parameter table does not exist */
3073 }
3074 rc = sqlite3_prepare_v2(pArg->db,
drh65c29fd2019-03-25 21:56:26 +00003075 "SELECT value FROM temp.sqlite_parameters"
drh8b738d02019-02-25 18:43:54 +00003076 " WHERE key=?1", -1, &pQ, 0);
3077 if( rc || pQ==0 ) return;
3078 for(i=1; i<=nVar; i++){
3079 char zNum[30];
3080 const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
3081 if( zVar==0 ){
3082 sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
3083 zVar = zNum;
3084 }
3085 sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
3086 if( sqlite3_step(pQ)==SQLITE_ROW ){
3087 sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
3088 }else{
3089 sqlite3_bind_null(pStmt, i);
3090 }
3091 sqlite3_reset(pQ);
3092 }
3093 sqlite3_finalize(pQ);
3094}
3095
drh30c54a02020-05-28 23:49:50 +00003096/*
drh0908e382020-06-04 18:05:39 +00003097** UTF8 box-drawing characters. Imagine box lines like this:
3098**
3099** 1
3100** |
3101** 4 --+-- 2
3102** |
3103** 3
3104**
3105** Each box characters has between 2 and 4 of the lines leading from
3106** the center. The characters are here identified by the numbers of
3107** their corresponding lines.
3108*/
3109#define BOX_24 "\342\224\200" /* U+2500 --- */
3110#define BOX_13 "\342\224\202" /* U+2502 | */
3111#define BOX_23 "\342\224\214" /* U+250c ,- */
3112#define BOX_34 "\342\224\220" /* U+2510 -, */
3113#define BOX_12 "\342\224\224" /* U+2514 '- */
3114#define BOX_14 "\342\224\230" /* U+2518 -' */
3115#define BOX_123 "\342\224\234" /* U+251c |- */
3116#define BOX_134 "\342\224\244" /* U+2524 -| */
3117#define BOX_234 "\342\224\254" /* U+252c -,- */
3118#define BOX_124 "\342\224\264" /* U+2534 -'- */
3119#define BOX_1234 "\342\224\274" /* U+253c -|- */
3120
3121/* Draw horizontal line N characters long using unicode box
3122** characters
3123*/
3124static void print_box_line(FILE *out, int N){
3125 const char zDash[] =
3126 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
3127 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
3128 const int nDash = sizeof(zDash) - 1;
3129 N *= 3;
3130 while( N>nDash ){
3131 utf8_printf(out, zDash);
3132 N -= nDash;
3133 }
3134 utf8_printf(out, "%.*s", N, zDash);
3135}
3136
3137/*
3138** Draw a horizontal separator for a MODE_Box table.
3139*/
3140static void print_box_row_separator(
3141 ShellState *p,
3142 int nArg,
3143 const char *zSep1,
3144 const char *zSep2,
3145 const char *zSep3
3146){
3147 int i;
3148 if( nArg>0 ){
3149 utf8_printf(p->out, "%s", zSep1);
3150 print_box_line(p->out, p->actualWidth[0]+2);
3151 for(i=1; i<nArg; i++){
3152 utf8_printf(p->out, "%s", zSep2);
3153 print_box_line(p->out, p->actualWidth[i]+2);
3154 }
3155 utf8_printf(p->out, "%s", zSep3);
3156 }
3157 fputs("\n", p->out);
3158}
3159
3160
3161
3162/*
drh30c54a02020-05-28 23:49:50 +00003163** Run a prepared statement and output the result in one of the
drh0908e382020-06-04 18:05:39 +00003164** table-oriented formats: MODE_Column, MODE_Markdown, MODE_Table,
3165** or MODE_Box.
drh30c54a02020-05-28 23:49:50 +00003166**
3167** This is different from ordinary exec_prepared_stmt() in that
3168** it has to run the entire query and gather the results into memory
3169** first, in order to determine column widths, before providing
3170** any output.
3171*/
drh8c748632020-05-29 16:15:58 +00003172static void exec_prepared_stmt_columnar(
3173 ShellState *p, /* Pointer to ShellState */
3174 sqlite3_stmt *pStmt /* Statment to run */
drh30c54a02020-05-28 23:49:50 +00003175){
drhf82ce382020-08-06 16:45:22 +00003176 sqlite3_int64 nRow = 0;
drh8c748632020-05-29 16:15:58 +00003177 int nColumn = 0;
3178 char **azData = 0;
drhf82ce382020-08-06 16:45:22 +00003179 sqlite3_int64 nAlloc = 0;
drh8c748632020-05-29 16:15:58 +00003180 const char *z;
3181 int rc;
drhf82ce382020-08-06 16:45:22 +00003182 sqlite3_int64 i, nData;
3183 int j, nTotal, w, n;
drh0908e382020-06-04 18:05:39 +00003184 const char *colSep = 0;
3185 const char *rowSep = 0;
drh30c54a02020-05-28 23:49:50 +00003186
drhf82ce382020-08-06 16:45:22 +00003187 rc = sqlite3_step(pStmt);
3188 if( rc!=SQLITE_ROW ) return;
3189 nColumn = sqlite3_column_count(pStmt);
3190 nAlloc = nColumn*4;
drh01a8ad22021-03-20 23:15:52 +00003191 if( nAlloc<=0 ) nAlloc = 1;
drhf82ce382020-08-06 16:45:22 +00003192 azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
drhe3e25652021-12-16 13:29:28 +00003193 shell_check_oom(azData);
drhf82ce382020-08-06 16:45:22 +00003194 for(i=0; i<nColumn; i++){
3195 azData[i] = strdup(sqlite3_column_name(pStmt,i));
drh8c748632020-05-29 16:15:58 +00003196 }
drhf82ce382020-08-06 16:45:22 +00003197 do{
3198 if( (nRow+2)*nColumn >= nAlloc ){
3199 nAlloc *= 2;
3200 azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*));
drhe3e25652021-12-16 13:29:28 +00003201 shell_check_oom(azData);
drhf82ce382020-08-06 16:45:22 +00003202 }
3203 nRow++;
3204 for(i=0; i<nColumn; i++){
3205 z = (const char*)sqlite3_column_text(pStmt,i);
3206 azData[nRow*nColumn + i] = z ? strdup(z) : 0;
3207 }
drh76fc88f2021-10-02 16:39:16 +00003208 }while( sqlite3_step(pStmt)==SQLITE_ROW );
drh8c748632020-05-29 16:15:58 +00003209 if( nColumn>p->nWidth ){
drh76fc88f2021-10-02 16:39:16 +00003210 p->colWidth = realloc(p->colWidth, (nColumn+1)*2*sizeof(int));
drhe3e25652021-12-16 13:29:28 +00003211 shell_check_oom(p->colWidth);
drh8c748632020-05-29 16:15:58 +00003212 for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0;
3213 p->nWidth = nColumn;
3214 p->actualWidth = &p->colWidth[nColumn];
3215 }
3216 memset(p->actualWidth, 0, nColumn*sizeof(int));
3217 for(i=0; i<nColumn; i++){
3218 w = p->colWidth[i];
3219 if( w<0 ) w = -w;
3220 p->actualWidth[i] = w;
3221 }
3222 nTotal = nColumn*(nRow+1);
3223 for(i=0; i<nTotal; i++){
3224 z = azData[i];
3225 if( z==0 ) z = p->nullValue;
3226 n = strlenChar(z);
3227 j = i%nColumn;
3228 if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
3229 }
drh99942982020-06-15 20:05:37 +00003230 if( seenInterrupt ) goto columnar_end;
drh01a8ad22021-03-20 23:15:52 +00003231 if( nColumn==0 ) goto columnar_end;
drh0908e382020-06-04 18:05:39 +00003232 switch( p->cMode ){
3233 case MODE_Column: {
3234 colSep = " ";
3235 rowSep = "\n";
3236 if( p->showHeader ){
3237 for(i=0; i<nColumn; i++){
3238 w = p->actualWidth[i];
3239 if( p->colWidth[i]<0 ) w = -w;
3240 utf8_width_print(p->out, w, azData[i]);
3241 fputs(i==nColumn-1?"\n":" ", p->out);
3242 }
3243 for(i=0; i<nColumn; i++){
3244 print_dashes(p->out, p->actualWidth[i]);
3245 fputs(i==nColumn-1?"\n":" ", p->out);
3246 }
3247 }
3248 break;
3249 }
3250 case MODE_Table: {
3251 colSep = " | ";
3252 rowSep = " |\n";
3253 print_row_separator(p, nColumn, "+");
3254 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003255 for(i=0; i<nColumn; i++){
3256 w = p->actualWidth[i];
drh0908e382020-06-04 18:05:39 +00003257 n = strlenChar(azData[i]);
3258 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
3259 fputs(i==nColumn-1?" |\n":" | ", p->out);
drh8c748632020-05-29 16:15:58 +00003260 }
drh0908e382020-06-04 18:05:39 +00003261 print_row_separator(p, nColumn, "+");
3262 break;
3263 }
3264 case MODE_Markdown: {
3265 colSep = " | ";
3266 rowSep = " |\n";
3267 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003268 for(i=0; i<nColumn; i++){
drh0908e382020-06-04 18:05:39 +00003269 w = p->actualWidth[i];
3270 n = strlenChar(azData[i]);
3271 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
3272 fputs(i==nColumn-1?" |\n":" | ", p->out);
drh8c748632020-05-29 16:15:58 +00003273 }
drh0908e382020-06-04 18:05:39 +00003274 print_row_separator(p, nColumn, "|");
3275 break;
drh8c748632020-05-29 16:15:58 +00003276 }
drh0908e382020-06-04 18:05:39 +00003277 case MODE_Box: {
3278 colSep = " " BOX_13 " ";
3279 rowSep = " " BOX_13 "\n";
3280 print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34);
3281 utf8_printf(p->out, BOX_13 " ");
3282 for(i=0; i<nColumn; i++){
3283 w = p->actualWidth[i];
3284 n = strlenChar(azData[i]);
3285 utf8_printf(p->out, "%*s%s%*s%s",
3286 (w-n)/2, "", azData[i], (w-n+1)/2, "",
3287 i==nColumn-1?" "BOX_13"\n":" "BOX_13" ");
3288 }
3289 print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
3290 break;
drh8c748632020-05-29 16:15:58 +00003291 }
drh8c748632020-05-29 16:15:58 +00003292 }
3293 for(i=nColumn, j=0; i<nTotal; i++, j++){
drh0908e382020-06-04 18:05:39 +00003294 if( j==0 && p->cMode!=MODE_Column ){
3295 utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| ");
3296 }
drh8c748632020-05-29 16:15:58 +00003297 z = azData[i];
3298 if( z==0 ) z = p->nullValue;
3299 w = p->actualWidth[j];
3300 if( p->colWidth[j]<0 ) w = -w;
3301 utf8_width_print(p->out, w, z);
3302 if( j==nColumn-1 ){
drh0908e382020-06-04 18:05:39 +00003303 utf8_printf(p->out, "%s", rowSep);
drh8c748632020-05-29 16:15:58 +00003304 j = -1;
drhdd853c32020-06-16 17:34:40 +00003305 if( seenInterrupt ) goto columnar_end;
drh8c748632020-05-29 16:15:58 +00003306 }else{
drh0908e382020-06-04 18:05:39 +00003307 utf8_printf(p->out, "%s", colSep);
drh8c748632020-05-29 16:15:58 +00003308 }
3309 }
3310 if( p->cMode==MODE_Table ){
3311 print_row_separator(p, nColumn, "+");
drh0908e382020-06-04 18:05:39 +00003312 }else if( p->cMode==MODE_Box ){
3313 print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14);
drh8c748632020-05-29 16:15:58 +00003314 }
drh99942982020-06-15 20:05:37 +00003315columnar_end:
drhdd853c32020-06-16 17:34:40 +00003316 if( seenInterrupt ){
3317 utf8_printf(p->out, "Interrupt\n");
3318 }
drhf82ce382020-08-06 16:45:22 +00003319 nData = (nRow+1)*nColumn;
3320 for(i=0; i<nData; i++) free(azData[i]);
3321 sqlite3_free(azData);
drh30c54a02020-05-28 23:49:50 +00003322}
drh30c54a02020-05-28 23:49:50 +00003323
drh2ce15c32017-07-11 13:34:40 +00003324/*
3325** Run a prepared statement
3326*/
3327static void exec_prepared_stmt(
3328 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003329 sqlite3_stmt *pStmt /* Statment to run */
drh2ce15c32017-07-11 13:34:40 +00003330){
3331 int rc;
drh5d88be82021-12-09 16:17:43 +00003332 sqlite3_uint64 nRow = 0;
drh2ce15c32017-07-11 13:34:40 +00003333
drh8c748632020-05-29 16:15:58 +00003334 if( pArg->cMode==MODE_Column
3335 || pArg->cMode==MODE_Table
drh0908e382020-06-04 18:05:39 +00003336 || pArg->cMode==MODE_Box
drh8c748632020-05-29 16:15:58 +00003337 || pArg->cMode==MODE_Markdown
3338 ){
3339 exec_prepared_stmt_columnar(pArg, pStmt);
3340 return;
3341 }
3342
drh2ce15c32017-07-11 13:34:40 +00003343 /* perform the first step. this will tell us if we
3344 ** have a result set or not and how wide it is.
3345 */
3346 rc = sqlite3_step(pStmt);
3347 /* if we have a result set... */
3348 if( SQLITE_ROW == rc ){
drha10b9992018-03-09 15:24:33 +00003349 /* allocate space for col name ptr, value ptr, and type */
3350 int nCol = sqlite3_column_count(pStmt);
3351 void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
3352 if( !pData ){
drhe85e1da2021-10-01 21:01:07 +00003353 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00003354 }else{
drha10b9992018-03-09 15:24:33 +00003355 char **azCols = (char **)pData; /* Names of result columns */
3356 char **azVals = &azCols[nCol]; /* Results */
3357 int *aiTypes = (int *)&azVals[nCol]; /* Result types */
3358 int i, x;
3359 assert(sizeof(int) <= sizeof(char *));
3360 /* save off ptrs to column names */
3361 for(i=0; i<nCol; i++){
3362 azCols[i] = (char *)sqlite3_column_name(pStmt, i);
3363 }
drh2ce15c32017-07-11 13:34:40 +00003364 do{
drh5d88be82021-12-09 16:17:43 +00003365 nRow++;
drha10b9992018-03-09 15:24:33 +00003366 /* extract the data and data types */
3367 for(i=0; i<nCol; i++){
3368 aiTypes[i] = x = sqlite3_column_type(pStmt, i);
drh5d1bf4f2022-01-02 20:54:33 +00003369 if( x==SQLITE_BLOB
3370 && pArg
3371 && (pArg->cMode==MODE_Insert || pArg->cMode==MODE_Quote)
3372 ){
drha10b9992018-03-09 15:24:33 +00003373 azVals[i] = "";
3374 }else{
3375 azVals[i] = (char*)sqlite3_column_text(pStmt, i);
3376 }
3377 if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
3378 rc = SQLITE_NOMEM;
3379 break; /* from for */
3380 }
3381 } /* end for */
3382
3383 /* if data and types extracted successfully... */
3384 if( SQLITE_ROW == rc ){
3385 /* call the supplied callback with the result row data */
3386 if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){
3387 rc = SQLITE_ABORT;
3388 }else{
3389 rc = sqlite3_step(pStmt);
3390 }
3391 }
3392 } while( SQLITE_ROW == rc );
3393 sqlite3_free(pData);
drh0908e382020-06-04 18:05:39 +00003394 if( pArg->cMode==MODE_Json ){
drh30c54a02020-05-28 23:49:50 +00003395 fputs("]\n", pArg->out);
drh5d88be82021-12-09 16:17:43 +00003396 }else if( pArg->cMode==MODE_Count ){
mistachkinc158c072021-12-31 19:08:20 +00003397 char zBuf[200];
3398 sqlite3_snprintf(sizeof(zBuf), zBuf, "%llu row%s\n",
3399 nRow, nRow!=1 ? "s" : "");
3400 printf("%s", zBuf);
drh30c54a02020-05-28 23:49:50 +00003401 }
drh2ce15c32017-07-11 13:34:40 +00003402 }
3403 }
3404}
3405
dan6b046be2018-01-09 15:25:55 +00003406#ifndef SQLITE_OMIT_VIRTUALTABLE
drh2ce15c32017-07-11 13:34:40 +00003407/*
dan43efc182017-12-19 17:42:13 +00003408** This function is called to process SQL if the previous shell command
3409** was ".expert". It passes the SQL in the second argument directly to
3410** the sqlite3expert object.
3411**
3412** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3413** code. In this case, (*pzErr) may be set to point to a buffer containing
3414** an English language error message. It is the responsibility of the
3415** caller to eventually free this buffer using sqlite3_free().
3416*/
3417static int expertHandleSQL(
3418 ShellState *pState,
3419 const char *zSql,
3420 char **pzErr
3421){
3422 assert( pState->expert.pExpert );
3423 assert( pzErr==0 || *pzErr==0 );
3424 return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr);
3425}
3426
3427/*
3428** This function is called either to silently clean up the object
3429** created by the ".expert" command (if bCancel==1), or to generate a
3430** report from it and then clean it up (if bCancel==0).
3431**
3432** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3433** code. In this case, (*pzErr) may be set to point to a buffer containing
3434** an English language error message. It is the responsibility of the
3435** caller to eventually free this buffer using sqlite3_free().
3436*/
3437static int expertFinish(
3438 ShellState *pState,
3439 int bCancel,
3440 char **pzErr
3441){
3442 int rc = SQLITE_OK;
3443 sqlite3expert *p = pState->expert.pExpert;
3444 assert( p );
3445 assert( bCancel || pzErr==0 || *pzErr==0 );
3446 if( bCancel==0 ){
3447 FILE *out = pState->out;
3448 int bVerbose = pState->expert.bVerbose;
3449
3450 rc = sqlite3_expert_analyze(p, pzErr);
3451 if( rc==SQLITE_OK ){
3452 int nQuery = sqlite3_expert_count(p);
3453 int i;
3454
3455 if( bVerbose ){
3456 const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
3457 raw_printf(out, "-- Candidates -----------------------------\n");
3458 raw_printf(out, "%s\n", zCand);
3459 }
3460 for(i=0; i<nQuery; i++){
3461 const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
3462 const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
3463 const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
3464 if( zIdx==0 ) zIdx = "(no new indexes)\n";
3465 if( bVerbose ){
3466 raw_printf(out, "-- Query %d --------------------------------\n",i+1);
3467 raw_printf(out, "%s\n\n", zSql);
3468 }
3469 raw_printf(out, "%s\n", zIdx);
3470 raw_printf(out, "%s\n", zEQP);
3471 }
3472 }
3473 }
3474 sqlite3_expert_destroy(p);
3475 pState->expert.pExpert = 0;
3476 return rc;
3477}
3478
dan6b046be2018-01-09 15:25:55 +00003479/*
3480** Implementation of ".expert" dot command.
3481*/
3482static int expertDotCommand(
3483 ShellState *pState, /* Current shell tool state */
3484 char **azArg, /* Array of arguments passed to dot command */
3485 int nArg /* Number of entries in azArg[] */
3486){
3487 int rc = SQLITE_OK;
3488 char *zErr = 0;
3489 int i;
3490 int iSample = 0;
3491
3492 assert( pState->expert.pExpert==0 );
3493 memset(&pState->expert, 0, sizeof(ExpertInfo));
3494
3495 for(i=1; rc==SQLITE_OK && i<nArg; i++){
3496 char *z = azArg[i];
3497 int n;
3498 if( z[0]=='-' && z[1]=='-' ) z++;
3499 n = strlen30(z);
3500 if( n>=2 && 0==strncmp(z, "-verbose", n) ){
3501 pState->expert.bVerbose = 1;
3502 }
3503 else if( n>=2 && 0==strncmp(z, "-sample", n) ){
3504 if( i==(nArg-1) ){
3505 raw_printf(stderr, "option requires an argument: %s\n", z);
3506 rc = SQLITE_ERROR;
3507 }else{
3508 iSample = (int)integerValue(azArg[++i]);
3509 if( iSample<0 || iSample>100 ){
3510 raw_printf(stderr, "value out of range: %s\n", azArg[i]);
3511 rc = SQLITE_ERROR;
3512 }
3513 }
3514 }
3515 else{
3516 raw_printf(stderr, "unknown option: %s\n", z);
3517 rc = SQLITE_ERROR;
3518 }
3519 }
3520
3521 if( rc==SQLITE_OK ){
3522 pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
3523 if( pState->expert.pExpert==0 ){
drhe0adf602021-12-16 14:26:16 +00003524 raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr ? zErr : "out of memory");
dan6b046be2018-01-09 15:25:55 +00003525 rc = SQLITE_ERROR;
3526 }else{
3527 sqlite3_expert_config(
3528 pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
3529 );
3530 }
3531 }
drhe0adf602021-12-16 14:26:16 +00003532 sqlite3_free(zErr);
dan6b046be2018-01-09 15:25:55 +00003533
3534 return rc;
3535}
3536#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
dan43efc182017-12-19 17:42:13 +00003537
3538/*
drh2ce15c32017-07-11 13:34:40 +00003539** Execute a statement or set of statements. Print
3540** any result rows/columns depending on the current mode
3541** set via the supplied callback.
3542**
3543** This is very similar to SQLite's built-in sqlite3_exec()
3544** function except it takes a slightly different callback
3545** and callback data argument.
3546*/
3547static int shell_exec(
drh2ce15c32017-07-11 13:34:40 +00003548 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003549 const char *zSql, /* SQL to be evaluated */
drh2ce15c32017-07-11 13:34:40 +00003550 char **pzErrMsg /* Error msg written here */
3551){
3552 sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
3553 int rc = SQLITE_OK; /* Return Code */
3554 int rc2;
3555 const char *zLeftover; /* Tail of unprocessed SQL */
drha10b9992018-03-09 15:24:33 +00003556 sqlite3 *db = pArg->db;
drh2ce15c32017-07-11 13:34:40 +00003557
3558 if( pzErrMsg ){
3559 *pzErrMsg = NULL;
3560 }
3561
dan6b046be2018-01-09 15:25:55 +00003562#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00003563 if( pArg->expert.pExpert ){
3564 rc = expertHandleSQL(pArg, zSql, pzErrMsg);
3565 return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
3566 }
dan6b046be2018-01-09 15:25:55 +00003567#endif
dan43efc182017-12-19 17:42:13 +00003568
drh2ce15c32017-07-11 13:34:40 +00003569 while( zSql[0] && (SQLITE_OK == rc) ){
3570 static const char *zStmtSql;
3571 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
3572 if( SQLITE_OK != rc ){
3573 if( pzErrMsg ){
drhf62641e2021-12-24 20:22:13 +00003574 *pzErrMsg = save_err_msg(db, "in prepare, %s (%d)%s", rc, zSql);
drh2ce15c32017-07-11 13:34:40 +00003575 }
3576 }else{
3577 if( !pStmt ){
3578 /* this happens for a comment or white-space */
3579 zSql = zLeftover;
3580 while( IsSpace(zSql[0]) ) zSql++;
3581 continue;
3582 }
3583 zStmtSql = sqlite3_sql(pStmt);
3584 if( zStmtSql==0 ) zStmtSql = "";
3585 while( IsSpace(zStmtSql[0]) ) zStmtSql++;
3586
3587 /* save off the prepared statment handle and reset row count */
3588 if( pArg ){
3589 pArg->pStmt = pStmt;
3590 pArg->cnt = 0;
3591 }
3592
3593 /* echo the sql statement if echo on */
3594 if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
3595 utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
3596 }
3597
3598 /* Show the EXPLAIN QUERY PLAN if .eqp is on */
drh39c5c4a2019-03-06 14:53:27 +00003599 if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
drh2ce15c32017-07-11 13:34:40 +00003600 sqlite3_stmt *pExplain;
3601 char *zEQP;
drhada70452017-12-21 21:02:27 +00003602 int triggerEQP = 0;
drh2ce15c32017-07-11 13:34:40 +00003603 disable_debug_trace_modes();
drhada70452017-12-21 21:02:27 +00003604 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
3605 if( pArg->autoEQP>=AUTOEQP_trigger ){
3606 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
3607 }
drh2ce15c32017-07-11 13:34:40 +00003608 zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
drhe3e25652021-12-16 13:29:28 +00003609 shell_check_oom(zEQP);
drh2ce15c32017-07-11 13:34:40 +00003610 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3611 if( rc==SQLITE_OK ){
3612 while( sqlite3_step(pExplain)==SQLITE_ROW ){
drh4b5345c2018-04-24 13:07:40 +00003613 const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
drhe2ca99c2018-05-02 00:33:43 +00003614 int iEqpId = sqlite3_column_int(pExplain, 0);
3615 int iParentId = sqlite3_column_int(pExplain, 1);
drh7e088a62020-05-02 00:01:39 +00003616 if( zEQPLine==0 ) zEQPLine = "";
drh4b5345c2018-04-24 13:07:40 +00003617 if( zEQPLine[0]=='-' ) eqp_render(pArg);
drhe2ca99c2018-05-02 00:33:43 +00003618 eqp_append(pArg, iEqpId, iParentId, zEQPLine);
drh2ce15c32017-07-11 13:34:40 +00003619 }
drh4b5345c2018-04-24 13:07:40 +00003620 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003621 }
3622 sqlite3_finalize(pExplain);
3623 sqlite3_free(zEQP);
drhada70452017-12-21 21:02:27 +00003624 if( pArg->autoEQP>=AUTOEQP_full ){
drh2ce15c32017-07-11 13:34:40 +00003625 /* Also do an EXPLAIN for ".eqp full" mode */
3626 zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
drhe3e25652021-12-16 13:29:28 +00003627 shell_check_oom(zEQP);
drh2ce15c32017-07-11 13:34:40 +00003628 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3629 if( rc==SQLITE_OK ){
3630 pArg->cMode = MODE_Explain;
3631 explain_data_prepare(pArg, pExplain);
drha10b9992018-03-09 15:24:33 +00003632 exec_prepared_stmt(pArg, pExplain);
drh2ce15c32017-07-11 13:34:40 +00003633 explain_data_delete(pArg);
3634 }
3635 sqlite3_finalize(pExplain);
3636 sqlite3_free(zEQP);
3637 }
drh51efe092018-03-20 12:04:38 +00003638 if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
3639 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
3640 /* Reprepare pStmt before reactiving trace modes */
3641 sqlite3_finalize(pStmt);
3642 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
drh3c49eaf2018-06-07 15:23:43 +00003643 if( pArg ) pArg->pStmt = pStmt;
drh51efe092018-03-20 12:04:38 +00003644 }
drh2ce15c32017-07-11 13:34:40 +00003645 restore_debug_trace_modes();
3646 }
3647
3648 if( pArg ){
3649 pArg->cMode = pArg->mode;
drh4b5345c2018-04-24 13:07:40 +00003650 if( pArg->autoExplain ){
drh39c5c4a2019-03-06 14:53:27 +00003651 if( sqlite3_stmt_isexplain(pStmt)==1 ){
drh4b5345c2018-04-24 13:07:40 +00003652 pArg->cMode = MODE_Explain;
3653 }
drh39c5c4a2019-03-06 14:53:27 +00003654 if( sqlite3_stmt_isexplain(pStmt)==2 ){
drh4b5345c2018-04-24 13:07:40 +00003655 pArg->cMode = MODE_EQP;
3656 }
drh2ce15c32017-07-11 13:34:40 +00003657 }
3658
3659 /* If the shell is currently in ".explain" mode, gather the extra
3660 ** data required to add indents to the output.*/
3661 if( pArg->cMode==MODE_Explain ){
3662 explain_data_prepare(pArg, pStmt);
3663 }
3664 }
3665
drh8b738d02019-02-25 18:43:54 +00003666 bind_prepared_stmt(pArg, pStmt);
drha10b9992018-03-09 15:24:33 +00003667 exec_prepared_stmt(pArg, pStmt);
drh2ce15c32017-07-11 13:34:40 +00003668 explain_data_delete(pArg);
drh4b5345c2018-04-24 13:07:40 +00003669 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003670
3671 /* print usage stats if stats on */
3672 if( pArg && pArg->statsOn ){
3673 display_stats(db, pArg, 0);
3674 }
3675
3676 /* print loop-counters if required */
3677 if( pArg && pArg->scanstatsOn ){
3678 display_scanstats(db, pArg);
3679 }
3680
3681 /* Finalize the statement just executed. If this fails, save a
3682 ** copy of the error message. Otherwise, set zSql to point to the
3683 ** next statement to execute. */
3684 rc2 = sqlite3_finalize(pStmt);
3685 if( rc!=SQLITE_NOMEM ) rc = rc2;
3686 if( rc==SQLITE_OK ){
3687 zSql = zLeftover;
3688 while( IsSpace(zSql[0]) ) zSql++;
3689 }else if( pzErrMsg ){
drhf62641e2021-12-24 20:22:13 +00003690 *pzErrMsg = save_err_msg(db, "stepping, %s (%d)", rc, 0);
drh2ce15c32017-07-11 13:34:40 +00003691 }
3692
3693 /* clear saved stmt handle */
3694 if( pArg ){
3695 pArg->pStmt = NULL;
3696 }
3697 }
3698 } /* end while */
3699
3700 return rc;
3701}
3702
3703/*
3704** Release memory previously allocated by tableColumnList().
3705*/
3706static void freeColumnList(char **azCol){
3707 int i;
3708 for(i=1; azCol[i]; i++){
3709 sqlite3_free(azCol[i]);
3710 }
3711 /* azCol[0] is a static string */
3712 sqlite3_free(azCol);
3713}
3714
3715/*
3716** Return a list of pointers to strings which are the names of all
3717** columns in table zTab. The memory to hold the names is dynamically
3718** allocated and must be released by the caller using a subsequent call
3719** to freeColumnList().
3720**
3721** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
3722** value that needs to be preserved, then azCol[0] is filled in with the
3723** name of the rowid column.
3724**
3725** The first regular column in the table is azCol[1]. The list is terminated
3726** by an entry with azCol[i]==0.
3727*/
3728static char **tableColumnList(ShellState *p, const char *zTab){
3729 char **azCol = 0;
3730 sqlite3_stmt *pStmt;
3731 char *zSql;
3732 int nCol = 0;
3733 int nAlloc = 0;
3734 int nPK = 0; /* Number of PRIMARY KEY columns seen */
3735 int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
3736 int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
3737 int rc;
3738
3739 zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
drhe3e25652021-12-16 13:29:28 +00003740 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +00003741 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3742 sqlite3_free(zSql);
3743 if( rc ) return 0;
3744 while( sqlite3_step(pStmt)==SQLITE_ROW ){
3745 if( nCol>=nAlloc-2 ){
3746 nAlloc = nAlloc*2 + nCol + 10;
3747 azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
drhe3e25652021-12-16 13:29:28 +00003748 shell_check_oom(azCol);
drh2ce15c32017-07-11 13:34:40 +00003749 }
3750 azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
drhe3e25652021-12-16 13:29:28 +00003751 shell_check_oom(azCol[nCol]);
drh2ce15c32017-07-11 13:34:40 +00003752 if( sqlite3_column_int(pStmt, 5) ){
3753 nPK++;
3754 if( nPK==1
3755 && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
3756 "INTEGER")==0
3757 ){
3758 isIPK = 1;
3759 }else{
3760 isIPK = 0;
3761 }
3762 }
3763 }
3764 sqlite3_finalize(pStmt);
drh4c6cddc2017-10-12 10:28:30 +00003765 if( azCol==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00003766 azCol[0] = 0;
3767 azCol[nCol+1] = 0;
3768
3769 /* The decision of whether or not a rowid really needs to be preserved
3770 ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
3771 ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
3772 ** rowids on tables where the rowid is inaccessible because there are other
3773 ** columns in the table named "rowid", "_rowid_", and "oid".
3774 */
3775 if( preserveRowid && isIPK ){
3776 /* If a single PRIMARY KEY column with type INTEGER was seen, then it
3777 ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID
3778 ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
3779 ** ROWID aliases. To distinguish these cases, check to see if
3780 ** there is a "pk" entry in "PRAGMA index_list". There will be
3781 ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
3782 */
3783 zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
3784 " WHERE origin='pk'", zTab);
drhe3e25652021-12-16 13:29:28 +00003785 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +00003786 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3787 sqlite3_free(zSql);
3788 if( rc ){
3789 freeColumnList(azCol);
3790 return 0;
3791 }
3792 rc = sqlite3_step(pStmt);
3793 sqlite3_finalize(pStmt);
3794 preserveRowid = rc==SQLITE_ROW;
3795 }
3796 if( preserveRowid ){
3797 /* Only preserve the rowid if we can find a name to use for the
3798 ** rowid */
3799 static char *azRowid[] = { "rowid", "_rowid_", "oid" };
3800 int i, j;
3801 for(j=0; j<3; j++){
3802 for(i=1; i<=nCol; i++){
3803 if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
3804 }
3805 if( i>nCol ){
3806 /* At this point, we know that azRowid[j] is not the name of any
3807 ** ordinary column in the table. Verify that azRowid[j] is a valid
3808 ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
3809 ** tables will fail this last check */
3810 rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
3811 if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
3812 break;
3813 }
3814 }
3815 }
3816 return azCol;
3817}
3818
3819/*
3820** Toggle the reverse_unordered_selects setting.
3821*/
3822static void toggleSelectOrder(sqlite3 *db){
3823 sqlite3_stmt *pStmt = 0;
3824 int iSetting = 0;
3825 char zStmt[100];
3826 sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0);
3827 if( sqlite3_step(pStmt)==SQLITE_ROW ){
3828 iSetting = sqlite3_column_int(pStmt, 0);
3829 }
3830 sqlite3_finalize(pStmt);
3831 sqlite3_snprintf(sizeof(zStmt), zStmt,
3832 "PRAGMA reverse_unordered_selects(%d)", !iSetting);
3833 sqlite3_exec(db, zStmt, 0, 0, 0);
3834}
3835
3836/*
3837** This is a different callback routine used for dumping the database.
3838** Each row received by this callback consists of a table name,
3839** the table type ("index" or "table") and SQL to create the table.
3840** This routine should print text sufficient to recreate the table.
3841*/
3842static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
3843 int rc;
3844 const char *zTable;
3845 const char *zType;
3846 const char *zSql;
3847 ShellState *p = (ShellState *)pArg;
mistachkina00a0162020-10-18 18:35:34 +00003848 int dataOnly;
3849 int noSys;
drh2ce15c32017-07-11 13:34:40 +00003850
3851 UNUSED_PARAMETER(azNotUsed);
drhb3c45232017-08-28 14:33:27 +00003852 if( nArg!=3 || azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00003853 zTable = azArg[0];
3854 zType = azArg[1];
3855 zSql = azArg[2];
mistachkina00a0162020-10-18 18:35:34 +00003856 dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
3857 noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
drh2ce15c32017-07-11 13:34:40 +00003858
drhc1962192020-10-12 16:54:28 +00003859 if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
3860 if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
3861 }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
3862 if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00003863 }else if( strncmp(zTable, "sqlite_", 7)==0 ){
3864 return 0;
drhc1962192020-10-12 16:54:28 +00003865 }else if( dataOnly ){
3866 /* no-op */
drh2ce15c32017-07-11 13:34:40 +00003867 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
3868 char *zIns;
3869 if( !p->writableSchema ){
3870 raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
3871 p->writableSchema = 1;
3872 }
3873 zIns = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00003874 "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
drh2ce15c32017-07-11 13:34:40 +00003875 "VALUES('table','%q','%q',0,'%q');",
3876 zTable, zTable, zSql);
drhe3e25652021-12-16 13:29:28 +00003877 shell_check_oom(zIns);
drh2ce15c32017-07-11 13:34:40 +00003878 utf8_printf(p->out, "%s\n", zIns);
3879 sqlite3_free(zIns);
3880 return 0;
3881 }else{
3882 printSchemaLine(p->out, zSql, ";\n");
3883 }
3884
3885 if( strcmp(zType, "table")==0 ){
3886 ShellText sSelect;
3887 ShellText sTable;
3888 char **azCol;
3889 int i;
3890 char *savedDestTable;
3891 int savedMode;
3892
3893 azCol = tableColumnList(p, zTable);
3894 if( azCol==0 ){
3895 p->nErr++;
3896 return 0;
3897 }
3898
3899 /* Always quote the table name, even if it appears to be pure ascii,
3900 ** in case it is a keyword. Ex: INSERT INTO "table" ... */
3901 initText(&sTable);
3902 appendText(&sTable, zTable, quoteChar(zTable));
3903 /* If preserving the rowid, add a column list after the table name.
3904 ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
3905 ** instead of the usual "INSERT INTO tab VALUES(...)".
3906 */
3907 if( azCol[0] ){
3908 appendText(&sTable, "(", 0);
3909 appendText(&sTable, azCol[0], 0);
3910 for(i=1; azCol[i]; i++){
3911 appendText(&sTable, ",", 0);
3912 appendText(&sTable, azCol[i], quoteChar(azCol[i]));
3913 }
3914 appendText(&sTable, ")", 0);
3915 }
3916
3917 /* Build an appropriate SELECT statement */
3918 initText(&sSelect);
3919 appendText(&sSelect, "SELECT ", 0);
3920 if( azCol[0] ){
3921 appendText(&sSelect, azCol[0], 0);
3922 appendText(&sSelect, ",", 0);
3923 }
3924 for(i=1; azCol[i]; i++){
3925 appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
3926 if( azCol[i+1] ){
3927 appendText(&sSelect, ",", 0);
3928 }
3929 }
3930 freeColumnList(azCol);
3931 appendText(&sSelect, " FROM ", 0);
3932 appendText(&sSelect, zTable, quoteChar(zTable));
3933
3934 savedDestTable = p->zDestTable;
3935 savedMode = p->mode;
3936 p->zDestTable = sTable.z;
3937 p->mode = p->cMode = MODE_Insert;
drha10b9992018-03-09 15:24:33 +00003938 rc = shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00003939 if( (rc&0xff)==SQLITE_CORRUPT ){
3940 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
3941 toggleSelectOrder(p->db);
drha10b9992018-03-09 15:24:33 +00003942 shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00003943 toggleSelectOrder(p->db);
3944 }
3945 p->zDestTable = savedDestTable;
3946 p->mode = savedMode;
3947 freeText(&sTable);
3948 freeText(&sSelect);
3949 if( rc ) p->nErr++;
3950 }
3951 return 0;
3952}
3953
3954/*
3955** Run zQuery. Use dump_callback() as the callback routine so that
3956** the contents of the query are output as SQL statements.
3957**
3958** If we get a SQLITE_CORRUPT error, rerun the query after appending
3959** "ORDER BY rowid DESC" to the end.
3960*/
3961static int run_schema_dump_query(
3962 ShellState *p,
3963 const char *zQuery
3964){
3965 int rc;
3966 char *zErr = 0;
3967 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
3968 if( rc==SQLITE_CORRUPT ){
3969 char *zQ2;
3970 int len = strlen30(zQuery);
3971 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
3972 if( zErr ){
3973 utf8_printf(p->out, "/****** %s ******/\n", zErr);
3974 sqlite3_free(zErr);
3975 zErr = 0;
3976 }
3977 zQ2 = malloc( len+100 );
3978 if( zQ2==0 ) return rc;
3979 sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
3980 rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
3981 if( rc ){
3982 utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
3983 }else{
3984 rc = SQLITE_CORRUPT;
3985 }
3986 sqlite3_free(zErr);
3987 free(zQ2);
3988 }
3989 return rc;
3990}
3991
3992/*
drh98aa2ab2018-09-26 16:53:51 +00003993** Text of help messages.
3994**
3995** The help text for each individual command begins with a line that starts
3996** with ".". Subsequent lines are supplimental information.
3997**
3998** There must be two or more spaces between the end of the command and the
3999** start of the description of what that command does.
drh2ce15c32017-07-11 13:34:40 +00004000*/
drh98aa2ab2018-09-26 16:53:51 +00004001static const char *(azHelp[]) = {
drhe37c0e12018-01-06 19:19:50 +00004002#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drh98aa2ab2018-09-26 16:53:51 +00004003 ".archive ... Manage SQL archives",
4004 " Each command must have exactly one of the following options:",
4005 " -c, --create Create a new archive",
drhe2754c12019-08-26 12:50:01 +00004006 " -u, --update Add or update files with changed mtime",
4007 " -i, --insert Like -u but always add even if unchanged",
larrybr47061b92021-11-01 17:22:52 +00004008 " -r, --remove Remove files from archive",
drh98aa2ab2018-09-26 16:53:51 +00004009 " -t, --list List contents of archive",
4010 " -x, --extract Extract files from archive",
4011 " Optional arguments:",
4012 " -v, --verbose Print each filename as it is processed",
drhe2754c12019-08-26 12:50:01 +00004013 " -f FILE, --file FILE Use archive FILE (default is current db)",
4014 " -a FILE, --append FILE Open FILE using the apndvfs VFS",
4015 " -C DIR, --directory DIR Read/extract files from directory DIR",
larrybr8f09f4b2021-11-02 00:18:11 +00004016 " -g, --glob Use glob matching for names in archive",
drh98aa2ab2018-09-26 16:53:51 +00004017 " -n, --dryrun Show the SQL that would have occurred",
4018 " Examples:",
drhe2754c12019-08-26 12:50:01 +00004019 " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
4020 " .ar -tf ARCHIVE # List members of ARCHIVE",
4021 " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE",
drh98aa2ab2018-09-26 16:53:51 +00004022 " See also:",
larrybrbd0d62c2021-06-13 08:23:28 +00004023 " http://sqlite.org/cli.html#sqlite_archive_support",
drhe37c0e12018-01-06 19:19:50 +00004024#endif
drh2ce15c32017-07-11 13:34:40 +00004025#ifndef SQLITE_OMIT_AUTHORIZATION
drh98aa2ab2018-09-26 16:53:51 +00004026 ".auth ON|OFF Show authorizer callbacks",
drh2ce15c32017-07-11 13:34:40 +00004027#endif
drh98aa2ab2018-09-26 16:53:51 +00004028 ".backup ?DB? FILE Backup DB (default \"main\") to FILE",
4029 " --append Use the appendvfs",
drhe2754c12019-08-26 12:50:01 +00004030 " --async Write to FILE without journal and fsync()",
drh98aa2ab2018-09-26 16:53:51 +00004031 ".bail on|off Stop after hitting an error. Default OFF",
4032 ".binary on|off Turn binary output on or off. Default OFF",
4033 ".cd DIRECTORY Change the working directory to DIRECTORY",
4034 ".changes on|off Show number of rows changed by SQL",
4035 ".check GLOB Fail if output since .testcase does not match",
4036 ".clone NEWDB Clone data into NEWDB from the existing database",
drh37407122021-07-23 18:43:58 +00004037 ".connection [close] [#] Open or close an auxiliary database connection",
drh98aa2ab2018-09-26 16:53:51 +00004038 ".databases List names and files of attached databases",
4039 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
4040 ".dbinfo ?DB? Show status information about the database",
larrybr7bdbe592021-03-15 12:56:00 +00004041 ".dump ?OBJECTS? Render database content as SQL",
drheb7f2a02018-09-26 18:02:32 +00004042 " Options:",
drhc1962192020-10-12 16:54:28 +00004043 " --data-only Output only INSERT statements",
drheb7f2a02018-09-26 18:02:32 +00004044 " --newlines Allow unescaped newline characters in output",
drhc1962192020-10-12 16:54:28 +00004045 " --nosys Omit system tables (ex: \"sqlite_stat1\")",
4046 " --preserve-rowids Include ROWID values in the output",
larrybr7bdbe592021-03-15 12:56:00 +00004047 " OBJECTS is a LIKE pattern for tables, indexes, triggers or views to dump",
drh8e9297f2020-03-25 12:50:13 +00004048 " Additional LIKE patterns can be given in subsequent arguments",
drh98aa2ab2018-09-26 16:53:51 +00004049 ".echo on|off Turn command echo on or off",
drhb4e50392019-01-26 15:40:04 +00004050 ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
4051 " Other Modes:",
4052#ifdef SQLITE_DEBUG
4053 " test Show raw EXPLAIN QUERY PLAN output",
drhe2754c12019-08-26 12:50:01 +00004054 " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"",
drhb4e50392019-01-26 15:40:04 +00004055#endif
4056 " trigger Like \"full\" but also show trigger bytecode",
drhe2754c12019-08-26 12:50:01 +00004057 ".excel Display the output of next command in spreadsheet",
drh7a431002020-04-18 14:12:00 +00004058 " --bom Put a UTF8 byte-order mark on intermediate file",
drheb7f2a02018-09-26 18:02:32 +00004059 ".exit ?CODE? Exit this program with return-code CODE",
drhe2754c12019-08-26 12:50:01 +00004060 ".expert EXPERIMENTAL. Suggest indexes for queries",
drh978256f2019-11-02 00:00:14 +00004061 ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto",
drhd985f722019-06-05 14:29:53 +00004062 ".filectrl CMD ... Run various sqlite3_file_control() operations",
drh541ef2c2020-04-20 16:21:30 +00004063 " --schema SCHEMA Use SCHEMA instead of \"main\"",
4064 " --help Show CMD details",
drh98aa2ab2018-09-26 16:53:51 +00004065 ".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
4066 ".headers on|off Turn display of headers on or off",
4067 ".help ?-all? ?PATTERN? Show help text for PATTERN",
4068 ".import FILE TABLE Import data from FILE into TABLE",
drhccb37812020-03-09 15:39:39 +00004069 " Options:",
4070 " --ascii Use \\037 and \\036 as column and row separators",
4071 " --csv Use , and \\n as column and row separators",
4072 " --skip N Skip the first N rows of input",
4073 " -v \"Verbose\" - increase auxiliary output",
4074 " Notes:",
4075 " * If TABLE does not exist, it is created. The first row of input",
4076 " determines the column names.",
4077 " * If neither --csv or --ascii are used, the input mode is derived",
4078 " from the \".mode\" output mode",
4079 " * If FILE begins with \"|\" then it is a command that generates the",
4080 " input text.",
drh2ce15c32017-07-11 13:34:40 +00004081#ifndef SQLITE_OMIT_TEST_CONTROL
drh98aa2ab2018-09-26 16:53:51 +00004082 ".imposter INDEX TABLE Create imposter table TABLE on index INDEX",
drh2ce15c32017-07-11 13:34:40 +00004083#endif
drh98aa2ab2018-09-26 16:53:51 +00004084 ".indexes ?TABLE? Show names of indexes",
4085 " If TABLE is specified, only show indexes for",
4086 " tables matching TABLE using the LIKE operator.",
drh2ce15c32017-07-11 13:34:40 +00004087#ifdef SQLITE_ENABLE_IOTRACE
drh98aa2ab2018-09-26 16:53:51 +00004088 ".iotrace FILE Enable I/O diagnostic logging to FILE",
drh2ce15c32017-07-11 13:34:40 +00004089#endif
drh98aa2ab2018-09-26 16:53:51 +00004090 ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
4091 ".lint OPTIONS Report potential schema issues.",
4092 " Options:",
4093 " fkey-indexes Find missing foreign key indexes",
drh2ce15c32017-07-11 13:34:40 +00004094#ifndef SQLITE_OMIT_LOAD_EXTENSION
drh98aa2ab2018-09-26 16:53:51 +00004095 ".load FILE ?ENTRY? Load an extension library",
drh2ce15c32017-07-11 13:34:40 +00004096#endif
drh98aa2ab2018-09-26 16:53:51 +00004097 ".log FILE|off Turn logging on or off. FILE can be stderr/stdout",
4098 ".mode MODE ?TABLE? Set output mode",
4099 " MODE is one of:",
drh7da29a32020-05-29 19:17:20 +00004100 " ascii Columns/rows delimited by 0x1F and 0x1E",
drh0908e382020-06-04 18:05:39 +00004101 " box Tables using unicode box-drawing characters",
drh7da29a32020-05-29 19:17:20 +00004102 " csv Comma-separated values",
4103 " column Output in columns. (See .width)",
4104 " html HTML <table> code",
4105 " insert SQL insert statements for TABLE",
4106 " json Results in a JSON array",
4107 " line One value per line",
4108 " list Values delimited by \"|\"",
4109 " markdown Markdown table format",
4110 " quote Escape answers as for SQL",
4111 " table ASCII-art table",
4112 " tabs Tab-separated values",
4113 " tcl TCL list elements",
drhb97e2ad2021-08-26 18:31:39 +00004114 ".nonce STRING Disable safe mode for one command if the nonce matches",
drh98aa2ab2018-09-26 16:53:51 +00004115 ".nullvalue STRING Use STRING in place of NULL values",
drh7a431002020-04-18 14:12:00 +00004116 ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE",
drh98aa2ab2018-09-26 16:53:51 +00004117 " If FILE begins with '|' then open as a pipe",
drh7a431002020-04-18 14:12:00 +00004118 " --bom Put a UTF8 byte-order mark at the beginning",
4119 " -e Send output to the system text editor",
4120 " -x Send output as CSV to a spreadsheet (same as \".excel\")",
drh98aa2ab2018-09-26 16:53:51 +00004121 ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
4122 " Options:",
drh60f34ae2018-10-30 13:19:49 +00004123 " --append Use appendvfs to append database to the end of FILE",
drh8d889af2021-05-08 17:18:23 +00004124#ifndef SQLITE_OMIT_DESERIALIZE
drhd10c3ca2021-05-08 11:57:35 +00004125 " --deserialize Load into memory using sqlite3_deserialize()",
drhe2754c12019-08-26 12:50:01 +00004126 " --hexdb Load the output of \"dbtotxt\" as an in-memory db",
drh6ca64482019-01-22 16:06:20 +00004127 " --maxsize N Maximum size for --hexdb or --deserialized database",
drha751f392018-10-30 15:31:22 +00004128#endif
drh60f34ae2018-10-30 13:19:49 +00004129 " --new Initialize FILE to an empty database",
drh0933aad2019-11-18 17:46:38 +00004130 " --nofollow Do not follow symbolic links",
drh60f34ae2018-10-30 13:19:49 +00004131 " --readonly Open FILE readonly",
4132 " --zip FILE is a ZIP archive",
drh98aa2ab2018-09-26 16:53:51 +00004133 ".output ?FILE? Send output to FILE or stdout if FILE is omitted",
drh7a431002020-04-18 14:12:00 +00004134 " If FILE begins with '|' then open it as a pipe.",
4135 " Options:",
4136 " --bom Prefix output with a UTF8 byte-order mark",
4137 " -e Send output to the system text editor",
4138 " -x Send output as CSV to a spreadsheet",
drh9cb02642019-02-28 20:10:52 +00004139 ".parameter CMD ... Manage SQL parameter bindings",
4140 " clear Erase all bindings",
4141 " init Initialize the TEMP table that holds bindings",
4142 " list List the current parameter bindings",
4143 " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE",
drhe2754c12019-08-26 12:50:01 +00004144 " PARAMETER should start with one of: $ : @ ?",
drh9cb02642019-02-28 20:10:52 +00004145 " unset PARAMETER Remove PARAMETER from the binding table",
drh98aa2ab2018-09-26 16:53:51 +00004146 ".print STRING... Print literal STRING",
drh569b1d92019-02-05 20:51:41 +00004147#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh3f83f592019-02-04 14:53:18 +00004148 ".progress N Invoke progress handler after every N opcodes",
4149 " --limit N Interrupt after N progress callbacks",
4150 " --once Do no more than one progress interrupt",
4151 " --quiet|-q No output except at interrupts",
4152 " --reset Reset the count for each input and interrupt",
drh569b1d92019-02-05 20:51:41 +00004153#endif
drh98aa2ab2018-09-26 16:53:51 +00004154 ".prompt MAIN CONTINUE Replace the standard prompts",
4155 ".quit Exit this program",
larrybra2ba25b2021-12-28 05:08:38 +00004156 ".read FILE Read input from FILE or command output",
4157 " If FILE begins with \"|\", it is a command that generates the input.",
dan1b162162019-04-27 20:15:15 +00004158#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan42ebb012019-04-27 18:47:03 +00004159 ".recover Recover as much data as possible from corrupt db.",
drhe2754c12019-08-26 12:50:01 +00004160 " --freelist-corrupt Assume the freelist is corrupt",
4161 " --recovery-db NAME Store recovery metadata in database file NAME",
4162 " --lost-and-found TABLE Alternative name for the lost-and-found table",
dan8cce6b82019-09-14 16:44:51 +00004163 " --no-rowids Do not attempt to recover rowid values",
4164 " that are not also INTEGER PRIMARY KEYs",
dan1b162162019-04-27 20:15:15 +00004165#endif
drh98aa2ab2018-09-26 16:53:51 +00004166 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
4167 ".save FILE Write in-memory database into FILE",
4168 ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
4169 ".schema ?PATTERN? Show the CREATE statements matching PATTERN",
drhbbb29ec2020-10-12 14:56:47 +00004170 " Options:",
4171 " --indent Try to pretty-print the schema",
4172 " --nosys Omit objects whose names start with \"sqlite_\"",
drheb7f2a02018-09-26 18:02:32 +00004173 ".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
4174 " Options:",
4175 " --init Create a new SELFTEST table",
4176 " -v Verbose output",
drh98aa2ab2018-09-26 16:53:51 +00004177 ".separator COL ?ROW? Change the column and row separators",
drh2ce15c32017-07-11 13:34:40 +00004178#if defined(SQLITE_ENABLE_SESSION)
drheb7f2a02018-09-26 18:02:32 +00004179 ".session ?NAME? CMD ... Create or control sessions",
4180 " Subcommands:",
4181 " attach TABLE Attach TABLE",
4182 " changeset FILE Write a changeset into FILE",
4183 " close Close one session",
4184 " enable ?BOOLEAN? Set or query the enable bit",
4185 " filter GLOB... Reject tables matching GLOBs",
4186 " indirect ?BOOLEAN? Mark or query the indirect status",
4187 " isempty Query whether the session is empty",
4188 " list List currently open session names",
4189 " open DB NAME Open a new session on DB",
4190 " patchset FILE Write a patchset into FILE",
4191 " If ?NAME? is omitted, the first defined session is used.",
drh2ce15c32017-07-11 13:34:40 +00004192#endif
drheb7f2a02018-09-26 18:02:32 +00004193 ".sha3sum ... Compute a SHA3 hash of database content",
4194 " Options:",
drh067b92b2020-06-19 15:24:12 +00004195 " --schema Also hash the sqlite_schema table",
drheb7f2a02018-09-26 18:02:32 +00004196 " --sha3-224 Use the sha3-224 algorithm",
drhe2754c12019-08-26 12:50:01 +00004197 " --sha3-256 Use the sha3-256 algorithm (default)",
drheb7f2a02018-09-26 18:02:32 +00004198 " --sha3-384 Use the sha3-384 algorithm",
4199 " --sha3-512 Use the sha3-512 algorithm",
4200 " Any other argument is a LIKE pattern for tables to hash",
drh04a28c32018-01-31 01:38:44 +00004201#ifndef SQLITE_NOHAVE_SYSTEM
drh98aa2ab2018-09-26 16:53:51 +00004202 ".shell CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004203#endif
drh98aa2ab2018-09-26 16:53:51 +00004204 ".show Show the current values for various settings",
drha6e6cf22021-01-09 19:10:04 +00004205 ".stats ?ARG? Show stats or turn stats on or off",
4206 " off Turn off automatic stat display",
4207 " on Turn on automatic stat display",
4208 " stmt Show statement stats",
4209 " vmstep Show the virtual machine step count only",
drh04a28c32018-01-31 01:38:44 +00004210#ifndef SQLITE_NOHAVE_SYSTEM
drh98aa2ab2018-09-26 16:53:51 +00004211 ".system CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004212#endif
drh98aa2ab2018-09-26 16:53:51 +00004213 ".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
4214 ".testcase NAME Begin redirecting output to 'testcase-out.txt'",
drhd985f722019-06-05 14:29:53 +00004215 ".testctrl CMD ... Run various sqlite3_test_control() operations",
4216 " Run \".testctrl\" with no arguments for details",
drh98aa2ab2018-09-26 16:53:51 +00004217 ".timeout MS Try opening locked tables for MS milliseconds",
4218 ".timer on|off Turn SQL timer on or off",
drh707821f2018-12-05 13:39:06 +00004219#ifndef SQLITE_OMIT_TRACE
4220 ".trace ?OPTIONS? Output each SQL statement as it is run",
4221 " FILE Send output to FILE",
4222 " stdout Send output to stdout",
4223 " stderr Send output to stderr",
4224 " off Disable tracing",
4225 " --expanded Expand query parameters",
4226#ifdef SQLITE_ENABLE_NORMALIZE
4227 " --normalized Normal the SQL statements",
4228#endif
4229 " --plain Show SQL as it is input",
4230 " --stmt Trace statement execution (SQLITE_TRACE_STMT)",
4231 " --profile Profile statements (SQLITE_TRACE_PROFILE)",
4232 " --row Trace each row (SQLITE_TRACE_ROW)",
4233 " --close Trace connection close (SQLITE_TRACE_CLOSE)",
4234#endif /* SQLITE_OMIT_TRACE */
drhcc5979d2019-08-16 22:58:29 +00004235#ifdef SQLITE_DEBUG
4236 ".unmodule NAME ... Unregister virtual table modules",
drh5df84282019-08-17 19:45:25 +00004237 " --allexcept Unregister everything except those named",
drhcc5979d2019-08-16 22:58:29 +00004238#endif
drh98aa2ab2018-09-26 16:53:51 +00004239 ".vfsinfo ?AUX? Information about the top-level VFS",
4240 ".vfslist List all available VFSes",
4241 ".vfsname ?AUX? Print the name of the VFS stack",
drh7da29a32020-05-29 19:17:20 +00004242 ".width NUM1 NUM2 ... Set minimum column widths for columnar output",
drh98aa2ab2018-09-26 16:53:51 +00004243 " Negative values right-justify",
4244};
4245
4246/*
4247** Output help text.
4248**
4249** zPattern describes the set of commands for which help text is provided.
4250** If zPattern is NULL, then show all commands, but only give a one-line
4251** description of each.
4252**
4253** Return the number of matches.
4254*/
4255static int showHelp(FILE *out, const char *zPattern){
drhe93f8262018-10-11 16:53:37 +00004256 int i = 0;
4257 int j = 0;
drh98aa2ab2018-09-26 16:53:51 +00004258 int n = 0;
4259 char *zPat;
drh488cddf2018-10-06 14:38:17 +00004260 if( zPattern==0
4261 || zPattern[0]=='0'
4262 || strcmp(zPattern,"-a")==0
4263 || strcmp(zPattern,"-all")==0
drh7a431002020-04-18 14:12:00 +00004264 || strcmp(zPattern,"--all")==0
drh488cddf2018-10-06 14:38:17 +00004265 ){
drh98aa2ab2018-09-26 16:53:51 +00004266 /* Show all commands, but only one line per command */
drh488cddf2018-10-06 14:38:17 +00004267 if( zPattern==0 ) zPattern = "";
drh98aa2ab2018-09-26 16:53:51 +00004268 for(i=0; i<ArraySize(azHelp); i++){
drh488cddf2018-10-06 14:38:17 +00004269 if( azHelp[i][0]=='.' || zPattern[0] ){
drh98aa2ab2018-09-26 16:53:51 +00004270 utf8_printf(out, "%s\n", azHelp[i]);
4271 n++;
4272 }
4273 }
4274 }else{
4275 /* Look for commands that for which zPattern is an exact prefix */
4276 zPat = sqlite3_mprintf(".%s*", zPattern);
drhe3e25652021-12-16 13:29:28 +00004277 shell_check_oom(zPat);
drh98aa2ab2018-09-26 16:53:51 +00004278 for(i=0; i<ArraySize(azHelp); i++){
4279 if( sqlite3_strglob(zPat, azHelp[i])==0 ){
4280 utf8_printf(out, "%s\n", azHelp[i]);
drheb7f2a02018-09-26 18:02:32 +00004281 j = i+1;
drh98aa2ab2018-09-26 16:53:51 +00004282 n++;
4283 }
4284 }
4285 sqlite3_free(zPat);
drheb7f2a02018-09-26 18:02:32 +00004286 if( n ){
4287 if( n==1 ){
4288 /* when zPattern is a prefix of exactly one command, then include the
4289 ** details of that command, which should begin at offset j */
4290 while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){
4291 utf8_printf(out, "%s\n", azHelp[j]);
4292 j++;
4293 }
4294 }
4295 return n;
4296 }
4297 /* Look for commands that contain zPattern anywhere. Show the complete
4298 ** text of all commands that match. */
drh98aa2ab2018-09-26 16:53:51 +00004299 zPat = sqlite3_mprintf("%%%s%%", zPattern);
drhe3e25652021-12-16 13:29:28 +00004300 shell_check_oom(zPat);
drh98aa2ab2018-09-26 16:53:51 +00004301 for(i=0; i<ArraySize(azHelp); i++){
4302 if( azHelp[i][0]=='.' ) j = i;
4303 if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
4304 utf8_printf(out, "%s\n", azHelp[j]);
4305 while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
4306 j++;
4307 utf8_printf(out, "%s\n", azHelp[j]);
4308 }
4309 i = j;
4310 n++;
4311 }
4312 }
4313 sqlite3_free(zPat);
4314 }
4315 return n;
4316}
drh2ce15c32017-07-11 13:34:40 +00004317
drh2ce15c32017-07-11 13:34:40 +00004318/* Forward reference */
drh60379d42018-12-13 18:30:01 +00004319static int process_input(ShellState *p);
drh2ce15c32017-07-11 13:34:40 +00004320
4321/*
4322** Read the content of file zName into memory obtained from sqlite3_malloc64()
4323** and return a pointer to the buffer. The caller is responsible for freeing
4324** the memory.
4325**
4326** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
4327** read.
4328**
4329** For convenience, a nul-terminator byte is always appended to the data read
4330** from the file before the buffer is returned. This byte is not included in
4331** the final value of (*pnByte), if applicable.
4332**
4333** NULL is returned if any error is encountered. The final value of *pnByte
4334** is undefined in this case.
4335*/
4336static char *readFile(const char *zName, int *pnByte){
4337 FILE *in = fopen(zName, "rb");
4338 long nIn;
4339 size_t nRead;
4340 char *pBuf;
4341 if( in==0 ) return 0;
4342 fseek(in, 0, SEEK_END);
4343 nIn = ftell(in);
4344 rewind(in);
4345 pBuf = sqlite3_malloc64( nIn+1 );
drh1dbb1472018-10-11 10:37:24 +00004346 if( pBuf==0 ){ fclose(in); return 0; }
drh2ce15c32017-07-11 13:34:40 +00004347 nRead = fread(pBuf, nIn, 1, in);
4348 fclose(in);
4349 if( nRead!=1 ){
4350 sqlite3_free(pBuf);
4351 return 0;
4352 }
4353 pBuf[nIn] = 0;
4354 if( pnByte ) *pnByte = nIn;
4355 return pBuf;
4356}
4357
4358#if defined(SQLITE_ENABLE_SESSION)
4359/*
4360** Close a single OpenSession object and release all of its associated
4361** resources.
4362*/
4363static void session_close(OpenSession *pSession){
4364 int i;
4365 sqlite3session_delete(pSession->p);
4366 sqlite3_free(pSession->zName);
4367 for(i=0; i<pSession->nFilter; i++){
4368 sqlite3_free(pSession->azFilter[i]);
4369 }
4370 sqlite3_free(pSession->azFilter);
4371 memset(pSession, 0, sizeof(OpenSession));
4372}
4373#endif
4374
4375/*
4376** Close all OpenSession objects and release all associated resources.
4377*/
4378#if defined(SQLITE_ENABLE_SESSION)
drh37407122021-07-23 18:43:58 +00004379static void session_close_all(ShellState *p, int i){
4380 int j;
4381 struct AuxDb *pAuxDb = i<0 ? p->pAuxDb : &p->aAuxDb[i];
4382 for(j=0; j<pAuxDb->nSession; j++){
4383 session_close(&pAuxDb->aSession[j]);
drh2ce15c32017-07-11 13:34:40 +00004384 }
drh37407122021-07-23 18:43:58 +00004385 pAuxDb->nSession = 0;
drh2ce15c32017-07-11 13:34:40 +00004386}
4387#else
drh37407122021-07-23 18:43:58 +00004388# define session_close_all(X,Y)
drh2ce15c32017-07-11 13:34:40 +00004389#endif
4390
4391/*
4392** Implementation of the xFilter function for an open session. Omit
4393** any tables named by ".session filter" but let all other table through.
4394*/
4395#if defined(SQLITE_ENABLE_SESSION)
4396static int session_filter(void *pCtx, const char *zTab){
4397 OpenSession *pSession = (OpenSession*)pCtx;
4398 int i;
4399 for(i=0; i<pSession->nFilter; i++){
4400 if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
4401 }
4402 return 1;
4403}
4404#endif
4405
4406/*
drh1fa6d9f2018-01-06 21:46:01 +00004407** Try to deduce the type of file for zName based on its content. Return
4408** one of the SHELL_OPEN_* constants.
drh1bf208c2018-03-09 21:54:01 +00004409**
4410** If the file does not exist or is empty but its name looks like a ZIP
4411** archive and the dfltZip flag is true, then assume it is a ZIP archive.
4412** Otherwise, assume an ordinary database regardless of the filename if
4413** the type cannot be determined from content.
drh1fa6d9f2018-01-06 21:46:01 +00004414*/
drhfc97c1c2018-05-14 00:41:12 +00004415int deduceDatabaseType(const char *zName, int dfltZip){
drh1fa6d9f2018-01-06 21:46:01 +00004416 FILE *f = fopen(zName, "rb");
4417 size_t n;
4418 int rc = SHELL_OPEN_UNSPEC;
4419 char zBuf[100];
drh1bf208c2018-03-09 21:54:01 +00004420 if( f==0 ){
drhbe4ccb22018-05-17 20:04:24 +00004421 if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
4422 return SHELL_OPEN_ZIPFILE;
4423 }else{
4424 return SHELL_OPEN_NORMAL;
4425 }
drh1bf208c2018-03-09 21:54:01 +00004426 }
drh2b3c4af2018-10-30 14:36:21 +00004427 n = fread(zBuf, 16, 1, f);
4428 if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
4429 fclose(f);
4430 return SHELL_OPEN_NORMAL;
4431 }
drh1fa6d9f2018-01-06 21:46:01 +00004432 fseek(f, -25, SEEK_END);
4433 n = fread(zBuf, 25, 1, f);
4434 if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
4435 rc = SHELL_OPEN_APPENDVFS;
4436 }else{
4437 fseek(f, -22, SEEK_END);
4438 n = fread(zBuf, 22, 1, f);
4439 if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
4440 && zBuf[3]==0x06 ){
4441 rc = SHELL_OPEN_ZIPFILE;
drh1bf208c2018-03-09 21:54:01 +00004442 }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
mistachkina3926f42018-05-14 12:23:04 +00004443 rc = SHELL_OPEN_ZIPFILE;
drh1fa6d9f2018-01-06 21:46:01 +00004444 }
4445 }
4446 fclose(f);
4447 return rc;
4448}
4449
drh8d889af2021-05-08 17:18:23 +00004450#ifndef SQLITE_OMIT_DESERIALIZE
drh33746482018-12-13 15:06:26 +00004451/*
4452** Reconstruct an in-memory database using the output from the "dbtotxt"
drh37407122021-07-23 18:43:58 +00004453** program. Read content from the file in p->aAuxDb[].zDbFilename.
4454** If p->aAuxDb[].zDbFilename is 0, then read from standard input.
drh33746482018-12-13 15:06:26 +00004455*/
4456static unsigned char *readHexDb(ShellState *p, int *pnData){
4457 unsigned char *a = 0;
drh2c8ee022018-12-13 18:59:30 +00004458 int nLine;
drh33746482018-12-13 15:06:26 +00004459 int n = 0;
4460 int pgsz = 0;
4461 int iOffset = 0;
4462 int j, k;
4463 int rc;
4464 FILE *in;
drh37407122021-07-23 18:43:58 +00004465 const char *zDbFilename = p->pAuxDb->zDbFilename;
drh3ea557e2019-04-23 15:30:58 +00004466 unsigned int x[16];
drh2c8ee022018-12-13 18:59:30 +00004467 char zLine[1000];
drh37407122021-07-23 18:43:58 +00004468 if( zDbFilename ){
4469 in = fopen(zDbFilename, "r");
drh33746482018-12-13 15:06:26 +00004470 if( in==0 ){
drh37407122021-07-23 18:43:58 +00004471 utf8_printf(stderr, "cannot open \"%s\" for reading\n", zDbFilename);
drh33746482018-12-13 15:06:26 +00004472 return 0;
4473 }
drh2c8ee022018-12-13 18:59:30 +00004474 nLine = 0;
drh33746482018-12-13 15:06:26 +00004475 }else{
drh60379d42018-12-13 18:30:01 +00004476 in = p->in;
drh2c8ee022018-12-13 18:59:30 +00004477 nLine = p->lineno;
drh5bf46442019-05-03 02:41:36 +00004478 if( in==0 ) in = stdin;
drh33746482018-12-13 15:06:26 +00004479 }
4480 *pnData = 0;
drh2c8ee022018-12-13 18:59:30 +00004481 nLine++;
drh33746482018-12-13 15:06:26 +00004482 if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
4483 rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
4484 if( rc!=2 ) goto readHexDb_error;
drh68feae52019-05-09 11:18:41 +00004485 if( n<0 ) goto readHexDb_error;
drh09ea1252019-07-17 15:05:16 +00004486 if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
4487 n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */
drh68feae52019-05-09 11:18:41 +00004488 a = sqlite3_malloc( n ? n : 1 );
drhe3e25652021-12-16 13:29:28 +00004489 shell_check_oom(a);
drh33746482018-12-13 15:06:26 +00004490 memset(a, 0, n);
4491 if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
4492 utf8_printf(stderr, "invalid pagesize\n");
4493 goto readHexDb_error;
4494 }
drh2c8ee022018-12-13 18:59:30 +00004495 for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
drh33746482018-12-13 15:06:26 +00004496 rc = sscanf(zLine, "| page %d offset %d", &j, &k);
4497 if( rc==2 ){
4498 iOffset = k;
4499 continue;
4500 }
4501 if( strncmp(zLine, "| end ", 6)==0 ){
4502 break;
4503 }
drh3ea557e2019-04-23 15:30:58 +00004504 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 +00004505 &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
4506 &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
4507 if( rc==17 ){
4508 k = iOffset+j;
drh82978ac2021-10-01 17:06:44 +00004509 if( k+16<=n && k>=0 ){
drh3ea557e2019-04-23 15:30:58 +00004510 int ii;
4511 for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
drh33746482018-12-13 15:06:26 +00004512 }
drh33746482018-12-13 15:06:26 +00004513 }
4514 }
4515 *pnData = n;
drh2c8ee022018-12-13 18:59:30 +00004516 if( in!=p->in ){
4517 fclose(in);
4518 }else{
4519 p->lineno = nLine;
4520 }
drh33746482018-12-13 15:06:26 +00004521 return a;
4522
4523readHexDb_error:
drh68feae52019-05-09 11:18:41 +00004524 if( in!=p->in ){
drh33746482018-12-13 15:06:26 +00004525 fclose(in);
4526 }else{
drh60379d42018-12-13 18:30:01 +00004527 while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
drh2c8ee022018-12-13 18:59:30 +00004528 nLine++;
drh33746482018-12-13 15:06:26 +00004529 if(strncmp(zLine, "| end ", 6)==0 ) break;
4530 }
drh2c8ee022018-12-13 18:59:30 +00004531 p->lineno = nLine;
drh33746482018-12-13 15:06:26 +00004532 }
4533 sqlite3_free(a);
4534 utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
4535 return 0;
4536}
drh8d889af2021-05-08 17:18:23 +00004537#endif /* SQLITE_OMIT_DESERIALIZE */
drh33746482018-12-13 15:06:26 +00004538
danb1825882019-04-23 20:48:32 +00004539/*
dan9c014f82019-04-25 19:23:15 +00004540** Scalar function "shell_int32". The first argument to this function
4541** must be a blob. The second a non-negative integer. This function
4542** reads and returns a 32-bit big-endian integer from byte
4543** offset (4*<arg2>) of the blob.
4544*/
4545static void shellInt32(
4546 sqlite3_context *context,
4547 int argc,
4548 sqlite3_value **argv
4549){
4550 const unsigned char *pBlob;
4551 int nBlob;
4552 int iInt;
drh9546c762019-05-10 17:50:33 +00004553
4554 UNUSED_PARAMETER(argc);
dan9c014f82019-04-25 19:23:15 +00004555 nBlob = sqlite3_value_bytes(argv[0]);
4556 pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
4557 iInt = sqlite3_value_int(argv[1]);
4558
4559 if( iInt>=0 && (iInt+1)*4<=nBlob ){
4560 const unsigned char *a = &pBlob[iInt*4];
4561 sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24)
4562 + ((sqlite3_int64)a[1]<<16)
4563 + ((sqlite3_int64)a[2]<< 8)
4564 + ((sqlite3_int64)a[3]<< 0);
4565 sqlite3_result_int64(context, iVal);
4566 }
4567}
4568
4569/*
drha2de66c2019-08-06 20:26:17 +00004570** Scalar function "shell_idquote(X)" returns string X quoted as an identifier,
4571** using "..." with internal double-quote characters doubled.
4572*/
4573static void shellIdQuote(
4574 sqlite3_context *context,
4575 int argc,
4576 sqlite3_value **argv
4577){
4578 const char *zName = (const char*)sqlite3_value_text(argv[0]);
drh51755a72019-08-08 19:40:29 +00004579 UNUSED_PARAMETER(argc);
drha2de66c2019-08-06 20:26:17 +00004580 if( zName ){
4581 char *z = sqlite3_mprintf("\"%w\"", zName);
4582 sqlite3_result_text(context, z, -1, sqlite3_free);
4583 }
4584}
4585
4586/*
drhddcfe922020-09-15 12:29:35 +00004587** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
4588*/
4589static void shellUSleepFunc(
4590 sqlite3_context *context,
drhd36f5882020-11-25 16:28:04 +00004591 int argcUnused,
drhddcfe922020-09-15 12:29:35 +00004592 sqlite3_value **argv
4593){
4594 int sleep = sqlite3_value_int(argv[0]);
drhd36f5882020-11-25 16:28:04 +00004595 (void)argcUnused;
drhddcfe922020-09-15 12:29:35 +00004596 sqlite3_sleep(sleep/1000);
4597 sqlite3_result_int(context, sleep);
4598}
4599
4600/*
danb1825882019-04-23 20:48:32 +00004601** Scalar function "shell_escape_crnl" used by the .recover command.
4602** The argument passed to this function is the output of built-in
4603** function quote(). If the first character of the input is "'",
4604** indicating that the value passed to quote() was a text value,
4605** then this function searches the input for "\n" and "\r" characters
4606** and adds a wrapper similar to the following:
4607**
4608** replace(replace(<input>, '\n', char(10), '\r', char(13));
4609**
4610** Or, if the first character of the input is not "'", then a copy
4611** of the input is returned.
4612*/
4613static void shellEscapeCrnl(
4614 sqlite3_context *context,
4615 int argc,
4616 sqlite3_value **argv
4617){
4618 const char *zText = (const char*)sqlite3_value_text(argv[0]);
drh9546c762019-05-10 17:50:33 +00004619 UNUSED_PARAMETER(argc);
drh621a5e02021-12-16 17:35:27 +00004620 if( zText && zText[0]=='\'' ){
danb1825882019-04-23 20:48:32 +00004621 int nText = sqlite3_value_bytes(argv[0]);
4622 int i;
4623 char zBuf1[20];
4624 char zBuf2[20];
4625 const char *zNL = 0;
4626 const char *zCR = 0;
4627 int nCR = 0;
4628 int nNL = 0;
4629
4630 for(i=0; zText[i]; i++){
4631 if( zNL==0 && zText[i]=='\n' ){
4632 zNL = unused_string(zText, "\\n", "\\012", zBuf1);
4633 nNL = (int)strlen(zNL);
4634 }
4635 if( zCR==0 && zText[i]=='\r' ){
4636 zCR = unused_string(zText, "\\r", "\\015", zBuf2);
4637 nCR = (int)strlen(zCR);
4638 }
4639 }
4640
4641 if( zNL || zCR ){
4642 int iOut = 0;
4643 i64 nMax = (nNL > nCR) ? nNL : nCR;
dan51f5ffa2019-04-29 11:41:46 +00004644 i64 nAlloc = nMax * nText + (nMax+64)*2;
danb1825882019-04-23 20:48:32 +00004645 char *zOut = (char*)sqlite3_malloc64(nAlloc);
4646 if( zOut==0 ){
4647 sqlite3_result_error_nomem(context);
4648 return;
4649 }
4650
4651 if( zNL && zCR ){
4652 memcpy(&zOut[iOut], "replace(replace(", 16);
4653 iOut += 16;
4654 }else{
4655 memcpy(&zOut[iOut], "replace(", 8);
4656 iOut += 8;
4657 }
4658 for(i=0; zText[i]; i++){
4659 if( zText[i]=='\n' ){
4660 memcpy(&zOut[iOut], zNL, nNL);
4661 iOut += nNL;
4662 }else if( zText[i]=='\r' ){
4663 memcpy(&zOut[iOut], zCR, nCR);
4664 iOut += nCR;
4665 }else{
4666 zOut[iOut] = zText[i];
4667 iOut++;
4668 }
4669 }
4670
4671 if( zNL ){
4672 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
4673 memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
4674 memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
4675 }
4676 if( zCR ){
4677 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
4678 memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
4679 memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
4680 }
4681
4682 sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
4683 sqlite3_free(zOut);
4684 return;
4685 }
4686 }
4687
4688 sqlite3_result_value(context, argv[0]);
4689}
4690
drhbe4ccb22018-05-17 20:04:24 +00004691/* Flags for open_db().
4692**
4693** The default behavior of open_db() is to exit(1) if the database fails to
4694** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
4695** but still returns without calling exit.
4696**
4697** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a
4698** ZIP archive if the file does not exist or is empty and its name matches
4699** the *.zip pattern.
4700*/
4701#define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */
4702#define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */
4703
drh1fa6d9f2018-01-06 21:46:01 +00004704/*
drh2ce15c32017-07-11 13:34:40 +00004705** Make sure the database is open. If it is not, then open it. If
4706** the database fails to open, print an error message and exit.
4707*/
drhbe4ccb22018-05-17 20:04:24 +00004708static void open_db(ShellState *p, int openFlags){
drh2ce15c32017-07-11 13:34:40 +00004709 if( p->db==0 ){
drh37407122021-07-23 18:43:58 +00004710 const char *zDbFilename = p->pAuxDb->zDbFilename;
drhf2072d12018-05-11 15:10:11 +00004711 if( p->openMode==SHELL_OPEN_UNSPEC ){
drh37407122021-07-23 18:43:58 +00004712 if( zDbFilename==0 || zDbFilename[0]==0 ){
drhf2072d12018-05-11 15:10:11 +00004713 p->openMode = SHELL_OPEN_NORMAL;
drhbe4ccb22018-05-17 20:04:24 +00004714 }else{
drh37407122021-07-23 18:43:58 +00004715 p->openMode = (u8)deduceDatabaseType(zDbFilename,
drhbe4ccb22018-05-17 20:04:24 +00004716 (openFlags & OPEN_DB_ZIPFILE)!=0);
drhf2072d12018-05-11 15:10:11 +00004717 }
drh1fa6d9f2018-01-06 21:46:01 +00004718 }
4719 switch( p->openMode ){
4720 case SHELL_OPEN_APPENDVFS: {
drh37407122021-07-23 18:43:58 +00004721 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004722 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
drh1fa6d9f2018-01-06 21:46:01 +00004723 break;
4724 }
drh33746482018-12-13 15:06:26 +00004725 case SHELL_OPEN_HEXDB:
drh60f34ae2018-10-30 13:19:49 +00004726 case SHELL_OPEN_DESERIALIZE: {
4727 sqlite3_open(0, &p->db);
4728 break;
4729 }
drh1fa6d9f2018-01-06 21:46:01 +00004730 case SHELL_OPEN_ZIPFILE: {
4731 sqlite3_open(":memory:", &p->db);
4732 break;
4733 }
drhee269a62018-02-14 23:27:43 +00004734 case SHELL_OPEN_READONLY: {
drh37407122021-07-23 18:43:58 +00004735 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004736 SQLITE_OPEN_READONLY|p->openFlags, 0);
drhee269a62018-02-14 23:27:43 +00004737 break;
4738 }
drh1fa6d9f2018-01-06 21:46:01 +00004739 case SHELL_OPEN_UNSPEC:
4740 case SHELL_OPEN_NORMAL: {
drh37407122021-07-23 18:43:58 +00004741 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004742 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
drh1fa6d9f2018-01-06 21:46:01 +00004743 break;
4744 }
4745 }
drh2ce15c32017-07-11 13:34:40 +00004746 globalDb = p->db;
4747 if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
4748 utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
drh37407122021-07-23 18:43:58 +00004749 zDbFilename, sqlite3_errmsg(p->db));
drhf25cc4f2019-01-04 14:29:21 +00004750 if( openFlags & OPEN_DB_KEEPALIVE ){
4751 sqlite3_open(":memory:", &p->db);
4752 return;
4753 }
drh2ce15c32017-07-11 13:34:40 +00004754 exit(1);
4755 }
4756#ifndef SQLITE_OMIT_LOAD_EXTENSION
4757 sqlite3_enable_load_extension(p->db, 1);
4758#endif
4759 sqlite3_fileio_init(p->db, 0, 0);
4760 sqlite3_shathree_init(p->db, 0, 0);
drh56eb09b2017-07-11 13:59:07 +00004761 sqlite3_completion_init(p->db, 0, 0);
drhf05dd032020-04-14 15:53:58 +00004762 sqlite3_uint_init(p->db, 0, 0);
drhbeb9def2020-06-22 19:12:23 +00004763 sqlite3_decimal_init(p->db, 0, 0);
drh64689902021-06-03 13:51:31 +00004764 sqlite3_regexp_init(p->db, 0, 0);
drh8cda77d2020-06-24 15:06:29 +00004765 sqlite3_ieee_init(p->db, 0, 0);
mistachkin72c38d82020-08-28 18:47:39 +00004766 sqlite3_series_init(p->db, 0, 0);
dan1b162162019-04-27 20:15:15 +00004767#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00004768 sqlite3_dbdata_init(p->db, 0, 0);
dan1b162162019-04-27 20:15:15 +00004769#endif
dan72afc3c2017-12-05 18:32:40 +00004770#ifdef SQLITE_HAVE_ZLIB
dan9ebfaad2017-12-26 20:39:58 +00004771 sqlite3_zipfile_init(p->db, 0, 0);
dand1b51d42017-12-16 19:11:26 +00004772 sqlite3_sqlar_init(p->db, 0, 0);
dan72afc3c2017-12-05 18:32:40 +00004773#endif
drhceba7922018-01-01 21:28:25 +00004774 sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
drh2ce15c32017-07-11 13:34:40 +00004775 shellAddSchemaName, 0, 0);
drh667a2a22018-01-02 00:04:37 +00004776 sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
4777 shellModuleSchema, 0, 0);
drh634c70f2018-01-10 16:50:18 +00004778 sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
4779 shellPutsFunc, 0, 0);
danb1825882019-04-23 20:48:32 +00004780 sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0,
4781 shellEscapeCrnl, 0, 0);
dan9c014f82019-04-25 19:23:15 +00004782 sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
4783 shellInt32, 0, 0);
drha2de66c2019-08-06 20:26:17 +00004784 sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
4785 shellIdQuote, 0, 0);
drhddcfe922020-09-15 12:29:35 +00004786 sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
4787 shellUSleepFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00004788#ifndef SQLITE_NOHAVE_SYSTEM
drh97913132018-01-11 00:04:00 +00004789 sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
4790 editFunc, 0, 0);
4791 sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
4792 editFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00004793#endif
drh1fa6d9f2018-01-06 21:46:01 +00004794 if( p->openMode==SHELL_OPEN_ZIPFILE ){
4795 char *zSql = sqlite3_mprintf(
drh37407122021-07-23 18:43:58 +00004796 "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename);
drhe3e25652021-12-16 13:29:28 +00004797 shell_check_oom(zSql);
drh1fa6d9f2018-01-06 21:46:01 +00004798 sqlite3_exec(p->db, zSql, 0, 0, 0);
4799 sqlite3_free(zSql);
drha751f392018-10-30 15:31:22 +00004800 }
drh8d889af2021-05-08 17:18:23 +00004801#ifndef SQLITE_OMIT_DESERIALIZE
drh33746482018-12-13 15:06:26 +00004802 else
4803 if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
mistachkin99490932018-12-17 22:19:57 +00004804 int rc;
drh60f34ae2018-10-30 13:19:49 +00004805 int nData = 0;
drh33746482018-12-13 15:06:26 +00004806 unsigned char *aData;
4807 if( p->openMode==SHELL_OPEN_DESERIALIZE ){
drh37407122021-07-23 18:43:58 +00004808 aData = (unsigned char*)readFile(zDbFilename, &nData);
drh33746482018-12-13 15:06:26 +00004809 }else{
4810 aData = readHexDb(p, &nData);
4811 if( aData==0 ){
drh33746482018-12-13 15:06:26 +00004812 return;
4813 }
4814 }
mistachkin99490932018-12-17 22:19:57 +00004815 rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
drh60f34ae2018-10-30 13:19:49 +00004816 SQLITE_DESERIALIZE_RESIZEABLE |
4817 SQLITE_DESERIALIZE_FREEONCLOSE);
4818 if( rc ){
4819 utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
4820 }
drh6ca64482019-01-22 16:06:20 +00004821 if( p->szMax>0 ){
4822 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
4823 }
drh1fa6d9f2018-01-06 21:46:01 +00004824 }
drha751f392018-10-30 15:31:22 +00004825#endif
drh2ce15c32017-07-11 13:34:40 +00004826 }
drhb97e2ad2021-08-26 18:31:39 +00004827 if( p->bSafeModePersist && p->db!=0 ){
4828 sqlite3_set_authorizer(p->db, safeModeAuth, p);
4829 }
drh2ce15c32017-07-11 13:34:40 +00004830}
4831
drh9e804032018-05-18 17:11:50 +00004832/*
4833** Attempt to close the databaes connection. Report errors.
4834*/
4835void close_db(sqlite3 *db){
4836 int rc = sqlite3_close(db);
4837 if( rc ){
4838 utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
4839 rc, sqlite3_errmsg(db));
4840 }
4841}
4842
drh56eb09b2017-07-11 13:59:07 +00004843#if HAVE_READLINE || HAVE_EDITLINE
4844/*
4845** Readline completion callbacks
4846*/
4847static char *readline_completion_generator(const char *text, int state){
4848 static sqlite3_stmt *pStmt = 0;
4849 char *zRet;
4850 if( state==0 ){
4851 char *zSql;
drh56eb09b2017-07-11 13:59:07 +00004852 sqlite3_finalize(pStmt);
4853 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
4854 " FROM completion(%Q) ORDER BY 1", text);
drhe3e25652021-12-16 13:29:28 +00004855 shell_check_oom(zSql);
drh56eb09b2017-07-11 13:59:07 +00004856 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
4857 sqlite3_free(zSql);
4858 }
4859 if( sqlite3_step(pStmt)==SQLITE_ROW ){
drh621a5e02021-12-16 17:35:27 +00004860 const char *z = (const char*)sqlite3_column_text(pStmt,0);
4861 zRet = z ? strdup(z) : 0;
drh56eb09b2017-07-11 13:59:07 +00004862 }else{
4863 sqlite3_finalize(pStmt);
4864 pStmt = 0;
4865 zRet = 0;
4866 }
4867 return zRet;
4868}
4869static char **readline_completion(const char *zText, int iStart, int iEnd){
4870 rl_attempted_completion_over = 1;
4871 return rl_completion_matches(zText, readline_completion_generator);
4872}
4873
4874#elif HAVE_LINENOISE
4875/*
4876** Linenoise completion callback
4877*/
4878static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
drhaf2770f2018-01-05 14:55:43 +00004879 int nLine = strlen30(zLine);
drh56eb09b2017-07-11 13:59:07 +00004880 int i, iStart;
4881 sqlite3_stmt *pStmt = 0;
4882 char *zSql;
4883 char zBuf[1000];
4884
4885 if( nLine>sizeof(zBuf)-30 ) return;
drh1615c372018-05-12 23:56:22 +00004886 if( zLine[0]=='.' || zLine[0]=='#') return;
drh56eb09b2017-07-11 13:59:07 +00004887 for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
4888 if( i==nLine-1 ) return;
4889 iStart = i+1;
4890 memcpy(zBuf, zLine, iStart);
4891 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
4892 " FROM completion(%Q,%Q) ORDER BY 1",
4893 &zLine[iStart], zLine);
drhe3e25652021-12-16 13:29:28 +00004894 shell_check_oom(zSql);
drh56eb09b2017-07-11 13:59:07 +00004895 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
4896 sqlite3_free(zSql);
4897 sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
4898 while( sqlite3_step(pStmt)==SQLITE_ROW ){
4899 const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
4900 int nCompletion = sqlite3_column_bytes(pStmt, 0);
drh621a5e02021-12-16 17:35:27 +00004901 if( iStart+nCompletion < sizeof(zBuf)-1 && zCompletion ){
drh56eb09b2017-07-11 13:59:07 +00004902 memcpy(zBuf+iStart, zCompletion, nCompletion+1);
4903 linenoiseAddCompletion(lc, zBuf);
4904 }
4905 }
4906 sqlite3_finalize(pStmt);
4907}
4908#endif
4909
drh2ce15c32017-07-11 13:34:40 +00004910/*
4911** Do C-language style dequoting.
4912**
4913** \a -> alarm
4914** \b -> backspace
4915** \t -> tab
4916** \n -> newline
4917** \v -> vertical tab
4918** \f -> form feed
4919** \r -> carriage return
4920** \s -> space
4921** \" -> "
4922** \' -> '
4923** \\ -> backslash
4924** \NNN -> ascii character NNN in octal
4925*/
4926static void resolve_backslashes(char *z){
4927 int i, j;
4928 char c;
4929 while( *z && *z!='\\' ) z++;
4930 for(i=j=0; (c = z[i])!=0; i++, j++){
4931 if( c=='\\' && z[i+1]!=0 ){
4932 c = z[++i];
4933 if( c=='a' ){
4934 c = '\a';
4935 }else if( c=='b' ){
4936 c = '\b';
4937 }else if( c=='t' ){
4938 c = '\t';
4939 }else if( c=='n' ){
4940 c = '\n';
4941 }else if( c=='v' ){
4942 c = '\v';
4943 }else if( c=='f' ){
4944 c = '\f';
4945 }else if( c=='r' ){
4946 c = '\r';
4947 }else if( c=='"' ){
4948 c = '"';
4949 }else if( c=='\'' ){
4950 c = '\'';
4951 }else if( c=='\\' ){
4952 c = '\\';
4953 }else if( c>='0' && c<='7' ){
4954 c -= '0';
4955 if( z[i+1]>='0' && z[i+1]<='7' ){
4956 i++;
4957 c = (c<<3) + z[i] - '0';
4958 if( z[i+1]>='0' && z[i+1]<='7' ){
4959 i++;
4960 c = (c<<3) + z[i] - '0';
4961 }
4962 }
4963 }
4964 }
4965 z[j] = c;
4966 }
4967 if( j<i ) z[j] = 0;
4968}
4969
4970/*
drh2ce15c32017-07-11 13:34:40 +00004971** Interpret zArg as either an integer or a boolean value. Return 1 or 0
4972** for TRUE and FALSE. Return the integer value if appropriate.
4973*/
4974static int booleanValue(const char *zArg){
4975 int i;
4976 if( zArg[0]=='0' && zArg[1]=='x' ){
4977 for(i=2; hexDigitValue(zArg[i])>=0; i++){}
4978 }else{
4979 for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
4980 }
4981 if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
4982 if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
4983 return 1;
4984 }
4985 if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
4986 return 0;
4987 }
4988 utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
4989 zArg);
4990 return 0;
4991}
4992
4993/*
4994** Set or clear a shell flag according to a boolean value.
4995*/
4996static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){
4997 if( booleanValue(zArg) ){
4998 ShellSetFlag(p, mFlag);
4999 }else{
5000 ShellClearFlag(p, mFlag);
5001 }
5002}
5003
5004/*
5005** Close an output file, assuming it is not stderr or stdout
5006*/
5007static void output_file_close(FILE *f){
5008 if( f && f!=stdout && f!=stderr ) fclose(f);
5009}
5010
5011/*
5012** Try to open an output file. The names "stdout" and "stderr" are
5013** recognized and do the right thing. NULL is returned if the output
5014** filename is "off".
5015*/
drha92a01a2018-01-10 22:15:37 +00005016static FILE *output_file_open(const char *zFile, int bTextMode){
drh2ce15c32017-07-11 13:34:40 +00005017 FILE *f;
5018 if( strcmp(zFile,"stdout")==0 ){
5019 f = stdout;
5020 }else if( strcmp(zFile, "stderr")==0 ){
5021 f = stderr;
5022 }else if( strcmp(zFile, "off")==0 ){
5023 f = 0;
5024 }else{
drha92a01a2018-01-10 22:15:37 +00005025 f = fopen(zFile, bTextMode ? "w" : "wb");
drh2ce15c32017-07-11 13:34:40 +00005026 if( f==0 ){
5027 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
5028 }
5029 }
5030 return f;
5031}
5032
drh707821f2018-12-05 13:39:06 +00005033#ifndef SQLITE_OMIT_TRACE
drh2ce15c32017-07-11 13:34:40 +00005034/*
5035** A routine for handling output from sqlite3_trace().
5036*/
5037static int sql_trace_callback(
drh707821f2018-12-05 13:39:06 +00005038 unsigned mType, /* The trace type */
5039 void *pArg, /* The ShellState pointer */
5040 void *pP, /* Usually a pointer to sqlite_stmt */
5041 void *pX /* Auxiliary output */
drh2ce15c32017-07-11 13:34:40 +00005042){
drh707821f2018-12-05 13:39:06 +00005043 ShellState *p = (ShellState*)pArg;
5044 sqlite3_stmt *pStmt;
5045 const char *zSql;
5046 int nSql;
5047 if( p->traceOut==0 ) return 0;
5048 if( mType==SQLITE_TRACE_CLOSE ){
5049 utf8_printf(p->traceOut, "-- closing database connection\n");
5050 return 0;
5051 }
5052 if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){
5053 zSql = (const char*)pX;
5054 }else{
5055 pStmt = (sqlite3_stmt*)pP;
5056 switch( p->eTraceType ){
5057 case SHELL_TRACE_EXPANDED: {
5058 zSql = sqlite3_expanded_sql(pStmt);
5059 break;
5060 }
5061#ifdef SQLITE_ENABLE_NORMALIZE
5062 case SHELL_TRACE_NORMALIZED: {
5063 zSql = sqlite3_normalized_sql(pStmt);
5064 break;
5065 }
5066#endif
5067 default: {
5068 zSql = sqlite3_sql(pStmt);
5069 break;
5070 }
5071 }
5072 }
5073 if( zSql==0 ) return 0;
5074 nSql = strlen30(zSql);
5075 while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
5076 switch( mType ){
5077 case SQLITE_TRACE_ROW:
5078 case SQLITE_TRACE_STMT: {
5079 utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql);
5080 break;
5081 }
5082 case SQLITE_TRACE_PROFILE: {
5083 sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
5084 utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec);
5085 break;
5086 }
drh2ce15c32017-07-11 13:34:40 +00005087 }
5088 return 0;
5089}
5090#endif
drh2ce15c32017-07-11 13:34:40 +00005091
5092/*
5093** A no-op routine that runs with the ".breakpoint" doc-command. This is
5094** a useful spot to set a debugger breakpoint.
5095*/
5096static void test_breakpoint(void){
5097 static int nCall = 0;
5098 nCall++;
5099}
5100
5101/*
5102** An object used to read a CSV and other files for import.
5103*/
5104typedef struct ImportCtx ImportCtx;
5105struct ImportCtx {
5106 const char *zFile; /* Name of the input file */
5107 FILE *in; /* Read the CSV text from this input stream */
drh97767842020-05-29 19:39:35 +00005108 int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */
drh2ce15c32017-07-11 13:34:40 +00005109 char *z; /* Accumulated text for a field */
5110 int n; /* Number of bytes in z */
5111 int nAlloc; /* Space allocated for z[] */
5112 int nLine; /* Current line number */
drhccb37812020-03-09 15:39:39 +00005113 int nRow; /* Number of rows imported */
5114 int nErr; /* Number of errors encountered */
drh2ce15c32017-07-11 13:34:40 +00005115 int bNotFirst; /* True if one or more bytes already read */
5116 int cTerm; /* Character that terminated the most recent field */
5117 int cColSep; /* The column separator character. (Usually ",") */
5118 int cRowSep; /* The row separator character. (Usually "\n") */
5119};
5120
drh97767842020-05-29 19:39:35 +00005121/* Clean up resourced used by an ImportCtx */
5122static void import_cleanup(ImportCtx *p){
drh42c2a042020-05-29 20:16:19 +00005123 if( p->in!=0 && p->xCloser!=0 ){
drh97767842020-05-29 19:39:35 +00005124 p->xCloser(p->in);
5125 p->in = 0;
5126 }
5127 sqlite3_free(p->z);
5128 p->z = 0;
5129}
5130
drh2ce15c32017-07-11 13:34:40 +00005131/* Append a single byte to z[] */
5132static void import_append_char(ImportCtx *p, int c){
5133 if( p->n+1>=p->nAlloc ){
5134 p->nAlloc += p->nAlloc + 100;
5135 p->z = sqlite3_realloc64(p->z, p->nAlloc);
drhe3e25652021-12-16 13:29:28 +00005136 shell_check_oom(p->z);
drh2ce15c32017-07-11 13:34:40 +00005137 }
5138 p->z[p->n++] = (char)c;
5139}
5140
5141/* Read a single field of CSV text. Compatible with rfc4180 and extended
5142** with the option of having a separator other than ",".
5143**
5144** + Input comes from p->in.
5145** + Store results in p->z of length p->n. Space to hold p->z comes
5146** from sqlite3_malloc64().
5147** + Use p->cSep as the column separator. The default is ",".
5148** + Use p->rSep as the row separator. The default is "\n".
5149** + Keep track of the line number in p->nLine.
5150** + Store the character that terminates the field in p->cTerm. Store
5151** EOF on end-of-file.
5152** + Report syntax errors on stderr
5153*/
5154static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
5155 int c;
5156 int cSep = p->cColSep;
5157 int rSep = p->cRowSep;
5158 p->n = 0;
5159 c = fgetc(p->in);
5160 if( c==EOF || seenInterrupt ){
5161 p->cTerm = EOF;
5162 return 0;
5163 }
5164 if( c=='"' ){
5165 int pc, ppc;
5166 int startLine = p->nLine;
5167 int cQuote = c;
5168 pc = ppc = 0;
5169 while( 1 ){
5170 c = fgetc(p->in);
5171 if( c==rSep ) p->nLine++;
5172 if( c==cQuote ){
5173 if( pc==cQuote ){
5174 pc = 0;
5175 continue;
5176 }
5177 }
5178 if( (c==cSep && pc==cQuote)
5179 || (c==rSep && pc==cQuote)
5180 || (c==rSep && pc=='\r' && ppc==cQuote)
5181 || (c==EOF && pc==cQuote)
5182 ){
5183 do{ p->n--; }while( p->z[p->n]!=cQuote );
5184 p->cTerm = c;
5185 break;
5186 }
5187 if( pc==cQuote && c!='\r' ){
5188 utf8_printf(stderr, "%s:%d: unescaped %c character\n",
5189 p->zFile, p->nLine, cQuote);
5190 }
5191 if( c==EOF ){
5192 utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
5193 p->zFile, startLine, cQuote);
5194 p->cTerm = c;
5195 break;
5196 }
5197 import_append_char(p, c);
5198 ppc = pc;
5199 pc = c;
5200 }
5201 }else{
5202 /* If this is the first field being parsed and it begins with the
5203 ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
5204 if( (c&0xff)==0xef && p->bNotFirst==0 ){
5205 import_append_char(p, c);
5206 c = fgetc(p->in);
5207 if( (c&0xff)==0xbb ){
5208 import_append_char(p, c);
5209 c = fgetc(p->in);
5210 if( (c&0xff)==0xbf ){
5211 p->bNotFirst = 1;
5212 p->n = 0;
5213 return csv_read_one_field(p);
5214 }
5215 }
5216 }
5217 while( c!=EOF && c!=cSep && c!=rSep ){
5218 import_append_char(p, c);
5219 c = fgetc(p->in);
5220 }
5221 if( c==rSep ){
5222 p->nLine++;
5223 if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
5224 }
5225 p->cTerm = c;
5226 }
5227 if( p->z ) p->z[p->n] = 0;
5228 p->bNotFirst = 1;
5229 return p->z;
5230}
5231
5232/* Read a single field of ASCII delimited text.
5233**
5234** + Input comes from p->in.
5235** + Store results in p->z of length p->n. Space to hold p->z comes
5236** from sqlite3_malloc64().
5237** + Use p->cSep as the column separator. The default is "\x1F".
5238** + Use p->rSep as the row separator. The default is "\x1E".
5239** + Keep track of the row number in p->nLine.
5240** + Store the character that terminates the field in p->cTerm. Store
5241** EOF on end-of-file.
5242** + Report syntax errors on stderr
5243*/
5244static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
5245 int c;
5246 int cSep = p->cColSep;
5247 int rSep = p->cRowSep;
5248 p->n = 0;
5249 c = fgetc(p->in);
5250 if( c==EOF || seenInterrupt ){
5251 p->cTerm = EOF;
5252 return 0;
5253 }
5254 while( c!=EOF && c!=cSep && c!=rSep ){
5255 import_append_char(p, c);
5256 c = fgetc(p->in);
5257 }
5258 if( c==rSep ){
5259 p->nLine++;
5260 }
5261 p->cTerm = c;
5262 if( p->z ) p->z[p->n] = 0;
5263 return p->z;
5264}
5265
5266/*
5267** Try to transfer data for table zTable. If an error is seen while
5268** moving forward, try to go backwards. The backwards movement won't
5269** work for WITHOUT ROWID tables.
5270*/
5271static void tryToCloneData(
5272 ShellState *p,
5273 sqlite3 *newDb,
5274 const char *zTable
5275){
5276 sqlite3_stmt *pQuery = 0;
5277 sqlite3_stmt *pInsert = 0;
5278 char *zQuery = 0;
5279 char *zInsert = 0;
5280 int rc;
5281 int i, j, n;
drhaf2770f2018-01-05 14:55:43 +00005282 int nTable = strlen30(zTable);
drh2ce15c32017-07-11 13:34:40 +00005283 int k = 0;
5284 int cnt = 0;
5285 const int spinRate = 10000;
5286
5287 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
drhe3e25652021-12-16 13:29:28 +00005288 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005289 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5290 if( rc ){
5291 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5292 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5293 zQuery);
5294 goto end_data_xfer;
5295 }
5296 n = sqlite3_column_count(pQuery);
5297 zInsert = sqlite3_malloc64(200 + nTable + n*3);
drhe3e25652021-12-16 13:29:28 +00005298 shell_check_oom(zInsert);
drh2ce15c32017-07-11 13:34:40 +00005299 sqlite3_snprintf(200+nTable,zInsert,
5300 "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
drhaf2770f2018-01-05 14:55:43 +00005301 i = strlen30(zInsert);
drh2ce15c32017-07-11 13:34:40 +00005302 for(j=1; j<n; j++){
5303 memcpy(zInsert+i, ",?", 2);
5304 i += 2;
5305 }
5306 memcpy(zInsert+i, ");", 3);
5307 rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
5308 if( rc ){
5309 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5310 sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
5311 zQuery);
5312 goto end_data_xfer;
5313 }
5314 for(k=0; k<2; k++){
5315 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5316 for(i=0; i<n; i++){
5317 switch( sqlite3_column_type(pQuery, i) ){
5318 case SQLITE_NULL: {
5319 sqlite3_bind_null(pInsert, i+1);
5320 break;
5321 }
5322 case SQLITE_INTEGER: {
5323 sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
5324 break;
5325 }
5326 case SQLITE_FLOAT: {
5327 sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
5328 break;
5329 }
5330 case SQLITE_TEXT: {
5331 sqlite3_bind_text(pInsert, i+1,
5332 (const char*)sqlite3_column_text(pQuery,i),
5333 -1, SQLITE_STATIC);
5334 break;
5335 }
5336 case SQLITE_BLOB: {
5337 sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
5338 sqlite3_column_bytes(pQuery,i),
5339 SQLITE_STATIC);
5340 break;
5341 }
5342 }
5343 } /* End for */
5344 rc = sqlite3_step(pInsert);
5345 if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
5346 utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
5347 sqlite3_errmsg(newDb));
5348 }
5349 sqlite3_reset(pInsert);
5350 cnt++;
5351 if( (cnt%spinRate)==0 ){
5352 printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
5353 fflush(stdout);
5354 }
5355 } /* End while */
5356 if( rc==SQLITE_DONE ) break;
5357 sqlite3_finalize(pQuery);
5358 sqlite3_free(zQuery);
5359 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
5360 zTable);
drhe3e25652021-12-16 13:29:28 +00005361 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005362 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5363 if( rc ){
5364 utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
5365 break;
5366 }
5367 } /* End for(k=0...) */
5368
5369end_data_xfer:
5370 sqlite3_finalize(pQuery);
5371 sqlite3_finalize(pInsert);
5372 sqlite3_free(zQuery);
5373 sqlite3_free(zInsert);
5374}
5375
5376
5377/*
5378** Try to transfer all rows of the schema that match zWhere. For
5379** each row, invoke xForEach() on the object defined by that row.
5380** If an error is encountered while moving forward through the
drh067b92b2020-06-19 15:24:12 +00005381** sqlite_schema table, try again moving backwards.
drh2ce15c32017-07-11 13:34:40 +00005382*/
5383static void tryToCloneSchema(
5384 ShellState *p,
5385 sqlite3 *newDb,
5386 const char *zWhere,
5387 void (*xForEach)(ShellState*,sqlite3*,const char*)
5388){
5389 sqlite3_stmt *pQuery = 0;
5390 char *zQuery = 0;
5391 int rc;
5392 const unsigned char *zName;
5393 const unsigned char *zSql;
5394 char *zErrMsg = 0;
5395
drh067b92b2020-06-19 15:24:12 +00005396 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005397 " WHERE %s", zWhere);
drhe3e25652021-12-16 13:29:28 +00005398 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005399 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5400 if( rc ){
5401 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5402 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5403 zQuery);
5404 goto end_schema_xfer;
5405 }
5406 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5407 zName = sqlite3_column_text(pQuery, 0);
5408 zSql = sqlite3_column_text(pQuery, 1);
drh621a5e02021-12-16 17:35:27 +00005409 if( zName==0 || zSql==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00005410 printf("%s... ", zName); fflush(stdout);
5411 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5412 if( zErrMsg ){
5413 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5414 sqlite3_free(zErrMsg);
5415 zErrMsg = 0;
5416 }
5417 if( xForEach ){
5418 xForEach(p, newDb, (const char*)zName);
5419 }
5420 printf("done\n");
5421 }
5422 if( rc!=SQLITE_DONE ){
5423 sqlite3_finalize(pQuery);
5424 sqlite3_free(zQuery);
drh067b92b2020-06-19 15:24:12 +00005425 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005426 " WHERE %s ORDER BY rowid DESC", zWhere);
drhe3e25652021-12-16 13:29:28 +00005427 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005428 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5429 if( rc ){
5430 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5431 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5432 zQuery);
5433 goto end_schema_xfer;
5434 }
drh76fc88f2021-10-02 16:39:16 +00005435 while( sqlite3_step(pQuery)==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00005436 zName = sqlite3_column_text(pQuery, 0);
5437 zSql = sqlite3_column_text(pQuery, 1);
drh621a5e02021-12-16 17:35:27 +00005438 if( zName==0 || zSql==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00005439 printf("%s... ", zName); fflush(stdout);
5440 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5441 if( zErrMsg ){
5442 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5443 sqlite3_free(zErrMsg);
5444 zErrMsg = 0;
5445 }
5446 if( xForEach ){
5447 xForEach(p, newDb, (const char*)zName);
5448 }
5449 printf("done\n");
5450 }
5451 }
5452end_schema_xfer:
5453 sqlite3_finalize(pQuery);
5454 sqlite3_free(zQuery);
5455}
5456
5457/*
5458** Open a new database file named "zNewDb". Try to recover as much information
5459** as possible out of the main database (which might be corrupt) and write it
5460** into zNewDb.
5461*/
5462static void tryToClone(ShellState *p, const char *zNewDb){
5463 int rc;
5464 sqlite3 *newDb = 0;
5465 if( access(zNewDb,0)==0 ){
5466 utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
5467 return;
5468 }
5469 rc = sqlite3_open(zNewDb, &newDb);
5470 if( rc ){
5471 utf8_printf(stderr, "Cannot create output database: %s\n",
5472 sqlite3_errmsg(newDb));
5473 }else{
5474 sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
5475 sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
5476 tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
5477 tryToCloneSchema(p, newDb, "type!='table'", 0);
5478 sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
5479 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
5480 }
drh9e804032018-05-18 17:11:50 +00005481 close_db(newDb);
drh2ce15c32017-07-11 13:34:40 +00005482}
5483
5484/*
drh13c20932018-01-10 21:41:55 +00005485** Change the output file back to stdout.
5486**
5487** If the p->doXdgOpen flag is set, that means the output was being
5488** redirected to a temporary file named by p->zTempFile. In that case,
5489** launch start/open/xdg-open on that temporary file.
drh2ce15c32017-07-11 13:34:40 +00005490*/
5491static void output_reset(ShellState *p){
5492 if( p->outfile[0]=='|' ){
5493#ifndef SQLITE_OMIT_POPEN
5494 pclose(p->out);
5495#endif
5496 }else{
5497 output_file_close(p->out);
drh04a28c32018-01-31 01:38:44 +00005498#ifndef SQLITE_NOHAVE_SYSTEM
drh13c20932018-01-10 21:41:55 +00005499 if( p->doXdgOpen ){
5500 const char *zXdgOpenCmd =
5501#if defined(_WIN32)
5502 "start";
5503#elif defined(__APPLE__)
5504 "open";
5505#else
5506 "xdg-open";
5507#endif
5508 char *zCmd;
5509 zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
drha92a01a2018-01-10 22:15:37 +00005510 if( system(zCmd) ){
5511 utf8_printf(stderr, "Failed: [%s]\n", zCmd);
drh1d9ea272020-04-17 23:46:54 +00005512 }else{
5513 /* Give the start/open/xdg-open command some time to get
5514 ** going before we continue, and potential delete the
5515 ** p->zTempFile data file out from under it */
5516 sqlite3_sleep(2000);
drha92a01a2018-01-10 22:15:37 +00005517 }
drh13c20932018-01-10 21:41:55 +00005518 sqlite3_free(zCmd);
drh3c484e82018-01-10 22:27:21 +00005519 outputModePop(p);
drh13c20932018-01-10 21:41:55 +00005520 p->doXdgOpen = 0;
5521 }
drh04a28c32018-01-31 01:38:44 +00005522#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
drh2ce15c32017-07-11 13:34:40 +00005523 }
5524 p->outfile[0] = 0;
5525 p->out = stdout;
5526}
5527
5528/*
5529** Run an SQL command and return the single integer result.
5530*/
5531static int db_int(ShellState *p, const char *zSql){
5532 sqlite3_stmt *pStmt;
5533 int res = 0;
5534 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
5535 if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
5536 res = sqlite3_column_int(pStmt,0);
5537 }
5538 sqlite3_finalize(pStmt);
5539 return res;
5540}
5541
5542/*
5543** Convert a 2-byte or 4-byte big-endian integer into a native integer
5544*/
5545static unsigned int get2byteInt(unsigned char *a){
5546 return (a[0]<<8) + a[1];
5547}
5548static unsigned int get4byteInt(unsigned char *a){
5549 return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
5550}
5551
5552/*
drh76c12062020-01-14 13:13:19 +00005553** Implementation of the ".dbinfo" command.
drh2ce15c32017-07-11 13:34:40 +00005554**
5555** Return 1 on error, 2 to exit, and 0 otherwise.
5556*/
5557static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
5558 static const struct { const char *zName; int ofst; } aField[] = {
5559 { "file change counter:", 24 },
5560 { "database page count:", 28 },
5561 { "freelist page count:", 36 },
5562 { "schema cookie:", 40 },
5563 { "schema format:", 44 },
5564 { "default cache size:", 48 },
5565 { "autovacuum top root:", 52 },
5566 { "incremental vacuum:", 64 },
5567 { "text encoding:", 56 },
5568 { "user version:", 60 },
5569 { "application id:", 68 },
5570 { "software version:", 96 },
5571 };
5572 static const struct { const char *zName; const char *zSql; } aQuery[] = {
5573 { "number of tables:",
5574 "SELECT count(*) FROM %s WHERE type='table'" },
5575 { "number of indexes:",
5576 "SELECT count(*) FROM %s WHERE type='index'" },
5577 { "number of triggers:",
5578 "SELECT count(*) FROM %s WHERE type='trigger'" },
5579 { "number of views:",
5580 "SELECT count(*) FROM %s WHERE type='view'" },
5581 { "schema size:",
5582 "SELECT total(length(sql)) FROM %s" },
5583 };
drh87c889c2019-03-20 18:22:51 +00005584 int i, rc;
drhea99a312018-07-18 19:09:07 +00005585 unsigned iDataVersion;
drh2ce15c32017-07-11 13:34:40 +00005586 char *zSchemaTab;
5587 char *zDb = nArg>=2 ? azArg[1] : "main";
drh512e6c32017-10-11 17:51:08 +00005588 sqlite3_stmt *pStmt = 0;
drh2ce15c32017-07-11 13:34:40 +00005589 unsigned char aHdr[100];
5590 open_db(p, 0);
5591 if( p->db==0 ) return 1;
drh87c889c2019-03-20 18:22:51 +00005592 rc = sqlite3_prepare_v2(p->db,
5593 "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
5594 -1, &pStmt, 0);
5595 if( rc ){
drh451f89a2020-04-28 23:09:56 +00005596 utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
drh87c889c2019-03-20 18:22:51 +00005597 sqlite3_finalize(pStmt);
5598 return 1;
5599 }
drh512e6c32017-10-11 17:51:08 +00005600 sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
5601 if( sqlite3_step(pStmt)==SQLITE_ROW
5602 && sqlite3_column_bytes(pStmt,0)>100
5603 ){
5604 memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
5605 sqlite3_finalize(pStmt);
5606 }else{
drh2ce15c32017-07-11 13:34:40 +00005607 raw_printf(stderr, "unable to read database header\n");
drh512e6c32017-10-11 17:51:08 +00005608 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00005609 return 1;
5610 }
5611 i = get2byteInt(aHdr+16);
5612 if( i==1 ) i = 65536;
5613 utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
5614 utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
5615 utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
5616 utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
5617 for(i=0; i<ArraySize(aField); i++){
5618 int ofst = aField[i].ofst;
5619 unsigned int val = get4byteInt(aHdr + ofst);
5620 utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
5621 switch( ofst ){
5622 case 56: {
5623 if( val==1 ) raw_printf(p->out, " (utf8)");
5624 if( val==2 ) raw_printf(p->out, " (utf16le)");
5625 if( val==3 ) raw_printf(p->out, " (utf16be)");
5626 }
5627 }
5628 raw_printf(p->out, "\n");
5629 }
5630 if( zDb==0 ){
drh067b92b2020-06-19 15:24:12 +00005631 zSchemaTab = sqlite3_mprintf("main.sqlite_schema");
drh2ce15c32017-07-11 13:34:40 +00005632 }else if( strcmp(zDb,"temp")==0 ){
drh067b92b2020-06-19 15:24:12 +00005633 zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
drh2ce15c32017-07-11 13:34:40 +00005634 }else{
drh067b92b2020-06-19 15:24:12 +00005635 zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
drh2ce15c32017-07-11 13:34:40 +00005636 }
5637 for(i=0; i<ArraySize(aQuery); i++){
5638 char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
5639 int val = db_int(p, zSql);
5640 sqlite3_free(zSql);
5641 utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
5642 }
5643 sqlite3_free(zSchemaTab);
drhea99a312018-07-18 19:09:07 +00005644 sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
5645 utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
drh2ce15c32017-07-11 13:34:40 +00005646 return 0;
5647}
5648
5649/*
5650** Print the current sqlite3_errmsg() value to stderr and return 1.
5651*/
5652static int shellDatabaseError(sqlite3 *db){
5653 const char *zErr = sqlite3_errmsg(db);
5654 utf8_printf(stderr, "Error: %s\n", zErr);
5655 return 1;
5656}
5657
5658/*
drh2ce15c32017-07-11 13:34:40 +00005659** Compare the pattern in zGlob[] against the text in z[]. Return TRUE
5660** if they match and FALSE (0) if they do not match.
5661**
5662** Globbing rules:
5663**
5664** '*' Matches any sequence of zero or more characters.
5665**
5666** '?' Matches exactly one character.
5667**
5668** [...] Matches one character from the enclosed list of
5669** characters.
5670**
5671** [^...] Matches one character not in the enclosed list.
5672**
5673** '#' Matches any sequence of one or more digits with an
5674** optional + or - sign in front
5675**
5676** ' ' Any span of whitespace matches any other span of
5677** whitespace.
5678**
5679** Extra whitespace at the end of z[] is ignored.
5680*/
5681static int testcase_glob(const char *zGlob, const char *z){
5682 int c, c2;
5683 int invert;
5684 int seen;
5685
5686 while( (c = (*(zGlob++)))!=0 ){
5687 if( IsSpace(c) ){
5688 if( !IsSpace(*z) ) return 0;
5689 while( IsSpace(*zGlob) ) zGlob++;
5690 while( IsSpace(*z) ) z++;
5691 }else if( c=='*' ){
5692 while( (c=(*(zGlob++))) == '*' || c=='?' ){
5693 if( c=='?' && (*(z++))==0 ) return 0;
5694 }
5695 if( c==0 ){
5696 return 1;
5697 }else if( c=='[' ){
5698 while( *z && testcase_glob(zGlob-1,z)==0 ){
5699 z++;
5700 }
5701 return (*z)!=0;
5702 }
5703 while( (c2 = (*(z++)))!=0 ){
5704 while( c2!=c ){
5705 c2 = *(z++);
5706 if( c2==0 ) return 0;
5707 }
5708 if( testcase_glob(zGlob,z) ) return 1;
5709 }
5710 return 0;
5711 }else if( c=='?' ){
5712 if( (*(z++))==0 ) return 0;
5713 }else if( c=='[' ){
5714 int prior_c = 0;
5715 seen = 0;
5716 invert = 0;
5717 c = *(z++);
5718 if( c==0 ) return 0;
5719 c2 = *(zGlob++);
5720 if( c2=='^' ){
5721 invert = 1;
5722 c2 = *(zGlob++);
5723 }
5724 if( c2==']' ){
5725 if( c==']' ) seen = 1;
5726 c2 = *(zGlob++);
5727 }
5728 while( c2 && c2!=']' ){
5729 if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
5730 c2 = *(zGlob++);
5731 if( c>=prior_c && c<=c2 ) seen = 1;
5732 prior_c = 0;
5733 }else{
5734 if( c==c2 ){
5735 seen = 1;
5736 }
5737 prior_c = c2;
5738 }
5739 c2 = *(zGlob++);
5740 }
5741 if( c2==0 || (seen ^ invert)==0 ) return 0;
5742 }else if( c=='#' ){
5743 if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++;
5744 if( !IsDigit(z[0]) ) return 0;
5745 z++;
5746 while( IsDigit(z[0]) ){ z++; }
5747 }else{
5748 if( c!=(*(z++)) ) return 0;
5749 }
5750 }
5751 while( IsSpace(*z) ){ z++; }
5752 return *z==0;
5753}
5754
5755
5756/*
5757** Compare the string as a command-line option with either one or two
5758** initial "-" characters.
5759*/
5760static int optionMatch(const char *zStr, const char *zOpt){
5761 if( zStr[0]!='-' ) return 0;
5762 zStr++;
5763 if( zStr[0]=='-' ) zStr++;
5764 return strcmp(zStr, zOpt)==0;
5765}
5766
5767/*
5768** Delete a file.
5769*/
5770int shellDeleteFile(const char *zFilename){
5771 int rc;
5772#ifdef _WIN32
5773 wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
5774 rc = _wunlink(z);
5775 sqlite3_free(z);
5776#else
5777 rc = unlink(zFilename);
5778#endif
5779 return rc;
5780}
5781
drh13c20932018-01-10 21:41:55 +00005782/*
5783** Try to delete the temporary file (if there is one) and free the
5784** memory used to hold the name of the temp file.
5785*/
5786static void clearTempFile(ShellState *p){
5787 if( p->zTempFile==0 ) return;
drh536c3452018-01-11 00:38:39 +00005788 if( p->doXdgOpen ) return;
drh13c20932018-01-10 21:41:55 +00005789 if( shellDeleteFile(p->zTempFile) ) return;
5790 sqlite3_free(p->zTempFile);
5791 p->zTempFile = 0;
5792}
5793
5794/*
5795** Create a new temp file name with the given suffix.
5796*/
5797static void newTempFile(ShellState *p, const char *zSuffix){
5798 clearTempFile(p);
5799 sqlite3_free(p->zTempFile);
5800 p->zTempFile = 0;
drh7f3bf8a2018-01-10 21:50:08 +00005801 if( p->db ){
5802 sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
5803 }
drh13c20932018-01-10 21:41:55 +00005804 if( p->zTempFile==0 ){
drh1d9ea272020-04-17 23:46:54 +00005805 /* If p->db is an in-memory database then the TEMPFILENAME file-control
5806 ** will not work and we will need to fallback to guessing */
5807 char *zTemp;
drh13c20932018-01-10 21:41:55 +00005808 sqlite3_uint64 r;
5809 sqlite3_randomness(sizeof(r), &r);
drh1d9ea272020-04-17 23:46:54 +00005810 zTemp = getenv("TEMP");
5811 if( zTemp==0 ) zTemp = getenv("TMP");
5812 if( zTemp==0 ){
5813#ifdef _WIN32
5814 zTemp = "\\tmp";
5815#else
5816 zTemp = "/tmp";
5817#endif
5818 }
5819 p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix);
drh13c20932018-01-10 21:41:55 +00005820 }else{
5821 p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
5822 }
drhe3e25652021-12-16 13:29:28 +00005823 shell_check_oom(p->zTempFile);
drh13c20932018-01-10 21:41:55 +00005824}
5825
drh2ce15c32017-07-11 13:34:40 +00005826
5827/*
5828** The implementation of SQL scalar function fkey_collate_clause(), used
5829** by the ".lint fkey-indexes" command. This scalar function is always
5830** called with four arguments - the parent table name, the parent column name,
5831** the child table name and the child column name.
5832**
5833** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
5834**
5835** If either of the named tables or columns do not exist, this function
5836** returns an empty string. An empty string is also returned if both tables
5837** and columns exist but have the same default collation sequence. Or,
5838** if both exist but the default collation sequences are different, this
5839** function returns the string " COLLATE <parent-collation>", where
5840** <parent-collation> is the default collation sequence of the parent column.
5841*/
5842static void shellFkeyCollateClause(
5843 sqlite3_context *pCtx,
5844 int nVal,
5845 sqlite3_value **apVal
5846){
5847 sqlite3 *db = sqlite3_context_db_handle(pCtx);
5848 const char *zParent;
5849 const char *zParentCol;
5850 const char *zParentSeq;
5851 const char *zChild;
5852 const char *zChildCol;
5853 const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */
5854 int rc;
5855
5856 assert( nVal==4 );
5857 zParent = (const char*)sqlite3_value_text(apVal[0]);
5858 zParentCol = (const char*)sqlite3_value_text(apVal[1]);
5859 zChild = (const char*)sqlite3_value_text(apVal[2]);
5860 zChildCol = (const char*)sqlite3_value_text(apVal[3]);
5861
5862 sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
5863 rc = sqlite3_table_column_metadata(
5864 db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0
5865 );
5866 if( rc==SQLITE_OK ){
5867 rc = sqlite3_table_column_metadata(
5868 db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0
5869 );
5870 }
5871
5872 if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){
5873 char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq);
5874 sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
5875 sqlite3_free(z);
5876 }
5877}
5878
5879
5880/*
5881** The implementation of dot-command ".lint fkey-indexes".
5882*/
5883static int lintFkeyIndexes(
5884 ShellState *pState, /* Current shell tool state */
5885 char **azArg, /* Array of arguments passed to dot command */
5886 int nArg /* Number of entries in azArg[] */
5887){
5888 sqlite3 *db = pState->db; /* Database handle to query "main" db of */
5889 FILE *out = pState->out; /* Stream to write non-error output to */
5890 int bVerbose = 0; /* If -verbose is present */
5891 int bGroupByParent = 0; /* If -groupbyparent is present */
5892 int i; /* To iterate through azArg[] */
5893 const char *zIndent = ""; /* How much to indent CREATE INDEX by */
5894 int rc; /* Return code */
5895 sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */
5896
5897 /*
5898 ** This SELECT statement returns one row for each foreign key constraint
5899 ** in the schema of the main database. The column values are:
5900 **
5901 ** 0. The text of an SQL statement similar to:
5902 **
danf9679312017-12-01 18:40:18 +00005903 ** "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?"
drh2ce15c32017-07-11 13:34:40 +00005904 **
danf9679312017-12-01 18:40:18 +00005905 ** This SELECT is similar to the one that the foreign keys implementation
5906 ** needs to run internally on child tables. If there is an index that can
drh2ce15c32017-07-11 13:34:40 +00005907 ** be used to optimize this query, then it can also be used by the FK
5908 ** implementation to optimize DELETE or UPDATE statements on the parent
5909 ** table.
5910 **
5911 ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by
5912 ** the EXPLAIN QUERY PLAN command matches this pattern, then the schema
5913 ** contains an index that can be used to optimize the query.
5914 **
5915 ** 2. Human readable text that describes the child table and columns. e.g.
5916 **
5917 ** "child_table(child_key1, child_key2)"
5918 **
5919 ** 3. Human readable text that describes the parent table and columns. e.g.
5920 **
5921 ** "parent_table(parent_key1, parent_key2)"
5922 **
5923 ** 4. A full CREATE INDEX statement for an index that could be used to
5924 ** optimize DELETE or UPDATE statements on the parent table. e.g.
5925 **
5926 ** "CREATE INDEX child_table_child_key ON child_table(child_key)"
5927 **
5928 ** 5. The name of the parent table.
5929 **
5930 ** These six values are used by the C logic below to generate the report.
5931 */
5932 const char *zSql =
5933 "SELECT "
danf9679312017-12-01 18:40:18 +00005934 " 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
drh2ce15c32017-07-11 13:34:40 +00005935 " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
5936 " || fkey_collate_clause("
5937 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
5938 ", "
drh82102332021-03-20 15:11:29 +00005939 " 'SEARCH ' || s.name || ' USING COVERING INDEX*('"
drh2ce15c32017-07-11 13:34:40 +00005940 " || group_concat('*=?', ' AND ') || ')'"
5941 ", "
5942 " s.name || '(' || group_concat(f.[from], ', ') || ')'"
5943 ", "
5944 " f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
5945 ", "
5946 " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
5947 " || ' ON ' || quote(s.name) || '('"
5948 " || group_concat(quote(f.[from]) ||"
5949 " fkey_collate_clause("
5950 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
5951 " || ');'"
5952 ", "
5953 " f.[table] "
drh067b92b2020-06-19 15:24:12 +00005954 "FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f "
drh2ce15c32017-07-11 13:34:40 +00005955 "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
5956 "GROUP BY s.name, f.id "
5957 "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
5958 ;
drh82102332021-03-20 15:11:29 +00005959 const char *zGlobIPK = "SEARCH * USING INTEGER PRIMARY KEY (rowid=?)";
drh2ce15c32017-07-11 13:34:40 +00005960
5961 for(i=2; i<nArg; i++){
drhaf2770f2018-01-05 14:55:43 +00005962 int n = strlen30(azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00005963 if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
5964 bVerbose = 1;
5965 }
5966 else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
5967 bGroupByParent = 1;
5968 zIndent = " ";
5969 }
5970 else{
5971 raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
5972 azArg[0], azArg[1]
5973 );
5974 return SQLITE_ERROR;
5975 }
5976 }
5977
5978 /* Register the fkey_collate_clause() SQL function */
5979 rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
5980 0, shellFkeyCollateClause, 0, 0
5981 );
5982
5983
5984 if( rc==SQLITE_OK ){
5985 rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
5986 }
5987 if( rc==SQLITE_OK ){
5988 sqlite3_bind_int(pSql, 1, bGroupByParent);
5989 }
5990
5991 if( rc==SQLITE_OK ){
5992 int rc2;
5993 char *zPrev = 0;
5994 while( SQLITE_ROW==sqlite3_step(pSql) ){
5995 int res = -1;
5996 sqlite3_stmt *pExplain = 0;
5997 const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
5998 const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
5999 const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
6000 const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
6001 const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
6002 const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
6003
drh621a5e02021-12-16 17:35:27 +00006004 if( zEQP==0 ) continue;
6005 if( zGlob==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00006006 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
6007 if( rc!=SQLITE_OK ) break;
6008 if( SQLITE_ROW==sqlite3_step(pExplain) ){
6009 const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
drh621a5e02021-12-16 17:35:27 +00006010 res = zPlan!=0 && ( 0==sqlite3_strglob(zGlob, zPlan)
6011 || 0==sqlite3_strglob(zGlobIPK, zPlan));
drh2ce15c32017-07-11 13:34:40 +00006012 }
6013 rc = sqlite3_finalize(pExplain);
6014 if( rc!=SQLITE_OK ) break;
6015
6016 if( res<0 ){
6017 raw_printf(stderr, "Error: internal error");
6018 break;
6019 }else{
6020 if( bGroupByParent
6021 && (bVerbose || res==0)
6022 && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
6023 ){
6024 raw_printf(out, "-- Parent table %s\n", zParent);
6025 sqlite3_free(zPrev);
6026 zPrev = sqlite3_mprintf("%s", zParent);
6027 }
6028
6029 if( res==0 ){
6030 raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
6031 }else if( bVerbose ){
6032 raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
6033 zIndent, zFrom, zTarget
6034 );
6035 }
6036 }
6037 }
6038 sqlite3_free(zPrev);
6039
6040 if( rc!=SQLITE_OK ){
6041 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
6042 }
6043
6044 rc2 = sqlite3_finalize(pSql);
6045 if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
6046 rc = rc2;
6047 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
6048 }
6049 }else{
6050 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
6051 }
6052
6053 return rc;
6054}
6055
6056/*
6057** Implementation of ".lint" dot command.
6058*/
6059static int lintDotCommand(
6060 ShellState *pState, /* Current shell tool state */
6061 char **azArg, /* Array of arguments passed to dot command */
6062 int nArg /* Number of entries in azArg[] */
6063){
6064 int n;
drhaf2770f2018-01-05 14:55:43 +00006065 n = (nArg>=2 ? strlen30(azArg[1]) : 0);
drh2ce15c32017-07-11 13:34:40 +00006066 if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
6067 return lintFkeyIndexes(pState, azArg, nArg);
6068
6069 usage:
6070 raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
6071 raw_printf(stderr, "Where sub-commands are:\n");
6072 raw_printf(stderr, " fkey-indexes\n");
6073 return SQLITE_ERROR;
6074}
6075
dan1b162162019-04-27 20:15:15 +00006076#if !defined SQLITE_OMIT_VIRTUALTABLE
danfd0245d2017-12-07 15:44:29 +00006077static void shellPrepare(
dand4b56e52017-12-12 20:04:59 +00006078 sqlite3 *db,
danfd0245d2017-12-07 15:44:29 +00006079 int *pRc,
6080 const char *zSql,
6081 sqlite3_stmt **ppStmt
6082){
6083 *ppStmt = 0;
6084 if( *pRc==SQLITE_OK ){
dand4b56e52017-12-12 20:04:59 +00006085 int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
danfd0245d2017-12-07 15:44:29 +00006086 if( rc!=SQLITE_OK ){
6087 raw_printf(stderr, "sql error: %s (%d)\n",
dand4b56e52017-12-12 20:04:59 +00006088 sqlite3_errmsg(db), sqlite3_errcode(db)
danfd0245d2017-12-07 15:44:29 +00006089 );
6090 *pRc = rc;
6091 }
6092 }
6093}
6094
drh9546c762019-05-10 17:50:33 +00006095/*
6096** Create a prepared statement using printf-style arguments for the SQL.
6097**
6098** This routine is could be marked "static". But it is not always used,
6099** depending on compile-time options. By omitting the "static", we avoid
6100** nuisance compiler warnings about "defined but not used".
6101*/
6102void shellPreparePrintf(
dan3f67ddf2017-12-13 20:04:53 +00006103 sqlite3 *db,
6104 int *pRc,
danac15e2d2017-12-14 19:15:07 +00006105 sqlite3_stmt **ppStmt,
6106 const char *zFmt,
6107 ...
dan3f67ddf2017-12-13 20:04:53 +00006108){
danac15e2d2017-12-14 19:15:07 +00006109 *ppStmt = 0;
6110 if( *pRc==SQLITE_OK ){
6111 va_list ap;
6112 char *z;
6113 va_start(ap, zFmt);
6114 z = sqlite3_vmprintf(zFmt, ap);
drh1dbb1472018-10-11 10:37:24 +00006115 va_end(ap);
dan3f67ddf2017-12-13 20:04:53 +00006116 if( z==0 ){
6117 *pRc = SQLITE_NOMEM;
6118 }else{
6119 shellPrepare(db, pRc, z, ppStmt);
6120 sqlite3_free(z);
6121 }
dan3f67ddf2017-12-13 20:04:53 +00006122 }
6123}
6124
drh9546c762019-05-10 17:50:33 +00006125/* Finalize the prepared statement created using shellPreparePrintf().
6126**
6127** This routine is could be marked "static". But it is not always used,
6128** depending on compile-time options. By omitting the "static", we avoid
6129** nuisance compiler warnings about "defined but not used".
6130*/
6131void shellFinalize(
danfd0245d2017-12-07 15:44:29 +00006132 int *pRc,
6133 sqlite3_stmt *pStmt
6134){
dan25c12182017-12-07 21:03:33 +00006135 if( pStmt ){
6136 sqlite3 *db = sqlite3_db_handle(pStmt);
6137 int rc = sqlite3_finalize(pStmt);
6138 if( *pRc==SQLITE_OK ){
6139 if( rc!=SQLITE_OK ){
6140 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
6141 }
6142 *pRc = rc;
6143 }
6144 }
danfd0245d2017-12-07 15:44:29 +00006145}
6146
drh9546c762019-05-10 17:50:33 +00006147/* Reset the prepared statement created using shellPreparePrintf().
6148**
6149** This routine is could be marked "static". But it is not always used,
6150** depending on compile-time options. By omitting the "static", we avoid
6151** nuisance compiler warnings about "defined but not used".
6152*/
6153void shellReset(
danfd0245d2017-12-07 15:44:29 +00006154 int *pRc,
6155 sqlite3_stmt *pStmt
6156){
6157 int rc = sqlite3_reset(pStmt);
dan5a78b812017-12-27 18:54:11 +00006158 if( *pRc==SQLITE_OK ){
6159 if( rc!=SQLITE_OK ){
6160 sqlite3 *db = sqlite3_db_handle(pStmt);
6161 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
6162 }
6163 *pRc = rc;
6164 }
danfd0245d2017-12-07 15:44:29 +00006165}
dan1b162162019-04-27 20:15:15 +00006166#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
6167
6168#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drhe2754c12019-08-26 12:50:01 +00006169/******************************************************************************
dan1b162162019-04-27 20:15:15 +00006170** The ".archive" or ".ar" command.
6171*/
drhe37c0e12018-01-06 19:19:50 +00006172/*
dan88be0202017-12-09 17:58:02 +00006173** Structure representing a single ".ar" command.
6174*/
6175typedef struct ArCommand ArCommand;
6176struct ArCommand {
drhb376b3d2018-01-10 13:11:51 +00006177 u8 eCmd; /* An AR_CMD_* value */
6178 u8 bVerbose; /* True if --verbose */
drha5676c42018-01-10 15:17:34 +00006179 u8 bZip; /* True if the archive is a ZIP */
drhb376b3d2018-01-10 13:11:51 +00006180 u8 bDryRun; /* True if --dry-run */
drha5676c42018-01-10 15:17:34 +00006181 u8 bAppend; /* True if --append */
larrybr8f09f4b2021-11-02 00:18:11 +00006182 u8 bGlob; /* True if --glob */
drhd0f9cdc2018-05-17 14:09:06 +00006183 u8 fromCmdLine; /* Run from -A instead of .archive */
drhb376b3d2018-01-10 13:11:51 +00006184 int nArg; /* Number of command arguments */
drha5676c42018-01-10 15:17:34 +00006185 char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
dan88be0202017-12-09 17:58:02 +00006186 const char *zFile; /* --file argument, or NULL */
6187 const char *zDir; /* --directory argument, or NULL */
dan88be0202017-12-09 17:58:02 +00006188 char **azArg; /* Array of command arguments */
drhb376b3d2018-01-10 13:11:51 +00006189 ShellState *p; /* Shell state */
6190 sqlite3 *db; /* Database containing the archive */
dan88be0202017-12-09 17:58:02 +00006191};
6192
6193/*
6194** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
6195*/
dan0d0547f2017-12-14 15:40:42 +00006196static int arUsage(FILE *f){
drh98aa2ab2018-09-26 16:53:51 +00006197 showHelp(f,"archive");
dan0d0547f2017-12-14 15:40:42 +00006198 return SQLITE_ERROR;
6199}
6200
6201/*
6202** Print an error message for the .ar command to stderr and return
6203** SQLITE_ERROR.
6204*/
drhd0f9cdc2018-05-17 14:09:06 +00006205static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
dan0d0547f2017-12-14 15:40:42 +00006206 va_list ap;
6207 char *z;
6208 va_start(ap, zFmt);
6209 z = sqlite3_vmprintf(zFmt, ap);
6210 va_end(ap);
drhd0f9cdc2018-05-17 14:09:06 +00006211 utf8_printf(stderr, "Error: %s\n", z);
6212 if( pAr->fromCmdLine ){
6213 utf8_printf(stderr, "Use \"-A\" for more help\n");
6214 }else{
6215 utf8_printf(stderr, "Use \".archive --help\" for more help\n");
6216 }
dan0d0547f2017-12-14 15:40:42 +00006217 sqlite3_free(z);
dan88be0202017-12-09 17:58:02 +00006218 return SQLITE_ERROR;
6219}
6220
6221/*
6222** Values for ArCommand.eCmd.
6223*/
dand4b56e52017-12-12 20:04:59 +00006224#define AR_CMD_CREATE 1
drhb17ea912019-03-25 14:24:19 +00006225#define AR_CMD_UPDATE 2
6226#define AR_CMD_INSERT 3
6227#define AR_CMD_EXTRACT 4
6228#define AR_CMD_LIST 5
6229#define AR_CMD_HELP 6
larrybr47061b92021-11-01 17:22:52 +00006230#define AR_CMD_REMOVE 7
dand4b56e52017-12-12 20:04:59 +00006231
6232/*
6233** Other (non-command) switches.
6234*/
larrybr47061b92021-11-01 17:22:52 +00006235#define AR_SWITCH_VERBOSE 8
6236#define AR_SWITCH_FILE 9
6237#define AR_SWITCH_DIRECTORY 10
6238#define AR_SWITCH_APPEND 11
larrybr719506f2021-11-01 22:33:20 +00006239#define AR_SWITCH_DRYRUN 12
larrybr8f09f4b2021-11-02 00:18:11 +00006240#define AR_SWITCH_GLOB 13
dand4b56e52017-12-12 20:04:59 +00006241
6242static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
6243 switch( eSwitch ){
6244 case AR_CMD_CREATE:
6245 case AR_CMD_EXTRACT:
6246 case AR_CMD_LIST:
larrybr47061b92021-11-01 17:22:52 +00006247 case AR_CMD_REMOVE:
dand4b56e52017-12-12 20:04:59 +00006248 case AR_CMD_UPDATE:
drhb17ea912019-03-25 14:24:19 +00006249 case AR_CMD_INSERT:
dan0d0547f2017-12-14 15:40:42 +00006250 case AR_CMD_HELP:
6251 if( pAr->eCmd ){
drhd0f9cdc2018-05-17 14:09:06 +00006252 return arErrorMsg(pAr, "multiple command options");
dan0d0547f2017-12-14 15:40:42 +00006253 }
dand4b56e52017-12-12 20:04:59 +00006254 pAr->eCmd = eSwitch;
6255 break;
6256
drhb376b3d2018-01-10 13:11:51 +00006257 case AR_SWITCH_DRYRUN:
6258 pAr->bDryRun = 1;
6259 break;
larrybr8f09f4b2021-11-02 00:18:11 +00006260 case AR_SWITCH_GLOB:
6261 pAr->bGlob = 1;
6262 break;
dand4b56e52017-12-12 20:04:59 +00006263 case AR_SWITCH_VERBOSE:
6264 pAr->bVerbose = 1;
6265 break;
drha5676c42018-01-10 15:17:34 +00006266 case AR_SWITCH_APPEND:
6267 pAr->bAppend = 1;
drhca7733b2018-01-10 18:09:20 +00006268 /* Fall thru into --file */
dand4b56e52017-12-12 20:04:59 +00006269 case AR_SWITCH_FILE:
6270 pAr->zFile = zArg;
6271 break;
6272 case AR_SWITCH_DIRECTORY:
6273 pAr->zDir = zArg;
6274 break;
6275 }
6276
6277 return SQLITE_OK;
6278}
dan88be0202017-12-09 17:58:02 +00006279
6280/*
6281** Parse the command line for an ".ar" command. The results are written into
6282** structure (*pAr). SQLITE_OK is returned if the command line is parsed
6283** successfully, otherwise an error message is written to stderr and
6284** SQLITE_ERROR returned.
6285*/
6286static int arParseCommand(
6287 char **azArg, /* Array of arguments passed to dot command */
6288 int nArg, /* Number of entries in azArg[] */
6289 ArCommand *pAr /* Populate this object */
6290){
dand4b56e52017-12-12 20:04:59 +00006291 struct ArSwitch {
dand4b56e52017-12-12 20:04:59 +00006292 const char *zLong;
drhb376b3d2018-01-10 13:11:51 +00006293 char cShort;
6294 u8 eSwitch;
6295 u8 bArg;
dand4b56e52017-12-12 20:04:59 +00006296 } aSwitch[] = {
drhb376b3d2018-01-10 13:11:51 +00006297 { "create", 'c', AR_CMD_CREATE, 0 },
6298 { "extract", 'x', AR_CMD_EXTRACT, 0 },
drhb17ea912019-03-25 14:24:19 +00006299 { "insert", 'i', AR_CMD_INSERT, 0 },
drhb376b3d2018-01-10 13:11:51 +00006300 { "list", 't', AR_CMD_LIST, 0 },
larrybr47061b92021-11-01 17:22:52 +00006301 { "remove", 'r', AR_CMD_REMOVE, 0 },
drhb376b3d2018-01-10 13:11:51 +00006302 { "update", 'u', AR_CMD_UPDATE, 0 },
6303 { "help", 'h', AR_CMD_HELP, 0 },
6304 { "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
6305 { "file", 'f', AR_SWITCH_FILE, 1 },
drhca7733b2018-01-10 18:09:20 +00006306 { "append", 'a', AR_SWITCH_APPEND, 1 },
drhb376b3d2018-01-10 13:11:51 +00006307 { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
drhb376b3d2018-01-10 13:11:51 +00006308 { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
larrybr8f09f4b2021-11-02 00:18:11 +00006309 { "glob", 'g', AR_SWITCH_GLOB, 0 },
dand4b56e52017-12-12 20:04:59 +00006310 };
6311 int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
6312 struct ArSwitch *pEnd = &aSwitch[nSwitch];
6313
dan88be0202017-12-09 17:58:02 +00006314 if( nArg<=1 ){
drh98aa2ab2018-09-26 16:53:51 +00006315 utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
dan0d0547f2017-12-14 15:40:42 +00006316 return arUsage(stderr);
dan88be0202017-12-09 17:58:02 +00006317 }else{
6318 char *z = azArg[1];
dan88be0202017-12-09 17:58:02 +00006319 if( z[0]!='-' ){
6320 /* Traditional style [tar] invocation */
6321 int i;
6322 int iArg = 2;
6323 for(i=0; z[i]; i++){
dand4b56e52017-12-12 20:04:59 +00006324 const char *zArg = 0;
6325 struct ArSwitch *pOpt;
6326 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6327 if( z[i]==pOpt->cShort ) break;
dan88be0202017-12-09 17:58:02 +00006328 }
dan0d0547f2017-12-14 15:40:42 +00006329 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006330 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006331 }
dand4b56e52017-12-12 20:04:59 +00006332 if( pOpt->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006333 if( iArg>=nArg ){
drhd0f9cdc2018-05-17 14:09:06 +00006334 return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
dan0d0547f2017-12-14 15:40:42 +00006335 }
dand4b56e52017-12-12 20:04:59 +00006336 zArg = azArg[iArg++];
6337 }
6338 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
dan88be0202017-12-09 17:58:02 +00006339 }
dan88be0202017-12-09 17:58:02 +00006340 pAr->nArg = nArg-iArg;
6341 if( pAr->nArg>0 ){
6342 pAr->azArg = &azArg[iArg];
6343 }
dand4b56e52017-12-12 20:04:59 +00006344 }else{
6345 /* Non-traditional invocation */
6346 int iArg;
6347 for(iArg=1; iArg<nArg; iArg++){
6348 int n;
6349 z = azArg[iArg];
6350 if( z[0]!='-' ){
6351 /* All remaining command line words are command arguments. */
6352 pAr->azArg = &azArg[iArg];
6353 pAr->nArg = nArg-iArg;
6354 break;
6355 }
drhaf2770f2018-01-05 14:55:43 +00006356 n = strlen30(z);
dand4b56e52017-12-12 20:04:59 +00006357
6358 if( z[1]!='-' ){
6359 int i;
6360 /* One or more short options */
6361 for(i=1; i<n; i++){
6362 const char *zArg = 0;
6363 struct ArSwitch *pOpt;
6364 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6365 if( z[i]==pOpt->cShort ) break;
6366 }
dan0d0547f2017-12-14 15:40:42 +00006367 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006368 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006369 }
dand4b56e52017-12-12 20:04:59 +00006370 if( pOpt->bArg ){
6371 if( i<(n-1) ){
6372 zArg = &z[i+1];
6373 i = n;
6374 }else{
dan0d0547f2017-12-14 15:40:42 +00006375 if( iArg>=(nArg-1) ){
drhe2754c12019-08-26 12:50:01 +00006376 return arErrorMsg(pAr, "option requires an argument: %c",
6377 z[i]);
dan0d0547f2017-12-14 15:40:42 +00006378 }
dand4b56e52017-12-12 20:04:59 +00006379 zArg = azArg[++iArg];
6380 }
6381 }
6382 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
6383 }
6384 }else if( z[2]=='\0' ){
6385 /* A -- option, indicating that all remaining command line words
6386 ** are command arguments. */
6387 pAr->azArg = &azArg[iArg+1];
6388 pAr->nArg = nArg-iArg-1;
6389 break;
6390 }else{
6391 /* A long option */
6392 const char *zArg = 0; /* Argument for option, if any */
6393 struct ArSwitch *pMatch = 0; /* Matching option */
6394 struct ArSwitch *pOpt; /* Iterator */
6395 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6396 const char *zLong = pOpt->zLong;
drhaf2770f2018-01-05 14:55:43 +00006397 if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
dand4b56e52017-12-12 20:04:59 +00006398 if( pMatch ){
drhd0f9cdc2018-05-17 14:09:06 +00006399 return arErrorMsg(pAr, "ambiguous option: %s",z);
dand4b56e52017-12-12 20:04:59 +00006400 }else{
6401 pMatch = pOpt;
6402 }
6403 }
6404 }
6405
6406 if( pMatch==0 ){
drhd0f9cdc2018-05-17 14:09:06 +00006407 return arErrorMsg(pAr, "unrecognized option: %s", z);
dand4b56e52017-12-12 20:04:59 +00006408 }
6409 if( pMatch->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006410 if( iArg>=(nArg-1) ){
drhd0f9cdc2018-05-17 14:09:06 +00006411 return arErrorMsg(pAr, "option requires an argument: %s", z);
dan0d0547f2017-12-14 15:40:42 +00006412 }
dand4b56e52017-12-12 20:04:59 +00006413 zArg = azArg[++iArg];
6414 }
6415 if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
6416 }
6417 }
dan88be0202017-12-09 17:58:02 +00006418 }
6419 }
6420
6421 return SQLITE_OK;
6422}
6423
6424/*
dan3f67ddf2017-12-13 20:04:53 +00006425** This function assumes that all arguments within the ArCommand.azArg[]
larrybr47061b92021-11-01 17:22:52 +00006426** array refer to archive members, as for the --extract, --list or --remove
larrybr8f09f4b2021-11-02 00:18:11 +00006427** commands. It checks that each of them are "present". If any specified
6428** file is not present in the archive, an error is printed to stderr and an
larrybr47061b92021-11-01 17:22:52 +00006429** error code returned. Otherwise, if all specified arguments are present
larrybr8f09f4b2021-11-02 00:18:11 +00006430** in the archive, SQLITE_OK is returned. Here, "present" means either an
6431** exact equality when pAr->bGlob is false or a "name GLOB pattern" match
drh0c0fb9c2021-11-02 10:54:39 +00006432** when pAr->bGlob is true.
dan3f67ddf2017-12-13 20:04:53 +00006433**
6434** This function strips any trailing '/' characters from each argument.
6435** This is consistent with the way the [tar] command seems to work on
6436** Linux.
6437*/
drhb376b3d2018-01-10 13:11:51 +00006438static int arCheckEntries(ArCommand *pAr){
dan3f67ddf2017-12-13 20:04:53 +00006439 int rc = SQLITE_OK;
6440 if( pAr->nArg ){
drhb376b3d2018-01-10 13:11:51 +00006441 int i, j;
dan3f67ddf2017-12-13 20:04:53 +00006442 sqlite3_stmt *pTest = 0;
larrybr8f09f4b2021-11-02 00:18:11 +00006443 const char *zSel = (pAr->bGlob)
6444 ? "SELECT name FROM %s WHERE glob($name,name)"
6445 : "SELECT name FROM %s WHERE name=$name";
dan3f67ddf2017-12-13 20:04:53 +00006446
larrybr8f09f4b2021-11-02 00:18:11 +00006447 shellPreparePrintf(pAr->db, &rc, &pTest, zSel, pAr->zSrcTable);
drhb376b3d2018-01-10 13:11:51 +00006448 j = sqlite3_bind_parameter_index(pTest, "$name");
dan3f67ddf2017-12-13 20:04:53 +00006449 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
6450 char *z = pAr->azArg[i];
drhaf2770f2018-01-05 14:55:43 +00006451 int n = strlen30(z);
dan3f67ddf2017-12-13 20:04:53 +00006452 int bOk = 0;
6453 while( n>0 && z[n-1]=='/' ) n--;
6454 z[n] = '\0';
drhb376b3d2018-01-10 13:11:51 +00006455 sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
dan3f67ddf2017-12-13 20:04:53 +00006456 if( SQLITE_ROW==sqlite3_step(pTest) ){
6457 bOk = 1;
6458 }
6459 shellReset(&rc, pTest);
6460 if( rc==SQLITE_OK && bOk==0 ){
drhb376b3d2018-01-10 13:11:51 +00006461 utf8_printf(stderr, "not found in archive: %s\n", z);
dan3f67ddf2017-12-13 20:04:53 +00006462 rc = SQLITE_ERROR;
6463 }
6464 }
6465 shellFinalize(&rc, pTest);
6466 }
dan3f67ddf2017-12-13 20:04:53 +00006467 return rc;
6468}
6469
6470/*
6471** Format a WHERE clause that can be used against the "sqlar" table to
6472** identify all archive members that match the command arguments held
6473** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
6474** The caller is responsible for eventually calling sqlite3_free() on
larrybr8f09f4b2021-11-02 00:18:11 +00006475** any non-NULL (*pzWhere) value. Here, "match" means strict equality
6476** when pAr->bGlob is false and GLOB match when pAr->bGlob is true.
dan3f67ddf2017-12-13 20:04:53 +00006477*/
6478static void arWhereClause(
6479 int *pRc,
larrybr8f09f4b2021-11-02 00:18:11 +00006480 ArCommand *pAr,
danac15e2d2017-12-14 19:15:07 +00006481 char **pzWhere /* OUT: New WHERE clause */
dan3f67ddf2017-12-13 20:04:53 +00006482){
6483 char *zWhere = 0;
larrybr8f09f4b2021-11-02 00:18:11 +00006484 const char *zSameOp = (pAr->bGlob)? "GLOB" : "=";
dan3f67ddf2017-12-13 20:04:53 +00006485 if( *pRc==SQLITE_OK ){
danac15e2d2017-12-14 19:15:07 +00006486 if( pAr->nArg==0 ){
6487 zWhere = sqlite3_mprintf("1");
6488 }else{
6489 int i;
6490 const char *zSep = "";
6491 for(i=0; i<pAr->nArg; i++){
6492 const char *z = pAr->azArg[i];
6493 zWhere = sqlite3_mprintf(
larrybr8f09f4b2021-11-02 00:18:11 +00006494 "%z%s name %s '%q' OR substr(name,1,%d) %s '%q/'",
6495 zWhere, zSep, zSameOp, z, strlen30(z)+1, zSameOp, z
drhb376b3d2018-01-10 13:11:51 +00006496 );
danac15e2d2017-12-14 19:15:07 +00006497 if( zWhere==0 ){
6498 *pRc = SQLITE_NOMEM;
6499 break;
6500 }
6501 zSep = " OR ";
dan3f67ddf2017-12-13 20:04:53 +00006502 }
dan3f67ddf2017-12-13 20:04:53 +00006503 }
6504 }
6505 *pzWhere = zWhere;
6506}
6507
6508/*
dan88be0202017-12-09 17:58:02 +00006509** Implementation of .ar "lisT" command.
6510*/
drhb376b3d2018-01-10 13:11:51 +00006511static int arListCommand(ArCommand *pAr){
danb5090e42017-12-27 21:13:21 +00006512 const char *zSql = "SELECT %s FROM %s WHERE %s";
danb5090e42017-12-27 21:13:21 +00006513 const char *azCols[] = {
6514 "name",
drh410cad92018-01-10 17:19:16 +00006515 "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
danb5090e42017-12-27 21:13:21 +00006516 };
dan5a78b812017-12-27 18:54:11 +00006517
dan3f67ddf2017-12-13 20:04:53 +00006518 char *zWhere = 0;
6519 sqlite3_stmt *pSql = 0;
6520 int rc;
6521
drhb376b3d2018-01-10 13:11:51 +00006522 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006523 arWhereClause(&rc, pAr, &zWhere);
6524
drhb376b3d2018-01-10 13:11:51 +00006525 shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
6526 pAr->zSrcTable, zWhere);
drhb376b3d2018-01-10 13:11:51 +00006527 if( pAr->bDryRun ){
6528 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
6529 }else{
6530 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
6531 if( pAr->bVerbose ){
drh410cad92018-01-10 17:19:16 +00006532 utf8_printf(pAr->p->out, "%s % 10d %s %s\n",
6533 sqlite3_column_text(pSql, 0),
drhb376b3d2018-01-10 13:11:51 +00006534 sqlite3_column_int(pSql, 1),
6535 sqlite3_column_text(pSql, 2),
6536 sqlite3_column_text(pSql, 3)
6537 );
6538 }else{
6539 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
6540 }
danb5090e42017-12-27 21:13:21 +00006541 }
dan3f67ddf2017-12-13 20:04:53 +00006542 }
dan5a78b812017-12-27 18:54:11 +00006543 shellFinalize(&rc, pSql);
drhd0f9cdc2018-05-17 14:09:06 +00006544 sqlite3_free(zWhere);
dan3f67ddf2017-12-13 20:04:53 +00006545 return rc;
dan88be0202017-12-09 17:58:02 +00006546}
6547
6548
danfd0245d2017-12-07 15:44:29 +00006549/*
larrybr47061b92021-11-01 17:22:52 +00006550** Implementation of .ar "Remove" command.
6551*/
6552static int arRemoveCommand(ArCommand *pAr){
larrybr7774fc02021-11-01 22:30:24 +00006553 int rc = 0;
larrybr47061b92021-11-01 17:22:52 +00006554 char *zSql = 0;
6555 char *zWhere = 0;
6556
6557 if( pAr->nArg ){
6558 /* Verify that args actually exist within the archive before proceeding.
6559 ** And formulate a WHERE clause to match them. */
6560 rc = arCheckEntries(pAr);
6561 arWhereClause(&rc, pAr, &zWhere);
6562 }
6563 if( rc==SQLITE_OK ){
6564 zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;",
6565 pAr->zSrcTable, zWhere);
6566 if( pAr->bDryRun ){
6567 utf8_printf(pAr->p->out, "%s\n", zSql);
6568 }else{
6569 char *zErr = 0;
6570 rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0);
6571 if( rc==SQLITE_OK ){
6572 rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
6573 if( rc!=SQLITE_OK ){
6574 sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
6575 }else{
6576 rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0);
6577 }
6578 }
6579 if( zErr ){
6580 utf8_printf(stdout, "ERROR: %s\n", zErr);
6581 sqlite3_free(zErr);
6582 }
6583 }
6584 }
6585 sqlite3_free(zWhere);
6586 sqlite3_free(zSql);
6587 return rc;
6588}
6589
6590/*
danfd0245d2017-12-07 15:44:29 +00006591** Implementation of .ar "eXtract" command.
6592*/
drhb376b3d2018-01-10 13:11:51 +00006593static int arExtractCommand(ArCommand *pAr){
dan25c12182017-12-07 21:03:33 +00006594 const char *zSql1 =
dand1b51d42017-12-16 19:11:26 +00006595 "SELECT "
drhb376b3d2018-01-10 13:11:51 +00006596 " ($dir || name),"
6597 " writefile(($dir || name), %s, mode, mtime) "
drh0cfd46a2018-06-06 01:18:01 +00006598 "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
6599 " AND name NOT GLOB '*..[/\\]*'";
dan5a78b812017-12-27 18:54:11 +00006600
6601 const char *azExtraArg[] = {
6602 "sqlar_uncompress(data, sz)",
dan7c15ac12018-01-08 19:59:59 +00006603 "data"
dan5a78b812017-12-27 18:54:11 +00006604 };
dan5a78b812017-12-27 18:54:11 +00006605
danfd0245d2017-12-07 15:44:29 +00006606 sqlite3_stmt *pSql = 0;
6607 int rc = SQLITE_OK;
dan2ad09492017-12-09 18:28:22 +00006608 char *zDir = 0;
dan3f67ddf2017-12-13 20:04:53 +00006609 char *zWhere = 0;
drhb376b3d2018-01-10 13:11:51 +00006610 int i, j;
dan2ad09492017-12-09 18:28:22 +00006611
dan3f67ddf2017-12-13 20:04:53 +00006612 /* If arguments are specified, check that they actually exist within
6613 ** the archive before proceeding. And formulate a WHERE clause to
6614 ** match them. */
drhb376b3d2018-01-10 13:11:51 +00006615 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006616 arWhereClause(&rc, pAr, &zWhere);
6617
6618 if( rc==SQLITE_OK ){
6619 if( pAr->zDir ){
6620 zDir = sqlite3_mprintf("%s/", pAr->zDir);
6621 }else{
6622 zDir = sqlite3_mprintf("");
6623 }
6624 if( zDir==0 ) rc = SQLITE_NOMEM;
dan2ad09492017-12-09 18:28:22 +00006625 }
danfd0245d2017-12-07 15:44:29 +00006626
drhb376b3d2018-01-10 13:11:51 +00006627 shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
6628 azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
dan5a78b812017-12-27 18:54:11 +00006629 );
6630
dan2ad09492017-12-09 18:28:22 +00006631 if( rc==SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00006632 j = sqlite3_bind_parameter_index(pSql, "$dir");
6633 sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
dan25c12182017-12-07 21:03:33 +00006634
danac15e2d2017-12-14 19:15:07 +00006635 /* Run the SELECT statement twice. The first time, writefile() is called
6636 ** for all archive members that should be extracted. The second time,
6637 ** only for the directories. This is because the timestamps for
6638 ** extracted directories must be reset after they are populated (as
6639 ** populating them changes the timestamp). */
6640 for(i=0; i<2; i++){
drhb376b3d2018-01-10 13:11:51 +00006641 j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
6642 sqlite3_bind_int(pSql, j, i);
6643 if( pAr->bDryRun ){
6644 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
6645 }else{
6646 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
6647 if( i==0 && pAr->bVerbose ){
6648 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
6649 }
danac15e2d2017-12-14 19:15:07 +00006650 }
6651 }
6652 shellReset(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00006653 }
danac15e2d2017-12-14 19:15:07 +00006654 shellFinalize(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00006655 }
dan25c12182017-12-07 21:03:33 +00006656
dan2ad09492017-12-09 18:28:22 +00006657 sqlite3_free(zDir);
dan3f67ddf2017-12-13 20:04:53 +00006658 sqlite3_free(zWhere);
danfd0245d2017-12-07 15:44:29 +00006659 return rc;
6660}
6661
drhb376b3d2018-01-10 13:11:51 +00006662/*
6663** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out.
6664*/
6665static int arExecSql(ArCommand *pAr, const char *zSql){
6666 int rc;
6667 if( pAr->bDryRun ){
6668 utf8_printf(pAr->p->out, "%s\n", zSql);
6669 rc = SQLITE_OK;
6670 }else{
drh410cad92018-01-10 17:19:16 +00006671 char *zErr = 0;
6672 rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
6673 if( zErr ){
6674 utf8_printf(stdout, "ERROR: %s\n", zErr);
6675 sqlite3_free(zErr);
6676 }
drhb376b3d2018-01-10 13:11:51 +00006677 }
6678 return rc;
6679}
6680
dan1ad3f612017-12-11 20:22:02 +00006681
danfd0245d2017-12-07 15:44:29 +00006682/*
drhb17ea912019-03-25 14:24:19 +00006683** Implementation of .ar "create", "insert", and "update" commands.
6684**
6685** create -> Create a new SQL archive
6686** insert -> Insert or reinsert all files listed
6687** update -> Insert files that have changed or that were not
6688** previously in the archive
danfd0245d2017-12-07 15:44:29 +00006689**
6690** Create the "sqlar" table in the database if it does not already exist.
6691** Then add each file in the azFile[] array to the archive. Directories
6692** are added recursively. If argument bVerbose is non-zero, a message is
6693** printed on stdout for each file archived.
dan06741a32017-12-13 20:17:18 +00006694**
6695** The create command is the same as update, except that it drops
drhb17ea912019-03-25 14:24:19 +00006696** any existing "sqlar" table before beginning. The "insert" command
6697** always overwrites every file named on the command-line, where as
6698** "update" only overwrites if the size or mtime or mode has changed.
danfd0245d2017-12-07 15:44:29 +00006699*/
drhb376b3d2018-01-10 13:11:51 +00006700static int arCreateOrUpdateCommand(
dan06741a32017-12-13 20:17:18 +00006701 ArCommand *pAr, /* Command arguments and options */
drhb17ea912019-03-25 14:24:19 +00006702 int bUpdate, /* true for a --create. */
6703 int bOnlyIfChanged /* Only update if file has changed */
danfd0245d2017-12-07 15:44:29 +00006704){
dand4b56e52017-12-12 20:04:59 +00006705 const char *zCreate =
drhafba1802018-01-06 15:49:57 +00006706 "CREATE TABLE IF NOT EXISTS sqlar(\n"
6707 " name TEXT PRIMARY KEY, -- name of the file\n"
6708 " mode INT, -- access permissions\n"
6709 " mtime INT, -- last modification time\n"
6710 " sz INT, -- original file size\n"
6711 " data BLOB -- compressed content\n"
6712 ")";
dand4b56e52017-12-12 20:04:59 +00006713 const char *zDrop = "DROP TABLE IF EXISTS sqlar";
drh1bf208c2018-03-09 21:54:01 +00006714 const char *zInsertFmt[2] = {
6715 "REPLACE INTO %s(name,mode,mtime,sz,data)\n"
drh634c70f2018-01-10 16:50:18 +00006716 " SELECT\n"
6717 " %s,\n"
6718 " mode,\n"
6719 " mtime,\n"
drh410cad92018-01-10 17:19:16 +00006720 " CASE substr(lsmode(mode),1,1)\n"
6721 " WHEN '-' THEN length(data)\n"
6722 " WHEN 'd' THEN 0\n"
drh634c70f2018-01-10 16:50:18 +00006723 " ELSE -1 END,\n"
drh69d2d352018-03-09 22:18:53 +00006724 " sqlar_compress(data)\n"
drhb17ea912019-03-25 14:24:19 +00006725 " FROM fsdir(%Q,%Q) AS disk\n"
6726 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
6727 ,
drh1bf208c2018-03-09 21:54:01 +00006728 "REPLACE INTO %s(name,mode,mtime,data)\n"
6729 " SELECT\n"
6730 " %s,\n"
6731 " mode,\n"
6732 " mtime,\n"
6733 " data\n"
drhb17ea912019-03-25 14:24:19 +00006734 " FROM fsdir(%Q,%Q) AS disk\n"
6735 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
drh1bf208c2018-03-09 21:54:01 +00006736 };
danfd0245d2017-12-07 15:44:29 +00006737 int i; /* For iterating through azFile[] */
6738 int rc; /* Return code */
drh1bf208c2018-03-09 21:54:01 +00006739 const char *zTab = 0; /* SQL table into which to insert */
6740 char *zSql;
6741 char zTemp[50];
drhb17ea912019-03-25 14:24:19 +00006742 char *zExists = 0;
danfd0245d2017-12-07 15:44:29 +00006743
drh1bf208c2018-03-09 21:54:01 +00006744 arExecSql(pAr, "PRAGMA page_size=512");
drhb376b3d2018-01-10 13:11:51 +00006745 rc = arExecSql(pAr, "SAVEPOINT ar;");
danfd0245d2017-12-07 15:44:29 +00006746 if( rc!=SQLITE_OK ) return rc;
drh1bf208c2018-03-09 21:54:01 +00006747 zTemp[0] = 0;
6748 if( pAr->bZip ){
6749 /* Initialize the zipfile virtual table, if necessary */
6750 if( pAr->zFile ){
6751 sqlite3_uint64 r;
6752 sqlite3_randomness(sizeof(r),&r);
6753 sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
6754 zTab = zTemp;
6755 zSql = sqlite3_mprintf(
6756 "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)",
6757 zTab, pAr->zFile
6758 );
6759 rc = arExecSql(pAr, zSql);
6760 sqlite3_free(zSql);
6761 }else{
6762 zTab = "zip";
6763 }
6764 }else{
6765 /* Initialize the table for an SQLAR */
6766 zTab = "sqlar";
6767 if( bUpdate==0 ){
6768 rc = arExecSql(pAr, zDrop);
6769 if( rc!=SQLITE_OK ) goto end_ar_transaction;
6770 }
6771 rc = arExecSql(pAr, zCreate);
dan06741a32017-12-13 20:17:18 +00006772 }
drhb17ea912019-03-25 14:24:19 +00006773 if( bOnlyIfChanged ){
6774 zExists = sqlite3_mprintf(
6775 " AND NOT EXISTS("
6776 "SELECT 1 FROM %s AS mem"
6777 " WHERE mem.name=disk.name"
6778 " AND mem.mtime=disk.mtime"
6779 " AND mem.mode=disk.mode)", zTab);
6780 }else{
6781 zExists = sqlite3_mprintf("");
6782 }
6783 if( zExists==0 ) rc = SQLITE_NOMEM;
dan88be0202017-12-09 17:58:02 +00006784 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
mistachkince2052b2018-03-23 00:31:53 +00006785 char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
drh634c70f2018-01-10 16:50:18 +00006786 pAr->bVerbose ? "shell_putsnl(name)" : "name",
drhb17ea912019-03-25 14:24:19 +00006787 pAr->azArg[i], pAr->zDir, zExists);
mistachkince2052b2018-03-23 00:31:53 +00006788 rc = arExecSql(pAr, zSql2);
6789 sqlite3_free(zSql2);
danfd0245d2017-12-07 15:44:29 +00006790 }
drh1bf208c2018-03-09 21:54:01 +00006791end_ar_transaction:
danfd0245d2017-12-07 15:44:29 +00006792 if( rc!=SQLITE_OK ){
drh2bd207f2019-01-11 17:19:59 +00006793 sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
danfd0245d2017-12-07 15:44:29 +00006794 }else{
drhb376b3d2018-01-10 13:11:51 +00006795 rc = arExecSql(pAr, "RELEASE ar;");
drh1bf208c2018-03-09 21:54:01 +00006796 if( pAr->bZip && pAr->zFile ){
6797 zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
6798 arExecSql(pAr, zSql);
6799 sqlite3_free(zSql);
6800 }
danfd0245d2017-12-07 15:44:29 +00006801 }
drhb17ea912019-03-25 14:24:19 +00006802 sqlite3_free(zExists);
danfd0245d2017-12-07 15:44:29 +00006803 return rc;
6804}
6805
6806/*
6807** Implementation of ".ar" dot command.
6808*/
6809static int arDotCommand(
drhe2754c12019-08-26 12:50:01 +00006810 ShellState *pState, /* Current shell tool state */
6811 int fromCmdLine, /* True if -A command-line option, not .ar cmd */
6812 char **azArg, /* Array of arguments passed to dot command */
6813 int nArg /* Number of entries in azArg[] */
danfd0245d2017-12-07 15:44:29 +00006814){
dan88be0202017-12-09 17:58:02 +00006815 ArCommand cmd;
6816 int rc;
drh34660642018-01-10 17:39:54 +00006817 memset(&cmd, 0, sizeof(cmd));
drhd0f9cdc2018-05-17 14:09:06 +00006818 cmd.fromCmdLine = fromCmdLine;
dan88be0202017-12-09 17:58:02 +00006819 rc = arParseCommand(azArg, nArg, &cmd);
6820 if( rc==SQLITE_OK ){
drha5676c42018-01-10 15:17:34 +00006821 int eDbType = SHELL_OPEN_UNSPEC;
drhb376b3d2018-01-10 13:11:51 +00006822 cmd.p = pState;
6823 cmd.db = pState->db;
drha5676c42018-01-10 15:17:34 +00006824 if( cmd.zFile ){
drh1bf208c2018-03-09 21:54:01 +00006825 eDbType = deduceDatabaseType(cmd.zFile, 1);
drha5676c42018-01-10 15:17:34 +00006826 }else{
6827 eDbType = pState->openMode;
6828 }
6829 if( eDbType==SHELL_OPEN_ZIPFILE ){
drh1bf208c2018-03-09 21:54:01 +00006830 if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){
6831 if( cmd.zFile==0 ){
6832 cmd.zSrcTable = sqlite3_mprintf("zip");
6833 }else{
6834 cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
6835 }
dan5a78b812017-12-27 18:54:11 +00006836 }
drha5676c42018-01-10 15:17:34 +00006837 cmd.bZip = 1;
dan5a78b812017-12-27 18:54:11 +00006838 }else if( cmd.zFile ){
dand4b56e52017-12-12 20:04:59 +00006839 int flags;
drha5676c42018-01-10 15:17:34 +00006840 if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
drhb17ea912019-03-25 14:24:19 +00006841 if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
larrybr47061b92021-11-01 17:22:52 +00006842 || cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){
dand4b56e52017-12-12 20:04:59 +00006843 flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
6844 }else{
6845 flags = SQLITE_OPEN_READONLY;
6846 }
drha82c95b2018-01-10 14:00:00 +00006847 cmd.db = 0;
drha5676c42018-01-10 15:17:34 +00006848 if( cmd.bDryRun ){
6849 utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
6850 eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
6851 }
6852 rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
6853 eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
dand4b56e52017-12-12 20:04:59 +00006854 if( rc!=SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00006855 utf8_printf(stderr, "cannot open file: %s (%s)\n",
6856 cmd.zFile, sqlite3_errmsg(cmd.db)
dand4b56e52017-12-12 20:04:59 +00006857 );
drha5676c42018-01-10 15:17:34 +00006858 goto end_ar_command;
dand4b56e52017-12-12 20:04:59 +00006859 }
drhb376b3d2018-01-10 13:11:51 +00006860 sqlite3_fileio_init(cmd.db, 0, 0);
drhb376b3d2018-01-10 13:11:51 +00006861 sqlite3_sqlar_init(cmd.db, 0, 0);
drh34660642018-01-10 17:39:54 +00006862 sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
6863 shellPutsFunc, 0, 0);
6864
dand4b56e52017-12-12 20:04:59 +00006865 }
drhd0f9cdc2018-05-17 14:09:06 +00006866 if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
drh634c70f2018-01-10 16:50:18 +00006867 if( cmd.eCmd!=AR_CMD_CREATE
6868 && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
6869 ){
drha5676c42018-01-10 15:17:34 +00006870 utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
6871 rc = SQLITE_ERROR;
6872 goto end_ar_command;
6873 }
6874 cmd.zSrcTable = sqlite3_mprintf("sqlar");
6875 }
dand4b56e52017-12-12 20:04:59 +00006876
dan88be0202017-12-09 17:58:02 +00006877 switch( cmd.eCmd ){
6878 case AR_CMD_CREATE:
drhb17ea912019-03-25 14:24:19 +00006879 rc = arCreateOrUpdateCommand(&cmd, 0, 0);
dan88be0202017-12-09 17:58:02 +00006880 break;
danfd0245d2017-12-07 15:44:29 +00006881
dan88be0202017-12-09 17:58:02 +00006882 case AR_CMD_EXTRACT:
drhb376b3d2018-01-10 13:11:51 +00006883 rc = arExtractCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00006884 break;
6885
6886 case AR_CMD_LIST:
drhb376b3d2018-01-10 13:11:51 +00006887 rc = arListCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00006888 break;
6889
dan0d0547f2017-12-14 15:40:42 +00006890 case AR_CMD_HELP:
6891 arUsage(pState->out);
6892 break;
6893
drhb17ea912019-03-25 14:24:19 +00006894 case AR_CMD_INSERT:
6895 rc = arCreateOrUpdateCommand(&cmd, 1, 0);
6896 break;
6897
larrybr47061b92021-11-01 17:22:52 +00006898 case AR_CMD_REMOVE:
6899 rc = arRemoveCommand(&cmd);
6900 break;
6901
dan88be0202017-12-09 17:58:02 +00006902 default:
6903 assert( cmd.eCmd==AR_CMD_UPDATE );
drhb17ea912019-03-25 14:24:19 +00006904 rc = arCreateOrUpdateCommand(&cmd, 1, 1);
dan88be0202017-12-09 17:58:02 +00006905 break;
danfd0245d2017-12-07 15:44:29 +00006906 }
6907 }
drha5676c42018-01-10 15:17:34 +00006908end_ar_command:
6909 if( cmd.db!=pState->db ){
drh9e804032018-05-18 17:11:50 +00006910 close_db(cmd.db);
drha5676c42018-01-10 15:17:34 +00006911 }
6912 sqlite3_free(cmd.zSrcTable);
danfd0245d2017-12-07 15:44:29 +00006913
dan88be0202017-12-09 17:58:02 +00006914 return rc;
danfd0245d2017-12-07 15:44:29 +00006915}
drhe37c0e12018-01-06 19:19:50 +00006916/* End of the ".archive" or ".ar" command logic
drhe2754c12019-08-26 12:50:01 +00006917*******************************************************************************/
drhe37c0e12018-01-06 19:19:50 +00006918#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
danfd0245d2017-12-07 15:44:29 +00006919
dan1b162162019-04-27 20:15:15 +00006920#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan42ebb012019-04-27 18:47:03 +00006921/*
6922** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
6923** Otherwise, the SQL statement or statements in zSql are executed using
6924** database connection db and the error code written to *pRc before
6925** this function returns.
6926*/
dan68cb86e2019-04-20 20:57:28 +00006927static void shellExec(sqlite3 *db, int *pRc, const char *zSql){
6928 int rc = *pRc;
6929 if( rc==SQLITE_OK ){
6930 char *zErr = 0;
6931 rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
6932 if( rc!=SQLITE_OK ){
6933 raw_printf(stderr, "SQL error: %s\n", zErr);
6934 }
drhf83d5012021-05-03 13:35:00 +00006935 sqlite3_free(zErr);
dan68cb86e2019-04-20 20:57:28 +00006936 *pRc = rc;
6937 }
6938}
6939
dan42ebb012019-04-27 18:47:03 +00006940/*
6941** Like shellExec(), except that zFmt is a printf() style format string.
6942*/
danc0b42432019-04-26 15:14:53 +00006943static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){
6944 char *z = 0;
6945 if( *pRc==SQLITE_OK ){
6946 va_list ap;
6947 va_start(ap, zFmt);
6948 z = sqlite3_vmprintf(zFmt, ap);
6949 va_end(ap);
6950 if( z==0 ){
6951 *pRc = SQLITE_NOMEM;
6952 }else{
6953 shellExec(db, pRc, z);
6954 }
6955 sqlite3_free(z);
6956 }
6957}
6958
dan42ebb012019-04-27 18:47:03 +00006959/*
6960** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
6961** Otherwise, an attempt is made to allocate, zero and return a pointer
6962** to a buffer nByte bytes in size. If an OOM error occurs, *pRc is set
6963** to SQLITE_NOMEM and NULL returned.
6964*/
dan68cb86e2019-04-20 20:57:28 +00006965static void *shellMalloc(int *pRc, sqlite3_int64 nByte){
6966 void *pRet = 0;
6967 if( *pRc==SQLITE_OK ){
6968 pRet = sqlite3_malloc64(nByte);
6969 if( pRet==0 ){
6970 *pRc = SQLITE_NOMEM;
6971 }else{
6972 memset(pRet, 0, nByte);
6973 }
6974 }
6975 return pRet;
6976}
6977
dan42ebb012019-04-27 18:47:03 +00006978/*
6979** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
6980** Otherwise, zFmt is treated as a printf() style string. The result of
6981** formatting it along with any trailing arguments is written into a
6982** buffer obtained from sqlite3_malloc(), and pointer to which is returned.
6983** It is the responsibility of the caller to eventually free this buffer
6984** using a call to sqlite3_free().
6985**
6986** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL
6987** pointer returned.
6988*/
dan68cb86e2019-04-20 20:57:28 +00006989static char *shellMPrintf(int *pRc, const char *zFmt, ...){
6990 char *z = 0;
6991 if( *pRc==SQLITE_OK ){
6992 va_list ap;
6993 va_start(ap, zFmt);
6994 z = sqlite3_vmprintf(zFmt, ap);
6995 va_end(ap);
6996 if( z==0 ){
6997 *pRc = SQLITE_NOMEM;
6998 }
6999 }
7000 return z;
7001}
7002
dan42ebb012019-04-27 18:47:03 +00007003/*
7004** When running the ".recover" command, each output table, and the special
7005** orphaned row table if it is required, is represented by an instance
7006** of the following struct.
7007*/
dan68cb86e2019-04-20 20:57:28 +00007008typedef struct RecoverTable RecoverTable;
7009struct RecoverTable {
dan42ebb012019-04-27 18:47:03 +00007010 char *zQuoted; /* Quoted version of table name */
dan68cb86e2019-04-20 20:57:28 +00007011 int nCol; /* Number of columns in table */
7012 char **azlCol; /* Array of column lists */
dan42ebb012019-04-27 18:47:03 +00007013 int iPk; /* Index of IPK column */
dan68cb86e2019-04-20 20:57:28 +00007014};
7015
7016/*
dan42ebb012019-04-27 18:47:03 +00007017** Free a RecoverTable object allocated by recoverFindTable() or
7018** recoverOrphanTable().
dan68cb86e2019-04-20 20:57:28 +00007019*/
7020static void recoverFreeTable(RecoverTable *pTab){
7021 if( pTab ){
dan68cb86e2019-04-20 20:57:28 +00007022 sqlite3_free(pTab->zQuoted);
dan68cb86e2019-04-20 20:57:28 +00007023 if( pTab->azlCol ){
7024 int i;
dan98c5ad32019-04-26 21:11:37 +00007025 for(i=0; i<=pTab->nCol; i++){
dan68cb86e2019-04-20 20:57:28 +00007026 sqlite3_free(pTab->azlCol[i]);
7027 }
7028 sqlite3_free(pTab->azlCol);
7029 }
7030 sqlite3_free(pTab);
7031 }
7032}
7033
dan42ebb012019-04-27 18:47:03 +00007034/*
7035** This function is a no-op if (*pRc) is not SQLITE_OK when it is called.
7036** Otherwise, it allocates and returns a RecoverTable object based on the
7037** final four arguments passed to this function. It is the responsibility
7038** of the caller to eventually free the returned object using
7039** recoverFreeTable().
7040*/
7041static RecoverTable *recoverNewTable(
danb40af492019-04-22 20:52:12 +00007042 int *pRc, /* IN/OUT: Error code */
danb40af492019-04-22 20:52:12 +00007043 const char *zName, /* Name of table */
7044 const char *zSql, /* CREATE TABLE statement */
7045 int bIntkey,
7046 int nCol
7047){
7048 sqlite3 *dbtmp = 0; /* sqlite3 handle for testing CREATE TABLE */
7049 int rc = *pRc;
dan98c5ad32019-04-26 21:11:37 +00007050 RecoverTable *pTab = 0;
danb40af492019-04-22 20:52:12 +00007051
dan98c5ad32019-04-26 21:11:37 +00007052 pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable));
danb40af492019-04-22 20:52:12 +00007053 if( rc==SQLITE_OK ){
7054 int nSqlCol = 0;
7055 int bSqlIntkey = 0;
7056 sqlite3_stmt *pStmt = 0;
dan98c5ad32019-04-26 21:11:37 +00007057
danb40af492019-04-22 20:52:12 +00007058 rc = sqlite3_open("", &dbtmp);
7059 if( rc==SQLITE_OK ){
drha2de66c2019-08-06 20:26:17 +00007060 sqlite3_create_function(dbtmp, "shell_idquote", 1, SQLITE_UTF8, 0,
7061 shellIdQuote, 0, 0);
7062 }
7063 if( rc==SQLITE_OK ){
dan38f9c712019-04-23 18:03:02 +00007064 rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
7065 }
7066 if( rc==SQLITE_OK ){
danb40af492019-04-22 20:52:12 +00007067 rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0);
7068 if( rc==SQLITE_ERROR ){
7069 rc = SQLITE_OK;
7070 goto finished;
7071 }
7072 }
7073 shellPreparePrintf(dbtmp, &rc, &pStmt,
7074 "SELECT count(*) FROM pragma_table_info(%Q)", zName
7075 );
7076 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7077 nSqlCol = sqlite3_column_int(pStmt, 0);
7078 }
7079 shellFinalize(&rc, pStmt);
7080
7081 if( rc!=SQLITE_OK || nSqlCol<nCol ){
7082 goto finished;
7083 }
7084
7085 shellPreparePrintf(dbtmp, &rc, &pStmt,
7086 "SELECT ("
7087 " SELECT substr(data,1,1)==X'0D' FROM sqlite_dbpage WHERE pgno=rootpage"
drh067b92b2020-06-19 15:24:12 +00007088 ") FROM sqlite_schema WHERE name = %Q", zName
danb40af492019-04-22 20:52:12 +00007089 );
7090 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7091 bSqlIntkey = sqlite3_column_int(pStmt, 0);
7092 }
7093 shellFinalize(&rc, pStmt);
7094
7095 if( bIntkey==bSqlIntkey ){
dan98c5ad32019-04-26 21:11:37 +00007096 int i;
danb40af492019-04-22 20:52:12 +00007097 const char *zPk = "_rowid_";
7098 sqlite3_stmt *pPkFinder = 0;
7099
danf57bea32019-04-27 15:35:45 +00007100 /* If this is an intkey table and there is an INTEGER PRIMARY KEY,
7101 ** set zPk to the name of the PK column, and pTab->iPk to the index
7102 ** of the column, where columns are 0-numbered from left to right.
7103 ** Or, if this is a WITHOUT ROWID table or if there is no IPK column,
7104 ** leave zPk as "_rowid_" and pTab->iPk at -2. */
dan98c5ad32019-04-26 21:11:37 +00007105 pTab->iPk = -2;
7106 if( bIntkey ){
7107 shellPreparePrintf(dbtmp, &rc, &pPkFinder,
danb40af492019-04-22 20:52:12 +00007108 "SELECT cid, name FROM pragma_table_info(%Q) "
7109 " WHERE pk=1 AND type='integer' COLLATE nocase"
dan98c5ad32019-04-26 21:11:37 +00007110 " AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
7111 , zName, zName
7112 );
7113 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){
7114 pTab->iPk = sqlite3_column_int(pPkFinder, 0);
7115 zPk = (const char*)sqlite3_column_text(pPkFinder, 1);
drh621a5e02021-12-16 17:35:27 +00007116 if( zPk==0 ){ zPk = "_"; /* Defensive. Should never happen */ }
dan98c5ad32019-04-26 21:11:37 +00007117 }
danb40af492019-04-22 20:52:12 +00007118 }
7119
drha2de66c2019-08-06 20:26:17 +00007120 pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName);
dan98c5ad32019-04-26 21:11:37 +00007121 pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
danb40af492019-04-22 20:52:12 +00007122 pTab->nCol = nSqlCol;
7123
dan98c5ad32019-04-26 21:11:37 +00007124 if( bIntkey ){
drha2de66c2019-08-06 20:26:17 +00007125 pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk);
danb40af492019-04-22 20:52:12 +00007126 }else{
dan98c5ad32019-04-26 21:11:37 +00007127 pTab->azlCol[0] = shellMPrintf(&rc, "");
danb40af492019-04-22 20:52:12 +00007128 }
dan98c5ad32019-04-26 21:11:37 +00007129 i = 1;
7130 shellPreparePrintf(dbtmp, &rc, &pStmt,
drha2de66c2019-08-06 20:26:17 +00007131 "SELECT %Q || group_concat(shell_idquote(name), ', ') "
danf57bea32019-04-27 15:35:45 +00007132 " FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
dan98c5ad32019-04-26 21:11:37 +00007133 "FROM pragma_table_info(%Q)",
danf57bea32019-04-27 15:35:45 +00007134 bIntkey ? ", " : "", pTab->iPk,
7135 bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ",
7136 zName
dan98c5ad32019-04-26 21:11:37 +00007137 );
7138 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7139 const char *zText = (const char*)sqlite3_column_text(pStmt, 0);
7140 pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText);
7141 i++;
7142 }
7143 shellFinalize(&rc, pStmt);
7144
danb40af492019-04-22 20:52:12 +00007145 shellFinalize(&rc, pPkFinder);
7146 }
7147 }
7148
7149 finished:
7150 sqlite3_close(dbtmp);
7151 *pRc = rc;
dan98779652019-05-09 14:15:19 +00007152 if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){
dan98c5ad32019-04-26 21:11:37 +00007153 recoverFreeTable(pTab);
7154 pTab = 0;
7155 }
7156 return pTab;
danb40af492019-04-22 20:52:12 +00007157}
7158
dan0aa01ee2019-04-27 19:36:49 +00007159/*
7160** This function is called to search the schema recovered from the
drh067b92b2020-06-19 15:24:12 +00007161** sqlite_schema table of the (possibly) corrupt database as part
dan0aa01ee2019-04-27 19:36:49 +00007162** of a ".recover" command. Specifically, for a table with root page
7163** iRoot and at least nCol columns. Additionally, if bIntkey is 0, the
7164** table must be a WITHOUT ROWID table, or if non-zero, not one of
7165** those.
7166**
7167** If a table is found, a (RecoverTable*) object is returned. Or, if
7168** no such table is found, but bIntkey is false and iRoot is the
7169** root page of an index in the recovered schema, then (*pbNoop) is
7170** set to true and NULL returned. Or, if there is no such table or
7171** index, NULL is returned and (*pbNoop) set to 0, indicating that
7172** the caller should write data to the orphans table.
7173*/
dan42ebb012019-04-27 18:47:03 +00007174static RecoverTable *recoverFindTable(
dan0aa01ee2019-04-27 19:36:49 +00007175 ShellState *pState, /* Shell state object */
7176 int *pRc, /* IN/OUT: Error code */
7177 int iRoot, /* Root page of table */
7178 int bIntkey, /* True for an intkey table */
7179 int nCol, /* Number of columns in table */
7180 int *pbNoop /* OUT: True if iRoot is root of index */
dan68cb86e2019-04-20 20:57:28 +00007181){
danb40af492019-04-22 20:52:12 +00007182 sqlite3_stmt *pStmt = 0;
dan68cb86e2019-04-20 20:57:28 +00007183 RecoverTable *pRet = 0;
danb40af492019-04-22 20:52:12 +00007184 int bNoop = 0;
7185 const char *zSql = 0;
7186 const char *zName = 0;
dan68cb86e2019-04-20 20:57:28 +00007187
danb40af492019-04-22 20:52:12 +00007188 /* Search the recovered schema for an object with root page iRoot. */
7189 shellPreparePrintf(pState->db, pRc, &pStmt,
7190 "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot
7191 );
7192 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7193 const char *zType = (const char*)sqlite3_column_text(pStmt, 0);
7194 if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){
7195 bNoop = 1;
7196 break;
7197 }
7198 if( sqlite3_stricmp(zType, "table")==0 ){
7199 zName = (const char*)sqlite3_column_text(pStmt, 1);
7200 zSql = (const char*)sqlite3_column_text(pStmt, 2);
drh621a5e02021-12-16 17:35:27 +00007201 if( zName!=0 && zSql!=0 ){
7202 pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol);
7203 break;
7204 }
danb40af492019-04-22 20:52:12 +00007205 }
7206 }
dan98c5ad32019-04-26 21:11:37 +00007207
danb40af492019-04-22 20:52:12 +00007208 shellFinalize(pRc, pStmt);
dan98c5ad32019-04-26 21:11:37 +00007209 *pbNoop = bNoop;
7210 return pRet;
7211}
danb40af492019-04-22 20:52:12 +00007212
dan0aa01ee2019-04-27 19:36:49 +00007213/*
7214** Return a RecoverTable object representing the orphans table.
7215*/
dan98c5ad32019-04-26 21:11:37 +00007216static RecoverTable *recoverOrphanTable(
dan0aa01ee2019-04-27 19:36:49 +00007217 ShellState *pState, /* Shell state object */
7218 int *pRc, /* IN/OUT: Error code */
7219 const char *zLostAndFound, /* Base name for orphans table */
7220 int nCol /* Number of user data columns */
dan98c5ad32019-04-26 21:11:37 +00007221){
7222 RecoverTable *pTab = 0;
7223 if( nCol>=0 && *pRc==SQLITE_OK ){
7224 int i;
dan42ebb012019-04-27 18:47:03 +00007225
7226 /* This block determines the name of the orphan table. The prefered
7227 ** name is zLostAndFound. But if that clashes with another name
7228 ** in the recovered schema, try zLostAndFound_0, zLostAndFound_1
7229 ** and so on until a non-clashing name is found. */
7230 int iTab = 0;
7231 char *zTab = shellMPrintf(pRc, "%s", zLostAndFound);
7232 sqlite3_stmt *pTest = 0;
7233 shellPrepare(pState->db, pRc,
7234 "SELECT 1 FROM recovery.schema WHERE name=?", &pTest
dan68cb86e2019-04-20 20:57:28 +00007235 );
dan42ebb012019-04-27 18:47:03 +00007236 if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
7237 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){
7238 shellReset(pRc, pTest);
7239 sqlite3_free(zTab);
7240 zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++);
7241 sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
dan68cb86e2019-04-20 20:57:28 +00007242 }
dan42ebb012019-04-27 18:47:03 +00007243 shellFinalize(pRc, pTest);
dan68cb86e2019-04-20 20:57:28 +00007244
dan98c5ad32019-04-26 21:11:37 +00007245 pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
7246 if( pTab ){
drha2de66c2019-08-06 20:26:17 +00007247 pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab);
dan98c5ad32019-04-26 21:11:37 +00007248 pTab->nCol = nCol;
7249 pTab->iPk = -2;
7250 if( nCol>0 ){
7251 pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1));
7252 if( pTab->azlCol ){
7253 pTab->azlCol[nCol] = shellMPrintf(pRc, "");
7254 for(i=nCol-1; i>=0; i--){
7255 pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]);
7256 }
7257 }
danb40af492019-04-22 20:52:12 +00007258 }
dan68cb86e2019-04-20 20:57:28 +00007259
dan42ebb012019-04-27 18:47:03 +00007260 if( *pRc!=SQLITE_OK ){
7261 recoverFreeTable(pTab);
7262 pTab = 0;
7263 }else{
7264 raw_printf(pState->out,
7265 "CREATE TABLE %s(rootpgno INTEGER, "
7266 "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted
7267 );
7268 for(i=0; i<nCol; i++){
7269 raw_printf(pState->out, ", c%d", i);
7270 }
7271 raw_printf(pState->out, ");\n");
7272 }
dan98c5ad32019-04-26 21:11:37 +00007273 }
dan42ebb012019-04-27 18:47:03 +00007274 sqlite3_free(zTab);
dan68cb86e2019-04-20 20:57:28 +00007275 }
dan98c5ad32019-04-26 21:11:37 +00007276 return pTab;
dan68cb86e2019-04-20 20:57:28 +00007277}
7278
7279/*
7280** This function is called to recover data from the database. A script
7281** to construct a new database containing all recovered data is output
7282** on stream pState->out.
7283*/
danb9b71db2019-04-25 16:20:40 +00007284static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
dan68cb86e2019-04-20 20:57:28 +00007285 int rc = SQLITE_OK;
7286 sqlite3_stmt *pLoop = 0; /* Loop through all root pages */
danefa363b2019-04-24 20:48:55 +00007287 sqlite3_stmt *pPages = 0; /* Loop through all pages in a group */
7288 sqlite3_stmt *pCells = 0; /* Loop through all cells in a page */
danc0b42432019-04-26 15:14:53 +00007289 const char *zRecoveryDb = ""; /* Name of "recovery" database */
dan42ebb012019-04-27 18:47:03 +00007290 const char *zLostAndFound = "lost_and_found";
dan9c014f82019-04-25 19:23:15 +00007291 int i;
dan98c5ad32019-04-26 21:11:37 +00007292 int nOrphan = -1;
7293 RecoverTable *pOrphan = 0;
dan9c014f82019-04-25 19:23:15 +00007294
7295 int bFreelist = 1; /* 0 if --freelist-corrupt is specified */
dan8cce6b82019-09-14 16:44:51 +00007296 int bRowids = 1; /* 0 if --no-rowids */
dan9c014f82019-04-25 19:23:15 +00007297 for(i=1; i<nArg; i++){
7298 char *z = azArg[i];
7299 int n;
7300 if( z[0]=='-' && z[1]=='-' ) z++;
drh4245e042019-06-13 13:52:46 +00007301 n = strlen30(z);
dan9c014f82019-04-25 19:23:15 +00007302 if( n<=17 && memcmp("-freelist-corrupt", z, n)==0 ){
7303 bFreelist = 0;
dan42ebb012019-04-27 18:47:03 +00007304 }else
danc0b42432019-04-26 15:14:53 +00007305 if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
7306 i++;
7307 zRecoveryDb = azArg[i];
dan42ebb012019-04-27 18:47:03 +00007308 }else
7309 if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
7310 i++;
7311 zLostAndFound = azArg[i];
dan8cce6b82019-09-14 16:44:51 +00007312 }else
7313 if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
7314 bRowids = 0;
danc0b42432019-04-26 15:14:53 +00007315 }
dan9c014f82019-04-25 19:23:15 +00007316 else{
drhe2754c12019-08-26 12:50:01 +00007317 utf8_printf(stderr, "unexpected option: %s\n", azArg[i]);
7318 showHelp(pState->out, azArg[0]);
dan9c014f82019-04-25 19:23:15 +00007319 return 1;
7320 }
7321 }
dan68cb86e2019-04-20 20:57:28 +00007322
danc0b42432019-04-26 15:14:53 +00007323 shellExecPrintf(pState->db, &rc,
dan68cb86e2019-04-20 20:57:28 +00007324 /* Attach an in-memory database named 'recovery'. Create an indexed
7325 ** cache of the sqlite_dbptr virtual table. */
dan01c08bc2019-07-24 19:20:30 +00007326 "PRAGMA writable_schema = on;"
danc0b42432019-04-26 15:14:53 +00007327 "ATTACH %Q AS recovery;"
7328 "DROP TABLE IF EXISTS recovery.dbptr;"
7329 "DROP TABLE IF EXISTS recovery.freelist;"
7330 "DROP TABLE IF EXISTS recovery.map;"
7331 "DROP TABLE IF EXISTS recovery.schema;"
danc0b42432019-04-26 15:14:53 +00007332 "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb
dan9c014f82019-04-25 19:23:15 +00007333 );
7334
7335 if( bFreelist ){
7336 shellExec(pState->db, &rc,
7337 "WITH trunk(pgno) AS ("
7338 " SELECT shell_int32("
7339 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x "
7340 " WHERE x>0"
7341 " UNION"
7342 " SELECT shell_int32("
7343 " (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x "
7344 " FROM trunk WHERE x>0"
7345 "),"
7346 "freelist(data, n, freepgno) AS ("
danf6099e92019-05-09 16:57:39 +00007347 " SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno "
dan9c014f82019-04-25 19:23:15 +00007348 " FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno"
7349 " UNION ALL"
7350 " SELECT data, n-1, shell_int32(data, 2+n) "
7351 " FROM freelist WHERE n>=0"
7352 ")"
7353 "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;"
7354 );
7355 }
7356
dan95063c22019-07-24 08:15:09 +00007357 /* If this is an auto-vacuum database, add all pointer-map pages to
7358 ** the freelist table. Do this regardless of whether or not
7359 ** --freelist-corrupt was specified. */
7360 shellExec(pState->db, &rc,
7361 "WITH ptrmap(pgno) AS ("
7362 " SELECT 2 WHERE shell_int32("
7363 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 13"
7364 " )"
7365 " UNION ALL "
7366 " SELECT pgno+1+(SELECT page_size FROM pragma_page_size)/5 AS pp "
7367 " FROM ptrmap WHERE pp<=(SELECT page_count FROM pragma_page_count)"
7368 ")"
7369 "REPLACE INTO recovery.freelist SELECT pgno FROM ptrmap"
7370 );
7371
dan9c014f82019-04-25 19:23:15 +00007372 shellExec(pState->db, &rc,
danca424382019-04-26 15:40:27 +00007373 "CREATE TABLE recovery.dbptr("
7374 " pgno, child, PRIMARY KEY(child, pgno)"
7375 ") WITHOUT ROWID;"
7376 "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) "
7377 " SELECT * FROM sqlite_dbptr"
7378 " WHERE pgno NOT IN freelist AND child NOT IN freelist;"
7379
7380 /* Delete any pointer to page 1. This ensures that page 1 is considered
7381 ** a root page, regardless of how corrupt the db is. */
7382 "DELETE FROM recovery.dbptr WHERE child = 1;"
7383
7384 /* Delete all pointers to any pages that have more than one pointer
7385 ** to them. Such pages will be treated as root pages when recovering
7386 ** data. */
7387 "DELETE FROM recovery.dbptr WHERE child IN ("
7388 " SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1"
7389 ");"
7390
dan68cb86e2019-04-20 20:57:28 +00007391 /* Create the "map" table that will (eventually) contain instructions
7392 ** for dealing with each page in the db that contains one or more
7393 ** records. */
danb40af492019-04-22 20:52:12 +00007394 "CREATE TABLE recovery.map("
7395 "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT"
7396 ");"
dan68cb86e2019-04-20 20:57:28 +00007397
7398 /* Populate table [map]. If there are circular loops of pages in the
7399 ** database, the following adds all pages in such a loop to the map
7400 ** as individual root pages. This could be handled better. */
7401 "WITH pages(i, maxlen) AS ("
danb9b71db2019-04-25 16:20:40 +00007402 " SELECT page_count, ("
7403 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count"
dan13b87672019-05-09 11:45:21 +00007404 " ) FROM pragma_page_count WHERE page_count>0"
dan68cb86e2019-04-20 20:57:28 +00007405 " UNION ALL"
danb40af492019-04-22 20:52:12 +00007406 " SELECT i-1, ("
7407 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1"
7408 " ) FROM pages WHERE i>=2"
dan68cb86e2019-04-20 20:57:28 +00007409 ")"
danb40af492019-04-22 20:52:12 +00007410 "INSERT INTO recovery.map(pgno, maxlen, intkey, root) "
7411 " SELECT i, maxlen, NULL, ("
dan68cb86e2019-04-20 20:57:28 +00007412 " WITH p(orig, pgno, parent) AS ("
7413 " SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)"
dan39e04f82019-05-09 18:33:32 +00007414 " UNION "
dan68cb86e2019-04-20 20:57:28 +00007415 " SELECT i, p.parent, "
7416 " (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p"
7417 " )"
7418 " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
7419 ") "
dand790c9a2019-08-26 14:57:58 +00007420 "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;"
danb40af492019-04-22 20:52:12 +00007421 "UPDATE recovery.map AS o SET intkey = ("
7422 " SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
7423 ");"
dan68cb86e2019-04-20 20:57:28 +00007424
7425 /* Extract data from page 1 and any linked pages into table
drh067b92b2020-06-19 15:24:12 +00007426 ** recovery.schema. With the same schema as an sqlite_schema table. */
dan68cb86e2019-04-20 20:57:28 +00007427 "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
7428 "INSERT INTO recovery.schema SELECT "
7429 " max(CASE WHEN field=0 THEN value ELSE NULL END),"
7430 " max(CASE WHEN field=1 THEN value ELSE NULL END),"
7431 " max(CASE WHEN field=2 THEN value ELSE NULL END),"
7432 " max(CASE WHEN field=3 THEN value ELSE NULL END),"
7433 " max(CASE WHEN field=4 THEN value ELSE NULL END)"
7434 "FROM sqlite_dbdata WHERE pgno IN ("
7435 " SELECT pgno FROM recovery.map WHERE root=1"
7436 ")"
7437 "GROUP BY pgno, cell;"
dan98c5ad32019-04-26 21:11:37 +00007438 "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);"
dan68cb86e2019-04-20 20:57:28 +00007439 );
7440
danb40af492019-04-22 20:52:12 +00007441 /* Open a transaction, then print out all non-virtual, non-"sqlite_%"
7442 ** CREATE TABLE statements that extracted from the existing schema. */
7443 if( rc==SQLITE_OK ){
7444 sqlite3_stmt *pStmt = 0;
danf3210572019-08-06 18:40:36 +00007445 /* ".recover" might output content in an order which causes immediate
7446 ** foreign key constraints to be violated. So disable foreign-key
7447 ** constraint enforcement to prevent problems when running the output
7448 ** script. */
7449 raw_printf(pState->out, "PRAGMA foreign_keys=OFF;\n");
danb40af492019-04-22 20:52:12 +00007450 raw_printf(pState->out, "BEGIN;\n");
dan38f9c712019-04-23 18:03:02 +00007451 raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
7452 shellPrepare(pState->db, &rc,
danb40af492019-04-22 20:52:12 +00007453 "SELECT sql FROM recovery.schema "
dan38f9c712019-04-23 18:03:02 +00007454 "WHERE type='table' AND sql LIKE 'create table%'", &pStmt
danb40af492019-04-22 20:52:12 +00007455 );
7456 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7457 const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0);
dan38f9c712019-04-23 18:03:02 +00007458 raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n",
7459 &zCreateTable[12]
7460 );
danb40af492019-04-22 20:52:12 +00007461 }
7462 shellFinalize(&rc, pStmt);
7463 }
7464
dan98c5ad32019-04-26 21:11:37 +00007465 /* Figure out if an orphan table will be required. And if so, how many
7466 ** user columns it should contain */
7467 shellPrepare(pState->db, &rc,
dan98779652019-05-09 14:15:19 +00007468 "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1"
dan98c5ad32019-04-26 21:11:37 +00007469 , &pLoop
7470 );
7471 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
7472 nOrphan = sqlite3_column_int(pLoop, 0);
7473 }
7474 shellFinalize(&rc, pLoop);
7475 pLoop = 0;
dan98c5ad32019-04-26 21:11:37 +00007476
danefa363b2019-04-24 20:48:55 +00007477 shellPrepare(pState->db, &rc,
7478 "SELECT pgno FROM recovery.map WHERE root=?", &pPages
7479 );
dan8cce6b82019-09-14 16:44:51 +00007480
danefa363b2019-04-24 20:48:55 +00007481 shellPrepare(pState->db, &rc,
dan8cce6b82019-09-14 16:44:51 +00007482 "SELECT max(field), group_concat(shell_escape_crnl(quote"
7483 "(case when (? AND field<0) then NULL else value end)"
7484 "), ', ')"
dan9443dbc2019-07-24 20:10:27 +00007485 ", min(field) "
danefa363b2019-04-24 20:48:55 +00007486 "FROM sqlite_dbdata WHERE pgno = ? AND field != ?"
7487 "GROUP BY cell", &pCells
7488 );
7489
dan68cb86e2019-04-20 20:57:28 +00007490 /* Loop through each root page. */
danb40af492019-04-22 20:52:12 +00007491 shellPrepare(pState->db, &rc,
7492 "SELECT root, intkey, max(maxlen) FROM recovery.map"
dan38f9c712019-04-23 18:03:02 +00007493 " WHERE root>1 GROUP BY root, intkey ORDER BY root=("
7494 " SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'"
7495 ")", &pLoop
danb40af492019-04-22 20:52:12 +00007496 );
dan68cb86e2019-04-20 20:57:28 +00007497 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
7498 int iRoot = sqlite3_column_int(pLoop, 0);
danb40af492019-04-22 20:52:12 +00007499 int bIntkey = sqlite3_column_int(pLoop, 1);
7500 int nCol = sqlite3_column_int(pLoop, 2);
dan98c5ad32019-04-26 21:11:37 +00007501 int bNoop = 0;
dan68cb86e2019-04-20 20:57:28 +00007502 RecoverTable *pTab;
7503
dan9443dbc2019-07-24 20:10:27 +00007504 assert( bIntkey==0 || bIntkey==1 );
dan42ebb012019-04-27 18:47:03 +00007505 pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);
dan98c5ad32019-04-26 21:11:37 +00007506 if( bNoop || rc ) continue;
dan98779652019-05-09 14:15:19 +00007507 if( pTab==0 ){
7508 if( pOrphan==0 ){
7509 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
7510 }
7511 pTab = pOrphan;
7512 if( pTab==0 ) break;
7513 }
dan98c5ad32019-04-26 21:11:37 +00007514
drha2de66c2019-08-06 20:26:17 +00007515 if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){
dan98c5ad32019-04-26 21:11:37 +00007516 raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
7517 }
7518 sqlite3_bind_int(pPages, 1, iRoot);
dan8cce6b82019-09-14 16:44:51 +00007519 if( bRowids==0 && pTab->iPk<0 ){
7520 sqlite3_bind_int(pCells, 1, 1);
7521 }else{
7522 sqlite3_bind_int(pCells, 1, 0);
7523 }
7524 sqlite3_bind_int(pCells, 3, pTab->iPk);
dan98c5ad32019-04-26 21:11:37 +00007525
7526 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){
7527 int iPgno = sqlite3_column_int(pPages, 0);
dan8cce6b82019-09-14 16:44:51 +00007528 sqlite3_bind_int(pCells, 2, iPgno);
dan98c5ad32019-04-26 21:11:37 +00007529 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){
7530 int nField = sqlite3_column_int(pCells, 0);
dan9443dbc2019-07-24 20:10:27 +00007531 int iMin = sqlite3_column_int(pCells, 2);
dan98c5ad32019-04-26 21:11:37 +00007532 const char *zVal = (const char*)sqlite3_column_text(pCells, 1);
7533
dan9443dbc2019-07-24 20:10:27 +00007534 RecoverTable *pTab2 = pTab;
7535 if( pTab!=pOrphan && (iMin<0)!=bIntkey ){
7536 if( pOrphan==0 ){
7537 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
7538 }
7539 pTab2 = pOrphan;
7540 if( pTab2==0 ) break;
7541 }
7542
dan98c5ad32019-04-26 21:11:37 +00007543 nField = nField+1;
dan9443dbc2019-07-24 20:10:27 +00007544 if( pTab2==pOrphan ){
dan98c5ad32019-04-26 21:11:37 +00007545 raw_printf(pState->out,
7546 "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",
dan9443dbc2019-07-24 20:10:27 +00007547 pTab2->zQuoted, iRoot, iPgno, nField,
7548 iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField]
dan98c5ad32019-04-26 21:11:37 +00007549 );
7550 }else{
danefa363b2019-04-24 20:48:55 +00007551 raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n",
dan9443dbc2019-07-24 20:10:27 +00007552 pTab2->zQuoted, pTab2->azlCol[nField], zVal
danefa363b2019-04-24 20:48:55 +00007553 );
7554 }
dan68cb86e2019-04-20 20:57:28 +00007555 }
dan98c5ad32019-04-26 21:11:37 +00007556 shellReset(&rc, pCells);
dan68cb86e2019-04-20 20:57:28 +00007557 }
dan98c5ad32019-04-26 21:11:37 +00007558 shellReset(&rc, pPages);
7559 if( pTab!=pOrphan ) recoverFreeTable(pTab);
dan68cb86e2019-04-20 20:57:28 +00007560 }
7561 shellFinalize(&rc, pLoop);
danefa363b2019-04-24 20:48:55 +00007562 shellFinalize(&rc, pPages);
7563 shellFinalize(&rc, pCells);
dan98c5ad32019-04-26 21:11:37 +00007564 recoverFreeTable(pOrphan);
dan68cb86e2019-04-20 20:57:28 +00007565
dan38f9c712019-04-23 18:03:02 +00007566 /* The rest of the schema */
danb40af492019-04-22 20:52:12 +00007567 if( rc==SQLITE_OK ){
dan38f9c712019-04-23 18:03:02 +00007568 sqlite3_stmt *pStmt = 0;
7569 shellPrepare(pState->db, &rc,
7570 "SELECT sql, name FROM recovery.schema "
danb1825882019-04-23 20:48:32 +00007571 "WHERE sql NOT LIKE 'create table%'", &pStmt
dan38f9c712019-04-23 18:03:02 +00007572 );
7573 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7574 const char *zSql = (const char*)sqlite3_column_text(pStmt, 0);
7575 if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){
7576 const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
7577 char *zPrint = shellMPrintf(&rc,
drh067b92b2020-06-19 15:24:12 +00007578 "INSERT INTO sqlite_schema VALUES('table', %Q, %Q, 0, %Q)",
dan38f9c712019-04-23 18:03:02 +00007579 zName, zName, zSql
7580 );
7581 raw_printf(pState->out, "%s;\n", zPrint);
7582 sqlite3_free(zPrint);
7583 }else{
7584 raw_printf(pState->out, "%s;\n", zSql);
7585 }
7586 }
7587 shellFinalize(&rc, pStmt);
7588 }
7589
7590 if( rc==SQLITE_OK ){
7591 raw_printf(pState->out, "PRAGMA writable_schema = off;\n");
danb40af492019-04-22 20:52:12 +00007592 raw_printf(pState->out, "COMMIT;\n");
7593 }
dan68cb86e2019-04-20 20:57:28 +00007594 sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
7595 return rc;
7596}
dan1b162162019-04-27 20:15:15 +00007597#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
dan68cb86e2019-04-20 20:57:28 +00007598
drh2ce15c32017-07-11 13:34:40 +00007599/*
7600** If an input line begins with "." then invoke this routine to
7601** process that line.
7602**
7603** Return 1 on error, 2 to exit, and 0 otherwise.
7604*/
7605static int do_meta_command(char *zLine, ShellState *p){
7606 int h = 1;
7607 int nArg = 0;
7608 int n, c;
7609 int rc = 0;
drh5df84282019-08-17 19:45:25 +00007610 char *azArg[52];
drh2ce15c32017-07-11 13:34:40 +00007611
dan6b046be2018-01-09 15:25:55 +00007612#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00007613 if( p->expert.pExpert ){
7614 expertFinish(p, 1, 0);
7615 }
dan6b046be2018-01-09 15:25:55 +00007616#endif
dan43efc182017-12-19 17:42:13 +00007617
drh2ce15c32017-07-11 13:34:40 +00007618 /* Parse the input line into tokens.
7619 */
drh5df84282019-08-17 19:45:25 +00007620 while( zLine[h] && nArg<ArraySize(azArg)-1 ){
drh2ce15c32017-07-11 13:34:40 +00007621 while( IsSpace(zLine[h]) ){ h++; }
7622 if( zLine[h]==0 ) break;
7623 if( zLine[h]=='\'' || zLine[h]=='"' ){
7624 int delim = zLine[h++];
7625 azArg[nArg++] = &zLine[h];
7626 while( zLine[h] && zLine[h]!=delim ){
7627 if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
7628 h++;
7629 }
7630 if( zLine[h]==delim ){
7631 zLine[h++] = 0;
7632 }
7633 if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
7634 }else{
7635 azArg[nArg++] = &zLine[h];
7636 while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
7637 if( zLine[h] ) zLine[h++] = 0;
7638 resolve_backslashes(azArg[nArg-1]);
7639 }
7640 }
drh5df84282019-08-17 19:45:25 +00007641 azArg[nArg] = 0;
drh2ce15c32017-07-11 13:34:40 +00007642
7643 /* Process the input line.
7644 */
7645 if( nArg==0 ) return 0; /* no tokens, no error */
7646 n = strlen30(azArg[0]);
7647 c = azArg[0][0];
drh13c20932018-01-10 21:41:55 +00007648 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +00007649
7650#ifndef SQLITE_OMIT_AUTHORIZATION
7651 if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
7652 if( nArg!=2 ){
7653 raw_printf(stderr, "Usage: .auth ON|OFF\n");
7654 rc = 1;
7655 goto meta_command_exit;
7656 }
7657 open_db(p, 0);
7658 if( booleanValue(azArg[1]) ){
7659 sqlite3_set_authorizer(p->db, shellAuth, p);
drhb97e2ad2021-08-26 18:31:39 +00007660 }else if( p->bSafeModePersist ){
7661 sqlite3_set_authorizer(p->db, safeModeAuth, p);
drh2ce15c32017-07-11 13:34:40 +00007662 }else{
7663 sqlite3_set_authorizer(p->db, 0, 0);
7664 }
7665 }else
7666#endif
7667
drhe37c0e12018-01-06 19:19:50 +00007668#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
7669 if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
danfd0245d2017-12-07 15:44:29 +00007670 open_db(p, 0);
drhb97e2ad2021-08-26 18:31:39 +00007671 failIfSafeMode(p, "cannot run .archive in safe mode");
drhd0f9cdc2018-05-17 14:09:06 +00007672 rc = arDotCommand(p, 0, azArg, nArg);
danfd0245d2017-12-07 15:44:29 +00007673 }else
7674#endif
7675
drh2ce15c32017-07-11 13:34:40 +00007676 if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
7677 || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
7678 ){
7679 const char *zDestFile = 0;
7680 const char *zDb = 0;
7681 sqlite3 *pDest;
7682 sqlite3_backup *pBackup;
7683 int j;
drha50bffb2018-12-08 01:09:14 +00007684 int bAsync = 0;
drh69ed38a2018-05-14 00:23:08 +00007685 const char *zVfs = 0;
drhb97e2ad2021-08-26 18:31:39 +00007686 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00007687 for(j=1; j<nArg; j++){
7688 const char *z = azArg[j];
7689 if( z[0]=='-' ){
drh69ed38a2018-05-14 00:23:08 +00007690 if( z[1]=='-' ) z++;
7691 if( strcmp(z, "-append")==0 ){
7692 zVfs = "apndvfs";
7693 }else
drha50bffb2018-12-08 01:09:14 +00007694 if( strcmp(z, "-async")==0 ){
7695 bAsync = 1;
7696 }else
drh2ce15c32017-07-11 13:34:40 +00007697 {
7698 utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
7699 return 1;
7700 }
7701 }else if( zDestFile==0 ){
7702 zDestFile = azArg[j];
7703 }else if( zDb==0 ){
7704 zDb = zDestFile;
7705 zDestFile = azArg[j];
7706 }else{
drha50bffb2018-12-08 01:09:14 +00007707 raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
drh2ce15c32017-07-11 13:34:40 +00007708 return 1;
7709 }
7710 }
7711 if( zDestFile==0 ){
7712 raw_printf(stderr, "missing FILENAME argument on .backup\n");
7713 return 1;
7714 }
7715 if( zDb==0 ) zDb = "main";
drh69ed38a2018-05-14 00:23:08 +00007716 rc = sqlite3_open_v2(zDestFile, &pDest,
7717 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
drh2ce15c32017-07-11 13:34:40 +00007718 if( rc!=SQLITE_OK ){
7719 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
drh9e804032018-05-18 17:11:50 +00007720 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007721 return 1;
7722 }
drha50bffb2018-12-08 01:09:14 +00007723 if( bAsync ){
7724 sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
7725 0, 0, 0);
7726 }
drh2ce15c32017-07-11 13:34:40 +00007727 open_db(p, 0);
7728 pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
7729 if( pBackup==0 ){
7730 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
drh9e804032018-05-18 17:11:50 +00007731 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007732 return 1;
7733 }
7734 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
7735 sqlite3_backup_finish(pBackup);
7736 if( rc==SQLITE_DONE ){
7737 rc = 0;
7738 }else{
7739 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
7740 rc = 1;
7741 }
drh9e804032018-05-18 17:11:50 +00007742 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007743 }else
7744
7745 if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
7746 if( nArg==2 ){
7747 bail_on_error = booleanValue(azArg[1]);
7748 }else{
7749 raw_printf(stderr, "Usage: .bail on|off\n");
7750 rc = 1;
7751 }
7752 }else
7753
7754 if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
7755 if( nArg==2 ){
7756 if( booleanValue(azArg[1]) ){
7757 setBinaryMode(p->out, 1);
7758 }else{
7759 setTextMode(p->out, 1);
7760 }
7761 }else{
7762 raw_printf(stderr, "Usage: .binary on|off\n");
7763 rc = 1;
7764 }
7765 }else
7766
drh37407122021-07-23 18:43:58 +00007767 /* The undocumented ".breakpoint" command causes a call to the no-op
7768 ** routine named test_breakpoint().
7769 */
7770 if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
7771 test_breakpoint();
7772 }else
7773
drh2ce15c32017-07-11 13:34:40 +00007774 if( c=='c' && strcmp(azArg[0],"cd")==0 ){
drhb97e2ad2021-08-26 18:31:39 +00007775 failIfSafeMode(p, "cannot run .cd in safe mode");
drh2ce15c32017-07-11 13:34:40 +00007776 if( nArg==2 ){
7777#if defined(_WIN32) || defined(WIN32)
7778 wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
7779 rc = !SetCurrentDirectoryW(z);
7780 sqlite3_free(z);
7781#else
7782 rc = chdir(azArg[1]);
7783#endif
7784 if( rc ){
7785 utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
7786 rc = 1;
7787 }
7788 }else{
7789 raw_printf(stderr, "Usage: .cd DIRECTORY\n");
7790 rc = 1;
7791 }
7792 }else
7793
drh2ce15c32017-07-11 13:34:40 +00007794 if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
7795 if( nArg==2 ){
7796 setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
7797 }else{
7798 raw_printf(stderr, "Usage: .changes on|off\n");
7799 rc = 1;
7800 }
7801 }else
7802
7803 /* Cancel output redirection, if it is currently set (by .testcase)
7804 ** Then read the content of the testcase-out.txt file and compare against
7805 ** azArg[1]. If there are differences, report an error and exit.
7806 */
7807 if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
7808 char *zRes = 0;
7809 output_reset(p);
7810 if( nArg!=2 ){
7811 raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
7812 rc = 2;
7813 }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
7814 raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
7815 rc = 2;
7816 }else if( testcase_glob(azArg[1],zRes)==0 ){
7817 utf8_printf(stderr,
7818 "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
7819 p->zTestcase, azArg[1], zRes);
drhf30d3452017-10-17 13:44:46 +00007820 rc = 1;
drh2ce15c32017-07-11 13:34:40 +00007821 }else{
7822 utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
7823 p->nCheck++;
7824 }
7825 sqlite3_free(zRes);
7826 }else
7827
7828 if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
drhb97e2ad2021-08-26 18:31:39 +00007829 failIfSafeMode(p, "cannot run .clone in safe mode");
drh2ce15c32017-07-11 13:34:40 +00007830 if( nArg==2 ){
7831 tryToClone(p, azArg[1]);
7832 }else{
7833 raw_printf(stderr, "Usage: .clone FILENAME\n");
7834 rc = 1;
7835 }
7836 }else
7837
drh37407122021-07-23 18:43:58 +00007838 if( c=='c' && strncmp(azArg[0], "connection", n)==0 ){
7839 if( nArg==1 ){
7840 /* List available connections */
7841 int i;
7842 for(i=0; i<ArraySize(p->aAuxDb); i++){
7843 const char *zFile = p->aAuxDb[i].zDbFilename;
7844 if( p->aAuxDb[i].db==0 && p->pAuxDb!=&p->aAuxDb[i] ){
7845 zFile = "(not open)";
7846 }else if( zFile==0 ){
7847 zFile = "(memory)";
7848 }else if( zFile[0]==0 ){
7849 zFile = "(temporary-file)";
7850 }
7851 if( p->pAuxDb == &p->aAuxDb[i] ){
7852 utf8_printf(stdout, "ACTIVE %d: %s\n", i, zFile);
7853 }else if( p->aAuxDb[i].db!=0 ){
7854 utf8_printf(stdout, " %d: %s\n", i, zFile);
7855 }
7856 }
7857 }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){
7858 int i = azArg[1][0] - '0';
7859 if( p->pAuxDb != &p->aAuxDb[i] && i>=0 && i<ArraySize(p->aAuxDb) ){
7860 p->pAuxDb->db = p->db;
7861 p->pAuxDb = &p->aAuxDb[i];
7862 globalDb = p->db = p->pAuxDb->db;
7863 p->pAuxDb->db = 0;
7864 }
7865 }else if( nArg==3 && strcmp(azArg[1], "close")==0
7866 && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){
7867 int i = azArg[2][0] - '0';
7868 if( i<0 || i>=ArraySize(p->aAuxDb) ){
7869 /* No-op */
7870 }else if( p->pAuxDb == &p->aAuxDb[i] ){
7871 raw_printf(stderr, "cannot close the active database connection\n");
7872 rc = 1;
7873 }else if( p->aAuxDb[i].db ){
7874 session_close_all(p, i);
7875 close_db(p->aAuxDb[i].db);
7876 p->aAuxDb[i].db = 0;
7877 }
7878 }else{
7879 raw_printf(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n");
7880 rc = 1;
7881 }
7882 }else
7883
drh2ce15c32017-07-11 13:34:40 +00007884 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
drh60081a02020-08-26 19:07:18 +00007885 char **azName = 0;
7886 int nName = 0;
7887 sqlite3_stmt *pStmt;
drh60081a02020-08-26 19:07:18 +00007888 int i;
drh2ce15c32017-07-11 13:34:40 +00007889 open_db(p, 0);
drh60081a02020-08-26 19:07:18 +00007890 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
7891 if( rc ){
7892 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh2ce15c32017-07-11 13:34:40 +00007893 rc = 1;
drh60081a02020-08-26 19:07:18 +00007894 }else{
7895 while( sqlite3_step(pStmt)==SQLITE_ROW ){
7896 const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
7897 const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
drh621a5e02021-12-16 17:35:27 +00007898 if( zSchema==0 || zFile==0 ) continue;
drh60081a02020-08-26 19:07:18 +00007899 azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
drhe3e25652021-12-16 13:29:28 +00007900 shell_check_oom(azName);
drh60081a02020-08-26 19:07:18 +00007901 azName[nName*2] = strdup(zSchema);
7902 azName[nName*2+1] = strdup(zFile);
7903 nName++;
7904 }
drh2ce15c32017-07-11 13:34:40 +00007905 }
drh60081a02020-08-26 19:07:18 +00007906 sqlite3_finalize(pStmt);
7907 for(i=0; i<nName; i++){
7908 int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
7909 int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
7910 const char *z = azName[i*2+1];
7911 utf8_printf(p->out, "%s: %s %s%s\n",
7912 azName[i*2],
7913 z && z[0] ? z : "\"\"",
7914 bRdonly ? "r/o" : "r/w",
7915 eTxn==SQLITE_TXN_NONE ? "" :
7916 eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
7917 free(azName[i*2]);
7918 free(azName[i*2+1]);
7919 }
7920 sqlite3_free(azName);
drh2ce15c32017-07-11 13:34:40 +00007921 }else
7922
drh7df01192018-04-28 12:43:16 +00007923 if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
drheb7f2a02018-09-26 18:02:32 +00007924 static const struct DbConfigChoices {
7925 const char *zName;
7926 int op;
7927 } aDbConfig[] = {
drhb945bcd2019-12-31 22:52:10 +00007928 { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
7929 { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL },
7930 { "dqs_dml", SQLITE_DBCONFIG_DQS_DML },
drh0a6873b2019-06-14 21:25:25 +00007931 { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
drhb945bcd2019-12-31 22:52:10 +00007932 { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
drh0a6873b2019-06-14 21:25:25 +00007933 { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
drh11d88e62019-08-15 21:27:20 +00007934 { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
drh0a6873b2019-06-14 21:25:25 +00007935 { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
drhb945bcd2019-12-31 22:52:10 +00007936 { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
7937 { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
drh0a6873b2019-06-14 21:25:25 +00007938 { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
7939 { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
drh0a6873b2019-06-14 21:25:25 +00007940 { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
drhb945bcd2019-12-31 22:52:10 +00007941 { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
drhb77da372020-01-07 16:09:11 +00007942 { "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA },
dan07312a62019-06-21 14:05:27 +00007943 { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA },
drh7df01192018-04-28 12:43:16 +00007944 };
7945 int ii, v;
7946 open_db(p, 0);
7947 for(ii=0; ii<ArraySize(aDbConfig); ii++){
7948 if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
7949 if( nArg>=3 ){
7950 sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
7951 }
7952 sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
drhb945bcd2019-12-31 22:52:10 +00007953 utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
drh7df01192018-04-28 12:43:16 +00007954 if( nArg>1 ) break;
7955 }
7956 if( nArg>1 && ii==ArraySize(aDbConfig) ){
7957 utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
7958 utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
7959 }
7960 }else
7961
7962 if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00007963 rc = shell_dbinfo_command(p, nArg, azArg);
7964 }else
7965
dan1b162162019-04-27 20:15:15 +00007966#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00007967 if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){
7968 open_db(p, 0);
danb9b71db2019-04-25 16:20:40 +00007969 rc = recoverDatabaseCmd(p, nArg, azArg);
dan68cb86e2019-04-20 20:57:28 +00007970 }else
dan1b162162019-04-27 20:15:15 +00007971#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
dan68cb86e2019-04-20 20:57:28 +00007972
drh2ce15c32017-07-11 13:34:40 +00007973 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
drh8e9297f2020-03-25 12:50:13 +00007974 char *zLike = 0;
7975 char *zSql;
drh2ce15c32017-07-11 13:34:40 +00007976 int i;
7977 int savedShowHeader = p->showHeader;
drhf213b332018-07-05 17:35:46 +00007978 int savedShellFlags = p->shellFlgs;
drhc1962192020-10-12 16:54:28 +00007979 ShellClearFlag(p,
7980 SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
7981 |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
drh2ce15c32017-07-11 13:34:40 +00007982 for(i=1; i<nArg; i++){
7983 if( azArg[i][0]=='-' ){
7984 const char *z = azArg[i]+1;
7985 if( z[0]=='-' ) z++;
7986 if( strcmp(z,"preserve-rowids")==0 ){
7987#ifdef SQLITE_OMIT_VIRTUALTABLE
7988 raw_printf(stderr, "The --preserve-rowids option is not compatible"
7989 " with SQLITE_OMIT_VIRTUALTABLE\n");
7990 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00007991 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00007992 goto meta_command_exit;
7993#else
7994 ShellSetFlag(p, SHFLG_PreserveRowid);
7995#endif
7996 }else
7997 if( strcmp(z,"newlines")==0 ){
7998 ShellSetFlag(p, SHFLG_Newlines);
7999 }else
drhc1962192020-10-12 16:54:28 +00008000 if( strcmp(z,"data-only")==0 ){
8001 ShellSetFlag(p, SHFLG_DumpDataOnly);
8002 }else
8003 if( strcmp(z,"nosys")==0 ){
8004 ShellSetFlag(p, SHFLG_DumpNoSys);
8005 }else
drh2ce15c32017-07-11 13:34:40 +00008006 {
8007 raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
8008 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00008009 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00008010 goto meta_command_exit;
8011 }
drh2ce15c32017-07-11 13:34:40 +00008012 }else{
dan78a9d752021-05-25 11:39:14 +00008013 /* azArg[i] contains a LIKE pattern. This ".dump" request should
8014 ** only dump data for tables for which either the table name matches
8015 ** the LIKE pattern, or the table appears to be a shadow table of
8016 ** a virtual table for which the name matches the LIKE pattern.
8017 */
8018 char *zExpr = sqlite3_mprintf(
8019 "name LIKE %Q ESCAPE '\\' OR EXISTS ("
8020 " SELECT 1 FROM sqlite_schema WHERE "
8021 " name LIKE %Q ESCAPE '\\' AND"
8022 " sql LIKE 'CREATE VIRTUAL TABLE%%' AND"
8023 " substr(o.name, 1, length(name)+1) == (name||'_')"
8024 ")", azArg[i], azArg[i]
8025 );
8026
8027 if( zLike ){
8028 zLike = sqlite3_mprintf("%z OR %z", zLike, zExpr);
8029 }else{
8030 zLike = zExpr;
8031 }
drh2ce15c32017-07-11 13:34:40 +00008032 }
8033 }
dan68cb86e2019-04-20 20:57:28 +00008034
drh2ce15c32017-07-11 13:34:40 +00008035 open_db(p, 0);
dan68cb86e2019-04-20 20:57:28 +00008036
drhc1962192020-10-12 16:54:28 +00008037 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
8038 /* When playing back a "dump", the content might appear in an order
8039 ** which causes immediate foreign key constraints to be violated.
8040 ** So disable foreign-key constraint enforcement to prevent problems. */
8041 raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
8042 raw_printf(p->out, "BEGIN TRANSACTION;\n");
8043 }
drh2ce15c32017-07-11 13:34:40 +00008044 p->writableSchema = 0;
8045 p->showHeader = 0;
8046 /* Set writable_schema=ON since doing so forces SQLite to initialize
drh067b92b2020-06-19 15:24:12 +00008047 ** as much of the schema as it can even if the sqlite_schema table is
drh2ce15c32017-07-11 13:34:40 +00008048 ** corrupt. */
8049 sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
8050 p->nErr = 0;
drh8e9297f2020-03-25 12:50:13 +00008051 if( zLike==0 ) zLike = sqlite3_mprintf("true");
8052 zSql = sqlite3_mprintf(
dan78a9d752021-05-25 11:39:14 +00008053 "SELECT name, type, sql FROM sqlite_schema AS o "
drh8e9297f2020-03-25 12:50:13 +00008054 "WHERE (%s) AND type=='table'"
8055 " AND sql NOT NULL"
8056 " ORDER BY tbl_name='sqlite_sequence', rowid",
8057 zLike
8058 );
8059 run_schema_dump_query(p,zSql);
8060 sqlite3_free(zSql);
drhc1962192020-10-12 16:54:28 +00008061 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
8062 zSql = sqlite3_mprintf(
dan78a9d752021-05-25 11:39:14 +00008063 "SELECT sql FROM sqlite_schema AS o "
drhc1962192020-10-12 16:54:28 +00008064 "WHERE (%s) AND sql NOT NULL"
8065 " AND type IN ('index','trigger','view')",
8066 zLike
8067 );
8068 run_table_dump_query(p, zSql);
8069 sqlite3_free(zSql);
8070 }
drh8e9297f2020-03-25 12:50:13 +00008071 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00008072 if( p->writableSchema ){
8073 raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
8074 p->writableSchema = 0;
8075 }
8076 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
8077 sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
drhc1962192020-10-12 16:54:28 +00008078 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
8079 raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
8080 }
drh2ce15c32017-07-11 13:34:40 +00008081 p->showHeader = savedShowHeader;
drhf213b332018-07-05 17:35:46 +00008082 p->shellFlgs = savedShellFlags;
drh2ce15c32017-07-11 13:34:40 +00008083 }else
8084
8085 if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
8086 if( nArg==2 ){
8087 setOrClearFlag(p, SHFLG_Echo, azArg[1]);
8088 }else{
8089 raw_printf(stderr, "Usage: .echo on|off\n");
8090 rc = 1;
8091 }
8092 }else
8093
8094 if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
8095 if( nArg==2 ){
drhe2ca99c2018-05-02 00:33:43 +00008096 p->autoEQPtest = 0;
drhb4e50392019-01-26 15:40:04 +00008097 if( p->autoEQPtrace ){
8098 if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
8099 p->autoEQPtrace = 0;
8100 }
drh2ce15c32017-07-11 13:34:40 +00008101 if( strcmp(azArg[1],"full")==0 ){
drhada70452017-12-21 21:02:27 +00008102 p->autoEQP = AUTOEQP_full;
8103 }else if( strcmp(azArg[1],"trigger")==0 ){
8104 p->autoEQP = AUTOEQP_trigger;
drhb4e50392019-01-26 15:40:04 +00008105#ifdef SQLITE_DEBUG
drhe2ca99c2018-05-02 00:33:43 +00008106 }else if( strcmp(azArg[1],"test")==0 ){
8107 p->autoEQP = AUTOEQP_on;
8108 p->autoEQPtest = 1;
drhb4e50392019-01-26 15:40:04 +00008109 }else if( strcmp(azArg[1],"trace")==0 ){
8110 p->autoEQP = AUTOEQP_full;
8111 p->autoEQPtrace = 1;
8112 open_db(p, 0);
drh067b92b2020-06-19 15:24:12 +00008113 sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0);
drhb4e50392019-01-26 15:40:04 +00008114 sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
8115#endif
drh2ce15c32017-07-11 13:34:40 +00008116 }else{
mistachkinb71aa092018-01-23 00:05:18 +00008117 p->autoEQP = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00008118 }
8119 }else{
drhb4e50392019-01-26 15:40:04 +00008120 raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
drh2ce15c32017-07-11 13:34:40 +00008121 rc = 1;
8122 }
8123 }else
8124
8125 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
8126 if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
8127 rc = 2;
8128 }else
8129
8130 /* The ".explain" command is automatic now. It is largely pointless. It
8131 ** retained purely for backwards compatibility */
8132 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
8133 int val = 1;
8134 if( nArg>=2 ){
8135 if( strcmp(azArg[1],"auto")==0 ){
8136 val = 99;
8137 }else{
8138 val = booleanValue(azArg[1]);
8139 }
8140 }
8141 if( val==1 && p->mode!=MODE_Explain ){
8142 p->normalMode = p->mode;
8143 p->mode = MODE_Explain;
8144 p->autoExplain = 0;
8145 }else if( val==0 ){
8146 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
8147 p->autoExplain = 0;
8148 }else if( val==99 ){
8149 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
8150 p->autoExplain = 1;
8151 }
8152 }else
8153
dan6b046be2018-01-09 15:25:55 +00008154#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00008155 if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
drhfe463172021-12-16 17:57:21 +00008156 if( p->bSafeMode ){
8157 raw_printf(stderr,
8158 "Cannot run experimental commands such as \"%s\" in safe mode\n",
8159 azArg[0]);
8160 rc = 1;
8161 }else{
8162 open_db(p, 0);
8163 expertDotCommand(p, azArg, nArg);
8164 }
dan43efc182017-12-19 17:42:13 +00008165 }else
dan6b046be2018-01-09 15:25:55 +00008166#endif
dan43efc182017-12-19 17:42:13 +00008167
drhd985f722019-06-05 14:29:53 +00008168 if( c=='f' && strncmp(azArg[0], "filectrl", n)==0 ){
8169 static const struct {
8170 const char *zCtrlName; /* Name of a test-control option */
8171 int ctrlCode; /* Integer code for that option */
8172 const char *zUsage; /* Usage notes */
8173 } aCtrl[] = {
drhd985f722019-06-05 14:29:53 +00008174 { "chunk_size", SQLITE_FCNTL_CHUNK_SIZE, "SIZE" },
drh18a4bbd2020-12-17 15:17:42 +00008175 { "data_version", SQLITE_FCNTL_DATA_VERSION, "" },
drhd985f722019-06-05 14:29:53 +00008176 { "has_moved", SQLITE_FCNTL_HAS_MOVED, "" },
8177 { "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" },
drh18a4bbd2020-12-17 15:17:42 +00008178 { "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" },
8179 /* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/
8180 { "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" },
drh541ef2c2020-04-20 16:21:30 +00008181 { "reserve_bytes", SQLITE_FCNTL_RESERVE_BYTES, "[N]" },
drh18a4bbd2020-12-17 15:17:42 +00008182 { "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" },
8183 { "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" },
8184 /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/
drhd985f722019-06-05 14:29:53 +00008185 };
8186 int filectrl = -1;
8187 int iCtrl = -1;
drh4245e042019-06-13 13:52:46 +00008188 sqlite3_int64 iRes = 0; /* Integer result to display if rc2==1 */
8189 int isOk = 0; /* 0: usage 1: %lld 2: no-result */
drhd985f722019-06-05 14:29:53 +00008190 int n2, i;
8191 const char *zCmd = 0;
drh541ef2c2020-04-20 16:21:30 +00008192 const char *zSchema = 0;
drhd985f722019-06-05 14:29:53 +00008193
8194 open_db(p, 0);
8195 zCmd = nArg>=2 ? azArg[1] : "help";
8196
drh541ef2c2020-04-20 16:21:30 +00008197 if( zCmd[0]=='-'
8198 && (strcmp(zCmd,"--schema")==0 || strcmp(zCmd,"-schema")==0)
8199 && nArg>=4
8200 ){
8201 zSchema = azArg[2];
8202 for(i=3; i<nArg; i++) azArg[i-2] = azArg[i];
8203 nArg -= 2;
8204 zCmd = azArg[1];
8205 }
8206
drhd985f722019-06-05 14:29:53 +00008207 /* The argument can optionally begin with "-" or "--" */
8208 if( zCmd[0]=='-' && zCmd[1] ){
8209 zCmd++;
8210 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
8211 }
8212
8213 /* --help lists all file-controls */
8214 if( strcmp(zCmd,"help")==0 ){
8215 utf8_printf(p->out, "Available file-controls:\n");
8216 for(i=0; i<ArraySize(aCtrl); i++){
8217 utf8_printf(p->out, " .filectrl %s %s\n",
8218 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
8219 }
8220 rc = 1;
8221 goto meta_command_exit;
8222 }
8223
8224 /* convert filectrl text option to value. allow any unique prefix
8225 ** of the option name, or a numerical value. */
8226 n2 = strlen30(zCmd);
8227 for(i=0; i<ArraySize(aCtrl); i++){
8228 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
8229 if( filectrl<0 ){
8230 filectrl = aCtrl[i].ctrlCode;
8231 iCtrl = i;
8232 }else{
8233 utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n"
8234 "Use \".filectrl --help\" for help\n", zCmd);
8235 rc = 1;
8236 goto meta_command_exit;
8237 }
8238 }
8239 }
8240 if( filectrl<0 ){
8241 utf8_printf(stderr,"Error: unknown file-control: %s\n"
8242 "Use \".filectrl --help\" for help\n", zCmd);
8243 }else{
8244 switch(filectrl){
8245 case SQLITE_FCNTL_SIZE_LIMIT: {
8246 if( nArg!=2 && nArg!=3 ) break;
8247 iRes = nArg==3 ? integerValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00008248 sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
drhd985f722019-06-05 14:29:53 +00008249 isOk = 1;
8250 break;
8251 }
8252 case SQLITE_FCNTL_LOCK_TIMEOUT:
8253 case SQLITE_FCNTL_CHUNK_SIZE: {
8254 int x;
8255 if( nArg!=3 ) break;
8256 x = (int)integerValue(azArg[2]);
drh541ef2c2020-04-20 16:21:30 +00008257 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008258 isOk = 2;
8259 break;
8260 }
8261 case SQLITE_FCNTL_PERSIST_WAL:
8262 case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
8263 int x;
8264 if( nArg!=2 && nArg!=3 ) break;
8265 x = nArg==3 ? booleanValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00008266 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008267 iRes = x;
8268 isOk = 1;
8269 break;
8270 }
drh18a4bbd2020-12-17 15:17:42 +00008271 case SQLITE_FCNTL_DATA_VERSION:
drhd985f722019-06-05 14:29:53 +00008272 case SQLITE_FCNTL_HAS_MOVED: {
8273 int x;
8274 if( nArg!=2 ) break;
drh541ef2c2020-04-20 16:21:30 +00008275 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008276 iRes = x;
8277 isOk = 1;
8278 break;
8279 }
8280 case SQLITE_FCNTL_TEMPFILENAME: {
8281 char *z = 0;
8282 if( nArg!=2 ) break;
drh541ef2c2020-04-20 16:21:30 +00008283 sqlite3_file_control(p->db, zSchema, filectrl, &z);
drhd985f722019-06-05 14:29:53 +00008284 if( z ){
8285 utf8_printf(p->out, "%s\n", z);
8286 sqlite3_free(z);
8287 }
8288 isOk = 2;
8289 break;
8290 }
drh541ef2c2020-04-20 16:21:30 +00008291 case SQLITE_FCNTL_RESERVE_BYTES: {
8292 int x;
8293 if( nArg>=3 ){
8294 x = atoi(azArg[2]);
8295 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8296 }
8297 x = -1;
8298 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8299 utf8_printf(p->out,"%d\n", x);
8300 isOk = 2;
8301 break;
8302 }
drhd985f722019-06-05 14:29:53 +00008303 }
8304 }
8305 if( isOk==0 && iCtrl>=0 ){
8306 utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
8307 rc = 1;
8308 }else if( isOk==1 ){
drhe2500762019-06-13 14:07:41 +00008309 char zBuf[100];
8310 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
8311 raw_printf(p->out, "%s\n", zBuf);
drhd985f722019-06-05 14:29:53 +00008312 }
8313 }else
8314
drh2ce15c32017-07-11 13:34:40 +00008315 if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
8316 ShellState data;
drh2ce15c32017-07-11 13:34:40 +00008317 int doStats = 0;
8318 memcpy(&data, p, sizeof(data));
8319 data.showHeader = 0;
8320 data.cMode = data.mode = MODE_Semi;
8321 if( nArg==2 && optionMatch(azArg[1], "indent") ){
8322 data.cMode = data.mode = MODE_Pretty;
8323 nArg = 1;
8324 }
8325 if( nArg!=1 ){
8326 raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
8327 rc = 1;
8328 goto meta_command_exit;
8329 }
8330 open_db(p, 0);
8331 rc = sqlite3_exec(p->db,
8332 "SELECT sql FROM"
8333 " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
drh067b92b2020-06-19 15:24:12 +00008334 " FROM sqlite_schema UNION ALL"
8335 " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
drh2ce15c32017-07-11 13:34:40 +00008336 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
drh69935c02021-06-25 11:14:10 +00008337 "ORDER BY x",
drhf83d5012021-05-03 13:35:00 +00008338 callback, &data, 0
drh2ce15c32017-07-11 13:34:40 +00008339 );
8340 if( rc==SQLITE_OK ){
8341 sqlite3_stmt *pStmt;
8342 rc = sqlite3_prepare_v2(p->db,
drh067b92b2020-06-19 15:24:12 +00008343 "SELECT rowid FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00008344 " WHERE name GLOB 'sqlite_stat[134]'",
8345 -1, &pStmt, 0);
8346 doStats = sqlite3_step(pStmt)==SQLITE_ROW;
8347 sqlite3_finalize(pStmt);
8348 }
8349 if( doStats==0 ){
8350 raw_printf(p->out, "/* No STAT tables available */\n");
8351 }else{
drh067b92b2020-06-19 15:24:12 +00008352 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00008353 data.cMode = data.mode = MODE_Insert;
8354 data.zDestTable = "sqlite_stat1";
drhf83d5012021-05-03 13:35:00 +00008355 shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
drh2ce15c32017-07-11 13:34:40 +00008356 data.zDestTable = "sqlite_stat4";
drhf83d5012021-05-03 13:35:00 +00008357 shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
drh067b92b2020-06-19 15:24:12 +00008358 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00008359 }
8360 }else
8361
8362 if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
8363 if( nArg==2 ){
8364 p->showHeader = booleanValue(azArg[1]);
drhc0605082020-06-05 00:54:27 +00008365 p->shellFlgs |= SHFLG_HeaderSet;
drh2ce15c32017-07-11 13:34:40 +00008366 }else{
8367 raw_printf(stderr, "Usage: .headers on|off\n");
8368 rc = 1;
8369 }
8370 }else
8371
8372 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
drh98aa2ab2018-09-26 16:53:51 +00008373 if( nArg>=2 ){
drhe93f8262018-10-11 16:53:37 +00008374 n = showHelp(p->out, azArg[1]);
drh98aa2ab2018-09-26 16:53:51 +00008375 if( n==0 ){
8376 utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
8377 }
8378 }else{
8379 showHelp(p->out, 0);
8380 }
drh2ce15c32017-07-11 13:34:40 +00008381 }else
8382
8383 if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
drhccb37812020-03-09 15:39:39 +00008384 char *zTable = 0; /* Insert data into this table */
8385 char *zFile = 0; /* Name of file to extra content from */
drh2ce15c32017-07-11 13:34:40 +00008386 sqlite3_stmt *pStmt = NULL; /* A statement */
8387 int nCol; /* Number of columns in the table */
8388 int nByte; /* Number of bytes in an SQL string */
8389 int i, j; /* Loop counters */
8390 int needCommit; /* True to COMMIT or ROLLBACK at end */
8391 int nSep; /* Number of bytes in p->colSeparator[] */
8392 char *zSql; /* An SQL statement */
8393 ImportCtx sCtx; /* Reader context */
8394 char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
drhccb37812020-03-09 15:39:39 +00008395 int eVerbose = 0; /* Larger for more console output */
8396 int nSkip = 0; /* Initial lines to skip */
8397 int useOutputMode = 1; /* Use output mode to determine separators */
drh2ce15c32017-07-11 13:34:40 +00008398
drhb97e2ad2021-08-26 18:31:39 +00008399 failIfSafeMode(p, "cannot run .import in safe mode");
drhccb37812020-03-09 15:39:39 +00008400 memset(&sCtx, 0, sizeof(sCtx));
larrybr6ac9a5c2021-10-28 19:49:23 +00008401 sCtx.z = sqlite3_malloc64(120);
8402 if( sCtx.z==0 ){
8403 import_cleanup(&sCtx);
8404 shell_out_of_memory();
8405 }
drhccb37812020-03-09 15:39:39 +00008406 if( p->mode==MODE_Ascii ){
8407 xRead = ascii_read_one_field;
8408 }else{
8409 xRead = csv_read_one_field;
8410 }
8411 for(i=1; i<nArg; i++){
8412 char *z = azArg[i];
8413 if( z[0]=='-' && z[1]=='-' ) z++;
8414 if( z[0]!='-' ){
8415 if( zFile==0 ){
8416 zFile = z;
8417 }else if( zTable==0 ){
8418 zTable = z;
8419 }else{
8420 utf8_printf(p->out, "ERROR: extra argument: \"%s\". Usage:\n", z);
8421 showHelp(p->out, "import");
8422 rc = 1;
8423 goto meta_command_exit;
8424 }
8425 }else if( strcmp(z,"-v")==0 ){
8426 eVerbose++;
8427 }else if( strcmp(z,"-skip")==0 && i<nArg-1 ){
8428 nSkip = integerValue(azArg[++i]);
8429 }else if( strcmp(z,"-ascii")==0 ){
8430 sCtx.cColSep = SEP_Unit[0];
8431 sCtx.cRowSep = SEP_Record[0];
8432 xRead = ascii_read_one_field;
8433 useOutputMode = 0;
8434 }else if( strcmp(z,"-csv")==0 ){
8435 sCtx.cColSep = ',';
8436 sCtx.cRowSep = '\n';
8437 xRead = csv_read_one_field;
8438 useOutputMode = 0;
8439 }else{
8440 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", z);
8441 showHelp(p->out, "import");
8442 rc = 1;
8443 goto meta_command_exit;
8444 }
8445 }
8446 if( zTable==0 ){
8447 utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
8448 zFile==0 ? "FILE" : "TABLE");
8449 showHelp(p->out, "import");
8450 rc = 1;
drh2ce15c32017-07-11 13:34:40 +00008451 goto meta_command_exit;
8452 }
drh2ce15c32017-07-11 13:34:40 +00008453 seenInterrupt = 0;
drh2ce15c32017-07-11 13:34:40 +00008454 open_db(p, 0);
drhccb37812020-03-09 15:39:39 +00008455 if( useOutputMode ){
8456 /* If neither the --csv or --ascii options are specified, then set
8457 ** the column and row separator characters from the output mode. */
8458 nSep = strlen30(p->colSeparator);
8459 if( nSep==0 ){
8460 raw_printf(stderr,
8461 "Error: non-null column separator required for import\n");
8462 rc = 1;
8463 goto meta_command_exit;
8464 }
8465 if( nSep>1 ){
8466 raw_printf(stderr,
8467 "Error: multi-character column separators not allowed"
8468 " for import\n");
8469 rc = 1;
8470 goto meta_command_exit;
8471 }
drh2ce15c32017-07-11 13:34:40 +00008472 nSep = strlen30(p->rowSeparator);
drhccb37812020-03-09 15:39:39 +00008473 if( nSep==0 ){
8474 raw_printf(stderr,
8475 "Error: non-null row separator required for import\n");
8476 rc = 1;
8477 goto meta_command_exit;
8478 }
8479 if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator,SEP_CrLf)==0 ){
8480 /* When importing CSV (only), if the row separator is set to the
8481 ** default output row separator, change it to the default input
8482 ** row separator. This avoids having to maintain different input
8483 ** and output row separators. */
8484 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8485 nSep = strlen30(p->rowSeparator);
8486 }
8487 if( nSep>1 ){
8488 raw_printf(stderr, "Error: multi-character row separators not allowed"
8489 " for import\n");
8490 rc = 1;
8491 goto meta_command_exit;
8492 }
8493 sCtx.cColSep = p->colSeparator[0];
8494 sCtx.cRowSep = p->rowSeparator[0];
drh2ce15c32017-07-11 13:34:40 +00008495 }
8496 sCtx.zFile = zFile;
8497 sCtx.nLine = 1;
8498 if( sCtx.zFile[0]=='|' ){
8499#ifdef SQLITE_OMIT_POPEN
8500 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
drhccb37812020-03-09 15:39:39 +00008501 rc = 1;
8502 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008503#else
8504 sCtx.in = popen(sCtx.zFile+1, "r");
8505 sCtx.zFile = "<pipe>";
drh97767842020-05-29 19:39:35 +00008506 sCtx.xCloser = pclose;
drh2ce15c32017-07-11 13:34:40 +00008507#endif
8508 }else{
8509 sCtx.in = fopen(sCtx.zFile, "rb");
drh97767842020-05-29 19:39:35 +00008510 sCtx.xCloser = fclose;
drh2ce15c32017-07-11 13:34:40 +00008511 }
drh2ce15c32017-07-11 13:34:40 +00008512 if( sCtx.in==0 ){
8513 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
drhccb37812020-03-09 15:39:39 +00008514 rc = 1;
dan07ed9c12021-11-02 14:01:41 +00008515 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008516 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008517 }
drhccb37812020-03-09 15:39:39 +00008518 if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
8519 char zSep[2];
8520 zSep[1] = 0;
8521 zSep[0] = sCtx.cColSep;
8522 utf8_printf(p->out, "Column separator ");
8523 output_c_string(p->out, zSep);
8524 utf8_printf(p->out, ", row separator ");
8525 zSep[0] = sCtx.cRowSep;
8526 output_c_string(p->out, zSep);
8527 utf8_printf(p->out, "\n");
8528 }
8529 while( (nSkip--)>0 ){
8530 while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
drhccb37812020-03-09 15:39:39 +00008531 }
drhc6712642020-10-12 17:57:29 +00008532 zSql = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
drh2ce15c32017-07-11 13:34:40 +00008533 if( zSql==0 ){
drh97767842020-05-29 19:39:35 +00008534 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00008535 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00008536 }
8537 nByte = strlen30(zSql);
8538 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8539 import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
8540 if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
drhc6712642020-10-12 17:57:29 +00008541 char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"", zTable);
drh2ce15c32017-07-11 13:34:40 +00008542 char cSep = '(';
8543 while( xRead(&sCtx) ){
8544 zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z);
8545 cSep = ',';
8546 if( sCtx.cTerm!=sCtx.cColSep ) break;
8547 }
8548 if( cSep=='(' ){
8549 sqlite3_free(zCreate);
drh97767842020-05-29 19:39:35 +00008550 import_cleanup(&sCtx);
drh2ce15c32017-07-11 13:34:40 +00008551 utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
drhccb37812020-03-09 15:39:39 +00008552 rc = 1;
8553 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008554 }
8555 zCreate = sqlite3_mprintf("%z\n)", zCreate);
drhccb37812020-03-09 15:39:39 +00008556 if( eVerbose>=1 ){
8557 utf8_printf(p->out, "%s\n", zCreate);
8558 }
drh2ce15c32017-07-11 13:34:40 +00008559 rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
8560 sqlite3_free(zCreate);
8561 if( rc ){
drhc6712642020-10-12 17:57:29 +00008562 utf8_printf(stderr, "CREATE TABLE \"%s\"(...) failed: %s\n", zTable,
drh2ce15c32017-07-11 13:34:40 +00008563 sqlite3_errmsg(p->db));
drh97767842020-05-29 19:39:35 +00008564 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008565 rc = 1;
8566 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008567 }
8568 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8569 }
8570 sqlite3_free(zSql);
8571 if( rc ){
8572 if (pStmt) sqlite3_finalize(pStmt);
8573 utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
drh97767842020-05-29 19:39:35 +00008574 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008575 rc = 1;
8576 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008577 }
8578 nCol = sqlite3_column_count(pStmt);
8579 sqlite3_finalize(pStmt);
8580 pStmt = 0;
8581 if( nCol==0 ) return 0; /* no columns, no error */
8582 zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
8583 if( zSql==0 ){
drh97767842020-05-29 19:39:35 +00008584 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00008585 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00008586 }
8587 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
8588 j = strlen30(zSql);
8589 for(i=1; i<nCol; i++){
8590 zSql[j++] = ',';
8591 zSql[j++] = '?';
8592 }
8593 zSql[j++] = ')';
8594 zSql[j] = 0;
drhccb37812020-03-09 15:39:39 +00008595 if( eVerbose>=2 ){
8596 utf8_printf(p->out, "Insert using: %s\n", zSql);
8597 }
drh2ce15c32017-07-11 13:34:40 +00008598 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8599 sqlite3_free(zSql);
8600 if( rc ){
8601 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
8602 if (pStmt) sqlite3_finalize(pStmt);
drh97767842020-05-29 19:39:35 +00008603 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008604 rc = 1;
8605 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008606 }
8607 needCommit = sqlite3_get_autocommit(p->db);
8608 if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
8609 do{
8610 int startLine = sCtx.nLine;
8611 for(i=0; i<nCol; i++){
8612 char *z = xRead(&sCtx);
8613 /*
8614 ** Did we reach end-of-file before finding any columns?
8615 ** If so, stop instead of NULL filling the remaining columns.
8616 */
8617 if( z==0 && i==0 ) break;
8618 /*
8619 ** Did we reach end-of-file OR end-of-line before finding any
8620 ** columns in ASCII mode? If so, stop instead of NULL filling
8621 ** the remaining columns.
8622 */
8623 if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
8624 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
8625 if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
8626 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
8627 "filling the rest with NULL\n",
8628 sCtx.zFile, startLine, nCol, i+1);
8629 i += 2;
8630 while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
8631 }
8632 }
8633 if( sCtx.cTerm==sCtx.cColSep ){
8634 do{
8635 xRead(&sCtx);
8636 i++;
8637 }while( sCtx.cTerm==sCtx.cColSep );
8638 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
8639 "extras ignored\n",
8640 sCtx.zFile, startLine, nCol, i);
8641 }
8642 if( i>=nCol ){
8643 sqlite3_step(pStmt);
8644 rc = sqlite3_reset(pStmt);
8645 if( rc!=SQLITE_OK ){
8646 utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
8647 startLine, sqlite3_errmsg(p->db));
drhccb37812020-03-09 15:39:39 +00008648 sCtx.nErr++;
8649 }else{
8650 sCtx.nRow++;
drh2ce15c32017-07-11 13:34:40 +00008651 }
8652 }
8653 }while( sCtx.cTerm!=EOF );
8654
drh97767842020-05-29 19:39:35 +00008655 import_cleanup(&sCtx);
drh2ce15c32017-07-11 13:34:40 +00008656 sqlite3_finalize(pStmt);
8657 if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
drhccb37812020-03-09 15:39:39 +00008658 if( eVerbose>0 ){
8659 utf8_printf(p->out,
8660 "Added %d rows with %d errors using %d lines of input\n",
8661 sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
8662 }
drh2ce15c32017-07-11 13:34:40 +00008663 }else
8664
8665#ifndef SQLITE_UNTESTABLE
8666 if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
8667 char *zSql;
8668 char *zCollist = 0;
8669 sqlite3_stmt *pStmt;
8670 int tnum = 0;
drh491c5be2019-10-18 15:58:50 +00008671 int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */
8672 int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
drh2ce15c32017-07-11 13:34:40 +00008673 int i;
drh48d219a2018-04-23 18:38:48 +00008674 if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
8675 utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
8676 " .imposter off\n");
drh491c5be2019-10-18 15:58:50 +00008677 /* Also allowed, but not documented:
8678 **
8679 ** .imposter TABLE IMPOSTER
8680 **
8681 ** where TABLE is a WITHOUT ROWID table. In that case, the
8682 ** imposter is another WITHOUT ROWID table with the columns in
8683 ** storage order. */
drh2ce15c32017-07-11 13:34:40 +00008684 rc = 1;
8685 goto meta_command_exit;
8686 }
8687 open_db(p, 0);
drh48d219a2018-04-23 18:38:48 +00008688 if( nArg==2 ){
8689 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
8690 goto meta_command_exit;
8691 }
drh491c5be2019-10-18 15:58:50 +00008692 zSql = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00008693 "SELECT rootpage, 0 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00008694 " WHERE name='%q' AND type='index'"
8695 "UNION ALL "
drh067b92b2020-06-19 15:24:12 +00008696 "SELECT rootpage, 1 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00008697 " WHERE name='%q' AND type='table'"
8698 " AND sql LIKE '%%without%%rowid%%'",
8699 azArg[1], azArg[1]
8700 );
drh2ce15c32017-07-11 13:34:40 +00008701 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8702 sqlite3_free(zSql);
8703 if( sqlite3_step(pStmt)==SQLITE_ROW ){
8704 tnum = sqlite3_column_int(pStmt, 0);
drh491c5be2019-10-18 15:58:50 +00008705 isWO = sqlite3_column_int(pStmt, 1);
drh2ce15c32017-07-11 13:34:40 +00008706 }
8707 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00008708 zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
8709 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8710 sqlite3_free(zSql);
8711 i = 0;
drhe85e1da2021-10-01 21:01:07 +00008712 while( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00008713 char zLabel[20];
8714 const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
8715 i++;
8716 if( zCol==0 ){
8717 if( sqlite3_column_int(pStmt,1)==-1 ){
8718 zCol = "_ROWID_";
8719 }else{
8720 sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
8721 zCol = zLabel;
8722 }
8723 }
drh491c5be2019-10-18 15:58:50 +00008724 if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){
8725 lenPK = (int)strlen(zCollist);
8726 }
drh2ce15c32017-07-11 13:34:40 +00008727 if( zCollist==0 ){
8728 zCollist = sqlite3_mprintf("\"%w\"", zCol);
8729 }else{
8730 zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
8731 }
8732 }
8733 sqlite3_finalize(pStmt);
drh491c5be2019-10-18 15:58:50 +00008734 if( i==0 || tnum==0 ){
8735 utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
8736 rc = 1;
8737 sqlite3_free(zCollist);
8738 goto meta_command_exit;
8739 }
8740 if( lenPK==0 ) lenPK = 100000;
drh2ce15c32017-07-11 13:34:40 +00008741 zSql = sqlite3_mprintf(
drh491c5be2019-10-18 15:58:50 +00008742 "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
8743 azArg[2], zCollist, lenPK, zCollist);
drh2ce15c32017-07-11 13:34:40 +00008744 sqlite3_free(zCollist);
8745 rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
8746 if( rc==SQLITE_OK ){
8747 rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
8748 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
8749 if( rc ){
8750 utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
8751 }else{
8752 utf8_printf(stdout, "%s;\n", zSql);
8753 raw_printf(stdout,
drh491c5be2019-10-18 15:58:50 +00008754 "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
8755 azArg[1], isWO ? "table" : "index"
drh2ce15c32017-07-11 13:34:40 +00008756 );
8757 }
8758 }else{
8759 raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
8760 rc = 1;
8761 }
8762 sqlite3_free(zSql);
8763 }else
8764#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
8765
8766#ifdef SQLITE_ENABLE_IOTRACE
8767 if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
8768 SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
8769 if( iotrace && iotrace!=stdout ) fclose(iotrace);
8770 iotrace = 0;
8771 if( nArg<2 ){
8772 sqlite3IoTrace = 0;
8773 }else if( strcmp(azArg[1], "-")==0 ){
8774 sqlite3IoTrace = iotracePrintf;
8775 iotrace = stdout;
8776 }else{
8777 iotrace = fopen(azArg[1], "w");
8778 if( iotrace==0 ){
8779 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
8780 sqlite3IoTrace = 0;
8781 rc = 1;
8782 }else{
8783 sqlite3IoTrace = iotracePrintf;
8784 }
8785 }
8786 }else
8787#endif
8788
8789 if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
8790 static const struct {
8791 const char *zLimitName; /* Name of a limit */
8792 int limitCode; /* Integer code for that limit */
8793 } aLimit[] = {
8794 { "length", SQLITE_LIMIT_LENGTH },
8795 { "sql_length", SQLITE_LIMIT_SQL_LENGTH },
8796 { "column", SQLITE_LIMIT_COLUMN },
8797 { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
8798 { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
8799 { "vdbe_op", SQLITE_LIMIT_VDBE_OP },
8800 { "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
8801 { "attached", SQLITE_LIMIT_ATTACHED },
8802 { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
8803 { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER },
8804 { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
8805 { "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
8806 };
8807 int i, n2;
8808 open_db(p, 0);
8809 if( nArg==1 ){
8810 for(i=0; i<ArraySize(aLimit); i++){
8811 printf("%20s %d\n", aLimit[i].zLimitName,
8812 sqlite3_limit(p->db, aLimit[i].limitCode, -1));
8813 }
8814 }else if( nArg>3 ){
8815 raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
8816 rc = 1;
8817 goto meta_command_exit;
8818 }else{
8819 int iLimit = -1;
8820 n2 = strlen30(azArg[1]);
8821 for(i=0; i<ArraySize(aLimit); i++){
8822 if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
8823 if( iLimit<0 ){
8824 iLimit = i;
8825 }else{
8826 utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
8827 rc = 1;
8828 goto meta_command_exit;
8829 }
8830 }
8831 }
8832 if( iLimit<0 ){
8833 utf8_printf(stderr, "unknown limit: \"%s\"\n"
8834 "enter \".limits\" with no arguments for a list.\n",
8835 azArg[1]);
8836 rc = 1;
8837 goto meta_command_exit;
8838 }
8839 if( nArg==3 ){
8840 sqlite3_limit(p->db, aLimit[iLimit].limitCode,
8841 (int)integerValue(azArg[2]));
8842 }
8843 printf("%20s %d\n", aLimit[iLimit].zLimitName,
8844 sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
8845 }
8846 }else
8847
8848 if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
8849 open_db(p, 0);
8850 lintDotCommand(p, azArg, nArg);
8851 }else
8852
8853#ifndef SQLITE_OMIT_LOAD_EXTENSION
8854 if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
8855 const char *zFile, *zProc;
8856 char *zErrMsg = 0;
drhb97e2ad2021-08-26 18:31:39 +00008857 failIfSafeMode(p, "cannot run .load in safe mode");
drh2ce15c32017-07-11 13:34:40 +00008858 if( nArg<2 ){
8859 raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
8860 rc = 1;
8861 goto meta_command_exit;
8862 }
8863 zFile = azArg[1];
8864 zProc = nArg>=3 ? azArg[2] : 0;
8865 open_db(p, 0);
8866 rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
8867 if( rc!=SQLITE_OK ){
8868 utf8_printf(stderr, "Error: %s\n", zErrMsg);
8869 sqlite3_free(zErrMsg);
8870 rc = 1;
8871 }
8872 }else
8873#endif
8874
8875 if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
drhb97e2ad2021-08-26 18:31:39 +00008876 failIfSafeMode(p, "cannot run .log in safe mode");
drh2ce15c32017-07-11 13:34:40 +00008877 if( nArg!=2 ){
8878 raw_printf(stderr, "Usage: .log FILENAME\n");
8879 rc = 1;
8880 }else{
8881 const char *zFile = azArg[1];
8882 output_file_close(p->pLog);
drha92a01a2018-01-10 22:15:37 +00008883 p->pLog = output_file_open(zFile, 0);
drh2ce15c32017-07-11 13:34:40 +00008884 }
8885 }else
8886
8887 if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
8888 const char *zMode = nArg>=2 ? azArg[1] : "";
drhaf2770f2018-01-05 14:55:43 +00008889 int n2 = strlen30(zMode);
drh2ce15c32017-07-11 13:34:40 +00008890 int c2 = zMode[0];
8891 if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){
8892 p->mode = MODE_Line;
8893 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8894 }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
8895 p->mode = MODE_Column;
drhc0605082020-06-05 00:54:27 +00008896 if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){
8897 p->showHeader = 1;
8898 }
drh2ce15c32017-07-11 13:34:40 +00008899 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8900 }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
8901 p->mode = MODE_List;
8902 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
8903 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8904 }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){
8905 p->mode = MODE_Html;
8906 }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
8907 p->mode = MODE_Tcl;
8908 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
8909 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8910 }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
8911 p->mode = MODE_Csv;
8912 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
8913 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
8914 }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
8915 p->mode = MODE_List;
8916 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
8917 }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
8918 p->mode = MODE_Insert;
8919 set_table_name(p, nArg>=3 ? azArg[2] : "table");
8920 }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
8921 p->mode = MODE_Quote;
drhc6835732020-05-28 20:37:17 +00008922 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
8923 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +00008924 }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
8925 p->mode = MODE_Ascii;
8926 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
8927 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
drh30c54a02020-05-28 23:49:50 +00008928 }else if( c2=='m' && strncmp(azArg[1],"markdown",n2)==0 ){
8929 p->mode = MODE_Markdown;
8930 }else if( c2=='t' && strncmp(azArg[1],"table",n2)==0 ){
8931 p->mode = MODE_Table;
drh0908e382020-06-04 18:05:39 +00008932 }else if( c2=='b' && strncmp(azArg[1],"box",n2)==0 ){
8933 p->mode = MODE_Box;
drh5d88be82021-12-09 16:17:43 +00008934 }else if( c2=='c' && strncmp(azArg[1],"count",n2)==0 ){
8935 p->mode = MODE_Count;
8936 }else if( c2=='o' && strncmp(azArg[1],"off",n2)==0 ){
8937 p->mode = MODE_Off;
drh30c54a02020-05-28 23:49:50 +00008938 }else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){
8939 p->mode = MODE_Json;
drh2ce15c32017-07-11 13:34:40 +00008940 }else if( nArg==1 ){
8941 raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
8942 }else{
8943 raw_printf(stderr, "Error: mode should be one of: "
drh0908e382020-06-04 18:05:39 +00008944 "ascii box column csv html insert json line list markdown "
drh30c54a02020-05-28 23:49:50 +00008945 "quote table tabs tcl\n");
drh2ce15c32017-07-11 13:34:40 +00008946 rc = 1;
8947 }
8948 p->cMode = p->mode;
8949 }else
8950
drhb97e2ad2021-08-26 18:31:39 +00008951 if( c=='n' && strcmp(azArg[0], "nonce")==0 ){
8952 if( nArg!=2 ){
8953 raw_printf(stderr, "Usage: .nonce NONCE\n");
8954 rc = 1;
8955 }else if( p->zNonce==0 || strcmp(azArg[1],p->zNonce)!=0 ){
drhfe463172021-12-16 17:57:21 +00008956 raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n",
8957 p->lineno, azArg[1]);
drhb97e2ad2021-08-26 18:31:39 +00008958 exit(1);
drhe85e1da2021-10-01 21:01:07 +00008959 }else{
8960 p->bSafeMode = 0;
8961 return 0; /* Return immediately to bypass the safe mode reset
8962 ** at the end of this procedure */
drhb97e2ad2021-08-26 18:31:39 +00008963 }
drhb97e2ad2021-08-26 18:31:39 +00008964 }else
8965
drh2ce15c32017-07-11 13:34:40 +00008966 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
8967 if( nArg==2 ){
8968 sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
8969 "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
8970 }else{
8971 raw_printf(stderr, "Usage: .nullvalue STRING\n");
8972 rc = 1;
8973 }
8974 }else
8975
8976 if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
drh61fd4b92021-12-16 14:59:25 +00008977 const char *zFN = 0; /* Pointer to constant filename */
drhf30bbce2020-12-02 18:27:48 +00008978 char *zNewFilename = 0; /* Name of the database file to open */
8979 int iName = 1; /* Index in azArg[] of the filename */
8980 int newFlag = 0; /* True to delete file before opening */
dan1872c5b2021-12-02 14:16:30 +00008981 int openMode = SHELL_OPEN_UNSPEC;
8982
drh2ce15c32017-07-11 13:34:40 +00008983 /* Check for command-line arguments */
drhf30bbce2020-12-02 18:27:48 +00008984 for(iName=1; iName<nArg; iName++){
drh2ce15c32017-07-11 13:34:40 +00008985 const char *z = azArg[iName];
8986 if( optionMatch(z,"new") ){
8987 newFlag = 1;
drh3baed312018-03-08 18:14:41 +00008988#ifdef SQLITE_HAVE_ZLIB
drh1fa6d9f2018-01-06 21:46:01 +00008989 }else if( optionMatch(z, "zip") ){
dan1872c5b2021-12-02 14:16:30 +00008990 openMode = SHELL_OPEN_ZIPFILE;
drh1fa6d9f2018-01-06 21:46:01 +00008991#endif
8992 }else if( optionMatch(z, "append") ){
dan1872c5b2021-12-02 14:16:30 +00008993 openMode = SHELL_OPEN_APPENDVFS;
drhee269a62018-02-14 23:27:43 +00008994 }else if( optionMatch(z, "readonly") ){
dan1872c5b2021-12-02 14:16:30 +00008995 openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +00008996 }else if( optionMatch(z, "nofollow") ){
8997 p->openFlags |= SQLITE_OPEN_NOFOLLOW;
drh8d889af2021-05-08 17:18:23 +00008998#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +00008999 }else if( optionMatch(z, "deserialize") ){
dan1872c5b2021-12-02 14:16:30 +00009000 openMode = SHELL_OPEN_DESERIALIZE;
drh33746482018-12-13 15:06:26 +00009001 }else if( optionMatch(z, "hexdb") ){
dan1872c5b2021-12-02 14:16:30 +00009002 openMode = SHELL_OPEN_HEXDB;
drh6ca64482019-01-22 16:06:20 +00009003 }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
9004 p->szMax = integerValue(azArg[++iName]);
drh8d889af2021-05-08 17:18:23 +00009005#endif /* SQLITE_OMIT_DESERIALIZE */
drh2ce15c32017-07-11 13:34:40 +00009006 }else if( z[0]=='-' ){
9007 utf8_printf(stderr, "unknown option: %s\n", z);
9008 rc = 1;
9009 goto meta_command_exit;
drh61fd4b92021-12-16 14:59:25 +00009010 }else if( zFN ){
drhf30bbce2020-12-02 18:27:48 +00009011 utf8_printf(stderr, "extra argument: \"%s\"\n", z);
9012 rc = 1;
9013 goto meta_command_exit;
9014 }else{
drh61fd4b92021-12-16 14:59:25 +00009015 zFN = z;
drh2ce15c32017-07-11 13:34:40 +00009016 }
9017 }
dan1872c5b2021-12-02 14:16:30 +00009018
9019 /* Close the existing database */
9020 session_close_all(p, -1);
9021 close_db(p->db);
9022 p->db = 0;
9023 p->pAuxDb->zDbFilename = 0;
9024 sqlite3_free(p->pAuxDb->zFreeOnClose);
9025 p->pAuxDb->zFreeOnClose = 0;
9026 p->openMode = openMode;
9027 p->openFlags = 0;
9028 p->szMax = 0;
9029
drh2ce15c32017-07-11 13:34:40 +00009030 /* If a filename is specified, try to open it first */
drh61fd4b92021-12-16 14:59:25 +00009031 if( zFN || p->openMode==SHELL_OPEN_HEXDB ){
drhc320e062021-12-24 19:44:11 +00009032 if( newFlag && zFN && !p->bSafeMode ) shellDeleteFile(zFN);
drhb97e2ad2021-08-26 18:31:39 +00009033 if( p->bSafeMode
9034 && p->openMode!=SHELL_OPEN_HEXDB
drhc320e062021-12-24 19:44:11 +00009035 && zFN
9036 && strcmp(zFN,":memory:")!=0
drhb97e2ad2021-08-26 18:31:39 +00009037 ){
9038 failIfSafeMode(p, "cannot open disk-based database files in safe mode");
9039 }
drh61fd4b92021-12-16 14:59:25 +00009040 if( zFN ){
9041 zNewFilename = sqlite3_mprintf("%s", zFN);
9042 shell_check_oom(zNewFilename);
9043 }else{
9044 zNewFilename = 0;
9045 }
drh37407122021-07-23 18:43:58 +00009046 p->pAuxDb->zDbFilename = zNewFilename;
drhbe4ccb22018-05-17 20:04:24 +00009047 open_db(p, OPEN_DB_KEEPALIVE);
drh2ce15c32017-07-11 13:34:40 +00009048 if( p->db==0 ){
9049 utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
9050 sqlite3_free(zNewFilename);
9051 }else{
drh37407122021-07-23 18:43:58 +00009052 p->pAuxDb->zFreeOnClose = zNewFilename;
drh2ce15c32017-07-11 13:34:40 +00009053 }
9054 }
9055 if( p->db==0 ){
9056 /* As a fall-back open a TEMP database */
drh37407122021-07-23 18:43:58 +00009057 p->pAuxDb->zDbFilename = 0;
drh2ce15c32017-07-11 13:34:40 +00009058 open_db(p, 0);
9059 }
9060 }else
9061
drh13c20932018-01-10 21:41:55 +00009062 if( (c=='o'
9063 && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
9064 || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
drh2ce15c32017-07-11 13:34:40 +00009065 ){
drh4b0229a2021-02-17 13:19:22 +00009066 char *zFile = 0;
drha92a01a2018-01-10 22:15:37 +00009067 int bTxtMode = 0;
drh7a431002020-04-18 14:12:00 +00009068 int i;
9069 int eMode = 0;
9070 int bBOM = 0;
drh5415ab42020-04-23 20:45:46 +00009071 int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */
drh7a431002020-04-18 14:12:00 +00009072
drhb97e2ad2021-08-26 18:31:39 +00009073 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh7a431002020-04-18 14:12:00 +00009074 if( c=='e' ){
9075 eMode = 'x';
9076 bOnce = 2;
9077 }else if( strncmp(azArg[0],"once",n)==0 ){
9078 bOnce = 1;
drh13c20932018-01-10 21:41:55 +00009079 }
drh7a431002020-04-18 14:12:00 +00009080 for(i=1; i<nArg; i++){
9081 char *z = azArg[i];
9082 if( z[0]=='-' ){
9083 if( z[1]=='-' ) z++;
9084 if( strcmp(z,"-bom")==0 ){
9085 bBOM = 1;
9086 }else if( c!='e' && strcmp(z,"-x")==0 ){
9087 eMode = 'x'; /* spreadsheet */
9088 }else if( c!='e' && strcmp(z,"-e")==0 ){
9089 eMode = 'e'; /* text editor */
9090 }else{
9091 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n",
9092 azArg[i]);
9093 showHelp(p->out, azArg[0]);
9094 rc = 1;
9095 goto meta_command_exit;
9096 }
drh4b0229a2021-02-17 13:19:22 +00009097 }else if( zFile==0 && eMode!='e' && eMode!='x' ){
9098 zFile = sqlite3_mprintf("%s", z);
drhe3e25652021-12-16 13:29:28 +00009099 if( zFile && zFile[0]=='|' ){
drh4b0229a2021-02-17 13:19:22 +00009100 while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]);
9101 break;
9102 }
drh7a431002020-04-18 14:12:00 +00009103 }else{
9104 utf8_printf(p->out,"ERROR: extra parameter: \"%s\". Usage:\n",
9105 azArg[i]);
9106 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00009107 rc = 1;
drh4b0229a2021-02-17 13:19:22 +00009108 sqlite3_free(zFile);
drh2ce15c32017-07-11 13:34:40 +00009109 goto meta_command_exit;
9110 }
drh7a431002020-04-18 14:12:00 +00009111 }
drhe3e25652021-12-16 13:29:28 +00009112 if( zFile==0 ){
9113 zFile = sqlite3_mprintf("stdout");
9114 }
drh7a431002020-04-18 14:12:00 +00009115 if( bOnce ){
drh2ce15c32017-07-11 13:34:40 +00009116 p->outCount = 2;
9117 }else{
9118 p->outCount = 0;
9119 }
9120 output_reset(p);
drh04a28c32018-01-31 01:38:44 +00009121#ifndef SQLITE_NOHAVE_SYSTEM
drh7a431002020-04-18 14:12:00 +00009122 if( eMode=='e' || eMode=='x' ){
drh3c484e82018-01-10 22:27:21 +00009123 p->doXdgOpen = 1;
9124 outputModePush(p);
drh7a431002020-04-18 14:12:00 +00009125 if( eMode=='x' ){
9126 /* spreadsheet mode. Output as CSV. */
drh13c20932018-01-10 21:41:55 +00009127 newTempFile(p, "csv");
drh7a431002020-04-18 14:12:00 +00009128 ShellClearFlag(p, SHFLG_Echo);
drh13c20932018-01-10 21:41:55 +00009129 p->mode = MODE_Csv;
9130 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
9131 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
9132 }else{
drh7a431002020-04-18 14:12:00 +00009133 /* text editor mode */
drh13c20932018-01-10 21:41:55 +00009134 newTempFile(p, "txt");
drha92a01a2018-01-10 22:15:37 +00009135 bTxtMode = 1;
drh13c20932018-01-10 21:41:55 +00009136 }
drh4b0229a2021-02-17 13:19:22 +00009137 sqlite3_free(zFile);
9138 zFile = sqlite3_mprintf("%s", p->zTempFile);
drh13c20932018-01-10 21:41:55 +00009139 }
drh04a28c32018-01-31 01:38:44 +00009140#endif /* SQLITE_NOHAVE_SYSTEM */
drhe3e25652021-12-16 13:29:28 +00009141 shell_check_oom(zFile);
drh2ce15c32017-07-11 13:34:40 +00009142 if( zFile[0]=='|' ){
9143#ifdef SQLITE_OMIT_POPEN
9144 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
9145 rc = 1;
9146 p->out = stdout;
9147#else
9148 p->out = popen(zFile + 1, "w");
9149 if( p->out==0 ){
9150 utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
9151 p->out = stdout;
9152 rc = 1;
9153 }else{
drh7a431002020-04-18 14:12:00 +00009154 if( bBOM ) fprintf(p->out,"\357\273\277");
drh2ce15c32017-07-11 13:34:40 +00009155 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
9156 }
9157#endif
9158 }else{
drha92a01a2018-01-10 22:15:37 +00009159 p->out = output_file_open(zFile, bTxtMode);
drh2ce15c32017-07-11 13:34:40 +00009160 if( p->out==0 ){
9161 if( strcmp(zFile,"off")!=0 ){
9162 utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
9163 }
9164 p->out = stdout;
9165 rc = 1;
9166 } else {
drh7a431002020-04-18 14:12:00 +00009167 if( bBOM ) fprintf(p->out,"\357\273\277");
drh2ce15c32017-07-11 13:34:40 +00009168 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
9169 }
9170 }
drh4b0229a2021-02-17 13:19:22 +00009171 sqlite3_free(zFile);
drh2ce15c32017-07-11 13:34:40 +00009172 }else
9173
drh9cb02642019-02-28 20:10:52 +00009174 if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
9175 open_db(p,0);
9176 if( nArg<=1 ) goto parameter_syntax_error;
9177
9178 /* .parameter clear
9179 ** Clear all bind parameters by dropping the TEMP table that holds them.
9180 */
9181 if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
drh65c29fd2019-03-25 21:56:26 +00009182 sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
drh9cb02642019-02-28 20:10:52 +00009183 0, 0, 0);
9184 }else
9185
9186 /* .parameter list
9187 ** List all bind parameters.
9188 */
9189 if( nArg==2 && strcmp(azArg[1],"list")==0 ){
9190 sqlite3_stmt *pStmt = 0;
9191 int rx;
9192 int len = 0;
9193 rx = sqlite3_prepare_v2(p->db,
9194 "SELECT max(length(key)) "
drh65c29fd2019-03-25 21:56:26 +00009195 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drh9cb02642019-02-28 20:10:52 +00009196 if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
9197 len = sqlite3_column_int(pStmt, 0);
9198 if( len>40 ) len = 40;
9199 }
9200 sqlite3_finalize(pStmt);
9201 pStmt = 0;
9202 if( len ){
9203 rx = sqlite3_prepare_v2(p->db,
9204 "SELECT key, quote(value) "
drh65c29fd2019-03-25 21:56:26 +00009205 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drhe85e1da2021-10-01 21:01:07 +00009206 while( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
drh9cb02642019-02-28 20:10:52 +00009207 utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
9208 sqlite3_column_text(pStmt,1));
9209 }
9210 sqlite3_finalize(pStmt);
9211 }
9212 }else
9213
9214 /* .parameter init
9215 ** Make sure the TEMP table used to hold bind parameters exists.
9216 ** Create it if necessary.
9217 */
9218 if( nArg==2 && strcmp(azArg[1],"init")==0 ){
9219 bind_table_init(p);
9220 }else
9221
9222 /* .parameter set NAME VALUE
9223 ** Set or reset a bind parameter. NAME should be the full parameter
9224 ** name exactly as it appears in the query. (ex: $abc, @def). The
9225 ** VALUE can be in either SQL literal notation, or if not it will be
9226 ** understood to be a text string.
9227 */
9228 if( nArg==4 && strcmp(azArg[1],"set")==0 ){
9229 int rx;
9230 char *zSql;
9231 sqlite3_stmt *pStmt;
9232 const char *zKey = azArg[2];
9233 const char *zValue = azArg[3];
9234 bind_table_init(p);
9235 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009236 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00009237 "VALUES(%Q,%s);", zKey, zValue);
drhe3e25652021-12-16 13:29:28 +00009238 shell_check_oom(zSql);
drh9cb02642019-02-28 20:10:52 +00009239 pStmt = 0;
9240 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9241 sqlite3_free(zSql);
9242 if( rx!=SQLITE_OK ){
9243 sqlite3_finalize(pStmt);
9244 pStmt = 0;
9245 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009246 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00009247 "VALUES(%Q,%Q);", zKey, zValue);
drhe3e25652021-12-16 13:29:28 +00009248 shell_check_oom(zSql);
drh9cb02642019-02-28 20:10:52 +00009249 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9250 sqlite3_free(zSql);
9251 if( rx!=SQLITE_OK ){
9252 utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
9253 sqlite3_finalize(pStmt);
9254 pStmt = 0;
9255 rc = 1;
9256 }
9257 }
9258 sqlite3_step(pStmt);
9259 sqlite3_finalize(pStmt);
9260 }else
9261
9262 /* .parameter unset NAME
9263 ** Remove the NAME binding from the parameter binding table, if it
9264 ** exists.
9265 */
9266 if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
9267 char *zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009268 "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
drhe3e25652021-12-16 13:29:28 +00009269 shell_check_oom(zSql);
drh9cb02642019-02-28 20:10:52 +00009270 sqlite3_exec(p->db, zSql, 0, 0, 0);
9271 sqlite3_free(zSql);
9272 }else
9273 /* If no command name matches, show a syntax error */
9274 parameter_syntax_error:
9275 showHelp(p->out, "parameter");
9276 }else
9277
drh2ce15c32017-07-11 13:34:40 +00009278 if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
9279 int i;
9280 for(i=1; i<nArg; i++){
9281 if( i>1 ) raw_printf(p->out, " ");
9282 utf8_printf(p->out, "%s", azArg[i]);
9283 }
9284 raw_printf(p->out, "\n");
9285 }else
9286
drh569b1d92019-02-05 20:51:41 +00009287#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh3f83f592019-02-04 14:53:18 +00009288 if( c=='p' && n>=3 && strncmp(azArg[0], "progress", n)==0 ){
9289 int i;
drhfc4eeef2019-02-05 19:48:46 +00009290 int nn = 0;
drh3f83f592019-02-04 14:53:18 +00009291 p->flgProgress = 0;
9292 p->mxProgress = 0;
9293 p->nProgress = 0;
9294 for(i=1; i<nArg; i++){
9295 const char *z = azArg[i];
9296 if( z[0]=='-' ){
9297 z++;
9298 if( z[0]=='-' ) z++;
9299 if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009300 p->flgProgress |= SHELL_PROGRESS_QUIET;
drh3f83f592019-02-04 14:53:18 +00009301 continue;
9302 }
9303 if( strcmp(z,"reset")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009304 p->flgProgress |= SHELL_PROGRESS_RESET;
drh3f83f592019-02-04 14:53:18 +00009305 continue;
9306 }
9307 if( strcmp(z,"once")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009308 p->flgProgress |= SHELL_PROGRESS_ONCE;
drh3f83f592019-02-04 14:53:18 +00009309 continue;
9310 }
9311 if( strcmp(z,"limit")==0 ){
9312 if( i+1>=nArg ){
9313 utf8_printf(stderr, "Error: missing argument on --limit\n");
9314 rc = 1;
9315 goto meta_command_exit;
9316 }else{
9317 p->mxProgress = (int)integerValue(azArg[++i]);
9318 }
9319 continue;
9320 }
9321 utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
9322 rc = 1;
9323 goto meta_command_exit;
9324 }else{
drhfc4eeef2019-02-05 19:48:46 +00009325 nn = (int)integerValue(z);
drh3f83f592019-02-04 14:53:18 +00009326 }
9327 }
9328 open_db(p, 0);
drhfc4eeef2019-02-05 19:48:46 +00009329 sqlite3_progress_handler(p->db, nn, progress_handler, p);
drh3f83f592019-02-04 14:53:18 +00009330 }else
drh569b1d92019-02-05 20:51:41 +00009331#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
drh3f83f592019-02-04 14:53:18 +00009332
drh2ce15c32017-07-11 13:34:40 +00009333 if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
9334 if( nArg >= 2) {
9335 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
9336 }
9337 if( nArg >= 3) {
9338 strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
9339 }
9340 }else
9341
9342 if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
9343 rc = 2;
9344 }else
9345
9346 if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
drh60379d42018-12-13 18:30:01 +00009347 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +00009348 int savedLineno = p->lineno;
drhb97e2ad2021-08-26 18:31:39 +00009349 failIfSafeMode(p, "cannot run .read in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009350 if( nArg!=2 ){
9351 raw_printf(stderr, "Usage: .read FILE\n");
9352 rc = 1;
9353 goto meta_command_exit;
9354 }
drh30497f42020-08-26 10:50:48 +00009355 if( azArg[1][0]=='|' ){
drh9d59e3b2021-03-12 01:49:08 +00009356#ifdef SQLITE_OMIT_POPEN
9357 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
9358 rc = 1;
9359 p->out = stdout;
9360#else
drh30497f42020-08-26 10:50:48 +00009361 p->in = popen(azArg[1]+1, "r");
9362 if( p->in==0 ){
9363 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
9364 rc = 1;
9365 }else{
9366 rc = process_input(p);
9367 pclose(p->in);
9368 }
drh9d59e3b2021-03-12 01:49:08 +00009369#endif
larrybrd96bcc72021-09-17 21:12:47 +00009370 }else if( (p->in = openChrSource(azArg[1]))==0 ){
drh2ce15c32017-07-11 13:34:40 +00009371 utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
9372 rc = 1;
9373 }else{
drh60379d42018-12-13 18:30:01 +00009374 rc = process_input(p);
9375 fclose(p->in);
drh2ce15c32017-07-11 13:34:40 +00009376 }
drh60379d42018-12-13 18:30:01 +00009377 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +00009378 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +00009379 }else
9380
9381 if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
9382 const char *zSrcFile;
9383 const char *zDb;
9384 sqlite3 *pSrc;
9385 sqlite3_backup *pBackup;
9386 int nTimeout = 0;
9387
drhb97e2ad2021-08-26 18:31:39 +00009388 failIfSafeMode(p, "cannot run .restore in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009389 if( nArg==2 ){
9390 zSrcFile = azArg[1];
9391 zDb = "main";
9392 }else if( nArg==3 ){
9393 zSrcFile = azArg[2];
9394 zDb = azArg[1];
9395 }else{
9396 raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
9397 rc = 1;
9398 goto meta_command_exit;
9399 }
9400 rc = sqlite3_open(zSrcFile, &pSrc);
9401 if( rc!=SQLITE_OK ){
9402 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
drh9e804032018-05-18 17:11:50 +00009403 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009404 return 1;
9405 }
9406 open_db(p, 0);
9407 pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
9408 if( pBackup==0 ){
9409 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh9e804032018-05-18 17:11:50 +00009410 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009411 return 1;
9412 }
9413 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
9414 || rc==SQLITE_BUSY ){
9415 if( rc==SQLITE_BUSY ){
9416 if( nTimeout++ >= 3 ) break;
9417 sqlite3_sleep(100);
9418 }
9419 }
9420 sqlite3_backup_finish(pBackup);
9421 if( rc==SQLITE_DONE ){
9422 rc = 0;
9423 }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
9424 raw_printf(stderr, "Error: source database is busy\n");
9425 rc = 1;
9426 }else{
9427 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9428 rc = 1;
9429 }
drh9e804032018-05-18 17:11:50 +00009430 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009431 }else
9432
drh2ce15c32017-07-11 13:34:40 +00009433 if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
9434 if( nArg==2 ){
mistachkinb71aa092018-01-23 00:05:18 +00009435 p->scanstatsOn = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00009436#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
9437 raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
9438#endif
9439 }else{
9440 raw_printf(stderr, "Usage: .scanstats on|off\n");
9441 rc = 1;
9442 }
9443 }else
9444
9445 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
9446 ShellText sSelect;
9447 ShellState data;
9448 char *zErrMsg = 0;
drh667a2a22018-01-02 00:04:37 +00009449 const char *zDiv = "(";
drhceba7922018-01-01 21:28:25 +00009450 const char *zName = 0;
drh2ce15c32017-07-11 13:34:40 +00009451 int iSchema = 0;
drhceba7922018-01-01 21:28:25 +00009452 int bDebug = 0;
drhbbb29ec2020-10-12 14:56:47 +00009453 int bNoSystemTabs = 0;
drhceba7922018-01-01 21:28:25 +00009454 int ii;
drh2ce15c32017-07-11 13:34:40 +00009455
9456 open_db(p, 0);
9457 memcpy(&data, p, sizeof(data));
9458 data.showHeader = 0;
9459 data.cMode = data.mode = MODE_Semi;
9460 initText(&sSelect);
drhceba7922018-01-01 21:28:25 +00009461 for(ii=1; ii<nArg; ii++){
9462 if( optionMatch(azArg[ii],"indent") ){
9463 data.cMode = data.mode = MODE_Pretty;
9464 }else if( optionMatch(azArg[ii],"debug") ){
9465 bDebug = 1;
drhbbb29ec2020-10-12 14:56:47 +00009466 }else if( optionMatch(azArg[ii],"nosys") ){
9467 bNoSystemTabs = 1;
9468 }else if( azArg[ii][0]=='-' ){
9469 utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
9470 rc = 1;
9471 goto meta_command_exit;
drhceba7922018-01-01 21:28:25 +00009472 }else if( zName==0 ){
9473 zName = azArg[ii];
drh2ce15c32017-07-11 13:34:40 +00009474 }else{
drhbbb29ec2020-10-12 14:56:47 +00009475 raw_printf(stderr, "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
drhceba7922018-01-01 21:28:25 +00009476 rc = 1;
9477 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00009478 }
drh2ce15c32017-07-11 13:34:40 +00009479 }
drhceba7922018-01-01 21:28:25 +00009480 if( zName!=0 ){
drh067b92b2020-06-19 15:24:12 +00009481 int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0
drh346a70c2020-06-15 20:27:35 +00009482 || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
9483 || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
9484 || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
drh067b92b2020-06-19 15:24:12 +00009485 if( isSchema ){
drh2ce15c32017-07-11 13:34:40 +00009486 char *new_argv[2], *new_colv[2];
drhc22b7162018-01-01 20:11:23 +00009487 new_argv[0] = sqlite3_mprintf(
9488 "CREATE TABLE %s (\n"
drh2ce15c32017-07-11 13:34:40 +00009489 " type text,\n"
9490 " name text,\n"
9491 " tbl_name text,\n"
9492 " rootpage integer,\n"
9493 " sql text\n"
drh346a70c2020-06-15 20:27:35 +00009494 ")", zName);
drhe3e25652021-12-16 13:29:28 +00009495 shell_check_oom(new_argv[0]);
drh2ce15c32017-07-11 13:34:40 +00009496 new_argv[1] = 0;
9497 new_colv[0] = "sql";
9498 new_colv[1] = 0;
9499 callback(&data, 1, new_argv, new_colv);
drhc22b7162018-01-01 20:11:23 +00009500 sqlite3_free(new_argv[0]);
drh2ce15c32017-07-11 13:34:40 +00009501 }
drh2ce15c32017-07-11 13:34:40 +00009502 }
9503 if( zDiv ){
9504 sqlite3_stmt *pStmt = 0;
9505 rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
9506 -1, &pStmt, 0);
9507 if( rc ){
9508 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9509 sqlite3_finalize(pStmt);
9510 rc = 1;
9511 goto meta_command_exit;
9512 }
9513 appendText(&sSelect, "SELECT sql FROM", 0);
9514 iSchema = 0;
9515 while( sqlite3_step(pStmt)==SQLITE_ROW ){
9516 const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
9517 char zScNum[30];
9518 sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
9519 appendText(&sSelect, zDiv, 0);
9520 zDiv = " UNION ALL ";
drhceba7922018-01-01 21:28:25 +00009521 appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
9522 if( sqlite3_stricmp(zDb, "main")!=0 ){
drhea38f4f2019-07-13 17:21:47 +00009523 appendText(&sSelect, zDb, '\'');
drh2ce15c32017-07-11 13:34:40 +00009524 }else{
drhceba7922018-01-01 21:28:25 +00009525 appendText(&sSelect, "NULL", 0);
drh2ce15c32017-07-11 13:34:40 +00009526 }
drhceba7922018-01-01 21:28:25 +00009527 appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0);
9528 appendText(&sSelect, zScNum, 0);
9529 appendText(&sSelect, " AS snum, ", 0);
9530 appendText(&sSelect, zDb, '\'');
9531 appendText(&sSelect, " AS sname FROM ", 0);
drhea38f4f2019-07-13 17:21:47 +00009532 appendText(&sSelect, zDb, quoteChar(zDb));
drh067b92b2020-06-19 15:24:12 +00009533 appendText(&sSelect, ".sqlite_schema", 0);
drh2ce15c32017-07-11 13:34:40 +00009534 }
9535 sqlite3_finalize(pStmt);
drhcc3f3d12019-08-17 15:27:58 +00009536#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
drh667a2a22018-01-02 00:04:37 +00009537 if( zName ){
9538 appendText(&sSelect,
9539 " UNION ALL SELECT shell_module_schema(name),"
drhe2754c12019-08-26 12:50:01 +00009540 " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
9541 0);
drh667a2a22018-01-02 00:04:37 +00009542 }
drhcde7b772018-01-02 12:50:40 +00009543#endif
drh2ce15c32017-07-11 13:34:40 +00009544 appendText(&sSelect, ") WHERE ", 0);
drhceba7922018-01-01 21:28:25 +00009545 if( zName ){
9546 char *zQarg = sqlite3_mprintf("%Q", zName);
mistachkinc158c072021-12-31 19:08:20 +00009547 int bGlob;
drhe3e25652021-12-16 13:29:28 +00009548 shell_check_oom(zQarg);
mistachkinc158c072021-12-31 19:08:20 +00009549 bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
9550 strchr(zName, '[') != 0;
drhceba7922018-01-01 21:28:25 +00009551 if( strchr(zName, '.') ){
drh2ce15c32017-07-11 13:34:40 +00009552 appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
9553 }else{
9554 appendText(&sSelect, "lower(tbl_name)", 0);
9555 }
mistachkin9d107262018-03-23 14:24:34 +00009556 appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0);
drh2ce15c32017-07-11 13:34:40 +00009557 appendText(&sSelect, zQarg, 0);
mistachkin9d107262018-03-23 14:24:34 +00009558 if( !bGlob ){
9559 appendText(&sSelect, " ESCAPE '\\' ", 0);
9560 }
drh2ce15c32017-07-11 13:34:40 +00009561 appendText(&sSelect, " AND ", 0);
9562 sqlite3_free(zQarg);
9563 }
drhbbb29ec2020-10-12 14:56:47 +00009564 if( bNoSystemTabs ){
9565 appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
9566 }
9567 appendText(&sSelect, "sql IS NOT NULL"
drh2ce15c32017-07-11 13:34:40 +00009568 " ORDER BY snum, rowid", 0);
drhceba7922018-01-01 21:28:25 +00009569 if( bDebug ){
9570 utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
9571 }else{
9572 rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
9573 }
drh2ce15c32017-07-11 13:34:40 +00009574 freeText(&sSelect);
9575 }
9576 if( zErrMsg ){
9577 utf8_printf(stderr,"Error: %s\n", zErrMsg);
9578 sqlite3_free(zErrMsg);
9579 rc = 1;
9580 }else if( rc != SQLITE_OK ){
9581 raw_printf(stderr,"Error: querying schema information\n");
9582 rc = 1;
9583 }else{
9584 rc = 0;
9585 }
9586 }else
9587
drh2ce15c32017-07-11 13:34:40 +00009588 if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
drhfda8e492020-12-04 16:04:45 +00009589 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
drhc0622a42020-12-04 01:17:57 +00009590 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
drh2ce15c32017-07-11 13:34:40 +00009591 }else
drh2ce15c32017-07-11 13:34:40 +00009592
9593#if defined(SQLITE_ENABLE_SESSION)
9594 if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
drh37407122021-07-23 18:43:58 +00009595 struct AuxDb *pAuxDb = p->pAuxDb;
9596 OpenSession *pSession = &pAuxDb->aSession[0];
drh2ce15c32017-07-11 13:34:40 +00009597 char **azCmd = &azArg[1];
9598 int iSes = 0;
9599 int nCmd = nArg - 1;
9600 int i;
9601 if( nArg<=1 ) goto session_syntax_error;
9602 open_db(p, 0);
9603 if( nArg>=3 ){
drh37407122021-07-23 18:43:58 +00009604 for(iSes=0; iSes<pAuxDb->nSession; iSes++){
9605 if( strcmp(pAuxDb->aSession[iSes].zName, azArg[1])==0 ) break;
drh2ce15c32017-07-11 13:34:40 +00009606 }
drh37407122021-07-23 18:43:58 +00009607 if( iSes<pAuxDb->nSession ){
9608 pSession = &pAuxDb->aSession[iSes];
drh2ce15c32017-07-11 13:34:40 +00009609 azCmd++;
9610 nCmd--;
9611 }else{
drh37407122021-07-23 18:43:58 +00009612 pSession = &pAuxDb->aSession[0];
drh2ce15c32017-07-11 13:34:40 +00009613 iSes = 0;
9614 }
9615 }
9616
9617 /* .session attach TABLE
9618 ** Invoke the sqlite3session_attach() interface to attach a particular
9619 ** table so that it is never filtered.
9620 */
9621 if( strcmp(azCmd[0],"attach")==0 ){
9622 if( nCmd!=2 ) goto session_syntax_error;
9623 if( pSession->p==0 ){
9624 session_not_open:
9625 raw_printf(stderr, "ERROR: No sessions are open\n");
9626 }else{
9627 rc = sqlite3session_attach(pSession->p, azCmd[1]);
9628 if( rc ){
9629 raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
9630 rc = 0;
9631 }
9632 }
9633 }else
9634
9635 /* .session changeset FILE
9636 ** .session patchset FILE
9637 ** Write a changeset or patchset into a file. The file is overwritten.
9638 */
9639 if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
9640 FILE *out = 0;
drhb97e2ad2021-08-26 18:31:39 +00009641 failIfSafeMode(p, "cannot run \".session %s\" in safe mode", azCmd[0]);
drh2ce15c32017-07-11 13:34:40 +00009642 if( nCmd!=2 ) goto session_syntax_error;
9643 if( pSession->p==0 ) goto session_not_open;
9644 out = fopen(azCmd[1], "wb");
9645 if( out==0 ){
drhe2754c12019-08-26 12:50:01 +00009646 utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
9647 azCmd[1]);
drh2ce15c32017-07-11 13:34:40 +00009648 }else{
9649 int szChng;
9650 void *pChng;
9651 if( azCmd[0][0]=='c' ){
9652 rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
9653 }else{
9654 rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
9655 }
9656 if( rc ){
9657 printf("Error: error code %d\n", rc);
9658 rc = 0;
9659 }
9660 if( pChng
9661 && fwrite(pChng, szChng, 1, out)!=1 ){
9662 raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
9663 szChng);
9664 }
9665 sqlite3_free(pChng);
9666 fclose(out);
9667 }
9668 }else
9669
9670 /* .session close
9671 ** Close the identified session
9672 */
9673 if( strcmp(azCmd[0], "close")==0 ){
9674 if( nCmd!=1 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009675 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009676 session_close(pSession);
drh37407122021-07-23 18:43:58 +00009677 pAuxDb->aSession[iSes] = pAuxDb->aSession[--pAuxDb->nSession];
drh2ce15c32017-07-11 13:34:40 +00009678 }
9679 }else
9680
9681 /* .session enable ?BOOLEAN?
9682 ** Query or set the enable flag
9683 */
9684 if( strcmp(azCmd[0], "enable")==0 ){
9685 int ii;
9686 if( nCmd>2 ) goto session_syntax_error;
9687 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
drh37407122021-07-23 18:43:58 +00009688 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009689 ii = sqlite3session_enable(pSession->p, ii);
9690 utf8_printf(p->out, "session %s enable flag = %d\n",
9691 pSession->zName, ii);
9692 }
9693 }else
9694
9695 /* .session filter GLOB ....
9696 ** Set a list of GLOB patterns of table names to be excluded.
9697 */
9698 if( strcmp(azCmd[0], "filter")==0 ){
9699 int ii, nByte;
9700 if( nCmd<2 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009701 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009702 for(ii=0; ii<pSession->nFilter; ii++){
9703 sqlite3_free(pSession->azFilter[ii]);
9704 }
9705 sqlite3_free(pSession->azFilter);
9706 nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
9707 pSession->azFilter = sqlite3_malloc( nByte );
9708 if( pSession->azFilter==0 ){
9709 raw_printf(stderr, "Error: out or memory\n");
9710 exit(1);
9711 }
9712 for(ii=1; ii<nCmd; ii++){
drhe3e25652021-12-16 13:29:28 +00009713 char *x = pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
9714 shell_check_oom(x);
drh2ce15c32017-07-11 13:34:40 +00009715 }
9716 pSession->nFilter = ii-1;
9717 }
9718 }else
9719
9720 /* .session indirect ?BOOLEAN?
9721 ** Query or set the indirect flag
9722 */
9723 if( strcmp(azCmd[0], "indirect")==0 ){
9724 int ii;
9725 if( nCmd>2 ) goto session_syntax_error;
9726 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
drh37407122021-07-23 18:43:58 +00009727 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009728 ii = sqlite3session_indirect(pSession->p, ii);
9729 utf8_printf(p->out, "session %s indirect flag = %d\n",
9730 pSession->zName, ii);
9731 }
9732 }else
9733
9734 /* .session isempty
9735 ** Determine if the session is empty
9736 */
9737 if( strcmp(azCmd[0], "isempty")==0 ){
9738 int ii;
9739 if( nCmd!=1 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009740 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009741 ii = sqlite3session_isempty(pSession->p);
9742 utf8_printf(p->out, "session %s isempty flag = %d\n",
9743 pSession->zName, ii);
9744 }
9745 }else
9746
9747 /* .session list
9748 ** List all currently open sessions
9749 */
9750 if( strcmp(azCmd[0],"list")==0 ){
drh37407122021-07-23 18:43:58 +00009751 for(i=0; i<pAuxDb->nSession; i++){
9752 utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName);
drh2ce15c32017-07-11 13:34:40 +00009753 }
9754 }else
9755
9756 /* .session open DB NAME
9757 ** Open a new session called NAME on the attached database DB.
9758 ** DB is normally "main".
9759 */
9760 if( strcmp(azCmd[0],"open")==0 ){
9761 char *zName;
9762 if( nCmd!=3 ) goto session_syntax_error;
9763 zName = azCmd[2];
9764 if( zName[0]==0 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009765 for(i=0; i<pAuxDb->nSession; i++){
9766 if( strcmp(pAuxDb->aSession[i].zName,zName)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009767 utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
9768 goto meta_command_exit;
9769 }
9770 }
drh37407122021-07-23 18:43:58 +00009771 if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){
9772 raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession));
drh2ce15c32017-07-11 13:34:40 +00009773 goto meta_command_exit;
9774 }
drh37407122021-07-23 18:43:58 +00009775 pSession = &pAuxDb->aSession[pAuxDb->nSession];
drh2ce15c32017-07-11 13:34:40 +00009776 rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
9777 if( rc ){
9778 raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
9779 rc = 0;
9780 goto meta_command_exit;
9781 }
9782 pSession->nFilter = 0;
9783 sqlite3session_table_filter(pSession->p, session_filter, pSession);
drh37407122021-07-23 18:43:58 +00009784 pAuxDb->nSession++;
drh2ce15c32017-07-11 13:34:40 +00009785 pSession->zName = sqlite3_mprintf("%s", zName);
drhe3e25652021-12-16 13:29:28 +00009786 shell_check_oom(pSession->zName);
drh2ce15c32017-07-11 13:34:40 +00009787 }else
9788 /* If no command name matches, show a syntax error */
9789 session_syntax_error:
drheb7f2a02018-09-26 18:02:32 +00009790 showHelp(p->out, "session");
drh2ce15c32017-07-11 13:34:40 +00009791 }else
9792#endif
9793
9794#ifdef SQLITE_DEBUG
9795 /* Undocumented commands for internal testing. Subject to change
9796 ** without notice. */
9797 if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
9798 if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
9799 int i, v;
9800 for(i=1; i<nArg; i++){
9801 v = booleanValue(azArg[i]);
9802 utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
9803 }
9804 }
9805 if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
9806 int i; sqlite3_int64 v;
9807 for(i=1; i<nArg; i++){
9808 char zBuf[200];
9809 v = integerValue(azArg[i]);
9810 sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
9811 utf8_printf(p->out, "%s", zBuf);
9812 }
9813 }
9814 }else
9815#endif
9816
9817 if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){
9818 int bIsInit = 0; /* True to initialize the SELFTEST table */
9819 int bVerbose = 0; /* Verbose output */
9820 int bSelftestExists; /* True if SELFTEST already exists */
9821 int i, k; /* Loop counters */
9822 int nTest = 0; /* Number of tests runs */
9823 int nErr = 0; /* Number of errors seen */
9824 ShellText str; /* Answer for a query */
9825 sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
9826
9827 open_db(p,0);
9828 for(i=1; i<nArg; i++){
9829 const char *z = azArg[i];
9830 if( z[0]=='-' && z[1]=='-' ) z++;
9831 if( strcmp(z,"-init")==0 ){
9832 bIsInit = 1;
9833 }else
9834 if( strcmp(z,"-v")==0 ){
9835 bVerbose++;
9836 }else
9837 {
9838 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
9839 azArg[i], azArg[0]);
9840 raw_printf(stderr, "Should be one of: --init -v\n");
9841 rc = 1;
9842 goto meta_command_exit;
9843 }
9844 }
9845 if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
9846 != SQLITE_OK ){
9847 bSelftestExists = 0;
9848 }else{
9849 bSelftestExists = 1;
9850 }
9851 if( bIsInit ){
9852 createSelftestTable(p);
9853 bSelftestExists = 1;
9854 }
9855 initText(&str);
9856 appendText(&str, "x", 0);
9857 for(k=bSelftestExists; k>=0; k--){
9858 if( k==1 ){
9859 rc = sqlite3_prepare_v2(p->db,
9860 "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
9861 -1, &pStmt, 0);
9862 }else{
9863 rc = sqlite3_prepare_v2(p->db,
9864 "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
9865 " (1,'run','PRAGMA integrity_check','ok')",
9866 -1, &pStmt, 0);
9867 }
9868 if( rc ){
9869 raw_printf(stderr, "Error querying the selftest table\n");
9870 rc = 1;
9871 sqlite3_finalize(pStmt);
9872 goto meta_command_exit;
9873 }
9874 for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
9875 int tno = sqlite3_column_int(pStmt, 0);
9876 const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
9877 const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
9878 const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
9879
drh621a5e02021-12-16 17:35:27 +00009880 if( zOp==0 ) continue;
9881 if( zSql==0 ) continue;
9882 if( zAns==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00009883 k = 0;
9884 if( bVerbose>0 ){
drh2ce15c32017-07-11 13:34:40 +00009885 printf("%d: %s %s\n", tno, zOp, zSql);
drh2ce15c32017-07-11 13:34:40 +00009886 }
9887 if( strcmp(zOp,"memo")==0 ){
9888 utf8_printf(p->out, "%s\n", zSql);
9889 }else
9890 if( strcmp(zOp,"run")==0 ){
9891 char *zErrMsg = 0;
9892 str.n = 0;
9893 str.z[0] = 0;
9894 rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
9895 nTest++;
9896 if( bVerbose ){
9897 utf8_printf(p->out, "Result: %s\n", str.z);
9898 }
9899 if( rc || zErrMsg ){
9900 nErr++;
9901 rc = 1;
9902 utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
9903 sqlite3_free(zErrMsg);
9904 }else if( strcmp(zAns,str.z)!=0 ){
9905 nErr++;
9906 rc = 1;
9907 utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
9908 utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z);
9909 }
9910 }else
9911 {
9912 utf8_printf(stderr,
9913 "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
9914 rc = 1;
9915 break;
9916 }
9917 } /* End loop over rows of content from SELFTEST */
9918 sqlite3_finalize(pStmt);
9919 } /* End loop over k */
9920 freeText(&str);
9921 utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
9922 }else
9923
9924 if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
9925 if( nArg<2 || nArg>3 ){
9926 raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
9927 rc = 1;
9928 }
9929 if( nArg>=2 ){
9930 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
9931 "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
9932 }
9933 if( nArg>=3 ){
9934 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator,
9935 "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]);
9936 }
9937 }else
9938
9939 if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){
9940 const char *zLike = 0; /* Which table to checksum. 0 means everything */
9941 int i; /* Loop counter */
9942 int bSchema = 0; /* Also hash the schema */
9943 int bSeparate = 0; /* Hash each table separately */
9944 int iSize = 224; /* Hash algorithm to use */
9945 int bDebug = 0; /* Only show the query that would have run */
9946 sqlite3_stmt *pStmt; /* For querying tables names */
9947 char *zSql; /* SQL to be run */
9948 char *zSep; /* Separator */
9949 ShellText sSql; /* Complete SQL for the query to run the hash */
9950 ShellText sQuery; /* Set of queries used to read all content */
9951 open_db(p, 0);
9952 for(i=1; i<nArg; i++){
9953 const char *z = azArg[i];
9954 if( z[0]=='-' ){
9955 z++;
9956 if( z[0]=='-' ) z++;
9957 if( strcmp(z,"schema")==0 ){
9958 bSchema = 1;
9959 }else
9960 if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
9961 || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
9962 ){
9963 iSize = atoi(&z[5]);
9964 }else
9965 if( strcmp(z,"debug")==0 ){
9966 bDebug = 1;
9967 }else
9968 {
9969 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
9970 azArg[i], azArg[0]);
drhe2754c12019-08-26 12:50:01 +00009971 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00009972 rc = 1;
9973 goto meta_command_exit;
9974 }
9975 }else if( zLike ){
9976 raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
9977 rc = 1;
9978 goto meta_command_exit;
9979 }else{
9980 zLike = z;
9981 bSeparate = 1;
drhcedfecf2018-03-23 12:59:10 +00009982 if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1;
drh2ce15c32017-07-11 13:34:40 +00009983 }
9984 }
9985 if( bSchema ){
drh067b92b2020-06-19 15:24:12 +00009986 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00009987 " WHERE type='table' AND coalesce(rootpage,0)>1"
drh067b92b2020-06-19 15:24:12 +00009988 " UNION ALL SELECT 'sqlite_schema'"
drh2ce15c32017-07-11 13:34:40 +00009989 " ORDER BY 1 collate nocase";
9990 }else{
drh067b92b2020-06-19 15:24:12 +00009991 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00009992 " WHERE type='table' AND coalesce(rootpage,0)>1"
9993 " AND name NOT LIKE 'sqlite_%'"
9994 " ORDER BY 1 collate nocase";
9995 }
9996 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9997 initText(&sQuery);
9998 initText(&sSql);
9999 appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
10000 zSep = "VALUES(";
10001 while( SQLITE_ROW==sqlite3_step(pStmt) ){
10002 const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
drh621a5e02021-12-16 17:35:27 +000010003 if( zTab==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +000010004 if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
10005 if( strncmp(zTab, "sqlite_",7)!=0 ){
10006 appendText(&sQuery,"SELECT * FROM ", 0);
10007 appendText(&sQuery,zTab,'"');
10008 appendText(&sQuery," NOT INDEXED;", 0);
drh067b92b2020-06-19 15:24:12 +000010009 }else if( strcmp(zTab, "sqlite_schema")==0 ){
10010 appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +000010011 " ORDER BY name;", 0);
10012 }else if( strcmp(zTab, "sqlite_sequence")==0 ){
10013 appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
10014 " ORDER BY name;", 0);
10015 }else if( strcmp(zTab, "sqlite_stat1")==0 ){
10016 appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
10017 " ORDER BY tbl,idx;", 0);
drh175b8f02019-08-08 15:24:17 +000010018 }else if( strcmp(zTab, "sqlite_stat4")==0 ){
drh2ce15c32017-07-11 13:34:40 +000010019 appendText(&sQuery, "SELECT * FROM ", 0);
10020 appendText(&sQuery, zTab, 0);
10021 appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
10022 }
10023 appendText(&sSql, zSep, 0);
10024 appendText(&sSql, sQuery.z, '\'');
10025 sQuery.n = 0;
10026 appendText(&sSql, ",", 0);
10027 appendText(&sSql, zTab, '\'');
10028 zSep = "),(";
10029 }
10030 sqlite3_finalize(pStmt);
10031 if( bSeparate ){
10032 zSql = sqlite3_mprintf(
10033 "%s))"
10034 " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
10035 " FROM [sha3sum$query]",
10036 sSql.z, iSize);
10037 }else{
10038 zSql = sqlite3_mprintf(
10039 "%s))"
10040 " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
10041 " FROM [sha3sum$query]",
10042 sSql.z, iSize);
10043 }
drhe3e25652021-12-16 13:29:28 +000010044 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +000010045 freeText(&sQuery);
10046 freeText(&sSql);
10047 if( bDebug ){
10048 utf8_printf(p->out, "%s\n", zSql);
10049 }else{
drha10b9992018-03-09 15:24:33 +000010050 shell_exec(p, zSql, 0);
drh2ce15c32017-07-11 13:34:40 +000010051 }
10052 sqlite3_free(zSql);
10053 }else
10054
drh04a28c32018-01-31 01:38:44 +000010055#ifndef SQLITE_NOHAVE_SYSTEM
drh2ce15c32017-07-11 13:34:40 +000010056 if( c=='s'
10057 && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
10058 ){
10059 char *zCmd;
10060 int i, x;
drhb97e2ad2021-08-26 18:31:39 +000010061 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh2ce15c32017-07-11 13:34:40 +000010062 if( nArg<2 ){
10063 raw_printf(stderr, "Usage: .system COMMAND\n");
10064 rc = 1;
10065 goto meta_command_exit;
10066 }
10067 zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
drhe3e25652021-12-16 13:29:28 +000010068 for(i=2; i<nArg && zCmd!=0; i++){
drh2ce15c32017-07-11 13:34:40 +000010069 zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
10070 zCmd, azArg[i]);
10071 }
drhe3e25652021-12-16 13:29:28 +000010072 x = zCmd!=0 ? system(zCmd) : 1;
drh2ce15c32017-07-11 13:34:40 +000010073 sqlite3_free(zCmd);
10074 if( x ) raw_printf(stderr, "System command returns %d\n", x);
10075 }else
drh04a28c32018-01-31 01:38:44 +000010076#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
drh2ce15c32017-07-11 13:34:40 +000010077
10078 if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
drhada70452017-12-21 21:02:27 +000010079 static const char *azBool[] = { "off", "on", "trigger", "full"};
drha6e6cf22021-01-09 19:10:04 +000010080 const char *zOut;
drh2ce15c32017-07-11 13:34:40 +000010081 int i;
10082 if( nArg!=1 ){
10083 raw_printf(stderr, "Usage: .show\n");
10084 rc = 1;
10085 goto meta_command_exit;
10086 }
10087 utf8_printf(p->out, "%12.12s: %s\n","echo",
10088 azBool[ShellHasFlag(p, SHFLG_Echo)]);
10089 utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
10090 utf8_printf(p->out, "%12.12s: %s\n","explain",
10091 p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
10092 utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
10093 utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
10094 utf8_printf(p->out, "%12.12s: ", "nullvalue");
10095 output_c_string(p->out, p->nullValue);
10096 raw_printf(p->out, "\n");
10097 utf8_printf(p->out,"%12.12s: %s\n","output",
10098 strlen30(p->outfile) ? p->outfile : "stdout");
10099 utf8_printf(p->out,"%12.12s: ", "colseparator");
10100 output_c_string(p->out, p->colSeparator);
10101 raw_printf(p->out, "\n");
10102 utf8_printf(p->out,"%12.12s: ", "rowseparator");
10103 output_c_string(p->out, p->rowSeparator);
10104 raw_printf(p->out, "\n");
drha6e6cf22021-01-09 19:10:04 +000010105 switch( p->statsOn ){
10106 case 0: zOut = "off"; break;
10107 default: zOut = "on"; break;
10108 case 2: zOut = "stmt"; break;
10109 case 3: zOut = "vmstep"; break;
10110 }
10111 utf8_printf(p->out, "%12.12s: %s\n","stats", zOut);
drh2ce15c32017-07-11 13:34:40 +000010112 utf8_printf(p->out, "%12.12s: ", "width");
drh0285d982020-05-29 14:38:43 +000010113 for (i=0;i<p->nWidth;i++) {
drh2ce15c32017-07-11 13:34:40 +000010114 raw_printf(p->out, "%d ", p->colWidth[i]);
10115 }
10116 raw_printf(p->out, "\n");
10117 utf8_printf(p->out, "%12.12s: %s\n", "filename",
drh37407122021-07-23 18:43:58 +000010118 p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : "");
drh2ce15c32017-07-11 13:34:40 +000010119 }else
10120
10121 if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
10122 if( nArg==2 ){
drha6e6cf22021-01-09 19:10:04 +000010123 if( strcmp(azArg[1],"stmt")==0 ){
10124 p->statsOn = 2;
10125 }else if( strcmp(azArg[1],"vmstep")==0 ){
10126 p->statsOn = 3;
10127 }else{
10128 p->statsOn = (u8)booleanValue(azArg[1]);
10129 }
drh2ce15c32017-07-11 13:34:40 +000010130 }else if( nArg==1 ){
10131 display_stats(p->db, p, 0);
10132 }else{
drha6e6cf22021-01-09 19:10:04 +000010133 raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n");
drh2ce15c32017-07-11 13:34:40 +000010134 rc = 1;
10135 }
10136 }else
10137
10138 if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0)
10139 || (c=='i' && (strncmp(azArg[0], "indices", n)==0
10140 || strncmp(azArg[0], "indexes", n)==0) )
10141 ){
10142 sqlite3_stmt *pStmt;
10143 char **azResult;
10144 int nRow, nAlloc;
10145 int ii;
10146 ShellText s;
10147 initText(&s);
10148 open_db(p, 0);
10149 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
drh9e804032018-05-18 17:11:50 +000010150 if( rc ){
10151 sqlite3_finalize(pStmt);
10152 return shellDatabaseError(p->db);
10153 }
drh2ce15c32017-07-11 13:34:40 +000010154
10155 if( nArg>2 && c=='i' ){
10156 /* It is an historical accident that the .indexes command shows an error
10157 ** when called with the wrong number of arguments whereas the .tables
10158 ** command does not. */
10159 raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
10160 rc = 1;
drh9e804032018-05-18 17:11:50 +000010161 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +000010162 goto meta_command_exit;
10163 }
10164 for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
10165 const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
10166 if( zDbName==0 ) continue;
10167 if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0);
10168 if( sqlite3_stricmp(zDbName, "main")==0 ){
10169 appendText(&s, "SELECT name FROM ", 0);
10170 }else{
10171 appendText(&s, "SELECT ", 0);
10172 appendText(&s, zDbName, '\'');
10173 appendText(&s, "||'.'||name FROM ", 0);
10174 }
10175 appendText(&s, zDbName, '"');
drh067b92b2020-06-19 15:24:12 +000010176 appendText(&s, ".sqlite_schema ", 0);
drh2ce15c32017-07-11 13:34:40 +000010177 if( c=='t' ){
10178 appendText(&s," WHERE type IN ('table','view')"
10179 " AND name NOT LIKE 'sqlite_%'"
10180 " AND name LIKE ?1", 0);
10181 }else{
10182 appendText(&s," WHERE type='index'"
10183 " AND tbl_name LIKE ?1", 0);
10184 }
10185 }
10186 rc = sqlite3_finalize(pStmt);
drhe85e1da2021-10-01 21:01:07 +000010187 if( rc==SQLITE_OK ){
10188 appendText(&s, " ORDER BY 1", 0);
10189 rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
10190 }
drh2ce15c32017-07-11 13:34:40 +000010191 freeText(&s);
10192 if( rc ) return shellDatabaseError(p->db);
10193
10194 /* Run the SQL statement prepared by the above block. Store the results
10195 ** as an array of nul-terminated strings in azResult[]. */
10196 nRow = nAlloc = 0;
10197 azResult = 0;
10198 if( nArg>1 ){
10199 sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
10200 }else{
10201 sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
10202 }
10203 while( sqlite3_step(pStmt)==SQLITE_ROW ){
10204 if( nRow>=nAlloc ){
10205 char **azNew;
10206 int n2 = nAlloc*2 + 10;
10207 azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
drhe3e25652021-12-16 13:29:28 +000010208 shell_check_oom(azNew);
drh2ce15c32017-07-11 13:34:40 +000010209 nAlloc = n2;
10210 azResult = azNew;
10211 }
10212 azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
drhe3e25652021-12-16 13:29:28 +000010213 shell_check_oom(azResult[nRow]);
drh2ce15c32017-07-11 13:34:40 +000010214 nRow++;
10215 }
10216 if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
10217 rc = shellDatabaseError(p->db);
10218 }
10219
10220 /* Pretty-print the contents of array azResult[] to the output */
10221 if( rc==0 && nRow>0 ){
10222 int len, maxlen = 0;
10223 int i, j;
10224 int nPrintCol, nPrintRow;
10225 for(i=0; i<nRow; i++){
10226 len = strlen30(azResult[i]);
10227 if( len>maxlen ) maxlen = len;
10228 }
10229 nPrintCol = 80/(maxlen+2);
10230 if( nPrintCol<1 ) nPrintCol = 1;
10231 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
10232 for(i=0; i<nPrintRow; i++){
10233 for(j=i; j<nRow; j+=nPrintRow){
10234 char *zSp = j<nPrintRow ? "" : " ";
10235 utf8_printf(p->out, "%s%-*s", zSp, maxlen,
10236 azResult[j] ? azResult[j]:"");
10237 }
10238 raw_printf(p->out, "\n");
10239 }
10240 }
10241
10242 for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
10243 sqlite3_free(azResult);
10244 }else
10245
10246 /* Begin redirecting output to the file "testcase-out.txt" */
10247 if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
10248 output_reset(p);
drha92a01a2018-01-10 22:15:37 +000010249 p->out = output_file_open("testcase-out.txt", 0);
drh2ce15c32017-07-11 13:34:40 +000010250 if( p->out==0 ){
10251 raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
10252 }
10253 if( nArg>=2 ){
10254 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
10255 }else{
10256 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
10257 }
10258 }else
10259
10260#ifndef SQLITE_UNTESTABLE
drh35f51a42017-11-15 17:07:22 +000010261 if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010262 static const struct {
10263 const char *zCtrlName; /* Name of a test-control option */
10264 int ctrlCode; /* Integer code for that option */
drh38ed1ce2021-12-06 15:24:36 +000010265 int unSafe; /* Not valid for --safe mode */
drhef302e82017-11-15 19:14:08 +000010266 const char *zUsage; /* Usage notes */
drh2ce15c32017-07-11 13:34:40 +000010267 } aCtrl[] = {
drh38ed1ce2021-12-06 15:24:36 +000010268 { "always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" },
10269 { "assert", SQLITE_TESTCTRL_ASSERT, 1, "BOOLEAN" },
10270 /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, "" },*/
10271 /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "" },*/
10272 { "byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" },
10273 { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" },
10274 /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"" },*/
10275 { "imposter", SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"},
10276 { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,"" },
10277 { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN" },
10278 { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" },
10279 { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" },
drh0d9de992017-12-26 18:04:23 +000010280#ifdef YYCOVERAGE
drh38ed1ce2021-12-06 15:24:36 +000010281 { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE,0,"" },
drh0d9de992017-12-26 18:04:23 +000010282#endif
drh38ed1ce2021-12-06 15:24:36 +000010283 { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET " },
10284 { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" },
10285 { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" },
10286 { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" },
10287 { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" },
10288 { "sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" },
10289 { "tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" },
drh2ce15c32017-07-11 13:34:40 +000010290 };
10291 int testctrl = -1;
drhef302e82017-11-15 19:14:08 +000010292 int iCtrl = -1;
10293 int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */
10294 int isOk = 0;
drh2ce15c32017-07-11 13:34:40 +000010295 int i, n2;
mistachkinc6bc15a2017-11-21 21:14:32 +000010296 const char *zCmd = 0;
10297
drh2ce15c32017-07-11 13:34:40 +000010298 open_db(p, 0);
mistachkinc6bc15a2017-11-21 21:14:32 +000010299 zCmd = nArg>=2 ? azArg[1] : "help";
drh35f51a42017-11-15 17:07:22 +000010300
10301 /* The argument can optionally begin with "-" or "--" */
10302 if( zCmd[0]=='-' && zCmd[1] ){
10303 zCmd++;
10304 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
10305 }
10306
10307 /* --help lists all test-controls */
10308 if( strcmp(zCmd,"help")==0 ){
10309 utf8_printf(p->out, "Available test-controls:\n");
10310 for(i=0; i<ArraySize(aCtrl); i++){
drhef302e82017-11-15 19:14:08 +000010311 utf8_printf(p->out, " .testctrl %s %s\n",
10312 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
drh35f51a42017-11-15 17:07:22 +000010313 }
10314 rc = 1;
10315 goto meta_command_exit;
10316 }
drh2ce15c32017-07-11 13:34:40 +000010317
10318 /* convert testctrl text option to value. allow any unique prefix
10319 ** of the option name, or a numerical value. */
drh35f51a42017-11-15 17:07:22 +000010320 n2 = strlen30(zCmd);
drh2ce15c32017-07-11 13:34:40 +000010321 for(i=0; i<ArraySize(aCtrl); i++){
drh35f51a42017-11-15 17:07:22 +000010322 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010323 if( testctrl<0 ){
10324 testctrl = aCtrl[i].ctrlCode;
drhef302e82017-11-15 19:14:08 +000010325 iCtrl = i;
drh2ce15c32017-07-11 13:34:40 +000010326 }else{
drh35f51a42017-11-15 17:07:22 +000010327 utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
10328 "Use \".testctrl --help\" for help\n", zCmd);
10329 rc = 1;
10330 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +000010331 }
10332 }
10333 }
drhef302e82017-11-15 19:14:08 +000010334 if( testctrl<0 ){
drh35f51a42017-11-15 17:07:22 +000010335 utf8_printf(stderr,"Error: unknown test-control: %s\n"
10336 "Use \".testctrl --help\" for help\n", zCmd);
drh38ed1ce2021-12-06 15:24:36 +000010337 }else if( aCtrl[iCtrl].unSafe && p->bSafeMode ){
10338 utf8_printf(stderr,
10339 "line %d: \".testctrl %s\" may not be used in safe mode\n",
10340 p->lineno, aCtrl[iCtrl].zCtrlName);
10341 exit(1);
drh2ce15c32017-07-11 13:34:40 +000010342 }else{
10343 switch(testctrl){
10344
10345 /* sqlite3_test_control(int, db, int) */
10346 case SQLITE_TESTCTRL_OPTIMIZATIONS:
drh2ce15c32017-07-11 13:34:40 +000010347 if( nArg==3 ){
drhaf7b7652021-01-13 19:28:17 +000010348 unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
drh2ce15c32017-07-11 13:34:40 +000010349 rc2 = sqlite3_test_control(testctrl, p->db, opt);
drhef302e82017-11-15 19:14:08 +000010350 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010351 }
10352 break;
10353
10354 /* sqlite3_test_control(int) */
10355 case SQLITE_TESTCTRL_PRNG_SAVE:
10356 case SQLITE_TESTCTRL_PRNG_RESTORE:
drh2ce15c32017-07-11 13:34:40 +000010357 case SQLITE_TESTCTRL_BYTEORDER:
10358 if( nArg==2 ){
10359 rc2 = sqlite3_test_control(testctrl);
drhef302e82017-11-15 19:14:08 +000010360 isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
drh2ce15c32017-07-11 13:34:40 +000010361 }
10362 break;
10363
10364 /* sqlite3_test_control(int, uint) */
10365 case SQLITE_TESTCTRL_PENDING_BYTE:
10366 if( nArg==3 ){
10367 unsigned int opt = (unsigned int)integerValue(azArg[2]);
10368 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010369 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010370 }
10371 break;
10372
drh2e6d83b2019-08-03 01:39:20 +000010373 /* sqlite3_test_control(int, int, sqlite3*) */
10374 case SQLITE_TESTCTRL_PRNG_SEED:
10375 if( nArg==3 || nArg==4 ){
drh51755a72019-08-08 19:40:29 +000010376 int ii = (int)integerValue(azArg[2]);
drh2e6d83b2019-08-03 01:39:20 +000010377 sqlite3 *db;
drh41428a92019-08-12 16:25:11 +000010378 if( ii==0 && strcmp(azArg[2],"random")==0 ){
10379 sqlite3_randomness(sizeof(ii),&ii);
10380 printf("-- random seed: %d\n", ii);
10381 }
drh2e6d83b2019-08-03 01:39:20 +000010382 if( nArg==3 ){
10383 db = 0;
10384 }else{
10385 db = p->db;
10386 /* Make sure the schema has been loaded */
10387 sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);
10388 }
drh51755a72019-08-08 19:40:29 +000010389 rc2 = sqlite3_test_control(testctrl, ii, db);
drh2e6d83b2019-08-03 01:39:20 +000010390 isOk = 3;
10391 }
10392 break;
10393
drh2ce15c32017-07-11 13:34:40 +000010394 /* sqlite3_test_control(int, int) */
10395 case SQLITE_TESTCTRL_ASSERT:
10396 case SQLITE_TESTCTRL_ALWAYS:
drhef302e82017-11-15 19:14:08 +000010397 if( nArg==3 ){
10398 int opt = booleanValue(azArg[2]);
10399 rc2 = sqlite3_test_control(testctrl, opt);
10400 isOk = 1;
10401 }
10402 break;
10403
10404 /* sqlite3_test_control(int, int) */
10405 case SQLITE_TESTCTRL_LOCALTIME_FAULT:
drh2ce15c32017-07-11 13:34:40 +000010406 case SQLITE_TESTCTRL_NEVER_CORRUPT:
10407 if( nArg==3 ){
10408 int opt = booleanValue(azArg[2]);
10409 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010410 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010411 }
10412 break;
10413
drh171c50e2020-01-01 15:43:30 +000010414 /* sqlite3_test_control(sqlite3*) */
10415 case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
10416 rc2 = sqlite3_test_control(testctrl, p->db);
drh2a83c102020-01-01 23:02:35 +000010417 isOk = 3;
drh171c50e2020-01-01 15:43:30 +000010418 break;
10419
drh2ce15c32017-07-11 13:34:40 +000010420 case SQLITE_TESTCTRL_IMPOSTER:
10421 if( nArg==5 ){
10422 rc2 = sqlite3_test_control(testctrl, p->db,
10423 azArg[2],
10424 integerValue(azArg[3]),
10425 integerValue(azArg[4]));
drhef302e82017-11-15 19:14:08 +000010426 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010427 }
10428 break;
drh0d9de992017-12-26 18:04:23 +000010429
drh37ccfcf2020-08-31 18:49:04 +000010430 case SQLITE_TESTCTRL_SEEK_COUNT: {
10431 u64 x = 0;
10432 rc2 = sqlite3_test_control(testctrl, p->db, &x);
10433 utf8_printf(p->out, "%llu\n", x);
10434 isOk = 3;
10435 break;
10436 }
10437
drh0d9de992017-12-26 18:04:23 +000010438#ifdef YYCOVERAGE
drhf3c12562021-06-04 13:16:46 +000010439 case SQLITE_TESTCTRL_PARSER_COVERAGE: {
drh0d9de992017-12-26 18:04:23 +000010440 if( nArg==2 ){
10441 sqlite3_test_control(testctrl, p->out);
10442 isOk = 3;
10443 }
drhf3c12562021-06-04 13:16:46 +000010444 break;
10445 }
10446#endif
10447#ifdef SQLITE_DEBUG
10448 case SQLITE_TESTCTRL_TUNE: {
10449 if( nArg==4 ){
10450 int id = (int)integerValue(azArg[2]);
drh2d26cfc2021-06-04 13:40:26 +000010451 int val = (int)integerValue(azArg[3]);
10452 sqlite3_test_control(testctrl, id, &val);
10453 isOk = 3;
10454 }else if( nArg==3 ){
10455 int id = (int)integerValue(azArg[2]);
10456 sqlite3_test_control(testctrl, -id, &rc2);
10457 isOk = 1;
10458 }else if( nArg==2 ){
10459 int id = 1;
10460 while(1){
10461 int val = 0;
10462 rc2 = sqlite3_test_control(testctrl, -id, &val);
10463 if( rc2!=SQLITE_OK ) break;
10464 if( id>1 ) utf8_printf(p->out, " ");
10465 utf8_printf(p->out, "%d: %d", id, val);
10466 id++;
10467 }
10468 if( id>1 ) utf8_printf(p->out, "\n");
drhf3c12562021-06-04 13:16:46 +000010469 isOk = 3;
10470 }
10471 break;
10472 }
drh0d9de992017-12-26 18:04:23 +000010473#endif
dan779e9902021-07-28 18:13:28 +000010474 case SQLITE_TESTCTRL_SORTER_MMAP:
10475 if( nArg==3 ){
10476 int opt = (unsigned int)integerValue(azArg[2]);
10477 rc2 = sqlite3_test_control(testctrl, p->db, opt);
10478 isOk = 3;
10479 }
10480 break;
drh2ce15c32017-07-11 13:34:40 +000010481 }
10482 }
drhef302e82017-11-15 19:14:08 +000010483 if( isOk==0 && iCtrl>=0 ){
drhe2754c12019-08-26 12:50:01 +000010484 utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
drhef302e82017-11-15 19:14:08 +000010485 rc = 1;
10486 }else if( isOk==1 ){
10487 raw_printf(p->out, "%d\n", rc2);
10488 }else if( isOk==2 ){
10489 raw_printf(p->out, "0x%08x\n", rc2);
10490 }
drh2ce15c32017-07-11 13:34:40 +000010491 }else
10492#endif /* !defined(SQLITE_UNTESTABLE) */
10493
10494 if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
10495 open_db(p, 0);
10496 sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
10497 }else
10498
10499 if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
10500 if( nArg==2 ){
10501 enableTimer = booleanValue(azArg[1]);
10502 if( enableTimer && !HAS_TIMER ){
10503 raw_printf(stderr, "Error: timer not available on this system.\n");
10504 enableTimer = 0;
10505 }
10506 }else{
10507 raw_printf(stderr, "Usage: .timer on|off\n");
10508 rc = 1;
10509 }
10510 }else
10511
drh707821f2018-12-05 13:39:06 +000010512#ifndef SQLITE_OMIT_TRACE
drh2ce15c32017-07-11 13:34:40 +000010513 if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
drh707821f2018-12-05 13:39:06 +000010514 int mType = 0;
10515 int jj;
drh2ce15c32017-07-11 13:34:40 +000010516 open_db(p, 0);
drh707821f2018-12-05 13:39:06 +000010517 for(jj=1; jj<nArg; jj++){
10518 const char *z = azArg[jj];
10519 if( z[0]=='-' ){
10520 if( optionMatch(z, "expanded") ){
10521 p->eTraceType = SHELL_TRACE_EXPANDED;
10522 }
10523#ifdef SQLITE_ENABLE_NORMALIZE
10524 else if( optionMatch(z, "normalized") ){
10525 p->eTraceType = SHELL_TRACE_NORMALIZED;
10526 }
10527#endif
10528 else if( optionMatch(z, "plain") ){
10529 p->eTraceType = SHELL_TRACE_PLAIN;
10530 }
10531 else if( optionMatch(z, "profile") ){
10532 mType |= SQLITE_TRACE_PROFILE;
10533 }
10534 else if( optionMatch(z, "row") ){
10535 mType |= SQLITE_TRACE_ROW;
10536 }
10537 else if( optionMatch(z, "stmt") ){
10538 mType |= SQLITE_TRACE_STMT;
10539 }
10540 else if( optionMatch(z, "close") ){
10541 mType |= SQLITE_TRACE_CLOSE;
10542 }
10543 else {
10544 raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
10545 rc = 1;
10546 goto meta_command_exit;
10547 }
10548 }else{
10549 output_file_close(p->traceOut);
10550 p->traceOut = output_file_open(azArg[1], 0);
10551 }
drh2ce15c32017-07-11 13:34:40 +000010552 }
drh2ce15c32017-07-11 13:34:40 +000010553 if( p->traceOut==0 ){
10554 sqlite3_trace_v2(p->db, 0, 0, 0);
10555 }else{
drh707821f2018-12-05 13:39:06 +000010556 if( mType==0 ) mType = SQLITE_TRACE_STMT;
10557 sqlite3_trace_v2(p->db, mType, sql_trace_callback, p);
drh2ce15c32017-07-11 13:34:40 +000010558 }
drh2ce15c32017-07-11 13:34:40 +000010559 }else
drh707821f2018-12-05 13:39:06 +000010560#endif /* !defined(SQLITE_OMIT_TRACE) */
drh2ce15c32017-07-11 13:34:40 +000010561
drhe2b7a762019-10-02 00:25:08 +000010562#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhcc5979d2019-08-16 22:58:29 +000010563 if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){
10564 int ii;
drh8c754a32019-08-19 20:35:30 +000010565 int lenOpt;
drh5df84282019-08-17 19:45:25 +000010566 char *zOpt;
drhcc5979d2019-08-16 22:58:29 +000010567 if( nArg<2 ){
drh5df84282019-08-17 19:45:25 +000010568 raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
drhcc5979d2019-08-16 22:58:29 +000010569 rc = 1;
10570 goto meta_command_exit;
10571 }
10572 open_db(p, 0);
drh5df84282019-08-17 19:45:25 +000010573 zOpt = azArg[1];
10574 if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
drh8c754a32019-08-19 20:35:30 +000010575 lenOpt = (int)strlen(zOpt);
10576 if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){
drh5df84282019-08-17 19:45:25 +000010577 assert( azArg[nArg]==0 );
drh8c754a32019-08-19 20:35:30 +000010578 sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0);
drh5df84282019-08-17 19:45:25 +000010579 }else{
10580 for(ii=1; ii<nArg; ii++){
10581 sqlite3_create_module(p->db, azArg[ii], 0, 0);
10582 }
drhcc5979d2019-08-16 22:58:29 +000010583 }
10584 }else
10585#endif
10586
drh2ce15c32017-07-11 13:34:40 +000010587#if SQLITE_USER_AUTHENTICATION
10588 if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
10589 if( nArg<2 ){
10590 raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
10591 rc = 1;
10592 goto meta_command_exit;
10593 }
10594 open_db(p, 0);
10595 if( strcmp(azArg[1],"login")==0 ){
10596 if( nArg!=4 ){
10597 raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
10598 rc = 1;
10599 goto meta_command_exit;
10600 }
drhe2754c12019-08-26 12:50:01 +000010601 rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
10602 strlen30(azArg[3]));
drh2ce15c32017-07-11 13:34:40 +000010603 if( rc ){
10604 utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
10605 rc = 1;
10606 }
10607 }else if( strcmp(azArg[1],"add")==0 ){
10608 if( nArg!=5 ){
10609 raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
10610 rc = 1;
10611 goto meta_command_exit;
10612 }
drhaf2770f2018-01-05 14:55:43 +000010613 rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000010614 booleanValue(azArg[4]));
10615 if( rc ){
10616 raw_printf(stderr, "User-Add failed: %d\n", rc);
10617 rc = 1;
10618 }
10619 }else if( strcmp(azArg[1],"edit")==0 ){
10620 if( nArg!=5 ){
10621 raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
10622 rc = 1;
10623 goto meta_command_exit;
10624 }
drhaf2770f2018-01-05 14:55:43 +000010625 rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000010626 booleanValue(azArg[4]));
10627 if( rc ){
10628 raw_printf(stderr, "User-Edit failed: %d\n", rc);
10629 rc = 1;
10630 }
10631 }else if( strcmp(azArg[1],"delete")==0 ){
10632 if( nArg!=3 ){
10633 raw_printf(stderr, "Usage: .user delete USER\n");
10634 rc = 1;
10635 goto meta_command_exit;
10636 }
10637 rc = sqlite3_user_delete(p->db, azArg[2]);
10638 if( rc ){
10639 raw_printf(stderr, "User-Delete failed: %d\n", rc);
10640 rc = 1;
10641 }
10642 }else{
10643 raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
10644 rc = 1;
10645 goto meta_command_exit;
10646 }
10647 }else
10648#endif /* SQLITE_USER_AUTHENTICATION */
10649
10650 if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
10651 utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
10652 sqlite3_libversion(), sqlite3_sourceid());
drh0ed2fd82018-01-16 20:05:27 +000010653#if SQLITE_HAVE_ZLIB
10654 utf8_printf(p->out, "zlib version %s\n", zlibVersion());
10655#endif
10656#define CTIMEOPT_VAL_(opt) #opt
10657#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
10658#if defined(__clang__) && defined(__clang_major__)
10659 utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
10660 CTIMEOPT_VAL(__clang_minor__) "."
10661 CTIMEOPT_VAL(__clang_patchlevel__) "\n");
10662#elif defined(_MSC_VER)
10663 utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n");
10664#elif defined(__GNUC__) && defined(__VERSION__)
10665 utf8_printf(p->out, "gcc-" __VERSION__ "\n");
10666#endif
drh2ce15c32017-07-11 13:34:40 +000010667 }else
10668
10669 if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
10670 const char *zDbName = nArg==2 ? azArg[1] : "main";
10671 sqlite3_vfs *pVfs = 0;
10672 if( p->db ){
10673 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
10674 if( pVfs ){
10675 utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
10676 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
10677 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
10678 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
10679 }
10680 }
10681 }else
10682
10683 if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){
10684 sqlite3_vfs *pVfs;
10685 sqlite3_vfs *pCurrent = 0;
10686 if( p->db ){
10687 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
10688 }
10689 for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
10690 utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName,
10691 pVfs==pCurrent ? " <--- CURRENT" : "");
10692 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
10693 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
10694 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
10695 if( pVfs->pNext ){
10696 raw_printf(p->out, "-----------------------------------\n");
10697 }
10698 }
10699 }else
10700
10701 if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
10702 const char *zDbName = nArg==2 ? azArg[1] : "main";
10703 char *zVfsName = 0;
10704 if( p->db ){
10705 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
10706 if( zVfsName ){
10707 utf8_printf(p->out, "%s\n", zVfsName);
10708 sqlite3_free(zVfsName);
10709 }
10710 }
10711 }else
10712
drh2ce15c32017-07-11 13:34:40 +000010713 if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
drhc0622a42020-12-04 01:17:57 +000010714 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
10715 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x);
drh2ce15c32017-07-11 13:34:40 +000010716 }else
drh2ce15c32017-07-11 13:34:40 +000010717
10718 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
10719 int j;
10720 assert( nArg<=ArraySize(azArg) );
drh0285d982020-05-29 14:38:43 +000010721 p->nWidth = nArg-1;
drh76fc88f2021-10-02 16:39:16 +000010722 p->colWidth = realloc(p->colWidth, (p->nWidth+1)*sizeof(int)*2);
drh0285d982020-05-29 14:38:43 +000010723 if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory();
10724 if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
10725 for(j=1; j<nArg; j++){
drh2ce15c32017-07-11 13:34:40 +000010726 p->colWidth[j-1] = (int)integerValue(azArg[j]);
10727 }
10728 }else
10729
10730 {
10731 utf8_printf(stderr, "Error: unknown command or invalid arguments: "
10732 " \"%s\". Enter \".help\" for help\n", azArg[0]);
10733 rc = 1;
10734 }
10735
10736meta_command_exit:
10737 if( p->outCount ){
10738 p->outCount--;
10739 if( p->outCount==0 ) output_reset(p);
10740 }
drhb97e2ad2021-08-26 18:31:39 +000010741 p->bSafeMode = p->bSafeModePersist;
drh2ce15c32017-07-11 13:34:40 +000010742 return rc;
10743}
10744
larrybr8bc4cbc2021-09-10 00:58:46 +000010745/* Line scan result and intermediate states (supporting scan resumption)
drh2ce15c32017-07-11 13:34:40 +000010746*/
drh68911c22021-09-22 14:26:22 +000010747#ifndef CHAR_BIT
10748# define CHAR_BIT 8
10749#endif
larrybr8bc4cbc2021-09-10 00:58:46 +000010750typedef enum {
larrybr7e009842021-09-18 21:35:22 +000010751 QSS_HasDark = 1<<CHAR_BIT, QSS_EndingSemi = 2<<CHAR_BIT,
10752 QSS_CharMask = (1<<CHAR_BIT)-1, QSS_ScanMask = 3<<CHAR_BIT,
larrybra96bbe92021-09-10 19:45:22 +000010753 QSS_Start = 0
larrybr8bc4cbc2021-09-10 00:58:46 +000010754} QuickScanState;
larrybr7e009842021-09-18 21:35:22 +000010755#define QSS_SETV(qss, newst) ((newst) | ((qss) & QSS_ScanMask))
10756#define QSS_INPLAIN(qss) (((qss)&QSS_CharMask)==QSS_Start)
10757#define QSS_PLAINWHITE(qss) (((qss)&~QSS_EndingSemi)==QSS_Start)
larrybra96bbe92021-09-10 19:45:22 +000010758#define QSS_PLAINDARK(qss) (((qss)&~QSS_EndingSemi)==QSS_HasDark)
larrybr7e009842021-09-18 21:35:22 +000010759#define QSS_SEMITERM(qss) (((qss)&~QSS_HasDark)==QSS_EndingSemi)
drh2ce15c32017-07-11 13:34:40 +000010760
10761/*
larrybr8bc4cbc2021-09-10 00:58:46 +000010762** Scan line for classification to guide shell's handling.
10763** The scan is resumable for subsequent lines when prior
10764** return values are passed as the 2nd argument.
drh2ce15c32017-07-11 13:34:40 +000010765*/
larrybr8bc4cbc2021-09-10 00:58:46 +000010766static QuickScanState quickscan(char *zLine, QuickScanState qss){
10767 char cin;
larrybr7e009842021-09-18 21:35:22 +000010768 char cWait = (char)qss; /* intentional narrowing loss */
10769 if( cWait==0 ){
10770 PlainScan:
drhe85e1da2021-10-01 21:01:07 +000010771 assert( cWait==0 );
drhfd7abcd2021-09-22 13:43:16 +000010772 while( (cin = *zLine++)!=0 ){
larrybr8bc4cbc2021-09-10 00:58:46 +000010773 if( IsSpace(cin) )
10774 continue;
10775 switch (cin){
10776 case '-':
larrybr7e009842021-09-18 21:35:22 +000010777 if( *zLine!='-' )
10778 break;
10779 while((cin = *++zLine)!=0 )
10780 if( cin=='\n')
10781 goto PlainScan;
10782 return qss;
larrybr8bc4cbc2021-09-10 00:58:46 +000010783 case ';':
larrybra96bbe92021-09-10 19:45:22 +000010784 qss |= QSS_EndingSemi;
10785 continue;
larrybr8bc4cbc2021-09-10 00:58:46 +000010786 case '/':
10787 if( *zLine=='*' ){
10788 ++zLine;
larrybr7e009842021-09-18 21:35:22 +000010789 cWait = '*';
10790 qss = QSS_SETV(qss, cWait);
10791 goto TermScan;
larrybr8bc4cbc2021-09-10 00:58:46 +000010792 }
10793 break;
larrybra96bbe92021-09-10 19:45:22 +000010794 case '[':
10795 cin = ']';
10796 /* fall thru */
10797 case '`': case '\'': case '"':
larrybr7e009842021-09-18 21:35:22 +000010798 cWait = cin;
10799 qss = QSS_HasDark | cWait;
10800 goto TermScan;
larrybr8bc4cbc2021-09-10 00:58:46 +000010801 default:
10802 break;
10803 }
larrybr7e009842021-09-18 21:35:22 +000010804 qss = (qss & ~QSS_EndingSemi) | QSS_HasDark;
drh2ce15c32017-07-11 13:34:40 +000010805 }
larrybr7e009842021-09-18 21:35:22 +000010806 }else{
10807 TermScan:
drhfd7abcd2021-09-22 13:43:16 +000010808 while( (cin = *zLine++)!=0 ){
larrybr7e009842021-09-18 21:35:22 +000010809 if( cin==cWait ){
10810 switch( cWait ){
10811 case '*':
10812 if( *zLine != '/' )
10813 continue;
10814 ++zLine;
10815 cWait = 0;
10816 qss = QSS_SETV(qss, 0);
10817 goto PlainScan;
10818 case '`': case '\'': case '"':
10819 if(*zLine==cWait){
larrybr8d463ce2021-09-11 02:42:04 +000010820 ++zLine;
larrybr7e009842021-09-18 21:35:22 +000010821 continue;
10822 }
10823 /* fall thru */
10824 case ']':
10825 cWait = 0;
10826 qss = QSS_SETV(qss, 0);
10827 goto PlainScan;
10828 default: assert(0);
larrybr8bc4cbc2021-09-10 00:58:46 +000010829 }
10830 }
10831 }
drh2ce15c32017-07-11 13:34:40 +000010832 }
larrybr8bc4cbc2021-09-10 00:58:46 +000010833 return qss;
drh2ce15c32017-07-11 13:34:40 +000010834}
10835
10836/*
10837** Return TRUE if the line typed in is an SQL command terminator other
10838** than a semi-colon. The SQL Server style "go" command is understood
10839** as is the Oracle "/".
10840*/
larrybr8bc4cbc2021-09-10 00:58:46 +000010841static int line_is_command_terminator(char *zLine){
drh2ce15c32017-07-11 13:34:40 +000010842 while( IsSpace(zLine[0]) ){ zLine++; };
larrybr8bc4cbc2021-09-10 00:58:46 +000010843 if( zLine[0]=='/' )
10844 zLine += 1; /* Oracle */
10845 else if ( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o' )
10846 zLine += 2; /* SQL Server */
10847 else
10848 return 0;
larrybra96bbe92021-09-10 19:45:22 +000010849 return quickscan(zLine,QSS_Start)==QSS_Start;
drh2ce15c32017-07-11 13:34:40 +000010850}
10851
10852/*
drh56f17742018-01-24 01:58:49 +000010853** We need a default sqlite3_complete() implementation to use in case
10854** the shell is compiled with SQLITE_OMIT_COMPLETE. The default assumes
10855** any arbitrary text is a complete SQL statement. This is not very
10856** user-friendly, but it does seem to work.
10857*/
10858#ifdef SQLITE_OMIT_COMPLETE
danc86b23b2018-11-16 14:36:42 +000010859#define sqlite3_complete(x) 1
drh56f17742018-01-24 01:58:49 +000010860#endif
10861
10862/*
drh2ce15c32017-07-11 13:34:40 +000010863** Return true if zSql is a complete SQL statement. Return false if it
10864** ends in the middle of a string literal or C-style comment.
10865*/
10866static int line_is_complete(char *zSql, int nSql){
10867 int rc;
10868 if( zSql==0 ) return 1;
10869 zSql[nSql] = ';';
10870 zSql[nSql+1] = 0;
10871 rc = sqlite3_complete(zSql);
10872 zSql[nSql] = 0;
10873 return rc;
10874}
10875
10876/*
drhfc29a862018-05-11 19:11:18 +000010877** Run a single line of SQL. Return the number of errors.
drh2ce15c32017-07-11 13:34:40 +000010878*/
10879static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
10880 int rc;
10881 char *zErrMsg = 0;
10882
10883 open_db(p, 0);
10884 if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
drhfc4eeef2019-02-05 19:48:46 +000010885 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
drh2ce15c32017-07-11 13:34:40 +000010886 BEGIN_TIMER;
drha10b9992018-03-09 15:24:33 +000010887 rc = shell_exec(p, zSql, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000010888 END_TIMER;
10889 if( rc || zErrMsg ){
10890 char zPrefix[100];
10891 if( in!=0 || !stdin_is_interactive ){
10892 sqlite3_snprintf(sizeof(zPrefix), zPrefix,
10893 "Error: near line %d:", startline);
10894 }else{
10895 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
10896 }
10897 if( zErrMsg!=0 ){
10898 utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
10899 sqlite3_free(zErrMsg);
10900 zErrMsg = 0;
10901 }else{
10902 utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
10903 }
10904 return 1;
10905 }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
drh6d9f0342021-09-22 10:28:50 +000010906 char zLineBuf[2000];
10907 sqlite3_snprintf(sizeof(zLineBuf), zLineBuf,
10908 "changes: %lld total_changes: %lld",
larrybr10496f72021-06-23 16:07:20 +000010909 sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
drh6d9f0342021-09-22 10:28:50 +000010910 raw_printf(p->out, "%s\n", zLineBuf);
drh2ce15c32017-07-11 13:34:40 +000010911 }
10912 return 0;
10913}
10914
10915
10916/*
10917** Read input from *in and process it. If *in==0 then input
10918** is interactive - the user is typing it it. Otherwise, input
10919** is coming from a file or device. A prompt is issued and history
10920** is saved only if input is interactive. An interrupt signal will
10921** cause this routine to exit immediately, unless input is interactive.
10922**
10923** Return the number of errors.
10924*/
drh60379d42018-12-13 18:30:01 +000010925static int process_input(ShellState *p){
drh2ce15c32017-07-11 13:34:40 +000010926 char *zLine = 0; /* A single input line */
10927 char *zSql = 0; /* Accumulated SQL text */
10928 int nLine; /* Length of current line */
10929 int nSql = 0; /* Bytes of zSql[] used */
10930 int nAlloc = 0; /* Allocated zSql[] space */
drh2ce15c32017-07-11 13:34:40 +000010931 int rc; /* Error code */
10932 int errCnt = 0; /* Number of errors seen */
drh2ce15c32017-07-11 13:34:40 +000010933 int startline = 0; /* Line number for start of current input */
larrybr7e009842021-09-18 21:35:22 +000010934 QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */
drh2ce15c32017-07-11 13:34:40 +000010935
drh2c8ee022018-12-13 18:59:30 +000010936 p->lineno = 0;
drh60379d42018-12-13 18:30:01 +000010937 while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
drh2ce15c32017-07-11 13:34:40 +000010938 fflush(p->out);
drh60379d42018-12-13 18:30:01 +000010939 zLine = one_input_line(p->in, zLine, nSql>0);
drh2ce15c32017-07-11 13:34:40 +000010940 if( zLine==0 ){
10941 /* End of input */
drh60379d42018-12-13 18:30:01 +000010942 if( p->in==0 && stdin_is_interactive ) printf("\n");
drh2ce15c32017-07-11 13:34:40 +000010943 break;
10944 }
10945 if( seenInterrupt ){
drh60379d42018-12-13 18:30:01 +000010946 if( p->in!=0 ) break;
drh2ce15c32017-07-11 13:34:40 +000010947 seenInterrupt = 0;
10948 }
drh2c8ee022018-12-13 18:59:30 +000010949 p->lineno++;
larrybr7e009842021-09-18 21:35:22 +000010950 if( QSS_INPLAIN(qss)
larrybr8bc4cbc2021-09-10 00:58:46 +000010951 && line_is_command_terminator(zLine)
10952 && line_is_complete(zSql, nSql) ){
10953 memcpy(zLine,";",2);
10954 }
10955 qss = quickscan(zLine, qss);
10956 if( QSS_PLAINWHITE(qss) && nSql==0 ){
10957 if( ShellHasFlag(p, SHFLG_Echo) )
10958 printf("%s\n", zLine);
larrybrd797d6b2021-10-03 22:03:59 +000010959 /* Just swallow single-line whitespace */
10960 qss = QSS_Start;
larrybr8bc4cbc2021-09-10 00:58:46 +000010961 continue;
drh2ce15c32017-07-11 13:34:40 +000010962 }
drh1615c372018-05-12 23:56:22 +000010963 if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
drh2ce15c32017-07-11 13:34:40 +000010964 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
drh1615c372018-05-12 23:56:22 +000010965 if( zLine[0]=='.' ){
10966 rc = do_meta_command(zLine, p);
10967 if( rc==2 ){ /* exit requested */
10968 break;
10969 }else if( rc ){
10970 errCnt++;
10971 }
drh2ce15c32017-07-11 13:34:40 +000010972 }
larrybr81012162021-10-02 15:34:52 +000010973 qss = QSS_Start;
drh2ce15c32017-07-11 13:34:40 +000010974 continue;
10975 }
larrybrd797d6b2021-10-03 22:03:59 +000010976 /* No single-line dispositions remain; accumulate line(s). */
drh2ce15c32017-07-11 13:34:40 +000010977 nLine = strlen30(zLine);
10978 if( nSql+nLine+2>=nAlloc ){
larrybr31bffb42021-09-08 21:49:03 +000010979 /* Grow buffer by half-again increments when big. */
10980 nAlloc = nSql+(nSql>>1)+nLine+100;
drh2ce15c32017-07-11 13:34:40 +000010981 zSql = realloc(zSql, nAlloc);
drhe3e25652021-12-16 13:29:28 +000010982 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +000010983 }
drh2ce15c32017-07-11 13:34:40 +000010984 if( nSql==0 ){
10985 int i;
10986 for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
10987 assert( nAlloc>0 && zSql!=0 );
10988 memcpy(zSql, zLine+i, nLine+1-i);
drh2c8ee022018-12-13 18:59:30 +000010989 startline = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000010990 nSql = nLine-i;
10991 }else{
10992 zSql[nSql++] = '\n';
10993 memcpy(zSql+nSql, zLine, nLine+1);
10994 nSql += nLine;
10995 }
larrybra96bbe92021-09-10 19:45:22 +000010996 if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){
drh60379d42018-12-13 18:30:01 +000010997 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000010998 nSql = 0;
10999 if( p->outCount ){
11000 output_reset(p);
11001 p->outCount = 0;
drh13c20932018-01-10 21:41:55 +000011002 }else{
11003 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +000011004 }
drhb97e2ad2021-08-26 18:31:39 +000011005 p->bSafeMode = p->bSafeModePersist;
larrybrd797d6b2021-10-03 22:03:59 +000011006 qss = QSS_Start;
larrybr8bc4cbc2021-09-10 00:58:46 +000011007 }else if( nSql && QSS_PLAINWHITE(qss) ){
drh2ce15c32017-07-11 13:34:40 +000011008 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
11009 nSql = 0;
larrybrd797d6b2021-10-03 22:03:59 +000011010 qss = QSS_Start;
drh2ce15c32017-07-11 13:34:40 +000011011 }
11012 }
larrybr8bc4cbc2021-09-10 00:58:46 +000011013 if( nSql && QSS_PLAINDARK(qss) ){
drh60379d42018-12-13 18:30:01 +000011014 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000011015 }
11016 free(zSql);
11017 free(zLine);
11018 return errCnt>0;
11019}
11020
11021/*
11022** Return a pathname which is the user's home directory. A
11023** 0 return indicates an error of some kind.
11024*/
11025static char *find_home_dir(int clearFlag){
11026 static char *home_dir = NULL;
11027 if( clearFlag ){
11028 free(home_dir);
11029 home_dir = 0;
11030 return 0;
11031 }
11032 if( home_dir ) return home_dir;
11033
11034#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
11035 && !defined(__RTP__) && !defined(_WRS_KERNEL)
11036 {
11037 struct passwd *pwent;
11038 uid_t uid = getuid();
11039 if( (pwent=getpwuid(uid)) != NULL) {
11040 home_dir = pwent->pw_dir;
11041 }
11042 }
11043#endif
11044
11045#if defined(_WIN32_WCE)
11046 /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
11047 */
11048 home_dir = "/";
11049#else
11050
11051#if defined(_WIN32) || defined(WIN32)
11052 if (!home_dir) {
11053 home_dir = getenv("USERPROFILE");
11054 }
11055#endif
11056
11057 if (!home_dir) {
11058 home_dir = getenv("HOME");
11059 }
11060
11061#if defined(_WIN32) || defined(WIN32)
11062 if (!home_dir) {
11063 char *zDrive, *zPath;
11064 int n;
11065 zDrive = getenv("HOMEDRIVE");
11066 zPath = getenv("HOMEPATH");
11067 if( zDrive && zPath ){
11068 n = strlen30(zDrive) + strlen30(zPath) + 1;
11069 home_dir = malloc( n );
11070 if( home_dir==0 ) return 0;
11071 sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
11072 return home_dir;
11073 }
11074 home_dir = "c:\\";
11075 }
11076#endif
11077
11078#endif /* !_WIN32_WCE */
11079
11080 if( home_dir ){
11081 int n = strlen30(home_dir) + 1;
11082 char *z = malloc( n );
11083 if( z ) memcpy(z, home_dir, n);
11084 home_dir = z;
11085 }
11086
11087 return home_dir;
11088}
11089
11090/*
11091** Read input from the file given by sqliterc_override. Or if that
11092** parameter is NULL, take input from ~/.sqliterc
11093**
11094** Returns the number of errors.
11095*/
11096static void process_sqliterc(
11097 ShellState *p, /* Configuration data */
11098 const char *sqliterc_override /* Name of config file. NULL to use default */
11099){
11100 char *home_dir = NULL;
11101 const char *sqliterc = sqliterc_override;
11102 char *zBuf = 0;
drh60379d42018-12-13 18:30:01 +000011103 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +000011104 int savedLineno = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000011105
11106 if (sqliterc == NULL) {
11107 home_dir = find_home_dir(0);
11108 if( home_dir==0 ){
11109 raw_printf(stderr, "-- warning: cannot find home directory;"
11110 " cannot read ~/.sqliterc\n");
11111 return;
11112 }
drh2ce15c32017-07-11 13:34:40 +000011113 zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
drhe3e25652021-12-16 13:29:28 +000011114 shell_check_oom(zBuf);
drh2ce15c32017-07-11 13:34:40 +000011115 sqliterc = zBuf;
11116 }
drh60379d42018-12-13 18:30:01 +000011117 p->in = fopen(sqliterc,"rb");
11118 if( p->in ){
drh2ce15c32017-07-11 13:34:40 +000011119 if( stdin_is_interactive ){
11120 utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
11121 }
drhb7c46aa2020-11-25 13:59:47 +000011122 if( process_input(p) && bail_on_error ) exit(1);
drh60379d42018-12-13 18:30:01 +000011123 fclose(p->in);
drhb7c46aa2020-11-25 13:59:47 +000011124 }else if( sqliterc_override!=0 ){
11125 utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
11126 if( bail_on_error ) exit(1);
drh2ce15c32017-07-11 13:34:40 +000011127 }
drh60379d42018-12-13 18:30:01 +000011128 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +000011129 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +000011130 sqlite3_free(zBuf);
11131}
11132
11133/*
11134** Show available command line options
11135*/
11136static const char zOptions[] =
drhda57d962018-03-05 19:34:05 +000011137#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhad7fd5d2018-03-05 20:21:50 +000011138 " -A ARGS... run \".archive ARGS\" and exit\n"
drhda57d962018-03-05 19:34:05 +000011139#endif
drh3baed312018-03-08 18:14:41 +000011140 " -append append the database to the end of the file\n"
drh2ce15c32017-07-11 13:34:40 +000011141 " -ascii set output mode to 'ascii'\n"
11142 " -bail stop after hitting an error\n"
11143 " -batch force batch I/O\n"
drh0908e382020-06-04 18:05:39 +000011144 " -box set output mode to 'box'\n"
drh2ce15c32017-07-11 13:34:40 +000011145 " -column set output mode to 'column'\n"
11146 " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
11147 " -csv set output mode to 'csv'\n"
drh8d889af2021-05-08 17:18:23 +000011148#if !defined(SQLITE_OMIT_DESERIALIZE)
drh6ca64482019-01-22 16:06:20 +000011149 " -deserialize open the database using sqlite3_deserialize()\n"
11150#endif
drh2ce15c32017-07-11 13:34:40 +000011151 " -echo print commands before execution\n"
11152 " -init FILENAME read/process named file\n"
11153 " -[no]header turn headers on or off\n"
11154#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
11155 " -heap SIZE Size of heap for memsys3 or memsys5\n"
11156#endif
11157 " -help show this message\n"
11158 " -html set output mode to HTML\n"
11159 " -interactive force interactive I/O\n"
drh30c54a02020-05-28 23:49:50 +000011160 " -json set output mode to 'json'\n"
drh2ce15c32017-07-11 13:34:40 +000011161 " -line set output mode to 'line'\n"
11162 " -list set output mode to 'list'\n"
11163 " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
drh30c54a02020-05-28 23:49:50 +000011164 " -markdown set output mode to 'markdown'\n"
drh8d889af2021-05-08 17:18:23 +000011165#if !defined(SQLITE_OMIT_DESERIALIZE)
drh6ca64482019-01-22 16:06:20 +000011166 " -maxsize N maximum size for a --deserialize database\n"
11167#endif
drhaf482572019-02-04 19:52:39 +000011168 " -memtrace trace all memory allocations and deallocations\n"
drh2ce15c32017-07-11 13:34:40 +000011169 " -mmap N default mmap size set to N\n"
11170#ifdef SQLITE_ENABLE_MULTIPLEX
11171 " -multiplex enable the multiplexor VFS\n"
11172#endif
11173 " -newline SEP set output row separator. Default: '\\n'\n"
drh0933aad2019-11-18 17:46:38 +000011174 " -nofollow refuse to open symbolic links to database files\n"
drhb97e2ad2021-08-26 18:31:39 +000011175 " -nonce STRING set the safe-mode escape nonce\n"
drh2ce15c32017-07-11 13:34:40 +000011176 " -nullvalue TEXT set text string for NULL values. Default ''\n"
11177 " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
11178 " -quote set output mode to 'quote'\n"
drhee269a62018-02-14 23:27:43 +000011179 " -readonly open the database read-only\n"
drhb97e2ad2021-08-26 18:31:39 +000011180 " -safe enable safe-mode\n"
drh2ce15c32017-07-11 13:34:40 +000011181 " -separator SEP set output column separator. Default: '|'\n"
drha90d84f2018-04-18 15:21:13 +000011182#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11183 " -sorterref SIZE sorter references threshold size\n"
11184#endif
drh2ce15c32017-07-11 13:34:40 +000011185 " -stats print memory stats before each finalize\n"
drh30c54a02020-05-28 23:49:50 +000011186 " -table set output mode to 'table'\n"
drh2fa78182020-10-31 18:58:37 +000011187 " -tabs set output mode to 'tabs'\n"
drh2ce15c32017-07-11 13:34:40 +000011188 " -version show SQLite version\n"
11189 " -vfs NAME use NAME as the default VFS\n"
11190#ifdef SQLITE_ENABLE_VFSTRACE
11191 " -vfstrace enable tracing of all VFS calls\n"
11192#endif
drh3baed312018-03-08 18:14:41 +000011193#ifdef SQLITE_HAVE_ZLIB
11194 " -zip open the file as a ZIP Archive\n"
11195#endif
drh2ce15c32017-07-11 13:34:40 +000011196;
11197static void usage(int showDetail){
11198 utf8_printf(stderr,
11199 "Usage: %s [OPTIONS] FILENAME [SQL]\n"
11200 "FILENAME is the name of an SQLite database. A new database is created\n"
11201 "if the file does not previously exist.\n", Argv0);
11202 if( showDetail ){
11203 utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
11204 }else{
11205 raw_printf(stderr, "Use the -help option for additional information\n");
11206 }
11207 exit(1);
11208}
11209
11210/*
drhe7df8922018-04-18 10:44:58 +000011211** Internal check: Verify that the SQLite is uninitialized. Print a
11212** error message if it is initialized.
11213*/
11214static void verify_uninitialized(void){
11215 if( sqlite3_config(-1)==SQLITE_MISUSE ){
drh8e02a182018-05-30 07:24:41 +000011216 utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
drhe7df8922018-04-18 10:44:58 +000011217 " initialization.\n");
11218 }
11219}
11220
11221/*
drh2ce15c32017-07-11 13:34:40 +000011222** Initialize the state information in data
11223*/
11224static void main_init(ShellState *data) {
11225 memset(data, 0, sizeof(*data));
11226 data->normalMode = data->cMode = data->mode = MODE_List;
11227 data->autoExplain = 1;
drh37407122021-07-23 18:43:58 +000011228 data->pAuxDb = &data->aAuxDb[0];
drh2ce15c32017-07-11 13:34:40 +000011229 memcpy(data->colSeparator,SEP_Column, 2);
11230 memcpy(data->rowSeparator,SEP_Row, 2);
11231 data->showHeader = 0;
11232 data->shellFlgs = SHFLG_Lookaside;
drhe7df8922018-04-18 10:44:58 +000011233 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000011234 sqlite3_config(SQLITE_CONFIG_URI, 1);
11235 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
11236 sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
11237 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
11238 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
11239}
11240
11241/*
11242** Output text to the console in a font that attracts extra attention.
11243*/
11244#ifdef _WIN32
11245static void printBold(const char *zText){
mistachkin43e86272020-04-09 15:31:22 +000011246#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000011247 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
11248 CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
11249 GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
11250 SetConsoleTextAttribute(out,
11251 FOREGROUND_RED|FOREGROUND_INTENSITY
11252 );
mistachkin43e86272020-04-09 15:31:22 +000011253#endif
drh2ce15c32017-07-11 13:34:40 +000011254 printf("%s", zText);
mistachkin43e86272020-04-09 15:31:22 +000011255#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000011256 SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
mistachkin43e86272020-04-09 15:31:22 +000011257#endif
drh2ce15c32017-07-11 13:34:40 +000011258}
11259#else
11260static void printBold(const char *zText){
11261 printf("\033[1m%s\033[0m", zText);
11262}
11263#endif
11264
11265/*
11266** Get the argument to an --option. Throw an error and die if no argument
11267** is available.
11268*/
11269static char *cmdline_option_value(int argc, char **argv, int i){
11270 if( i==argc ){
11271 utf8_printf(stderr, "%s: Error: missing argument to %s\n",
11272 argv[0], argv[argc-1]);
11273 exit(1);
11274 }
11275 return argv[i];
11276}
11277
11278#ifndef SQLITE_SHELL_IS_UTF8
dan39b6bd52021-03-04 18:31:07 +000011279# if (defined(_WIN32) || defined(WIN32)) \
11280 && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
drh2ce15c32017-07-11 13:34:40 +000011281# define SQLITE_SHELL_IS_UTF8 (0)
11282# else
11283# define SQLITE_SHELL_IS_UTF8 (1)
11284# endif
11285#endif
11286
11287#if SQLITE_SHELL_IS_UTF8
11288int SQLITE_CDECL main(int argc, char **argv){
11289#else
11290int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
11291 char **argv;
11292#endif
11293 char *zErrMsg = 0;
11294 ShellState data;
11295 const char *zInitFile = 0;
11296 int i;
11297 int rc = 0;
11298 int warnInmemoryDb = 0;
11299 int readStdin = 1;
11300 int nCmd = 0;
11301 char **azCmd = 0;
dan16a47422018-04-18 09:16:11 +000011302 const char *zVfs = 0; /* Value of -vfs command-line option */
drh1f22f622018-05-17 13:29:14 +000011303#if !SQLITE_SHELL_IS_UTF8
11304 char **argvToFree = 0;
11305 int argcToFree = 0;
11306#endif
drh2ce15c32017-07-11 13:34:40 +000011307
11308 setBinaryMode(stdin, 0);
11309 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
11310 stdin_is_interactive = isatty(0);
11311 stdout_is_console = isatty(1);
11312
mistachkin1e8487d2018-07-22 06:25:35 +000011313#if !defined(_WIN32_WCE)
11314 if( getenv("SQLITE_DEBUG_BREAK") ){
11315 if( isatty(0) && isatty(2) ){
11316 fprintf(stderr,
11317 "attach debugger to process %d and press any key to continue.\n",
11318 GETPID());
11319 fgetc(stdin);
11320 }else{
11321#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +000011322#if SQLITE_OS_WINRT
11323 __debugbreak();
11324#else
mistachkin1e8487d2018-07-22 06:25:35 +000011325 DebugBreak();
mistachkin43e86272020-04-09 15:31:22 +000011326#endif
mistachkin1e8487d2018-07-22 06:25:35 +000011327#elif defined(SIGTRAP)
11328 raise(SIGTRAP);
11329#endif
11330 }
11331 }
11332#endif
11333
drh2ce15c32017-07-11 13:34:40 +000011334#if USE_SYSTEM_SQLITE+0!=1
drhb3c45232017-08-28 14:33:27 +000011335 if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
drh2ce15c32017-07-11 13:34:40 +000011336 utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
11337 sqlite3_sourceid(), SQLITE_SOURCE_ID);
11338 exit(1);
11339 }
11340#endif
11341 main_init(&data);
drh501ea052018-02-15 01:03:37 +000011342
11343 /* On Windows, we must translate command-line arguments into UTF-8.
11344 ** The SQLite memory allocator subsystem has to be enabled in order to
11345 ** do this. But we want to run an sqlite3_shutdown() afterwards so that
11346 ** subsequent sqlite3_config() calls will work. So copy all results into
11347 ** memory that does not come from the SQLite memory allocator.
11348 */
drh4b18c1d2018-02-04 20:33:13 +000011349#if !SQLITE_SHELL_IS_UTF8
drh501ea052018-02-15 01:03:37 +000011350 sqlite3_initialize();
drh1f22f622018-05-17 13:29:14 +000011351 argvToFree = malloc(sizeof(argv[0])*argc*2);
drhe3e25652021-12-16 13:29:28 +000011352 shell_check_oom(argvToFree);
drh1f22f622018-05-17 13:29:14 +000011353 argcToFree = argc;
11354 argv = argvToFree + argc;
drh2ce15c32017-07-11 13:34:40 +000011355 for(i=0; i<argc; i++){
drh501ea052018-02-15 01:03:37 +000011356 char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
11357 int n;
drhe3e25652021-12-16 13:29:28 +000011358 shell_check_oom(z);
drh501ea052018-02-15 01:03:37 +000011359 n = (int)strlen(z);
11360 argv[i] = malloc( n+1 );
drhe3e25652021-12-16 13:29:28 +000011361 shell_check_oom(argv[i]);
drh501ea052018-02-15 01:03:37 +000011362 memcpy(argv[i], z, n+1);
drh1f22f622018-05-17 13:29:14 +000011363 argvToFree[i] = argv[i];
drh501ea052018-02-15 01:03:37 +000011364 sqlite3_free(z);
drh2ce15c32017-07-11 13:34:40 +000011365 }
drh501ea052018-02-15 01:03:37 +000011366 sqlite3_shutdown();
drh2ce15c32017-07-11 13:34:40 +000011367#endif
drh501ea052018-02-15 01:03:37 +000011368
drh2ce15c32017-07-11 13:34:40 +000011369 assert( argc>=1 && argv && argv[0] );
11370 Argv0 = argv[0];
11371
11372 /* Make sure we have a valid signal handler early, before anything
11373 ** else is done.
11374 */
11375#ifdef SIGINT
11376 signal(SIGINT, interrupt_handler);
mistachkinb4bab902017-10-27 17:09:44 +000011377#elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
11378 SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
drh2ce15c32017-07-11 13:34:40 +000011379#endif
11380
11381#ifdef SQLITE_SHELL_DBNAME_PROC
11382 {
11383 /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
11384 ** of a C-function that will provide the name of the database file. Use
11385 ** this compile-time option to embed this shell program in larger
11386 ** applications. */
11387 extern void SQLITE_SHELL_DBNAME_PROC(const char**);
drh37407122021-07-23 18:43:58 +000011388 SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename);
drh2ce15c32017-07-11 13:34:40 +000011389 warnInmemoryDb = 0;
11390 }
11391#endif
11392
11393 /* Do an initial pass through the command-line argument to locate
11394 ** the name of the database file, the name of the initialization file,
11395 ** the size of the alternative malloc heap,
11396 ** and the first command to execute.
11397 */
drhe7df8922018-04-18 10:44:58 +000011398 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000011399 for(i=1; i<argc; i++){
11400 char *z;
11401 z = argv[i];
11402 if( z[0]!='-' ){
drh37407122021-07-23 18:43:58 +000011403 if( data.aAuxDb->zDbFilename==0 ){
11404 data.aAuxDb->zDbFilename = z;
drh2ce15c32017-07-11 13:34:40 +000011405 }else{
11406 /* Excesss arguments are interpreted as SQL (or dot-commands) and
11407 ** mean that nothing is read from stdin */
11408 readStdin = 0;
11409 nCmd++;
11410 azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
drhe3e25652021-12-16 13:29:28 +000011411 shell_check_oom(azCmd);
drh2ce15c32017-07-11 13:34:40 +000011412 azCmd[nCmd-1] = z;
11413 }
11414 }
11415 if( z[1]=='-' ) z++;
11416 if( strcmp(z,"-separator")==0
11417 || strcmp(z,"-nullvalue")==0
11418 || strcmp(z,"-newline")==0
11419 || strcmp(z,"-cmd")==0
11420 ){
11421 (void)cmdline_option_value(argc, argv, ++i);
11422 }else if( strcmp(z,"-init")==0 ){
11423 zInitFile = cmdline_option_value(argc, argv, ++i);
11424 }else if( strcmp(z,"-batch")==0 ){
11425 /* Need to check for batch mode here to so we can avoid printing
11426 ** informational messages (like from process_sqliterc) before
11427 ** we do the actual processing of arguments later in a second pass.
11428 */
11429 stdin_is_interactive = 0;
11430 }else if( strcmp(z,"-heap")==0 ){
11431#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
11432 const char *zSize;
11433 sqlite3_int64 szHeap;
11434
11435 zSize = cmdline_option_value(argc, argv, ++i);
11436 szHeap = integerValue(zSize);
11437 if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
11438 sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
11439#else
11440 (void)cmdline_option_value(argc, argv, ++i);
11441#endif
drh2ce15c32017-07-11 13:34:40 +000011442 }else if( strcmp(z,"-pagecache")==0 ){
drhf573b4f2020-09-28 13:34:05 +000011443 sqlite3_int64 n, sz;
11444 sz = integerValue(cmdline_option_value(argc,argv,++i));
drh2ce15c32017-07-11 13:34:40 +000011445 if( sz>70000 ) sz = 70000;
11446 if( sz<0 ) sz = 0;
drhf573b4f2020-09-28 13:34:05 +000011447 n = integerValue(cmdline_option_value(argc,argv,++i));
11448 if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
11449 n = 0xffffffffffffLL/sz;
11450 }
drh2ce15c32017-07-11 13:34:40 +000011451 sqlite3_config(SQLITE_CONFIG_PAGECACHE,
11452 (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
11453 data.shellFlgs |= SHFLG_Pagecache;
11454 }else if( strcmp(z,"-lookaside")==0 ){
11455 int n, sz;
11456 sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
11457 if( sz<0 ) sz = 0;
11458 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
11459 if( n<0 ) n = 0;
11460 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
11461 if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
drhaf6d1af2021-08-09 17:37:58 +000011462 }else if( strcmp(z,"-threadsafe")==0 ){
drh9d16fb12021-08-09 17:45:00 +000011463 int n;
11464 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
11465 switch( n ){
drhaf6d1af2021-08-09 17:37:58 +000011466 case 0: sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); break;
11467 case 2: sqlite3_config(SQLITE_CONFIG_MULTITHREAD); break;
11468 default: sqlite3_config(SQLITE_CONFIG_SERIALIZED); break;
11469 }
drh2ce15c32017-07-11 13:34:40 +000011470#ifdef SQLITE_ENABLE_VFSTRACE
11471 }else if( strcmp(z,"-vfstrace")==0 ){
11472 extern int vfstrace_register(
11473 const char *zTraceName,
11474 const char *zOldVfsName,
11475 int (*xOut)(const char*,void*),
11476 void *pOutArg,
11477 int makeDefault
11478 );
11479 vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
11480#endif
11481#ifdef SQLITE_ENABLE_MULTIPLEX
11482 }else if( strcmp(z,"-multiplex")==0 ){
11483 extern int sqlite3_multiple_initialize(const char*,int);
11484 sqlite3_multiplex_initialize(0, 1);
11485#endif
11486 }else if( strcmp(z,"-mmap")==0 ){
11487 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
11488 sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
drha90d84f2018-04-18 15:21:13 +000011489#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11490 }else if( strcmp(z,"-sorterref")==0 ){
11491 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
11492 sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz);
11493#endif
drh2ce15c32017-07-11 13:34:40 +000011494 }else if( strcmp(z,"-vfs")==0 ){
dan16a47422018-04-18 09:16:11 +000011495 zVfs = cmdline_option_value(argc, argv, ++i);
drh3baed312018-03-08 18:14:41 +000011496#ifdef SQLITE_HAVE_ZLIB
drh8682e122018-01-07 20:38:10 +000011497 }else if( strcmp(z,"-zip")==0 ){
11498 data.openMode = SHELL_OPEN_ZIPFILE;
11499#endif
11500 }else if( strcmp(z,"-append")==0 ){
11501 data.openMode = SHELL_OPEN_APPENDVFS;
drh8d889af2021-05-08 17:18:23 +000011502#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +000011503 }else if( strcmp(z,"-deserialize")==0 ){
11504 data.openMode = SHELL_OPEN_DESERIALIZE;
drh6ca64482019-01-22 16:06:20 +000011505 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
11506 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000011507#endif
drhee269a62018-02-14 23:27:43 +000011508 }else if( strcmp(z,"-readonly")==0 ){
11509 data.openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +000011510 }else if( strcmp(z,"-nofollow")==0 ){
11511 data.openFlags = SQLITE_OPEN_NOFOLLOW;
drhda57d962018-03-05 19:34:05 +000011512#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drh93b77312018-03-05 20:20:22 +000011513 }else if( strncmp(z, "-A",2)==0 ){
drhda57d962018-03-05 19:34:05 +000011514 /* All remaining command-line arguments are passed to the ".archive"
11515 ** command, so ignore them */
11516 break;
11517#endif
drh50b910a2019-01-21 14:55:03 +000011518 }else if( strcmp(z, "-memtrace")==0 ){
11519 sqlite3MemTraceActivate(stderr);
drhb7c46aa2020-11-25 13:59:47 +000011520 }else if( strcmp(z,"-bail")==0 ){
11521 bail_on_error = 1;
drhb97e2ad2021-08-26 18:31:39 +000011522 }else if( strcmp(z,"-nonce")==0 ){
11523 free(data.zNonce);
11524 data.zNonce = strdup(argv[++i]);
11525 }else if( strcmp(z,"-safe")==0 ){
11526 /* no-op - catch this on the second pass */
drh2ce15c32017-07-11 13:34:40 +000011527 }
11528 }
drhe7df8922018-04-18 10:44:58 +000011529 verify_uninitialized();
11530
dan16a47422018-04-18 09:16:11 +000011531
drhd11b8f62018-04-25 13:27:07 +000011532#ifdef SQLITE_SHELL_INIT_PROC
11533 {
11534 /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name
11535 ** of a C-function that will perform initialization actions on SQLite that
11536 ** occur just before or after sqlite3_initialize(). Use this compile-time
11537 ** option to embed this shell program in larger applications. */
11538 extern void SQLITE_SHELL_INIT_PROC(void);
11539 SQLITE_SHELL_INIT_PROC();
11540 }
11541#else
dan16a47422018-04-18 09:16:11 +000011542 /* All the sqlite3_config() calls have now been made. So it is safe
11543 ** to call sqlite3_initialize() and process any command line -vfs option. */
11544 sqlite3_initialize();
drhd11b8f62018-04-25 13:27:07 +000011545#endif
11546
dan16a47422018-04-18 09:16:11 +000011547 if( zVfs ){
11548 sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
11549 if( pVfs ){
11550 sqlite3_vfs_register(pVfs, 1);
11551 }else{
11552 utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
11553 exit(1);
11554 }
11555 }
11556
drh37407122021-07-23 18:43:58 +000011557 if( data.pAuxDb->zDbFilename==0 ){
drh2ce15c32017-07-11 13:34:40 +000011558#ifndef SQLITE_OMIT_MEMORYDB
drh37407122021-07-23 18:43:58 +000011559 data.pAuxDb->zDbFilename = ":memory:";
drh2ce15c32017-07-11 13:34:40 +000011560 warnInmemoryDb = argc==1;
11561#else
11562 utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
11563 return 1;
11564#endif
11565 }
11566 data.out = stdout;
drh8682e122018-01-07 20:38:10 +000011567 sqlite3_appendvfs_init(0,0,0);
drh2ce15c32017-07-11 13:34:40 +000011568
11569 /* Go ahead and open the database file if it already exists. If the
11570 ** file does not exist, delay opening it. This prevents empty database
11571 ** files from being created if a user mistypes the database name argument
11572 ** to the sqlite command-line tool.
11573 */
drh37407122021-07-23 18:43:58 +000011574 if( access(data.pAuxDb->zDbFilename, 0)==0 ){
drh2ce15c32017-07-11 13:34:40 +000011575 open_db(&data, 0);
11576 }
11577
11578 /* Process the initialization file if there is one. If no -init option
11579 ** is given on the command line, look for a file named ~/.sqliterc and
11580 ** try to process it.
11581 */
11582 process_sqliterc(&data,zInitFile);
11583
11584 /* Make a second pass through the command-line argument and set
11585 ** options. This second pass is delayed until after the initialization
11586 ** file is processed so that the command-line arguments will override
11587 ** settings in the initialization file.
11588 */
11589 for(i=1; i<argc; i++){
11590 char *z = argv[i];
11591 if( z[0]!='-' ) continue;
11592 if( z[1]=='-' ){ z++; }
11593 if( strcmp(z,"-init")==0 ){
11594 i++;
11595 }else if( strcmp(z,"-html")==0 ){
11596 data.mode = MODE_Html;
11597 }else if( strcmp(z,"-list")==0 ){
11598 data.mode = MODE_List;
11599 }else if( strcmp(z,"-quote")==0 ){
11600 data.mode = MODE_Quote;
drh9191c702020-08-17 09:11:21 +000011601 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma);
11602 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +000011603 }else if( strcmp(z,"-line")==0 ){
11604 data.mode = MODE_Line;
11605 }else if( strcmp(z,"-column")==0 ){
11606 data.mode = MODE_Column;
drh30c54a02020-05-28 23:49:50 +000011607 }else if( strcmp(z,"-json")==0 ){
11608 data.mode = MODE_Json;
11609 }else if( strcmp(z,"-markdown")==0 ){
11610 data.mode = MODE_Markdown;
11611 }else if( strcmp(z,"-table")==0 ){
11612 data.mode = MODE_Table;
drh0908e382020-06-04 18:05:39 +000011613 }else if( strcmp(z,"-box")==0 ){
11614 data.mode = MODE_Box;
drh2ce15c32017-07-11 13:34:40 +000011615 }else if( strcmp(z,"-csv")==0 ){
11616 data.mode = MODE_Csv;
11617 memcpy(data.colSeparator,",",2);
drh3baed312018-03-08 18:14:41 +000011618#ifdef SQLITE_HAVE_ZLIB
drh1fa6d9f2018-01-06 21:46:01 +000011619 }else if( strcmp(z,"-zip")==0 ){
11620 data.openMode = SHELL_OPEN_ZIPFILE;
11621#endif
11622 }else if( strcmp(z,"-append")==0 ){
11623 data.openMode = SHELL_OPEN_APPENDVFS;
drh8d889af2021-05-08 17:18:23 +000011624#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +000011625 }else if( strcmp(z,"-deserialize")==0 ){
11626 data.openMode = SHELL_OPEN_DESERIALIZE;
drh6ca64482019-01-22 16:06:20 +000011627 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
11628 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000011629#endif
drh4aafe592018-03-23 16:08:30 +000011630 }else if( strcmp(z,"-readonly")==0 ){
11631 data.openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +000011632 }else if( strcmp(z,"-nofollow")==0 ){
11633 data.openFlags |= SQLITE_OPEN_NOFOLLOW;
drh2ce15c32017-07-11 13:34:40 +000011634 }else if( strcmp(z,"-ascii")==0 ){
11635 data.mode = MODE_Ascii;
drh2fa78182020-10-31 18:58:37 +000011636 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit);
11637 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record);
11638 }else if( strcmp(z,"-tabs")==0 ){
11639 data.mode = MODE_List;
11640 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Tab);
11641 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +000011642 }else if( strcmp(z,"-separator")==0 ){
11643 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
11644 "%s",cmdline_option_value(argc,argv,++i));
11645 }else if( strcmp(z,"-newline")==0 ){
11646 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
11647 "%s",cmdline_option_value(argc,argv,++i));
11648 }else if( strcmp(z,"-nullvalue")==0 ){
11649 sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
11650 "%s",cmdline_option_value(argc,argv,++i));
11651 }else if( strcmp(z,"-header")==0 ){
11652 data.showHeader = 1;
larrybrae509122021-09-10 01:45:20 +000011653 ShellSetFlag(&data, SHFLG_HeaderSet);
11654 }else if( strcmp(z,"-noheader")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011655 data.showHeader = 0;
larrybrae509122021-09-10 01:45:20 +000011656 ShellSetFlag(&data, SHFLG_HeaderSet);
drh2ce15c32017-07-11 13:34:40 +000011657 }else if( strcmp(z,"-echo")==0 ){
11658 ShellSetFlag(&data, SHFLG_Echo);
11659 }else if( strcmp(z,"-eqp")==0 ){
drhada70452017-12-21 21:02:27 +000011660 data.autoEQP = AUTOEQP_on;
drh2ce15c32017-07-11 13:34:40 +000011661 }else if( strcmp(z,"-eqpfull")==0 ){
drhada70452017-12-21 21:02:27 +000011662 data.autoEQP = AUTOEQP_full;
drh2ce15c32017-07-11 13:34:40 +000011663 }else if( strcmp(z,"-stats")==0 ){
11664 data.statsOn = 1;
11665 }else if( strcmp(z,"-scanstats")==0 ){
11666 data.scanstatsOn = 1;
11667 }else if( strcmp(z,"-backslash")==0 ){
11668 /* Undocumented command-line option: -backslash
11669 ** Causes C-style backslash escapes to be evaluated in SQL statements
11670 ** prior to sending the SQL into SQLite. Useful for injecting
11671 ** crazy bytes in the middle of SQL statements for testing and debugging.
11672 */
11673 ShellSetFlag(&data, SHFLG_Backslash);
11674 }else if( strcmp(z,"-bail")==0 ){
drhb7c46aa2020-11-25 13:59:47 +000011675 /* No-op. The bail_on_error flag should already be set. */
drh2ce15c32017-07-11 13:34:40 +000011676 }else if( strcmp(z,"-version")==0 ){
11677 printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
11678 return 0;
11679 }else if( strcmp(z,"-interactive")==0 ){
11680 stdin_is_interactive = 1;
11681 }else if( strcmp(z,"-batch")==0 ){
11682 stdin_is_interactive = 0;
11683 }else if( strcmp(z,"-heap")==0 ){
11684 i++;
drh2ce15c32017-07-11 13:34:40 +000011685 }else if( strcmp(z,"-pagecache")==0 ){
11686 i+=2;
11687 }else if( strcmp(z,"-lookaside")==0 ){
11688 i+=2;
drhaf6d1af2021-08-09 17:37:58 +000011689 }else if( strcmp(z,"-threadsafe")==0 ){
11690 i+=2;
drhb97e2ad2021-08-26 18:31:39 +000011691 }else if( strcmp(z,"-nonce")==0 ){
11692 i += 2;
drh2ce15c32017-07-11 13:34:40 +000011693 }else if( strcmp(z,"-mmap")==0 ){
11694 i++;
drh50b910a2019-01-21 14:55:03 +000011695 }else if( strcmp(z,"-memtrace")==0 ){
11696 i++;
drha90d84f2018-04-18 15:21:13 +000011697#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11698 }else if( strcmp(z,"-sorterref")==0 ){
11699 i++;
11700#endif
drh2ce15c32017-07-11 13:34:40 +000011701 }else if( strcmp(z,"-vfs")==0 ){
11702 i++;
11703#ifdef SQLITE_ENABLE_VFSTRACE
11704 }else if( strcmp(z,"-vfstrace")==0 ){
11705 i++;
11706#endif
11707#ifdef SQLITE_ENABLE_MULTIPLEX
11708 }else if( strcmp(z,"-multiplex")==0 ){
11709 i++;
11710#endif
11711 }else if( strcmp(z,"-help")==0 ){
11712 usage(1);
11713 }else if( strcmp(z,"-cmd")==0 ){
11714 /* Run commands that follow -cmd first and separately from commands
11715 ** that simply appear on the command-line. This seems goofy. It would
11716 ** be better if all commands ran in the order that they appear. But
11717 ** we retain the goofy behavior for historical compatibility. */
11718 if( i==argc-1 ) break;
11719 z = cmdline_option_value(argc,argv,++i);
11720 if( z[0]=='.' ){
11721 rc = do_meta_command(z, &data);
11722 if( rc && bail_on_error ) return rc==2 ? 0 : rc;
11723 }else{
11724 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000011725 rc = shell_exec(&data, z, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000011726 if( zErrMsg!=0 ){
11727 utf8_printf(stderr,"Error: %s\n", zErrMsg);
11728 if( bail_on_error ) return rc!=0 ? rc : 1;
11729 }else if( rc!=0 ){
11730 utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
11731 if( bail_on_error ) return rc;
11732 }
11733 }
drhda57d962018-03-05 19:34:05 +000011734#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drh93b77312018-03-05 20:20:22 +000011735 }else if( strncmp(z, "-A", 2)==0 ){
drhda57d962018-03-05 19:34:05 +000011736 if( nCmd>0 ){
11737 utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
11738 " with \"%s\"\n", z);
11739 return 1;
11740 }
drhbe4ccb22018-05-17 20:04:24 +000011741 open_db(&data, OPEN_DB_ZIPFILE);
drh93b77312018-03-05 20:20:22 +000011742 if( z[2] ){
11743 argv[i] = &z[2];
drhd0f9cdc2018-05-17 14:09:06 +000011744 arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
drh93b77312018-03-05 20:20:22 +000011745 }else{
drhd0f9cdc2018-05-17 14:09:06 +000011746 arDotCommand(&data, 1, argv+i, argc-i);
drh93b77312018-03-05 20:20:22 +000011747 }
drhda57d962018-03-05 19:34:05 +000011748 readStdin = 0;
11749 break;
11750#endif
drhb97e2ad2021-08-26 18:31:39 +000011751 }else if( strcmp(z,"-safe")==0 ){
11752 data.bSafeMode = data.bSafeModePersist = 1;
drh2ce15c32017-07-11 13:34:40 +000011753 }else{
11754 utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
11755 raw_printf(stderr,"Use -help for a list of options.\n");
11756 return 1;
11757 }
11758 data.cMode = data.mode;
11759 }
11760
11761 if( !readStdin ){
11762 /* Run all arguments that do not begin with '-' as if they were separate
11763 ** command-line inputs, except for the argToSkip argument which contains
11764 ** the database filename.
11765 */
11766 for(i=0; i<nCmd; i++){
11767 if( azCmd[i][0]=='.' ){
11768 rc = do_meta_command(azCmd[i], &data);
danaff1a572020-11-17 21:09:56 +000011769 if( rc ){
11770 free(azCmd);
11771 return rc==2 ? 0 : rc;
11772 }
drh2ce15c32017-07-11 13:34:40 +000011773 }else{
11774 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000011775 rc = shell_exec(&data, azCmd[i], &zErrMsg);
danaff1a572020-11-17 21:09:56 +000011776 if( zErrMsg || rc ){
11777 if( zErrMsg!=0 ){
11778 utf8_printf(stderr,"Error: %s\n", zErrMsg);
11779 }else{
11780 utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
11781 }
11782 sqlite3_free(zErrMsg);
11783 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000011784 return rc!=0 ? rc : 1;
drh2ce15c32017-07-11 13:34:40 +000011785 }
11786 }
11787 }
drh2ce15c32017-07-11 13:34:40 +000011788 }else{
11789 /* Run commands received from standard input
11790 */
11791 if( stdin_is_interactive ){
11792 char *zHome;
drha9e4be32018-10-10 18:56:40 +000011793 char *zHistory;
drh2ce15c32017-07-11 13:34:40 +000011794 int nHistory;
11795 printf(
11796 "SQLite version %s %.19s\n" /*extra-version-info*/
11797 "Enter \".help\" for usage hints.\n",
11798 sqlite3_libversion(), sqlite3_sourceid()
11799 );
11800 if( warnInmemoryDb ){
11801 printf("Connected to a ");
11802 printBold("transient in-memory database");
11803 printf(".\nUse \".open FILENAME\" to reopen on a "
11804 "persistent database.\n");
11805 }
drha9e4be32018-10-10 18:56:40 +000011806 zHistory = getenv("SQLITE_HISTORY");
11807 if( zHistory ){
11808 zHistory = strdup(zHistory);
11809 }else if( (zHome = find_home_dir(0))!=0 ){
drh2ce15c32017-07-11 13:34:40 +000011810 nHistory = strlen30(zHome) + 20;
11811 if( (zHistory = malloc(nHistory))!=0 ){
11812 sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
11813 }
11814 }
11815 if( zHistory ){ shell_read_history(zHistory); }
drh56eb09b2017-07-11 13:59:07 +000011816#if HAVE_READLINE || HAVE_EDITLINE
11817 rl_attempted_completion_function = readline_completion;
11818#elif HAVE_LINENOISE
11819 linenoiseSetCompletionCallback(linenoise_completion);
11820#endif
drh60379d42018-12-13 18:30:01 +000011821 data.in = 0;
11822 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000011823 if( zHistory ){
drh5a75dd82017-07-18 20:59:40 +000011824 shell_stifle_history(2000);
drh2ce15c32017-07-11 13:34:40 +000011825 shell_write_history(zHistory);
11826 free(zHistory);
11827 }
11828 }else{
drh60379d42018-12-13 18:30:01 +000011829 data.in = stdin;
11830 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000011831 }
11832 }
danaff1a572020-11-17 21:09:56 +000011833 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000011834 set_table_name(&data, 0);
11835 if( data.db ){
drh37407122021-07-23 18:43:58 +000011836 session_close_all(&data, -1);
drh9e804032018-05-18 17:11:50 +000011837 close_db(data.db);
drh2ce15c32017-07-11 13:34:40 +000011838 }
drh37407122021-07-23 18:43:58 +000011839 for(i=0; i<ArraySize(data.aAuxDb); i++){
11840 sqlite3_free(data.aAuxDb[i].zFreeOnClose);
11841 if( data.aAuxDb[i].db ){
11842 session_close_all(&data, i);
11843 close_db(data.aAuxDb[i].db);
11844 }
11845 }
drh2ce15c32017-07-11 13:34:40 +000011846 find_home_dir(1);
drh536c3452018-01-11 00:38:39 +000011847 output_reset(&data);
11848 data.doXdgOpen = 0;
drh13c20932018-01-10 21:41:55 +000011849 clearTempFile(&data);
drh2ce15c32017-07-11 13:34:40 +000011850#if !SQLITE_SHELL_IS_UTF8
drh1f22f622018-05-17 13:29:14 +000011851 for(i=0; i<argcToFree; i++) free(argvToFree[i]);
11852 free(argvToFree);
drh2ce15c32017-07-11 13:34:40 +000011853#endif
drh0285d982020-05-29 14:38:43 +000011854 free(data.colWidth);
drhb97e2ad2021-08-26 18:31:39 +000011855 free(data.zNonce);
drh9e804032018-05-18 17:11:50 +000011856 /* Clear the global data structure so that valgrind will detect memory
11857 ** leaks */
11858 memset(&data, 0, sizeof(data));
drh2ce15c32017-07-11 13:34:40 +000011859 return rc;
11860}