blob: 5e1eabfacb5c5bf2c860fc577c15eda51ed4c160 [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/*
mistachkin43e86272020-04-09 15:31:22 +000021** Determine if we are dealing with WinRT, which provides only a subset of
22** the full Win32 API.
23*/
24#if !defined(SQLITE_OS_WINRT)
25# define SQLITE_OS_WINRT 0
26#endif
27
28/*
drh2ce15c32017-07-11 13:34:40 +000029** Warning pragmas copied from msvc.h in the core.
30*/
31#if defined(_MSC_VER)
32#pragma warning(disable : 4054)
33#pragma warning(disable : 4055)
34#pragma warning(disable : 4100)
35#pragma warning(disable : 4127)
36#pragma warning(disable : 4130)
37#pragma warning(disable : 4152)
38#pragma warning(disable : 4189)
39#pragma warning(disable : 4206)
40#pragma warning(disable : 4210)
41#pragma warning(disable : 4232)
42#pragma warning(disable : 4244)
43#pragma warning(disable : 4305)
44#pragma warning(disable : 4306)
45#pragma warning(disable : 4702)
46#pragma warning(disable : 4706)
47#endif /* defined(_MSC_VER) */
48
49/*
50** No support for loadable extensions in VxWorks.
51*/
52#if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION
53# define SQLITE_OMIT_LOAD_EXTENSION 1
54#endif
55
56/*
57** Enable large-file support for fopen() and friends on unix.
58*/
59#ifndef SQLITE_DISABLE_LFS
60# define _LARGE_FILE 1
61# ifndef _FILE_OFFSET_BITS
62# define _FILE_OFFSET_BITS 64
63# endif
64# define _LARGEFILE_SOURCE 1
65#endif
66
67#include <stdlib.h>
68#include <string.h>
69#include <stdio.h>
70#include <assert.h>
71#include "sqlite3.h"
drh1e506b52018-01-05 21:01:37 +000072typedef sqlite3_int64 i64;
73typedef sqlite3_uint64 u64;
drh1fa6d9f2018-01-06 21:46:01 +000074typedef unsigned char u8;
drh2ce15c32017-07-11 13:34:40 +000075#if SQLITE_USER_AUTHENTICATION
76# include "sqlite3userauth.h"
77#endif
78#include <ctype.h>
79#include <stdarg.h>
80
81#if !defined(_WIN32) && !defined(WIN32)
82# include <signal.h>
83# if !defined(__RTP__) && !defined(_WRS_KERNEL)
84# include <pwd.h>
85# endif
mistachkinacae8c32018-01-05 20:08:46 +000086#endif
mistachkin562f0c82018-01-09 00:28:24 +000087#if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__)
drh2ce15c32017-07-11 13:34:40 +000088# include <unistd.h>
mistachkinacae8c32018-01-05 20:08:46 +000089# include <dirent.h>
mistachkin1e8487d2018-07-22 06:25:35 +000090# define GETPID getpid
mistachkin562f0c82018-01-09 00:28:24 +000091# if defined(__MINGW32__)
mistachkinacae8c32018-01-05 20:08:46 +000092# define DIRENT dirent
mistachkin2f74b3c2018-01-05 20:26:06 +000093# ifndef S_ISLNK
94# define S_ISLNK(mode) (0)
95# endif
mistachkinacae8c32018-01-05 20:08:46 +000096# endif
mistachkin1e8487d2018-07-22 06:25:35 +000097#else
98# define GETPID (int)GetCurrentProcessId
drh2ce15c32017-07-11 13:34:40 +000099#endif
mistachkindfdfd8c2018-01-04 22:46:08 +0000100#include <sys/types.h>
101#include <sys/stat.h>
drh2ce15c32017-07-11 13:34:40 +0000102
103#if HAVE_READLINE
104# include <readline/readline.h>
105# include <readline/history.h>
106#endif
107
108#if HAVE_EDITLINE
109# include <editline/readline.h>
110#endif
111
112#if HAVE_EDITLINE || HAVE_READLINE
113
114# define shell_add_history(X) add_history(X)
115# define shell_read_history(X) read_history(X)
116# define shell_write_history(X) write_history(X)
117# define shell_stifle_history(X) stifle_history(X)
118# define shell_readline(X) readline(X)
119
120#elif HAVE_LINENOISE
121
122# include "linenoise.h"
123# define shell_add_history(X) linenoiseHistoryAdd(X)
124# define shell_read_history(X) linenoiseHistoryLoad(X)
125# define shell_write_history(X) linenoiseHistorySave(X)
126# define shell_stifle_history(X) linenoiseHistorySetMaxLen(X)
127# define shell_readline(X) linenoise(X)
128
129#else
130
131# define shell_read_history(X)
132# define shell_write_history(X)
133# define shell_stifle_history(X)
134
135# define SHELL_USE_LOCAL_GETLINE 1
136#endif
137
138
139#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +0000140# if SQLITE_OS_WINRT
141# define SQLITE_OMIT_POPEN 1
142# else
143# include <io.h>
144# include <fcntl.h>
145# define isatty(h) _isatty(h)
146# ifndef access
147# define access(f,m) _access((f),(m))
148# endif
149# ifndef unlink
150# define unlink _unlink
151# endif
152# ifndef strdup
153# define strdup _strdup
154# endif
155# undef popen
156# define popen _popen
157# undef pclose
158# define pclose _pclose
drh2ce15c32017-07-11 13:34:40 +0000159# endif
drh2ce15c32017-07-11 13:34:40 +0000160#else
161 /* Make sure isatty() has a prototype. */
162 extern int isatty(int);
163
164# if !defined(__RTP__) && !defined(_WRS_KERNEL)
165 /* popen and pclose are not C89 functions and so are
166 ** sometimes omitted from the <stdio.h> header */
167 extern FILE *popen(const char*,const char*);
168 extern int pclose(FILE*);
169# else
170# define SQLITE_OMIT_POPEN 1
171# endif
172#endif
173
174#if defined(_WIN32_WCE)
175/* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty()
176 * thus we always assume that we have a console. That can be
177 * overridden with the -batch command line option.
178 */
179#define isatty(x) 1
180#endif
181
182/* ctype macros that work with signed characters */
183#define IsSpace(X) isspace((unsigned char)X)
184#define IsDigit(X) isdigit((unsigned char)X)
185#define ToLower(X) (char)tolower((unsigned char)X)
186
187#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +0000188#if SQLITE_OS_WINRT
189#include <intrin.h>
190#endif
drh2ce15c32017-07-11 13:34:40 +0000191#include <windows.h>
192
193/* string conversion routines only needed on Win32 */
194extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
195extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int);
196extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int);
197extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
198#endif
199
200/* On Windows, we normally run with output mode of TEXT so that \n characters
201** are automatically translated into \r\n. However, this behavior needs
202** to be disabled in some cases (ex: when generating CSV output and when
203** rendering quoted strings that contain \n characters). The following
204** routines take care of that.
205*/
mistachkin43e86272020-04-09 15:31:22 +0000206#if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +0000207static void setBinaryMode(FILE *file, int isOutput){
208 if( isOutput ) fflush(file);
209 _setmode(_fileno(file), _O_BINARY);
210}
211static void setTextMode(FILE *file, int isOutput){
212 if( isOutput ) fflush(file);
213 _setmode(_fileno(file), _O_TEXT);
214}
215#else
216# define setBinaryMode(X,Y)
217# define setTextMode(X,Y)
218#endif
219
220
221/* True if the timer is enabled */
222static int enableTimer = 0;
223
224/* Return the current wall-clock time */
225static sqlite3_int64 timeOfDay(void){
226 static sqlite3_vfs *clockVfs = 0;
227 sqlite3_int64 t;
228 if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
229 if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
230 clockVfs->xCurrentTimeInt64(clockVfs, &t);
231 }else{
232 double r;
233 clockVfs->xCurrentTime(clockVfs, &r);
234 t = (sqlite3_int64)(r*86400000.0);
235 }
236 return t;
237}
238
239#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
240#include <sys/time.h>
241#include <sys/resource.h>
242
243/* VxWorks does not support getrusage() as far as we can determine */
244#if defined(_WRS_KERNEL) || defined(__RTP__)
245struct rusage {
246 struct timeval ru_utime; /* user CPU time used */
247 struct timeval ru_stime; /* system CPU time used */
248};
249#define getrusage(A,B) memset(B,0,sizeof(*B))
250#endif
251
252/* Saved resource information for the beginning of an operation */
253static struct rusage sBegin; /* CPU time at start */
254static sqlite3_int64 iBegin; /* Wall-clock time at start */
255
256/*
257** Begin timing an operation
258*/
259static void beginTimer(void){
260 if( enableTimer ){
261 getrusage(RUSAGE_SELF, &sBegin);
262 iBegin = timeOfDay();
263 }
264}
265
266/* Return the difference of two time_structs in seconds */
267static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
268 return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
269 (double)(pEnd->tv_sec - pStart->tv_sec);
270}
271
272/*
273** Print the timing results.
274*/
275static void endTimer(void){
276 if( enableTimer ){
277 sqlite3_int64 iEnd = timeOfDay();
278 struct rusage sEnd;
279 getrusage(RUSAGE_SELF, &sEnd);
280 printf("Run Time: real %.3f user %f sys %f\n",
281 (iEnd - iBegin)*0.001,
282 timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
283 timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
284 }
285}
286
287#define BEGIN_TIMER beginTimer()
288#define END_TIMER endTimer()
289#define HAS_TIMER 1
290
291#elif (defined(_WIN32) || defined(WIN32))
292
293/* Saved resource information for the beginning of an operation */
294static HANDLE hProcess;
295static FILETIME ftKernelBegin;
296static FILETIME ftUserBegin;
297static sqlite3_int64 ftWallBegin;
298typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
299 LPFILETIME, LPFILETIME);
300static GETPROCTIMES getProcessTimesAddr = NULL;
301
302/*
303** Check to see if we have timer support. Return 1 if necessary
304** support found (or found previously).
305*/
306static int hasTimer(void){
307 if( getProcessTimesAddr ){
308 return 1;
309 } else {
mistachkin43e86272020-04-09 15:31:22 +0000310#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +0000311 /* GetProcessTimes() isn't supported in WIN95 and some other Windows
312 ** versions. See if the version we are running on has it, and if it
313 ** does, save off a pointer to it and the current process handle.
314 */
315 hProcess = GetCurrentProcess();
316 if( hProcess ){
317 HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
318 if( NULL != hinstLib ){
319 getProcessTimesAddr =
320 (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
321 if( NULL != getProcessTimesAddr ){
322 return 1;
323 }
324 FreeLibrary(hinstLib);
325 }
326 }
mistachkin43e86272020-04-09 15:31:22 +0000327#endif
drh2ce15c32017-07-11 13:34:40 +0000328 }
329 return 0;
330}
331
332/*
333** Begin timing an operation
334*/
335static void beginTimer(void){
336 if( enableTimer && getProcessTimesAddr ){
337 FILETIME ftCreation, ftExit;
338 getProcessTimesAddr(hProcess,&ftCreation,&ftExit,
339 &ftKernelBegin,&ftUserBegin);
340 ftWallBegin = timeOfDay();
341 }
342}
343
344/* Return the difference of two FILETIME structs in seconds */
345static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
346 sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
347 sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
348 return (double) ((i64End - i64Start) / 10000000.0);
349}
350
351/*
352** Print the timing results.
353*/
354static void endTimer(void){
355 if( enableTimer && getProcessTimesAddr){
356 FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
357 sqlite3_int64 ftWallEnd = timeOfDay();
358 getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
359 printf("Run Time: real %.3f user %f sys %f\n",
360 (ftWallEnd - ftWallBegin)*0.001,
361 timeDiff(&ftUserBegin, &ftUserEnd),
362 timeDiff(&ftKernelBegin, &ftKernelEnd));
363 }
364}
365
366#define BEGIN_TIMER beginTimer()
367#define END_TIMER endTimer()
368#define HAS_TIMER hasTimer()
369
370#else
371#define BEGIN_TIMER
372#define END_TIMER
373#define HAS_TIMER 0
374#endif
375
376/*
377** Used to prevent warnings about unused parameters
378*/
379#define UNUSED_PARAMETER(x) (void)(x)
380
381/*
drh5af06982018-01-10 00:53:55 +0000382** Number of elements in an array
383*/
384#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
385
386/*
drh2ce15c32017-07-11 13:34:40 +0000387** If the following flag is set, then command execution stops
388** at an error if we are not interactive.
389*/
390static int bail_on_error = 0;
391
392/*
393** Threat stdin as an interactive input if the following variable
394** is true. Otherwise, assume stdin is connected to a file or pipe.
395*/
396static int stdin_is_interactive = 1;
397
398/*
399** On Windows systems we have to know if standard output is a console
400** in order to translate UTF-8 into MBCS. The following variable is
401** true if translation is required.
402*/
403static int stdout_is_console = 1;
404
405/*
406** The following is the open SQLite database. We make a pointer
407** to this database a static variable so that it can be accessed
408** by the SIGINT handler to interrupt database processing.
409*/
410static sqlite3 *globalDb = 0;
411
412/*
413** True if an interrupt (Control-C) has been received.
414*/
415static volatile int seenInterrupt = 0;
416
drh4a3a3eb2020-02-29 15:53:48 +0000417#ifdef SQLITE_DEBUG
418/*
419** Out-of-memory simulator variables
420*/
421static unsigned int oomCounter = 0; /* Simulate OOM when equals 1 */
422static unsigned int oomRepeat = 0; /* Number of OOMs in a row */
423static void*(*defaultMalloc)(int) = 0; /* The low-level malloc routine */
424#endif /* SQLITE_DEBUG */
425
drh2ce15c32017-07-11 13:34:40 +0000426/*
427** This is the name of our program. It is set in main(), used
428** in a number of other places, mostly for error messages.
429*/
430static char *Argv0;
431
432/*
433** Prompt strings. Initialized in main. Settable with
434** .prompt main continue
435*/
436static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/
437static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */
438
439/*
440** Render output like fprintf(). Except, if the output is going to the
441** console and if this is running on a Windows machine, translate the
442** output from UTF-8 into MBCS.
443*/
444#if defined(_WIN32) || defined(WIN32)
445void utf8_printf(FILE *out, const char *zFormat, ...){
446 va_list ap;
447 va_start(ap, zFormat);
448 if( stdout_is_console && (out==stdout || out==stderr) ){
449 char *z1 = sqlite3_vmprintf(zFormat, ap);
450 char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0);
451 sqlite3_free(z1);
452 fputs(z2, out);
453 sqlite3_free(z2);
454 }else{
455 vfprintf(out, zFormat, ap);
456 }
457 va_end(ap);
458}
459#elif !defined(utf8_printf)
460# define utf8_printf fprintf
461#endif
462
463/*
464** Render output like fprintf(). This should not be used on anything that
465** includes string formatting (e.g. "%s").
466*/
467#if !defined(raw_printf)
468# define raw_printf fprintf
469#endif
470
drh4b5345c2018-04-24 13:07:40 +0000471/* Indicate out-of-memory and exit. */
472static void shell_out_of_memory(void){
473 raw_printf(stderr,"Error: out of memory\n");
474 exit(1);
475}
476
drh4a3a3eb2020-02-29 15:53:48 +0000477#ifdef SQLITE_DEBUG
478/* This routine is called when a simulated OOM occurs. It is broken
479** out as a separate routine to make it easy to set a breakpoint on
480** the OOM
481*/
482void shellOomFault(void){
483 if( oomRepeat>0 ){
484 oomRepeat--;
485 }else{
486 oomCounter--;
487 }
488}
489#endif /* SQLITE_DEBUG */
490
491#ifdef SQLITE_DEBUG
492/* This routine is a replacement malloc() that is used to simulate
493** Out-Of-Memory (OOM) errors for testing purposes.
494*/
495static void *oomMalloc(int nByte){
496 if( oomCounter ){
497 if( oomCounter==1 ){
498 shellOomFault();
499 return 0;
500 }else{
501 oomCounter--;
502 }
503 }
504 return defaultMalloc(nByte);
505}
506#endif /* SQLITE_DEBUG */
507
508#ifdef SQLITE_DEBUG
509/* Register the OOM simulator. This must occur before any memory
510** allocations */
511static void registerOomSimulator(void){
512 sqlite3_mem_methods mem;
513 sqlite3_config(SQLITE_CONFIG_GETMALLOC, &mem);
514 defaultMalloc = mem.xMalloc;
515 mem.xMalloc = oomMalloc;
516 sqlite3_config(SQLITE_CONFIG_MALLOC, &mem);
517}
518#endif
519
drh2ce15c32017-07-11 13:34:40 +0000520/*
521** Write I/O traces to the following stream.
522*/
523#ifdef SQLITE_ENABLE_IOTRACE
524static FILE *iotrace = 0;
525#endif
526
527/*
528** This routine works like printf in that its first argument is a
529** format string and subsequent arguments are values to be substituted
530** in place of % fields. The result of formatting this string
531** is written to iotrace.
532*/
533#ifdef SQLITE_ENABLE_IOTRACE
534static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
535 va_list ap;
536 char *z;
537 if( iotrace==0 ) return;
538 va_start(ap, zFormat);
539 z = sqlite3_vmprintf(zFormat, ap);
540 va_end(ap);
541 utf8_printf(iotrace, "%s", z);
542 sqlite3_free(z);
543}
544#endif
545
546/*
547** Output string zUtf to stream pOut as w characters. If w is negative,
548** then right-justify the text. W is the width in UTF-8 characters, not
549** in bytes. This is different from the %*.*s specification in printf
550** since with %*.*s the width is measured in bytes, not characters.
551*/
552static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
553 int i;
554 int n;
555 int aw = w<0 ? -w : w;
drh2ce15c32017-07-11 13:34:40 +0000556 for(i=n=0; zUtf[i]; i++){
557 if( (zUtf[i]&0xc0)!=0x80 ){
558 n++;
559 if( n==aw ){
560 do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
561 break;
562 }
563 }
564 }
565 if( n>=aw ){
566 utf8_printf(pOut, "%.*s", i, zUtf);
567 }else if( w<0 ){
568 utf8_printf(pOut, "%*s%s", aw-n, "", zUtf);
569 }else{
570 utf8_printf(pOut, "%s%*s", zUtf, aw-n, "");
571 }
572}
573
574
575/*
576** Determines if a string is a number of not.
577*/
578static int isNumber(const char *z, int *realnum){
579 if( *z=='-' || *z=='+' ) z++;
580 if( !IsDigit(*z) ){
581 return 0;
582 }
583 z++;
584 if( realnum ) *realnum = 0;
585 while( IsDigit(*z) ){ z++; }
586 if( *z=='.' ){
587 z++;
588 if( !IsDigit(*z) ) return 0;
589 while( IsDigit(*z) ){ z++; }
590 if( realnum ) *realnum = 1;
591 }
592 if( *z=='e' || *z=='E' ){
593 z++;
594 if( *z=='+' || *z=='-' ) z++;
595 if( !IsDigit(*z) ) return 0;
596 while( IsDigit(*z) ){ z++; }
597 if( realnum ) *realnum = 1;
598 }
599 return *z==0;
600}
601
602/*
603** Compute a string length that is limited to what can be stored in
604** lower 30 bits of a 32-bit signed integer.
605*/
606static int strlen30(const char *z){
607 const char *z2 = z;
608 while( *z2 ){ z2++; }
609 return 0x3fffffff & (int)(z2 - z);
610}
611
612/*
613** Return the length of a string in characters. Multibyte UTF8 characters
614** count as a single character.
615*/
616static int strlenChar(const char *z){
617 int n = 0;
618 while( *z ){
619 if( (0xc0&*(z++))!=0x80 ) n++;
620 }
621 return n;
622}
623
624/*
drhbbd620e2020-07-20 23:33:11 +0000625** Return true if zFile does not exist or if it is not an ordinary file.
626*/
627#ifdef _WIN32
628# define notNormalFile(X) 0
629#else
630static int notNormalFile(const char *zFile){
631 struct stat x;
632 int rc;
633 memset(&x, 0, sizeof(x));
634 rc = stat(zFile, &x);
635 return rc || !S_ISREG(x.st_mode);
636}
637#endif
638
639/*
drh2ce15c32017-07-11 13:34:40 +0000640** This routine reads a line of text from FILE in, stores
641** the text in memory obtained from malloc() and returns a pointer
642** to the text. NULL is returned at end of file, or if malloc()
643** fails.
644**
645** If zLine is not NULL then it is a malloced buffer returned from
646** a previous call to this routine that may be reused.
647*/
648static char *local_getline(char *zLine, FILE *in){
649 int nLine = zLine==0 ? 0 : 100;
650 int n = 0;
651
652 while( 1 ){
653 if( n+100>nLine ){
654 nLine = nLine*2 + 100;
655 zLine = realloc(zLine, nLine);
drh884406b2018-07-29 18:56:35 +0000656 if( zLine==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +0000657 }
658 if( fgets(&zLine[n], nLine - n, in)==0 ){
659 if( n==0 ){
660 free(zLine);
661 return 0;
662 }
663 zLine[n] = 0;
664 break;
665 }
666 while( zLine[n] ) n++;
667 if( n>0 && zLine[n-1]=='\n' ){
668 n--;
669 if( n>0 && zLine[n-1]=='\r' ) n--;
670 zLine[n] = 0;
671 break;
672 }
673 }
674#if defined(_WIN32) || defined(WIN32)
675 /* For interactive input on Windows systems, translate the
676 ** multi-byte characterset characters into UTF-8. */
677 if( stdin_is_interactive && in==stdin ){
678 char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
679 if( zTrans ){
680 int nTrans = strlen30(zTrans)+1;
681 if( nTrans>nLine ){
682 zLine = realloc(zLine, nTrans);
drh884406b2018-07-29 18:56:35 +0000683 if( zLine==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +0000684 }
685 memcpy(zLine, zTrans, nTrans);
686 sqlite3_free(zTrans);
687 }
688 }
689#endif /* defined(_WIN32) || defined(WIN32) */
690 return zLine;
691}
692
693/*
694** Retrieve a single line of input text.
695**
696** If in==0 then read from standard input and prompt before each line.
697** If isContinuation is true, then a continuation prompt is appropriate.
698** If isContinuation is zero, then the main prompt should be used.
699**
700** If zPrior is not NULL then it is a buffer from a prior call to this
701** routine that can be reused.
702**
703** The result is stored in space obtained from malloc() and must either
704** be freed by the caller or else passed back into this routine via the
705** zPrior argument for reuse.
706*/
707static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
708 char *zPrompt;
709 char *zResult;
710 if( in!=0 ){
711 zResult = local_getline(zPrior, in);
712 }else{
713 zPrompt = isContinuation ? continuePrompt : mainPrompt;
714#if SHELL_USE_LOCAL_GETLINE
715 printf("%s", zPrompt);
716 fflush(stdout);
717 zResult = local_getline(zPrior, stdin);
718#else
719 free(zPrior);
720 zResult = shell_readline(zPrompt);
721 if( zResult && *zResult ) shell_add_history(zResult);
722#endif
723 }
724 return zResult;
725}
drh5af06982018-01-10 00:53:55 +0000726
727
728/*
729** Return the value of a hexadecimal digit. Return -1 if the input
730** is not a hex digit.
731*/
732static int hexDigitValue(char c){
733 if( c>='0' && c<='9' ) return c - '0';
734 if( c>='a' && c<='f' ) return c - 'a' + 10;
735 if( c>='A' && c<='F' ) return c - 'A' + 10;
736 return -1;
737}
738
739/*
740** Interpret zArg as an integer value, possibly with suffixes.
741*/
742static sqlite3_int64 integerValue(const char *zArg){
743 sqlite3_int64 v = 0;
744 static const struct { char *zSuffix; int iMult; } aMult[] = {
745 { "KiB", 1024 },
746 { "MiB", 1024*1024 },
747 { "GiB", 1024*1024*1024 },
748 { "KB", 1000 },
749 { "MB", 1000000 },
750 { "GB", 1000000000 },
751 { "K", 1000 },
752 { "M", 1000000 },
753 { "G", 1000000000 },
754 };
755 int i;
756 int isNeg = 0;
757 if( zArg[0]=='-' ){
758 isNeg = 1;
759 zArg++;
760 }else if( zArg[0]=='+' ){
761 zArg++;
762 }
763 if( zArg[0]=='0' && zArg[1]=='x' ){
764 int x;
765 zArg += 2;
766 while( (x = hexDigitValue(zArg[0]))>=0 ){
767 v = (v<<4) + x;
768 zArg++;
769 }
770 }else{
771 while( IsDigit(zArg[0]) ){
772 v = v*10 + zArg[0] - '0';
773 zArg++;
774 }
775 }
776 for(i=0; i<ArraySize(aMult); i++){
777 if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
778 v *= aMult[i].iMult;
779 break;
780 }
781 }
782 return isNeg? -v : v;
783}
784
drh2ce15c32017-07-11 13:34:40 +0000785/*
786** A variable length string to which one can append text.
787*/
788typedef struct ShellText ShellText;
789struct ShellText {
790 char *z;
791 int n;
792 int nAlloc;
793};
794
795/*
796** Initialize and destroy a ShellText object
797*/
798static void initText(ShellText *p){
799 memset(p, 0, sizeof(*p));
800}
801static void freeText(ShellText *p){
802 free(p->z);
803 initText(p);
804}
805
806/* zIn is either a pointer to a NULL-terminated string in memory obtained
807** from malloc(), or a NULL pointer. The string pointed to by zAppend is
808** added to zIn, and the result returned in memory obtained from malloc().
809** zIn, if it was not NULL, is freed.
810**
811** If the third argument, quote, is not '\0', then it is used as a
812** quote character for zAppend.
813*/
814static void appendText(ShellText *p, char const *zAppend, char quote){
815 int len;
816 int i;
817 int nAppend = strlen30(zAppend);
818
819 len = nAppend+p->n+1;
820 if( quote ){
821 len += 2;
822 for(i=0; i<nAppend; i++){
823 if( zAppend[i]==quote ) len++;
824 }
825 }
826
827 if( p->n+len>=p->nAlloc ){
828 p->nAlloc = p->nAlloc*2 + len + 20;
829 p->z = realloc(p->z, p->nAlloc);
drh884406b2018-07-29 18:56:35 +0000830 if( p->z==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +0000831 }
832
833 if( quote ){
834 char *zCsr = p->z+p->n;
835 *zCsr++ = quote;
836 for(i=0; i<nAppend; i++){
837 *zCsr++ = zAppend[i];
838 if( zAppend[i]==quote ) *zCsr++ = quote;
839 }
840 *zCsr++ = quote;
841 p->n = (int)(zCsr - p->z);
842 *zCsr = '\0';
843 }else{
844 memcpy(p->z+p->n, zAppend, nAppend);
845 p->n += nAppend;
846 p->z[p->n] = '\0';
847 }
848}
849
850/*
851** Attempt to determine if identifier zName needs to be quoted, either
852** because it contains non-alphanumeric characters, or because it is an
853** SQLite keyword. Be conservative in this estimate: When in doubt assume
854** that quoting is required.
855**
856** Return '"' if quoting is required. Return 0 if no quoting is required.
857*/
858static char quoteChar(const char *zName){
drhfc0ec3e2018-04-25 19:02:48 +0000859 int i;
drh2ce15c32017-07-11 13:34:40 +0000860 if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
861 for(i=0; zName[i]; i++){
862 if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
863 }
drhfc0ec3e2018-04-25 19:02:48 +0000864 return sqlite3_keyword_check(zName, i) ? '"' : 0;
drh2ce15c32017-07-11 13:34:40 +0000865}
866
867/*
drh667a2a22018-01-02 00:04:37 +0000868** Construct a fake object name and column list to describe the structure
869** of the view, virtual table, or table valued function zSchema.zName.
drhceba7922018-01-01 21:28:25 +0000870*/
drh667a2a22018-01-02 00:04:37 +0000871static char *shellFakeSchema(
drhceba7922018-01-01 21:28:25 +0000872 sqlite3 *db, /* The database connection containing the vtab */
873 const char *zSchema, /* Schema of the database holding the vtab */
874 const char *zName /* The name of the virtual table */
875){
876 sqlite3_stmt *pStmt = 0;
877 char *zSql;
drh1d315cf2018-01-01 21:49:43 +0000878 ShellText s;
879 char cQuote;
880 char *zDiv = "(";
drh667a2a22018-01-02 00:04:37 +0000881 int nRow = 0;
drhceba7922018-01-01 21:28:25 +0000882
drh1d315cf2018-01-01 21:49:43 +0000883 zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
884 zSchema ? zSchema : "main", zName);
drhceba7922018-01-01 21:28:25 +0000885 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
886 sqlite3_free(zSql);
drh1d315cf2018-01-01 21:49:43 +0000887 initText(&s);
888 if( zSchema ){
889 cQuote = quoteChar(zSchema);
890 if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0;
891 appendText(&s, zSchema, cQuote);
892 appendText(&s, ".", 0);
drhceba7922018-01-01 21:28:25 +0000893 }
drh1d315cf2018-01-01 21:49:43 +0000894 cQuote = quoteChar(zName);
895 appendText(&s, zName, cQuote);
896 while( sqlite3_step(pStmt)==SQLITE_ROW ){
897 const char *zCol = (const char*)sqlite3_column_text(pStmt, 1);
drh667a2a22018-01-02 00:04:37 +0000898 nRow++;
drh1d315cf2018-01-01 21:49:43 +0000899 appendText(&s, zDiv, 0);
900 zDiv = ",";
901 cQuote = quoteChar(zCol);
902 appendText(&s, zCol, cQuote);
903 }
904 appendText(&s, ")", 0);
drhceba7922018-01-01 21:28:25 +0000905 sqlite3_finalize(pStmt);
drh667a2a22018-01-02 00:04:37 +0000906 if( nRow==0 ){
907 freeText(&s);
908 s.z = 0;
909 }
drh1d315cf2018-01-01 21:49:43 +0000910 return s.z;
drhceba7922018-01-01 21:28:25 +0000911}
912
913/*
drh667a2a22018-01-02 00:04:37 +0000914** SQL function: shell_module_schema(X)
915**
916** Return a fake schema for the table-valued function or eponymous virtual
917** table X.
918*/
919static void shellModuleSchema(
920 sqlite3_context *pCtx,
921 int nVal,
922 sqlite3_value **apVal
923){
924 const char *zName = (const char*)sqlite3_value_text(apVal[0]);
925 char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName);
drhb9685182018-01-17 13:15:23 +0000926 UNUSED_PARAMETER(nVal);
drh667a2a22018-01-02 00:04:37 +0000927 if( zFake ){
dandcfbff92018-01-08 17:05:32 +0000928 sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
drh667a2a22018-01-02 00:04:37 +0000929 -1, sqlite3_free);
dandcfbff92018-01-08 17:05:32 +0000930 free(zFake);
drh667a2a22018-01-02 00:04:37 +0000931 }
932}
933
934/*
drh2ce15c32017-07-11 13:34:40 +0000935** SQL function: shell_add_schema(S,X)
936**
937** Add the schema name X to the CREATE statement in S and return the result.
938** Examples:
939**
940** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x);
941**
942** Also works on
943**
944** CREATE INDEX
945** CREATE UNIQUE INDEX
946** CREATE VIEW
947** CREATE TRIGGER
948** CREATE VIRTUAL TABLE
949**
950** This UDF is used by the .schema command to insert the schema name of
drh067b92b2020-06-19 15:24:12 +0000951** attached databases into the middle of the sqlite_schema.sql field.
drh2ce15c32017-07-11 13:34:40 +0000952*/
953static void shellAddSchemaName(
954 sqlite3_context *pCtx,
955 int nVal,
956 sqlite3_value **apVal
957){
958 static const char *aPrefix[] = {
959 "TABLE",
960 "INDEX",
961 "UNIQUE INDEX",
962 "VIEW",
963 "TRIGGER",
964 "VIRTUAL TABLE"
965 };
966 int i = 0;
967 const char *zIn = (const char*)sqlite3_value_text(apVal[0]);
968 const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
drh667a2a22018-01-02 00:04:37 +0000969 const char *zName = (const char*)sqlite3_value_text(apVal[2]);
drhceba7922018-01-01 21:28:25 +0000970 sqlite3 *db = sqlite3_context_db_handle(pCtx);
drhb9685182018-01-17 13:15:23 +0000971 UNUSED_PARAMETER(nVal);
drh2ce15c32017-07-11 13:34:40 +0000972 if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
drh89997982017-07-11 18:11:33 +0000973 for(i=0; i<(int)(sizeof(aPrefix)/sizeof(aPrefix[0])); i++){
drh2ce15c32017-07-11 13:34:40 +0000974 int n = strlen30(aPrefix[i]);
975 if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
drhceba7922018-01-01 21:28:25 +0000976 char *z = 0;
drh667a2a22018-01-02 00:04:37 +0000977 char *zFake = 0;
drhceba7922018-01-01 21:28:25 +0000978 if( zSchema ){
979 char cQuote = quoteChar(zSchema);
980 if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){
981 z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8);
982 }else{
983 z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8);
984 }
drh2ce15c32017-07-11 13:34:40 +0000985 }
drh667a2a22018-01-02 00:04:37 +0000986 if( zName
987 && aPrefix[i][0]=='V'
988 && (zFake = shellFakeSchema(db, zSchema, zName))!=0
989 ){
990 if( z==0 ){
dandcfbff92018-01-08 17:05:32 +0000991 z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake);
drh667a2a22018-01-02 00:04:37 +0000992 }else{
dandcfbff92018-01-08 17:05:32 +0000993 z = sqlite3_mprintf("%z\n/* %s */", z, zFake);
drh667a2a22018-01-02 00:04:37 +0000994 }
dandcfbff92018-01-08 17:05:32 +0000995 free(zFake);
drhceba7922018-01-01 21:28:25 +0000996 }
997 if( z ){
998 sqlite3_result_text(pCtx, z, -1, sqlite3_free);
999 return;
1000 }
drh2ce15c32017-07-11 13:34:40 +00001001 }
1002 }
1003 }
1004 sqlite3_result_value(pCtx, apVal[0]);
1005}
1006
1007/*
1008** The source code for several run-time loadable extensions is inserted
1009** below by the ../tool/mkshellc.tcl script. Before processing that included
1010** code, we need to override some macros to make the included program code
1011** work here in the middle of this regular program.
1012*/
1013#define SQLITE_EXTENSION_INIT1
drh89997982017-07-11 18:11:33 +00001014#define SQLITE_EXTENSION_INIT2(X) (void)(X)
drh2ce15c32017-07-11 13:34:40 +00001015
mistachkinacae8c32018-01-05 20:08:46 +00001016#if defined(_WIN32) && defined(_MSC_VER)
drh03491a12018-01-07 21:58:17 +00001017INCLUDE test_windirent.h
mistachkindfdfd8c2018-01-04 22:46:08 +00001018INCLUDE test_windirent.c
1019#define dirent DIRENT
mistachkindfdfd8c2018-01-04 22:46:08 +00001020#endif
drh2ce15c32017-07-11 13:34:40 +00001021INCLUDE ../ext/misc/shathree.c
1022INCLUDE ../ext/misc/fileio.c
drh56eb09b2017-07-11 13:59:07 +00001023INCLUDE ../ext/misc/completion.c
drh8682e122018-01-07 20:38:10 +00001024INCLUDE ../ext/misc/appendvfs.c
drh50b910a2019-01-21 14:55:03 +00001025INCLUDE ../ext/misc/memtrace.c
drhf05dd032020-04-14 15:53:58 +00001026INCLUDE ../ext/misc/uint.c
drhbeb9def2020-06-22 19:12:23 +00001027INCLUDE ../ext/misc/decimal.c
drh8cda77d2020-06-24 15:06:29 +00001028INCLUDE ../ext/misc/ieee754.c
mistachkin72c38d82020-08-28 18:47:39 +00001029INCLUDE ../ext/misc/series.c
drh64689902021-06-03 13:51:31 +00001030INCLUDE ../ext/misc/regexp.c
dan72afc3c2017-12-05 18:32:40 +00001031#ifdef SQLITE_HAVE_ZLIB
dan9ebfaad2017-12-26 20:39:58 +00001032INCLUDE ../ext/misc/zipfile.c
dand1b51d42017-12-16 19:11:26 +00001033INCLUDE ../ext/misc/sqlar.c
dan72afc3c2017-12-05 18:32:40 +00001034#endif
dan43efc182017-12-19 17:42:13 +00001035INCLUDE ../ext/expert/sqlite3expert.h
1036INCLUDE ../ext/expert/sqlite3expert.c
drh2ce15c32017-07-11 13:34:40 +00001037
dan1b162162019-04-27 20:15:15 +00001038#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00001039INCLUDE ../ext/misc/dbdata.c
dan1b162162019-04-27 20:15:15 +00001040#endif
dan68cb86e2019-04-20 20:57:28 +00001041
drh2ce15c32017-07-11 13:34:40 +00001042#if defined(SQLITE_ENABLE_SESSION)
1043/*
1044** State information for a single open session
1045*/
1046typedef struct OpenSession OpenSession;
1047struct OpenSession {
1048 char *zName; /* Symbolic name for this session */
1049 int nFilter; /* Number of xFilter rejection GLOB patterns */
1050 char **azFilter; /* Array of xFilter rejection GLOB patterns */
1051 sqlite3_session *p; /* The open session */
1052};
1053#endif
1054
dan43efc182017-12-19 17:42:13 +00001055typedef struct ExpertInfo ExpertInfo;
1056struct ExpertInfo {
1057 sqlite3expert *pExpert;
1058 int bVerbose;
1059};
1060
drh4b5345c2018-04-24 13:07:40 +00001061/* A single line in the EQP output */
1062typedef struct EQPGraphRow EQPGraphRow;
1063struct EQPGraphRow {
drhe2ca99c2018-05-02 00:33:43 +00001064 int iEqpId; /* ID for this row */
1065 int iParentId; /* ID of the parent row */
drh4b5345c2018-04-24 13:07:40 +00001066 EQPGraphRow *pNext; /* Next row in sequence */
1067 char zText[1]; /* Text to display for this row */
1068};
1069
1070/* All EQP output is collected into an instance of the following */
1071typedef struct EQPGraph EQPGraph;
1072struct EQPGraph {
1073 EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */
1074 EQPGraphRow *pLast; /* Last element of the pRow list */
1075 char zPrefix[100]; /* Graph prefix */
1076};
1077
drh2ce15c32017-07-11 13:34:40 +00001078/*
1079** State information about the database connection is contained in an
1080** instance of the following structure.
1081*/
1082typedef struct ShellState ShellState;
1083struct ShellState {
1084 sqlite3 *db; /* The database */
drh1fa6d9f2018-01-06 21:46:01 +00001085 u8 autoExplain; /* Automatically turn on .explain mode */
1086 u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
drhe2ca99c2018-05-02 00:33:43 +00001087 u8 autoEQPtest; /* autoEQP is in test mode */
drhb4e50392019-01-26 15:40:04 +00001088 u8 autoEQPtrace; /* autoEQP is in trace mode */
drh1fa6d9f2018-01-06 21:46:01 +00001089 u8 scanstatsOn; /* True to display scan stats before each finalize */
1090 u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
drh13c20932018-01-10 21:41:55 +00001091 u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
drh4b5345c2018-04-24 13:07:40 +00001092 u8 nEqpLevel; /* Depth of the EQP output graph */
drh707821f2018-12-05 13:39:06 +00001093 u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
drha6e6cf22021-01-09 19:10:04 +00001094 unsigned statsOn; /* True to display memory stats before each finalize */
drh4b5345c2018-04-24 13:07:40 +00001095 unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */
drh2ce15c32017-07-11 13:34:40 +00001096 int outCount; /* Revert to stdout when reaching zero */
1097 int cnt; /* Number of records displayed so far */
drh2c8ee022018-12-13 18:59:30 +00001098 int lineno; /* Line number of last line read from in */
drh0933aad2019-11-18 17:46:38 +00001099 int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */
drh60379d42018-12-13 18:30:01 +00001100 FILE *in; /* Read commands from this stream */
drh2ce15c32017-07-11 13:34:40 +00001101 FILE *out; /* Write results here */
1102 FILE *traceOut; /* Output for sqlite3_trace() */
1103 int nErr; /* Number of errors seen */
1104 int mode; /* An output mode setting */
drh3c484e82018-01-10 22:27:21 +00001105 int modePrior; /* Saved mode */
drh2ce15c32017-07-11 13:34:40 +00001106 int cMode; /* temporary output mode for the current query */
1107 int normalMode; /* Output mode before ".explain on" */
1108 int writableSchema; /* True if PRAGMA writable_schema=ON */
1109 int showHeader; /* True to show column names in List or Column mode */
1110 int nCheck; /* Number of ".check" commands run */
drh3f83f592019-02-04 14:53:18 +00001111 unsigned nProgress; /* Number of progress callbacks encountered */
1112 unsigned mxProgress; /* Maximum progress callbacks before failing */
1113 unsigned flgProgress; /* Flags for the progress callback */
drh2ce15c32017-07-11 13:34:40 +00001114 unsigned shellFlgs; /* Various flags */
drh7a431002020-04-18 14:12:00 +00001115 unsigned priorShFlgs; /* Saved copy of flags */
drh6ca64482019-01-22 16:06:20 +00001116 sqlite3_int64 szMax; /* --maxsize argument to .open */
drh2ce15c32017-07-11 13:34:40 +00001117 char *zDestTable; /* Name of destination table when MODE_Insert */
drh13c20932018-01-10 21:41:55 +00001118 char *zTempFile; /* Temporary file that might need deleting */
drh2ce15c32017-07-11 13:34:40 +00001119 char zTestcase[30]; /* Name of current test case */
1120 char colSeparator[20]; /* Column separator character for several modes */
1121 char rowSeparator[20]; /* Row separator character for MODE_Ascii */
drh3c484e82018-01-10 22:27:21 +00001122 char colSepPrior[20]; /* Saved column separator */
1123 char rowSepPrior[20]; /* Saved row separator */
drh0285d982020-05-29 14:38:43 +00001124 int *colWidth; /* Requested width of each column in columnar modes */
1125 int *actualWidth; /* Actual width of each column */
1126 int nWidth; /* Number of slots in colWidth[] and actualWidth[] */
drh2ce15c32017-07-11 13:34:40 +00001127 char nullValue[20]; /* The text to print when a NULL comes back from
1128 ** the database */
1129 char outfile[FILENAME_MAX]; /* Filename for *out */
1130 const char *zDbFilename; /* name of the database file */
1131 char *zFreeOnClose; /* Filename to free when closing */
1132 const char *zVfs; /* Name of VFS to use */
1133 sqlite3_stmt *pStmt; /* Current statement if any. */
1134 FILE *pLog; /* Write log output here */
1135 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[] */
drh4b5345c2018-04-24 13:07:40 +00001138 EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */
drh2ce15c32017-07-11 13:34:40 +00001139#if defined(SQLITE_ENABLE_SESSION)
1140 int nSession; /* Number of active sessions */
1141 OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */
1142#endif
dan43efc182017-12-19 17:42:13 +00001143 ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
drh2ce15c32017-07-11 13:34:40 +00001144};
1145
drh1fa6d9f2018-01-06 21:46:01 +00001146
drhada70452017-12-21 21:02:27 +00001147/* Allowed values for ShellState.autoEQP
1148*/
drhe2ca99c2018-05-02 00:33:43 +00001149#define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */
1150#define AUTOEQP_on 1 /* Automatic EQP is on */
1151#define AUTOEQP_trigger 2 /* On and also show plans for triggers */
1152#define AUTOEQP_full 3 /* Show full EXPLAIN */
drhada70452017-12-21 21:02:27 +00001153
drh1fa6d9f2018-01-06 21:46:01 +00001154/* Allowed values for ShellState.openMode
1155*/
drh60f34ae2018-10-30 13:19:49 +00001156#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
1157#define SHELL_OPEN_NORMAL 1 /* Normal database file */
1158#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
1159#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
1160#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
1161#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
drh33746482018-12-13 15:06:26 +00001162#define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */
drh1fa6d9f2018-01-06 21:46:01 +00001163
drh707821f2018-12-05 13:39:06 +00001164/* Allowed values for ShellState.eTraceType
1165*/
1166#define SHELL_TRACE_PLAIN 0 /* Show input SQL text */
1167#define SHELL_TRACE_EXPANDED 1 /* Show expanded SQL text */
1168#define SHELL_TRACE_NORMALIZED 2 /* Show normalized SQL text */
1169
drh3f83f592019-02-04 14:53:18 +00001170/* Bits in the ShellState.flgProgress variable */
drhfc4eeef2019-02-05 19:48:46 +00001171#define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */
1172#define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progres
1173 ** callback limit is reached, and for each
1174 ** top-level SQL statement */
1175#define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */
drh3f83f592019-02-04 14:53:18 +00001176
drh2ce15c32017-07-11 13:34:40 +00001177/*
1178** These are the allowed shellFlgs values
1179*/
drhb2a0f752017-08-28 15:51:35 +00001180#define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */
1181#define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */
1182#define SHFLG_Backslash 0x00000004 /* The --backslash option is used */
1183#define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */
1184#define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
1185#define SHFLG_CountChanges 0x00000020 /* .changes setting */
1186#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
drhc0605082020-06-05 00:54:27 +00001187#define SHFLG_HeaderSet 0x00000080 /* .header has been used */
drhc1962192020-10-12 16:54:28 +00001188#define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */
1189#define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */
drh2ce15c32017-07-11 13:34:40 +00001190
1191/*
1192** Macros for testing and setting shellFlgs
1193*/
1194#define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0)
1195#define ShellSetFlag(P,X) ((P)->shellFlgs|=(X))
1196#define ShellClearFlag(P,X) ((P)->shellFlgs&=(~(X)))
1197
1198/*
1199** These are the allowed modes.
1200*/
1201#define MODE_Line 0 /* One column per line. Blank line between records */
1202#define MODE_Column 1 /* One record per line in neat columns */
1203#define MODE_List 2 /* One record per line with a separator */
1204#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
1205#define MODE_Html 4 /* Generate an XHTML table */
1206#define MODE_Insert 5 /* Generate SQL "insert" statements */
1207#define MODE_Quote 6 /* Quote values as for SQL */
1208#define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */
1209#define MODE_Csv 8 /* Quote strings, numbers are plain */
1210#define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */
1211#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
1212#define MODE_Pretty 11 /* Pretty-print schemas */
drh4b5345c2018-04-24 13:07:40 +00001213#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
drh30c54a02020-05-28 23:49:50 +00001214#define MODE_Json 13 /* Output JSON */
1215#define MODE_Markdown 14 /* Markdown formatting */
1216#define MODE_Table 15 /* MySQL-style table formatting */
drh0908e382020-06-04 18:05:39 +00001217#define MODE_Box 16 /* Unicode box-drawing characters */
drh2ce15c32017-07-11 13:34:40 +00001218
1219static const char *modeDescr[] = {
1220 "line",
1221 "column",
1222 "list",
1223 "semi",
1224 "html",
1225 "insert",
1226 "quote",
1227 "tcl",
1228 "csv",
1229 "explain",
1230 "ascii",
1231 "prettyprint",
drh30c54a02020-05-28 23:49:50 +00001232 "eqp",
1233 "json",
1234 "markdown",
drh0908e382020-06-04 18:05:39 +00001235 "table",
1236 "box"
drh2ce15c32017-07-11 13:34:40 +00001237};
1238
1239/*
1240** These are the column/row/line separators used by the various
1241** import/export modes.
1242*/
1243#define SEP_Column "|"
1244#define SEP_Row "\n"
1245#define SEP_Tab "\t"
1246#define SEP_Space " "
1247#define SEP_Comma ","
1248#define SEP_CrLf "\r\n"
1249#define SEP_Unit "\x1F"
1250#define SEP_Record "\x1E"
1251
1252/*
drh2ce15c32017-07-11 13:34:40 +00001253** A callback for the sqlite3_log() interface.
1254*/
1255static void shellLog(void *pArg, int iErrCode, const char *zMsg){
1256 ShellState *p = (ShellState*)pArg;
1257 if( p->pLog==0 ) return;
1258 utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
1259 fflush(p->pLog);
1260}
1261
1262/*
drh634c70f2018-01-10 16:50:18 +00001263** SQL function: shell_putsnl(X)
1264**
1265** Write the text X to the screen (or whatever output is being directed)
1266** adding a newline at the end, and then return X.
1267*/
1268static void shellPutsFunc(
1269 sqlite3_context *pCtx,
1270 int nVal,
1271 sqlite3_value **apVal
1272){
1273 ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
drhb9685182018-01-17 13:15:23 +00001274 (void)nVal;
drh634c70f2018-01-10 16:50:18 +00001275 utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
1276 sqlite3_result_value(pCtx, apVal[0]);
1277}
1278
1279/*
drh97913132018-01-11 00:04:00 +00001280** SQL function: edit(VALUE)
1281** edit(VALUE,EDITOR)
1282**
1283** These steps:
1284**
1285** (1) Write VALUE into a temporary file.
1286** (2) Run program EDITOR on that temporary file.
1287** (3) Read the temporary file back and return its content as the result.
1288** (4) Delete the temporary file
1289**
1290** If the EDITOR argument is omitted, use the value in the VISUAL
1291** environment variable. If still there is no EDITOR, through an error.
1292**
1293** Also throw an error if the EDITOR program returns a non-zero exit code.
1294*/
drh04a28c32018-01-31 01:38:44 +00001295#ifndef SQLITE_NOHAVE_SYSTEM
drh97913132018-01-11 00:04:00 +00001296static void editFunc(
1297 sqlite3_context *context,
1298 int argc,
1299 sqlite3_value **argv
1300){
1301 const char *zEditor;
1302 char *zTempFile = 0;
1303 sqlite3 *db;
1304 char *zCmd = 0;
1305 int bBin;
1306 int rc;
drhf018fd52018-08-06 02:08:53 +00001307 int hasCRNL = 0;
drh97913132018-01-11 00:04:00 +00001308 FILE *f = 0;
1309 sqlite3_int64 sz;
1310 sqlite3_int64 x;
1311 unsigned char *p = 0;
1312
1313 if( argc==2 ){
1314 zEditor = (const char*)sqlite3_value_text(argv[1]);
1315 }else{
1316 zEditor = getenv("VISUAL");
1317 }
1318 if( zEditor==0 ){
1319 sqlite3_result_error(context, "no editor for edit()", -1);
1320 return;
1321 }
1322 if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
1323 sqlite3_result_error(context, "NULL input to edit()", -1);
1324 return;
1325 }
1326 db = sqlite3_context_db_handle(context);
1327 zTempFile = 0;
1328 sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile);
1329 if( zTempFile==0 ){
1330 sqlite3_uint64 r = 0;
1331 sqlite3_randomness(sizeof(r), &r);
1332 zTempFile = sqlite3_mprintf("temp%llx", r);
1333 if( zTempFile==0 ){
1334 sqlite3_result_error_nomem(context);
1335 return;
1336 }
1337 }
1338 bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB;
drhf018fd52018-08-06 02:08:53 +00001339 /* When writing the file to be edited, do \n to \r\n conversions on systems
1340 ** that want \r\n line endings */
drh97913132018-01-11 00:04:00 +00001341 f = fopen(zTempFile, bBin ? "wb" : "w");
1342 if( f==0 ){
1343 sqlite3_result_error(context, "edit() cannot open temp file", -1);
1344 goto edit_func_end;
1345 }
1346 sz = sqlite3_value_bytes(argv[0]);
1347 if( bBin ){
dan4d02b5f2019-07-17 07:23:06 +00001348 x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001349 }else{
drhf018fd52018-08-06 02:08:53 +00001350 const char *z = (const char*)sqlite3_value_text(argv[0]);
1351 /* Remember whether or not the value originally contained \r\n */
1352 if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
dan4d02b5f2019-07-17 07:23:06 +00001353 x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001354 }
1355 fclose(f);
1356 f = 0;
1357 if( x!=sz ){
1358 sqlite3_result_error(context, "edit() could not write the whole file", -1);
1359 goto edit_func_end;
1360 }
1361 zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile);
1362 if( zCmd==0 ){
1363 sqlite3_result_error_nomem(context);
1364 goto edit_func_end;
1365 }
1366 rc = system(zCmd);
1367 sqlite3_free(zCmd);
1368 if( rc ){
1369 sqlite3_result_error(context, "EDITOR returned non-zero", -1);
1370 goto edit_func_end;
1371 }
drhf018fd52018-08-06 02:08:53 +00001372 f = fopen(zTempFile, "rb");
drh97913132018-01-11 00:04:00 +00001373 if( f==0 ){
1374 sqlite3_result_error(context,
1375 "edit() cannot reopen temp file after edit", -1);
1376 goto edit_func_end;
1377 }
1378 fseek(f, 0, SEEK_END);
1379 sz = ftell(f);
1380 rewind(f);
drhee37f8b2019-08-23 23:05:32 +00001381 p = sqlite3_malloc64( sz+1 );
drh97913132018-01-11 00:04:00 +00001382 if( p==0 ){
1383 sqlite3_result_error_nomem(context);
1384 goto edit_func_end;
1385 }
dan4d02b5f2019-07-17 07:23:06 +00001386 x = fread(p, 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001387 fclose(f);
1388 f = 0;
1389 if( x!=sz ){
1390 sqlite3_result_error(context, "could not read back the whole file", -1);
1391 goto edit_func_end;
1392 }
1393 if( bBin ){
mistachkinb71aa092018-01-23 00:05:18 +00001394 sqlite3_result_blob64(context, p, sz, sqlite3_free);
drh97913132018-01-11 00:04:00 +00001395 }else{
dan60bdcf52018-10-03 11:13:30 +00001396 sqlite3_int64 i, j;
drhf018fd52018-08-06 02:08:53 +00001397 if( hasCRNL ){
1398 /* If the original contains \r\n then do no conversions back to \n */
1399 j = sz;
1400 }else{
1401 /* If the file did not originally contain \r\n then convert any new
1402 ** \r\n back into \n */
1403 for(i=j=0; i<sz; i++){
1404 if( p[i]=='\r' && p[i+1]=='\n' ) i++;
1405 p[j++] = p[i];
1406 }
1407 sz = j;
1408 p[sz] = 0;
1409 }
mistachkinb71aa092018-01-23 00:05:18 +00001410 sqlite3_result_text64(context, (const char*)p, sz,
1411 sqlite3_free, SQLITE_UTF8);
drh97913132018-01-11 00:04:00 +00001412 }
1413 p = 0;
1414
1415edit_func_end:
1416 if( f ) fclose(f);
1417 unlink(zTempFile);
1418 sqlite3_free(zTempFile);
1419 sqlite3_free(p);
1420}
drh04a28c32018-01-31 01:38:44 +00001421#endif /* SQLITE_NOHAVE_SYSTEM */
drh97913132018-01-11 00:04:00 +00001422
1423/*
drh3c484e82018-01-10 22:27:21 +00001424** Save or restore the current output mode
1425*/
1426static void outputModePush(ShellState *p){
1427 p->modePrior = p->mode;
drh7a431002020-04-18 14:12:00 +00001428 p->priorShFlgs = p->shellFlgs;
drh3c484e82018-01-10 22:27:21 +00001429 memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));
1430 memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));
1431}
1432static void outputModePop(ShellState *p){
1433 p->mode = p->modePrior;
drh7a431002020-04-18 14:12:00 +00001434 p->shellFlgs = p->priorShFlgs;
drh3c484e82018-01-10 22:27:21 +00001435 memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
1436 memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
1437}
1438
1439/*
drh2ce15c32017-07-11 13:34:40 +00001440** Output the given string as a hex-encoded blob (eg. X'1234' )
1441*/
1442static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
1443 int i;
1444 char *zBlob = (char *)pBlob;
1445 raw_printf(out,"X'");
1446 for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); }
1447 raw_printf(out,"'");
1448}
1449
1450/*
1451** Find a string that is not found anywhere in z[]. Return a pointer
1452** to that string.
1453**
1454** Try to use zA and zB first. If both of those are already found in z[]
1455** then make up some string and store it in the buffer zBuf.
1456*/
1457static const char *unused_string(
1458 const char *z, /* Result must not appear anywhere in z */
1459 const char *zA, const char *zB, /* Try these first */
1460 char *zBuf /* Space to store a generated string */
1461){
1462 unsigned i = 0;
1463 if( strstr(z, zA)==0 ) return zA;
1464 if( strstr(z, zB)==0 ) return zB;
1465 do{
1466 sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
1467 }while( strstr(z,zBuf)!=0 );
1468 return zBuf;
1469}
1470
1471/*
1472** Output the given string as a quoted string using SQL quoting conventions.
1473**
1474** See also: output_quoted_escaped_string()
1475*/
1476static void output_quoted_string(FILE *out, const char *z){
1477 int i;
1478 char c;
1479 setBinaryMode(out, 1);
1480 for(i=0; (c = z[i])!=0 && c!='\''; i++){}
1481 if( c==0 ){
1482 utf8_printf(out,"'%s'",z);
1483 }else{
1484 raw_printf(out, "'");
1485 while( *z ){
1486 for(i=0; (c = z[i])!=0 && c!='\''; i++){}
1487 if( c=='\'' ) i++;
1488 if( i ){
1489 utf8_printf(out, "%.*s", i, z);
1490 z += i;
1491 }
1492 if( c=='\'' ){
1493 raw_printf(out, "'");
1494 continue;
1495 }
1496 if( c==0 ){
1497 break;
1498 }
1499 z++;
1500 }
1501 raw_printf(out, "'");
1502 }
1503 setTextMode(out, 1);
1504}
1505
1506/*
1507** Output the given string as a quoted string using SQL quoting conventions.
1508** Additionallly , escape the "\n" and "\r" characters so that they do not
1509** get corrupted by end-of-line translation facilities in some operating
1510** systems.
1511**
1512** This is like output_quoted_string() but with the addition of the \r\n
1513** escape mechanism.
1514*/
1515static void output_quoted_escaped_string(FILE *out, const char *z){
1516 int i;
1517 char c;
1518 setBinaryMode(out, 1);
1519 for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
1520 if( c==0 ){
1521 utf8_printf(out,"'%s'",z);
1522 }else{
1523 const char *zNL = 0;
1524 const char *zCR = 0;
1525 int nNL = 0;
1526 int nCR = 0;
1527 char zBuf1[20], zBuf2[20];
1528 for(i=0; z[i]; i++){
1529 if( z[i]=='\n' ) nNL++;
1530 if( z[i]=='\r' ) nCR++;
1531 }
1532 if( nNL ){
1533 raw_printf(out, "replace(");
1534 zNL = unused_string(z, "\\n", "\\012", zBuf1);
1535 }
1536 if( nCR ){
1537 raw_printf(out, "replace(");
1538 zCR = unused_string(z, "\\r", "\\015", zBuf2);
1539 }
1540 raw_printf(out, "'");
1541 while( *z ){
1542 for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
1543 if( c=='\'' ) i++;
1544 if( i ){
1545 utf8_printf(out, "%.*s", i, z);
1546 z += i;
1547 }
1548 if( c=='\'' ){
1549 raw_printf(out, "'");
1550 continue;
1551 }
1552 if( c==0 ){
1553 break;
1554 }
1555 z++;
1556 if( c=='\n' ){
1557 raw_printf(out, "%s", zNL);
1558 continue;
1559 }
1560 raw_printf(out, "%s", zCR);
1561 }
1562 raw_printf(out, "'");
1563 if( nCR ){
1564 raw_printf(out, ",'%s',char(13))", zCR);
1565 }
1566 if( nNL ){
1567 raw_printf(out, ",'%s',char(10))", zNL);
1568 }
1569 }
1570 setTextMode(out, 1);
1571}
1572
1573/*
1574** Output the given string as a quoted according to C or TCL quoting rules.
1575*/
1576static void output_c_string(FILE *out, const char *z){
1577 unsigned int c;
1578 fputc('"', out);
1579 while( (c = *(z++))!=0 ){
1580 if( c=='\\' ){
1581 fputc(c, out);
1582 fputc(c, out);
1583 }else if( c=='"' ){
1584 fputc('\\', out);
1585 fputc('"', out);
1586 }else if( c=='\t' ){
1587 fputc('\\', out);
1588 fputc('t', out);
1589 }else if( c=='\n' ){
1590 fputc('\\', out);
1591 fputc('n', out);
1592 }else if( c=='\r' ){
1593 fputc('\\', out);
1594 fputc('r', out);
1595 }else if( !isprint(c&0xff) ){
1596 raw_printf(out, "\\%03o", c&0xff);
1597 }else{
1598 fputc(c, out);
1599 }
1600 }
1601 fputc('"', out);
1602}
1603
1604/*
drh69c093d2020-05-29 00:21:43 +00001605** Output the given string as a quoted according to JSON quoting rules.
1606*/
1607static void output_json_string(FILE *out, const char *z, int n){
1608 unsigned int c;
1609 if( n<0 ) n = (int)strlen(z);
1610 fputc('"', out);
1611 while( n-- ){
1612 c = *(z++);
1613 if( c=='\\' || c=='"' ){
1614 fputc('\\', out);
1615 fputc(c, out);
1616 }else if( c<=0x1f ){
1617 fputc('\\', out);
1618 if( c=='\b' ){
1619 fputc('b', out);
1620 }else if( c=='\f' ){
1621 fputc('f', out);
1622 }else if( c=='\n' ){
1623 fputc('n', out);
1624 }else if( c=='\r' ){
1625 fputc('r', out);
1626 }else if( c=='\t' ){
1627 fputc('t', out);
1628 }else{
1629 raw_printf(out, "u%04x",c);
1630 }
1631 }else{
1632 fputc(c, out);
1633 }
1634 }
1635 fputc('"', out);
1636}
1637
1638/*
drh2ce15c32017-07-11 13:34:40 +00001639** Output the given string with characters that are special to
1640** HTML escaped.
1641*/
1642static void output_html_string(FILE *out, const char *z){
1643 int i;
1644 if( z==0 ) z = "";
1645 while( *z ){
1646 for(i=0; z[i]
1647 && z[i]!='<'
1648 && z[i]!='&'
1649 && z[i]!='>'
1650 && z[i]!='\"'
1651 && z[i]!='\'';
1652 i++){}
1653 if( i>0 ){
1654 utf8_printf(out,"%.*s",i,z);
1655 }
1656 if( z[i]=='<' ){
1657 raw_printf(out,"&lt;");
1658 }else if( z[i]=='&' ){
1659 raw_printf(out,"&amp;");
1660 }else if( z[i]=='>' ){
1661 raw_printf(out,"&gt;");
1662 }else if( z[i]=='\"' ){
1663 raw_printf(out,"&quot;");
1664 }else if( z[i]=='\'' ){
1665 raw_printf(out,"&#39;");
1666 }else{
1667 break;
1668 }
1669 z += i + 1;
1670 }
1671}
1672
1673/*
1674** If a field contains any character identified by a 1 in the following
1675** array, then the string must be quoted for CSV.
1676*/
1677static const char needCsvQuote[] = {
1678 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1679 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1680 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1681 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1682 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1683 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1684 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1685 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1686 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1687 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1688 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1689 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1690 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1691 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1692 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1693 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1694};
1695
1696/*
1697** Output a single term of CSV. Actually, p->colSeparator is used for
1698** the separator, which may or may not be a comma. p->nullValue is
1699** the null value. Strings are quoted if necessary. The separator
1700** is only issued if bSep is true.
1701*/
1702static void output_csv(ShellState *p, const char *z, int bSep){
1703 FILE *out = p->out;
1704 if( z==0 ){
1705 utf8_printf(out,"%s",p->nullValue);
1706 }else{
1707 int i;
1708 int nSep = strlen30(p->colSeparator);
1709 for(i=0; z[i]; i++){
1710 if( needCsvQuote[((unsigned char*)z)[i]]
1711 || (z[i]==p->colSeparator[0] &&
1712 (nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){
1713 i = 0;
1714 break;
1715 }
1716 }
1717 if( i==0 ){
drh9b7affc2017-11-26 02:14:18 +00001718 char *zQuoted = sqlite3_mprintf("\"%w\"", z);
1719 utf8_printf(out, "%s", zQuoted);
1720 sqlite3_free(zQuoted);
drh2ce15c32017-07-11 13:34:40 +00001721 }else{
1722 utf8_printf(out, "%s", z);
1723 }
1724 }
1725 if( bSep ){
1726 utf8_printf(p->out, "%s", p->colSeparator);
1727 }
1728}
1729
drh2ce15c32017-07-11 13:34:40 +00001730/*
1731** This routine runs when the user presses Ctrl-C
1732*/
1733static void interrupt_handler(int NotUsed){
1734 UNUSED_PARAMETER(NotUsed);
1735 seenInterrupt++;
1736 if( seenInterrupt>2 ) exit(1);
1737 if( globalDb ) sqlite3_interrupt(globalDb);
1738}
mistachkinb4bab902017-10-27 17:09:44 +00001739
1740#if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
1741/*
1742** This routine runs for console events (e.g. Ctrl-C) on Win32
1743*/
1744static BOOL WINAPI ConsoleCtrlHandler(
1745 DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */
1746){
1747 if( dwCtrlType==CTRL_C_EVENT ){
1748 interrupt_handler(0);
1749 return TRUE;
1750 }
1751 return FALSE;
1752}
drh2ce15c32017-07-11 13:34:40 +00001753#endif
1754
1755#ifndef SQLITE_OMIT_AUTHORIZATION
1756/*
1757** When the ".auth ON" is set, the following authorizer callback is
1758** invoked. It always returns SQLITE_OK.
1759*/
1760static int shellAuth(
1761 void *pClientData,
1762 int op,
1763 const char *zA1,
1764 const char *zA2,
1765 const char *zA3,
1766 const char *zA4
1767){
1768 ShellState *p = (ShellState*)pClientData;
1769 static const char *azAction[] = { 0,
1770 "CREATE_INDEX", "CREATE_TABLE", "CREATE_TEMP_INDEX",
1771 "CREATE_TEMP_TABLE", "CREATE_TEMP_TRIGGER", "CREATE_TEMP_VIEW",
1772 "CREATE_TRIGGER", "CREATE_VIEW", "DELETE",
1773 "DROP_INDEX", "DROP_TABLE", "DROP_TEMP_INDEX",
1774 "DROP_TEMP_TABLE", "DROP_TEMP_TRIGGER", "DROP_TEMP_VIEW",
1775 "DROP_TRIGGER", "DROP_VIEW", "INSERT",
1776 "PRAGMA", "READ", "SELECT",
1777 "TRANSACTION", "UPDATE", "ATTACH",
1778 "DETACH", "ALTER_TABLE", "REINDEX",
1779 "ANALYZE", "CREATE_VTABLE", "DROP_VTABLE",
1780 "FUNCTION", "SAVEPOINT", "RECURSIVE"
1781 };
1782 int i;
1783 const char *az[4];
1784 az[0] = zA1;
1785 az[1] = zA2;
1786 az[2] = zA3;
1787 az[3] = zA4;
1788 utf8_printf(p->out, "authorizer: %s", azAction[op]);
1789 for(i=0; i<4; i++){
1790 raw_printf(p->out, " ");
1791 if( az[i] ){
1792 output_c_string(p->out, az[i]);
1793 }else{
1794 raw_printf(p->out, "NULL");
1795 }
1796 }
1797 raw_printf(p->out, "\n");
1798 return SQLITE_OK;
1799}
1800#endif
1801
1802/*
1803** Print a schema statement. Part of MODE_Semi and MODE_Pretty output.
1804**
1805** This routine converts some CREATE TABLE statements for shadow tables
1806** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
1807*/
1808static void printSchemaLine(FILE *out, const char *z, const char *zTail){
drh0a0536a2019-05-09 18:13:30 +00001809 if( z==0 ) return;
1810 if( zTail==0 ) return;
drh2ce15c32017-07-11 13:34:40 +00001811 if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
1812 utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
1813 }else{
1814 utf8_printf(out, "%s%s", z, zTail);
1815 }
1816}
1817static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
1818 char c = z[n];
1819 z[n] = 0;
1820 printSchemaLine(out, z, zTail);
1821 z[n] = c;
1822}
1823
1824/*
drh11be81d2018-01-06 15:46:20 +00001825** Return true if string z[] has nothing but whitespace and comments to the
1826** end of the first line.
1827*/
1828static int wsToEol(const char *z){
1829 int i;
1830 for(i=0; z[i]; i++){
1831 if( z[i]=='\n' ) return 1;
1832 if( IsSpace(z[i]) ) continue;
1833 if( z[i]=='-' && z[i+1]=='-' ) return 1;
1834 return 0;
1835 }
1836 return 1;
1837}
drh4b5345c2018-04-24 13:07:40 +00001838
1839/*
1840** Add a new entry to the EXPLAIN QUERY PLAN data
1841*/
drhe2ca99c2018-05-02 00:33:43 +00001842static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
drh4b5345c2018-04-24 13:07:40 +00001843 EQPGraphRow *pNew;
1844 int nText = strlen30(zText);
drhe2ca99c2018-05-02 00:33:43 +00001845 if( p->autoEQPtest ){
1846 utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
1847 }
drh4b5345c2018-04-24 13:07:40 +00001848 pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
1849 if( pNew==0 ) shell_out_of_memory();
drhe2ca99c2018-05-02 00:33:43 +00001850 pNew->iEqpId = iEqpId;
1851 pNew->iParentId = p2;
drh4b5345c2018-04-24 13:07:40 +00001852 memcpy(pNew->zText, zText, nText+1);
1853 pNew->pNext = 0;
1854 if( p->sGraph.pLast ){
1855 p->sGraph.pLast->pNext = pNew;
1856 }else{
1857 p->sGraph.pRow = pNew;
1858 }
1859 p->sGraph.pLast = pNew;
1860}
1861
1862/*
1863** Free and reset the EXPLAIN QUERY PLAN data that has been collected
1864** in p->sGraph.
1865*/
1866static void eqp_reset(ShellState *p){
1867 EQPGraphRow *pRow, *pNext;
1868 for(pRow = p->sGraph.pRow; pRow; pRow = pNext){
1869 pNext = pRow->pNext;
1870 sqlite3_free(pRow);
1871 }
1872 memset(&p->sGraph, 0, sizeof(p->sGraph));
1873}
1874
drhe2ca99c2018-05-02 00:33:43 +00001875/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after
drh4b5345c2018-04-24 13:07:40 +00001876** pOld, or return the first such line if pOld is NULL
1877*/
drhe2ca99c2018-05-02 00:33:43 +00001878static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){
drh4b5345c2018-04-24 13:07:40 +00001879 EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow;
drhe2ca99c2018-05-02 00:33:43 +00001880 while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext;
drh4b5345c2018-04-24 13:07:40 +00001881 return pRow;
1882}
1883
drhe2ca99c2018-05-02 00:33:43 +00001884/* Render a single level of the graph that has iEqpId as its parent. Called
drh4b5345c2018-04-24 13:07:40 +00001885** recursively to render sublevels.
1886*/
drhe2ca99c2018-05-02 00:33:43 +00001887static void eqp_render_level(ShellState *p, int iEqpId){
drh4b5345c2018-04-24 13:07:40 +00001888 EQPGraphRow *pRow, *pNext;
drh4b5345c2018-04-24 13:07:40 +00001889 int n = strlen30(p->sGraph.zPrefix);
1890 char *z;
drhe2ca99c2018-05-02 00:33:43 +00001891 for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
1892 pNext = eqp_next_row(p, iEqpId, pRow);
drh4b5345c2018-04-24 13:07:40 +00001893 z = pRow->zText;
drhe2754c12019-08-26 12:50:01 +00001894 utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
1895 pNext ? "|--" : "`--", z);
drhe2188f02018-05-07 11:37:34 +00001896 if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){
drh4b5345c2018-04-24 13:07:40 +00001897 memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4);
drhe2ca99c2018-05-02 00:33:43 +00001898 eqp_render_level(p, pRow->iEqpId);
drh4b5345c2018-04-24 13:07:40 +00001899 p->sGraph.zPrefix[n] = 0;
1900 }
1901 }
1902}
1903
1904/*
1905** Display and reset the EXPLAIN QUERY PLAN data
1906*/
1907static void eqp_render(ShellState *p){
1908 EQPGraphRow *pRow = p->sGraph.pRow;
1909 if( pRow ){
1910 if( pRow->zText[0]=='-' ){
1911 if( pRow->pNext==0 ){
1912 eqp_reset(p);
1913 return;
1914 }
1915 utf8_printf(p->out, "%s\n", pRow->zText+3);
1916 p->sGraph.pRow = pRow->pNext;
1917 sqlite3_free(pRow);
1918 }else{
1919 utf8_printf(p->out, "QUERY PLAN\n");
1920 }
1921 p->sGraph.zPrefix[0] = 0;
1922 eqp_render_level(p, 0);
1923 eqp_reset(p);
1924 }
1925}
drh11be81d2018-01-06 15:46:20 +00001926
drh569b1d92019-02-05 20:51:41 +00001927#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh11be81d2018-01-06 15:46:20 +00001928/*
drh3f83f592019-02-04 14:53:18 +00001929** Progress handler callback.
1930*/
1931static int progress_handler(void *pClientData) {
1932 ShellState *p = (ShellState*)pClientData;
1933 p->nProgress++;
1934 if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
1935 raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
drhfc4eeef2019-02-05 19:48:46 +00001936 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
1937 if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
drh3f83f592019-02-04 14:53:18 +00001938 return 1;
1939 }
drhfc4eeef2019-02-05 19:48:46 +00001940 if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
drh3f83f592019-02-04 14:53:18 +00001941 raw_printf(p->out, "Progress %u\n", p->nProgress);
1942 }
1943 return 0;
1944}
drh569b1d92019-02-05 20:51:41 +00001945#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
drh3f83f592019-02-04 14:53:18 +00001946
1947/*
drh30c54a02020-05-28 23:49:50 +00001948** Print N dashes
1949*/
1950static void print_dashes(FILE *out, int N){
1951 const char zDash[] = "--------------------------------------------------";
1952 const int nDash = sizeof(zDash) - 1;
1953 while( N>nDash ){
1954 fputs(zDash, out);
1955 N -= nDash;
1956 }
1957 raw_printf(out, "%.*s", N, zDash);
1958}
1959
1960/*
drh0908e382020-06-04 18:05:39 +00001961** Print a markdown or table-style row separator using ascii-art
drh30c54a02020-05-28 23:49:50 +00001962*/
1963static void print_row_separator(
1964 ShellState *p,
1965 int nArg,
1966 const char *zSep
1967){
1968 int i;
drh0908e382020-06-04 18:05:39 +00001969 if( nArg>0 ){
drh30c54a02020-05-28 23:49:50 +00001970 fputs(zSep, p->out);
drh0908e382020-06-04 18:05:39 +00001971 print_dashes(p->out, p->actualWidth[0]+2);
1972 for(i=1; i<nArg; i++){
1973 fputs(zSep, p->out);
1974 print_dashes(p->out, p->actualWidth[i]+2);
1975 }
1976 fputs(zSep, p->out);
drh30c54a02020-05-28 23:49:50 +00001977 }
drh30c54a02020-05-28 23:49:50 +00001978 fputs("\n", p->out);
1979}
1980
1981/*
drh2ce15c32017-07-11 13:34:40 +00001982** This is the callback routine that the shell
1983** invokes for each row of a query result.
1984*/
1985static int shell_callback(
1986 void *pArg,
1987 int nArg, /* Number of result columns */
1988 char **azArg, /* Text of each result column */
1989 char **azCol, /* Column names */
drhd6f25242020-05-29 12:31:53 +00001990 int *aiType /* Column types. Might be NULL */
drh2ce15c32017-07-11 13:34:40 +00001991){
1992 int i;
1993 ShellState *p = (ShellState*)pArg;
1994
drhb3c45232017-08-28 14:33:27 +00001995 if( azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00001996 switch( p->cMode ){
1997 case MODE_Line: {
1998 int w = 5;
1999 if( azArg==0 ) break;
2000 for(i=0; i<nArg; i++){
2001 int len = strlen30(azCol[i] ? azCol[i] : "");
2002 if( len>w ) w = len;
2003 }
2004 if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
2005 for(i=0; i<nArg; i++){
2006 utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
2007 azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
2008 }
2009 break;
2010 }
drh8c748632020-05-29 16:15:58 +00002011 case MODE_Explain: {
2012 static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
2013 if( nArg>ArraySize(aExplainWidth) ){
2014 nArg = ArraySize(aExplainWidth);
drh2ce15c32017-07-11 13:34:40 +00002015 }
2016 if( p->cnt++==0 ){
2017 for(i=0; i<nArg; i++){
drh8c748632020-05-29 16:15:58 +00002018 int w = aExplainWidth[i];
2019 utf8_width_print(p->out, w, azCol[i]);
2020 fputs(i==nArg-1 ? "\n" : " ", p->out);
drh2ce15c32017-07-11 13:34:40 +00002021 }
drhe566ceb2020-05-30 15:34:49 +00002022 for(i=0; i<nArg; i++){
2023 int w = aExplainWidth[i];
2024 print_dashes(p->out, w);
2025 fputs(i==nArg-1 ? "\n" : " ", p->out);
2026 }
drh2ce15c32017-07-11 13:34:40 +00002027 }
2028 if( azArg==0 ) break;
2029 for(i=0; i<nArg; i++){
drh8c748632020-05-29 16:15:58 +00002030 int w = aExplainWidth[i];
drhaa556b02021-01-13 12:59:20 +00002031 if( i==nArg-1 ) w = 0;
drh8c748632020-05-29 16:15:58 +00002032 if( azArg[i] && strlenChar(azArg[i])>w ){
2033 w = strlenChar(azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00002034 }
drh8c748632020-05-29 16:15:58 +00002035 if( i==1 && p->aiIndent && p->pStmt ){
2036 if( p->iIndent<p->nIndent ){
2037 utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
drh2ce15c32017-07-11 13:34:40 +00002038 }
drh8c748632020-05-29 16:15:58 +00002039 p->iIndent++;
drh2ce15c32017-07-11 13:34:40 +00002040 }
2041 utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
drh8c748632020-05-29 16:15:58 +00002042 fputs(i==nArg-1 ? "\n" : " ", p->out);
drh2ce15c32017-07-11 13:34:40 +00002043 }
2044 break;
2045 }
2046 case MODE_Semi: { /* .schema and .fullschema output */
2047 printSchemaLine(p->out, azArg[0], ";\n");
2048 break;
2049 }
2050 case MODE_Pretty: { /* .schema and .fullschema with --indent */
2051 char *z;
2052 int j;
2053 int nParen = 0;
2054 char cEnd = 0;
2055 char c;
2056 int nLine = 0;
2057 assert( nArg==1 );
2058 if( azArg[0]==0 ) break;
2059 if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
2060 || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
2061 ){
2062 utf8_printf(p->out, "%s;\n", azArg[0]);
2063 break;
2064 }
2065 z = sqlite3_mprintf("%s", azArg[0]);
2066 j = 0;
2067 for(i=0; IsSpace(z[i]); i++){}
2068 for(; (c = z[i])!=0; i++){
2069 if( IsSpace(c) ){
drhc3cbd672017-10-05 19:12:10 +00002070 if( z[j-1]=='\r' ) z[j-1] = '\n';
drh2ce15c32017-07-11 13:34:40 +00002071 if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
2072 }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
2073 j--;
2074 }
2075 z[j++] = c;
2076 }
2077 while( j>0 && IsSpace(z[j-1]) ){ j--; }
2078 z[j] = 0;
2079 if( strlen30(z)>=79 ){
drhe2754c12019-08-26 12:50:01 +00002080 for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */
drh2ce15c32017-07-11 13:34:40 +00002081 if( c==cEnd ){
2082 cEnd = 0;
2083 }else if( c=='"' || c=='\'' || c=='`' ){
2084 cEnd = c;
2085 }else if( c=='[' ){
2086 cEnd = ']';
drh11be81d2018-01-06 15:46:20 +00002087 }else if( c=='-' && z[i+1]=='-' ){
2088 cEnd = '\n';
drh2ce15c32017-07-11 13:34:40 +00002089 }else if( c=='(' ){
2090 nParen++;
2091 }else if( c==')' ){
2092 nParen--;
2093 if( nLine>0 && nParen==0 && j>0 ){
2094 printSchemaLineN(p->out, z, j, "\n");
2095 j = 0;
2096 }
2097 }
2098 z[j++] = c;
drh11be81d2018-01-06 15:46:20 +00002099 if( nParen==1 && cEnd==0
2100 && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
2101 ){
drh2ce15c32017-07-11 13:34:40 +00002102 if( c=='\n' ) j--;
2103 printSchemaLineN(p->out, z, j, "\n ");
2104 j = 0;
2105 nLine++;
2106 while( IsSpace(z[i+1]) ){ i++; }
2107 }
2108 }
2109 z[j] = 0;
2110 }
2111 printSchemaLine(p->out, z, ";\n");
2112 sqlite3_free(z);
2113 break;
2114 }
2115 case MODE_List: {
2116 if( p->cnt++==0 && p->showHeader ){
2117 for(i=0; i<nArg; i++){
2118 utf8_printf(p->out,"%s%s",azCol[i],
2119 i==nArg-1 ? p->rowSeparator : p->colSeparator);
2120 }
2121 }
2122 if( azArg==0 ) break;
2123 for(i=0; i<nArg; i++){
2124 char *z = azArg[i];
2125 if( z==0 ) z = p->nullValue;
2126 utf8_printf(p->out, "%s", z);
2127 if( i<nArg-1 ){
2128 utf8_printf(p->out, "%s", p->colSeparator);
2129 }else{
2130 utf8_printf(p->out, "%s", p->rowSeparator);
2131 }
2132 }
2133 break;
2134 }
2135 case MODE_Html: {
2136 if( p->cnt++==0 && p->showHeader ){
2137 raw_printf(p->out,"<TR>");
2138 for(i=0; i<nArg; i++){
2139 raw_printf(p->out,"<TH>");
2140 output_html_string(p->out, azCol[i]);
2141 raw_printf(p->out,"</TH>\n");
2142 }
2143 raw_printf(p->out,"</TR>\n");
2144 }
2145 if( azArg==0 ) break;
2146 raw_printf(p->out,"<TR>");
2147 for(i=0; i<nArg; i++){
2148 raw_printf(p->out,"<TD>");
2149 output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
2150 raw_printf(p->out,"</TD>\n");
2151 }
2152 raw_printf(p->out,"</TR>\n");
2153 break;
2154 }
2155 case MODE_Tcl: {
2156 if( p->cnt++==0 && p->showHeader ){
2157 for(i=0; i<nArg; i++){
2158 output_c_string(p->out,azCol[i] ? azCol[i] : "");
2159 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
2160 }
2161 utf8_printf(p->out, "%s", p->rowSeparator);
2162 }
2163 if( azArg==0 ) break;
2164 for(i=0; i<nArg; i++){
2165 output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
2166 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
2167 }
2168 utf8_printf(p->out, "%s", p->rowSeparator);
2169 break;
2170 }
2171 case MODE_Csv: {
2172 setBinaryMode(p->out, 1);
2173 if( p->cnt++==0 && p->showHeader ){
2174 for(i=0; i<nArg; i++){
2175 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
2176 }
2177 utf8_printf(p->out, "%s", p->rowSeparator);
2178 }
2179 if( nArg>0 ){
2180 for(i=0; i<nArg; i++){
2181 output_csv(p, azArg[i], i<nArg-1);
2182 }
2183 utf8_printf(p->out, "%s", p->rowSeparator);
2184 }
2185 setTextMode(p->out, 1);
2186 break;
2187 }
2188 case MODE_Insert: {
2189 if( azArg==0 ) break;
2190 utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
2191 if( p->showHeader ){
2192 raw_printf(p->out,"(");
2193 for(i=0; i<nArg; i++){
2194 if( i>0 ) raw_printf(p->out, ",");
2195 if( quoteChar(azCol[i]) ){
2196 char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
2197 utf8_printf(p->out, "%s", z);
2198 sqlite3_free(z);
2199 }else{
2200 raw_printf(p->out, "%s", azCol[i]);
2201 }
2202 }
2203 raw_printf(p->out,")");
2204 }
2205 p->cnt++;
2206 for(i=0; i<nArg; i++){
2207 raw_printf(p->out, i>0 ? "," : " VALUES(");
2208 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2209 utf8_printf(p->out,"NULL");
2210 }else if( aiType && aiType[i]==SQLITE_TEXT ){
2211 if( ShellHasFlag(p, SHFLG_Newlines) ){
2212 output_quoted_string(p->out, azArg[i]);
2213 }else{
2214 output_quoted_escaped_string(p->out, azArg[i]);
2215 }
2216 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
2217 utf8_printf(p->out,"%s", azArg[i]);
2218 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2219 char z[50];
2220 double r = sqlite3_column_double(p->pStmt, i);
drh2f1f8802018-06-13 17:19:20 +00002221 sqlite3_uint64 ur;
2222 memcpy(&ur,&r,sizeof(r));
2223 if( ur==0x7ff0000000000000LL ){
2224 raw_printf(p->out, "1e999");
2225 }else if( ur==0xfff0000000000000LL ){
2226 raw_printf(p->out, "-1e999");
2227 }else{
2228 sqlite3_snprintf(50,z,"%!.20g", r);
2229 raw_printf(p->out, "%s", z);
2230 }
drh2ce15c32017-07-11 13:34:40 +00002231 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2232 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2233 int nBlob = sqlite3_column_bytes(p->pStmt, i);
2234 output_hex_blob(p->out, pBlob, nBlob);
2235 }else if( isNumber(azArg[i], 0) ){
2236 utf8_printf(p->out,"%s", azArg[i]);
2237 }else if( ShellHasFlag(p, SHFLG_Newlines) ){
2238 output_quoted_string(p->out, azArg[i]);
2239 }else{
2240 output_quoted_escaped_string(p->out, azArg[i]);
2241 }
2242 }
2243 raw_printf(p->out,");\n");
2244 break;
2245 }
drh30c54a02020-05-28 23:49:50 +00002246 case MODE_Json: {
2247 if( azArg==0 ) break;
2248 if( p->cnt==0 ){
2249 fputs("[{", p->out);
2250 }else{
2251 fputs(",\n{", p->out);
2252 }
2253 p->cnt++;
2254 for(i=0; i<nArg; i++){
drh69c093d2020-05-29 00:21:43 +00002255 output_json_string(p->out, azCol[i], -1);
drh30c54a02020-05-28 23:49:50 +00002256 putc(':', p->out);
2257 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2258 fputs("null",p->out);
2259 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2260 char z[50];
2261 double r = sqlite3_column_double(p->pStmt, i);
2262 sqlite3_uint64 ur;
2263 memcpy(&ur,&r,sizeof(r));
2264 if( ur==0x7ff0000000000000LL ){
2265 raw_printf(p->out, "1e999");
2266 }else if( ur==0xfff0000000000000LL ){
2267 raw_printf(p->out, "-1e999");
2268 }else{
2269 sqlite3_snprintf(50,z,"%!.20g", r);
2270 raw_printf(p->out, "%s", z);
2271 }
2272 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2273 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2274 int nBlob = sqlite3_column_bytes(p->pStmt, i);
drh69c093d2020-05-29 00:21:43 +00002275 output_json_string(p->out, pBlob, nBlob);
drh30c54a02020-05-28 23:49:50 +00002276 }else if( aiType && aiType[i]==SQLITE_TEXT ){
drh69c093d2020-05-29 00:21:43 +00002277 output_json_string(p->out, azArg[i], -1);
drh30c54a02020-05-28 23:49:50 +00002278 }else{
2279 utf8_printf(p->out,"%s", azArg[i]);
2280 }
2281 if( i<nArg-1 ){
2282 putc(',', p->out);
2283 }
2284 }
2285 putc('}', p->out);
2286 break;
2287 }
drh2ce15c32017-07-11 13:34:40 +00002288 case MODE_Quote: {
2289 if( azArg==0 ) break;
2290 if( p->cnt==0 && p->showHeader ){
2291 for(i=0; i<nArg; i++){
drhc6835732020-05-28 20:37:17 +00002292 if( i>0 ) fputs(p->colSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002293 output_quoted_string(p->out, azCol[i]);
2294 }
drhc6835732020-05-28 20:37:17 +00002295 fputs(p->rowSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002296 }
2297 p->cnt++;
2298 for(i=0; i<nArg; i++){
drhc6835732020-05-28 20:37:17 +00002299 if( i>0 ) fputs(p->colSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002300 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2301 utf8_printf(p->out,"NULL");
2302 }else if( aiType && aiType[i]==SQLITE_TEXT ){
2303 output_quoted_string(p->out, azArg[i]);
2304 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
2305 utf8_printf(p->out,"%s", azArg[i]);
2306 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2307 char z[50];
2308 double r = sqlite3_column_double(p->pStmt, i);
2309 sqlite3_snprintf(50,z,"%!.20g", r);
2310 raw_printf(p->out, "%s", z);
2311 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2312 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2313 int nBlob = sqlite3_column_bytes(p->pStmt, i);
2314 output_hex_blob(p->out, pBlob, nBlob);
2315 }else if( isNumber(azArg[i], 0) ){
2316 utf8_printf(p->out,"%s", azArg[i]);
2317 }else{
2318 output_quoted_string(p->out, azArg[i]);
2319 }
2320 }
drhc6835732020-05-28 20:37:17 +00002321 fputs(p->rowSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002322 break;
2323 }
2324 case MODE_Ascii: {
2325 if( p->cnt++==0 && p->showHeader ){
2326 for(i=0; i<nArg; i++){
2327 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
2328 utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
2329 }
2330 utf8_printf(p->out, "%s", p->rowSeparator);
2331 }
2332 if( azArg==0 ) break;
2333 for(i=0; i<nArg; i++){
2334 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
2335 utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
2336 }
2337 utf8_printf(p->out, "%s", p->rowSeparator);
2338 break;
2339 }
drh4b5345c2018-04-24 13:07:40 +00002340 case MODE_EQP: {
drhe2ca99c2018-05-02 00:33:43 +00002341 eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]);
drh4b5345c2018-04-24 13:07:40 +00002342 break;
2343 }
drh2ce15c32017-07-11 13:34:40 +00002344 }
2345 return 0;
2346}
2347
2348/*
2349** This is the callback routine that the SQLite library
2350** invokes for each row of a query result.
2351*/
2352static int callback(void *pArg, int nArg, char **azArg, char **azCol){
2353 /* since we don't have type info, call the shell_callback with a NULL value */
2354 return shell_callback(pArg, nArg, azArg, azCol, NULL);
2355}
2356
2357/*
2358** This is the callback routine from sqlite3_exec() that appends all
2359** output onto the end of a ShellText object.
2360*/
2361static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
2362 ShellText *p = (ShellText*)pArg;
2363 int i;
2364 UNUSED_PARAMETER(az);
drhb3c45232017-08-28 14:33:27 +00002365 if( azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00002366 if( p->n ) appendText(p, "|", 0);
2367 for(i=0; i<nArg; i++){
2368 if( i ) appendText(p, ",", 0);
2369 if( azArg[i] ) appendText(p, azArg[i], 0);
2370 }
2371 return 0;
2372}
2373
2374/*
2375** Generate an appropriate SELFTEST table in the main database.
2376*/
2377static void createSelftestTable(ShellState *p){
2378 char *zErrMsg = 0;
2379 sqlite3_exec(p->db,
2380 "SAVEPOINT selftest_init;\n"
2381 "CREATE TABLE IF NOT EXISTS selftest(\n"
2382 " tno INTEGER PRIMARY KEY,\n" /* Test number */
2383 " op TEXT,\n" /* Operator: memo run */
2384 " cmd TEXT,\n" /* Command text */
2385 " ans TEXT\n" /* Desired answer */
2386 ");"
2387 "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n"
2388 "INSERT INTO [_shell$self](rowid,op,cmd)\n"
2389 " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n"
2390 " 'memo','Tests generated by --init');\n"
2391 "INSERT INTO [_shell$self]\n"
2392 " SELECT 'run',\n"
2393 " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql "
drh067b92b2020-06-19 15:24:12 +00002394 "FROM sqlite_schema ORDER BY 2'',224))',\n"
drh2ce15c32017-07-11 13:34:40 +00002395 " hex(sha3_query('SELECT type,name,tbl_name,sql "
drh067b92b2020-06-19 15:24:12 +00002396 "FROM sqlite_schema ORDER BY 2',224));\n"
drh2ce15c32017-07-11 13:34:40 +00002397 "INSERT INTO [_shell$self]\n"
2398 " SELECT 'run',"
2399 " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||"
2400 " printf('%w',name) || '\" NOT INDEXED'',224))',\n"
2401 " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"
2402 " FROM (\n"
drh067b92b2020-06-19 15:24:12 +00002403 " SELECT name FROM sqlite_schema\n"
drh2ce15c32017-07-11 13:34:40 +00002404 " WHERE type='table'\n"
2405 " AND name<>'selftest'\n"
2406 " AND coalesce(rootpage,0)>0\n"
2407 " )\n"
2408 " ORDER BY name;\n"
2409 "INSERT INTO [_shell$self]\n"
2410 " VALUES('run','PRAGMA integrity_check','ok');\n"
2411 "INSERT INTO selftest(tno,op,cmd,ans)"
2412 " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n"
2413 "DROP TABLE [_shell$self];"
2414 ,0,0,&zErrMsg);
2415 if( zErrMsg ){
2416 utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
2417 sqlite3_free(zErrMsg);
2418 }
2419 sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
2420}
2421
2422
2423/*
2424** Set the destination table field of the ShellState structure to
2425** the name of the table given. Escape any quote characters in the
2426** table name.
2427*/
2428static void set_table_name(ShellState *p, const char *zName){
2429 int i, n;
mistachkin2158a0c2017-09-09 00:51:36 +00002430 char cQuote;
drh2ce15c32017-07-11 13:34:40 +00002431 char *z;
2432
2433 if( p->zDestTable ){
2434 free(p->zDestTable);
2435 p->zDestTable = 0;
2436 }
2437 if( zName==0 ) return;
2438 cQuote = quoteChar(zName);
2439 n = strlen30(zName);
2440 if( cQuote ) n += n+2;
2441 z = p->zDestTable = malloc( n+1 );
drh4b5345c2018-04-24 13:07:40 +00002442 if( z==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00002443 n = 0;
2444 if( cQuote ) z[n++] = cQuote;
2445 for(i=0; zName[i]; i++){
2446 z[n++] = zName[i];
2447 if( zName[i]==cQuote ) z[n++] = cQuote;
2448 }
2449 if( cQuote ) z[n++] = cQuote;
2450 z[n] = 0;
2451}
2452
2453
2454/*
2455** Execute a query statement that will generate SQL output. Print
2456** the result columns, comma-separated, on a line and then add a
2457** semicolon terminator to the end of that line.
2458**
2459** If the number of columns is 1 and that column contains text "--"
2460** then write the semicolon on a separate line. That way, if a
2461** "--" comment occurs at the end of the statement, the comment
2462** won't consume the semicolon terminator.
2463*/
2464static int run_table_dump_query(
2465 ShellState *p, /* Query context */
drh8e9297f2020-03-25 12:50:13 +00002466 const char *zSelect /* SELECT statement to extract content */
drh2ce15c32017-07-11 13:34:40 +00002467){
2468 sqlite3_stmt *pSelect;
2469 int rc;
2470 int nResult;
2471 int i;
2472 const char *z;
2473 rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
2474 if( rc!=SQLITE_OK || !pSelect ){
2475 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
2476 sqlite3_errmsg(p->db));
2477 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
2478 return rc;
2479 }
2480 rc = sqlite3_step(pSelect);
2481 nResult = sqlite3_column_count(pSelect);
2482 while( rc==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00002483 z = (const char*)sqlite3_column_text(pSelect, 0);
2484 utf8_printf(p->out, "%s", z);
2485 for(i=1; i<nResult; i++){
2486 utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
2487 }
2488 if( z==0 ) z = "";
2489 while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
2490 if( z[0] ){
2491 raw_printf(p->out, "\n;\n");
2492 }else{
2493 raw_printf(p->out, ";\n");
2494 }
2495 rc = sqlite3_step(pSelect);
2496 }
2497 rc = sqlite3_finalize(pSelect);
2498 if( rc!=SQLITE_OK ){
2499 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
2500 sqlite3_errmsg(p->db));
2501 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
2502 }
2503 return rc;
2504}
2505
2506/*
2507** Allocate space and save off current error string.
2508*/
2509static char *save_err_msg(
2510 sqlite3 *db /* Database to query */
2511){
2512 int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
2513 char *zErrMsg = sqlite3_malloc64(nErrMsg);
2514 if( zErrMsg ){
2515 memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
2516 }
2517 return zErrMsg;
2518}
2519
2520#ifdef __linux__
2521/*
2522** Attempt to display I/O stats on Linux using /proc/PID/io
2523*/
2524static void displayLinuxIoStats(FILE *out){
2525 FILE *in;
2526 char z[200];
2527 sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
2528 in = fopen(z, "rb");
2529 if( in==0 ) return;
2530 while( fgets(z, sizeof(z), in)!=0 ){
2531 static const struct {
2532 const char *zPattern;
2533 const char *zDesc;
2534 } aTrans[] = {
2535 { "rchar: ", "Bytes received by read():" },
2536 { "wchar: ", "Bytes sent to write():" },
2537 { "syscr: ", "Read() system calls:" },
2538 { "syscw: ", "Write() system calls:" },
2539 { "read_bytes: ", "Bytes read from storage:" },
2540 { "write_bytes: ", "Bytes written to storage:" },
2541 { "cancelled_write_bytes: ", "Cancelled write bytes:" },
2542 };
2543 int i;
2544 for(i=0; i<ArraySize(aTrans); i++){
drhaf2770f2018-01-05 14:55:43 +00002545 int n = strlen30(aTrans[i].zPattern);
drh2ce15c32017-07-11 13:34:40 +00002546 if( strncmp(aTrans[i].zPattern, z, n)==0 ){
2547 utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
2548 break;
2549 }
2550 }
2551 }
2552 fclose(in);
2553}
2554#endif
2555
2556/*
2557** Display a single line of status using 64-bit values.
2558*/
2559static void displayStatLine(
2560 ShellState *p, /* The shell context */
2561 char *zLabel, /* Label for this one line */
2562 char *zFormat, /* Format for the result */
2563 int iStatusCtrl, /* Which status to display */
2564 int bReset /* True to reset the stats */
2565){
2566 sqlite3_int64 iCur = -1;
2567 sqlite3_int64 iHiwtr = -1;
2568 int i, nPercent;
2569 char zLine[200];
2570 sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset);
2571 for(i=0, nPercent=0; zFormat[i]; i++){
2572 if( zFormat[i]=='%' ) nPercent++;
2573 }
2574 if( nPercent>1 ){
2575 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr);
2576 }else{
2577 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
2578 }
2579 raw_printf(p->out, "%-36s %s\n", zLabel, zLine);
2580}
2581
2582/*
2583** Display memory stats.
2584*/
2585static int display_stats(
2586 sqlite3 *db, /* Database to query */
2587 ShellState *pArg, /* Pointer to ShellState */
2588 int bReset /* True to reset the stats */
2589){
2590 int iCur;
2591 int iHiwtr;
drh393344f2018-03-09 16:37:05 +00002592 FILE *out;
2593 if( pArg==0 || pArg->out==0 ) return 0;
2594 out = pArg->out;
drh2ce15c32017-07-11 13:34:40 +00002595
drha6e6cf22021-01-09 19:10:04 +00002596 if( pArg->pStmt && pArg->statsOn==2 ){
drh393344f2018-03-09 16:37:05 +00002597 int nCol, i, x;
2598 sqlite3_stmt *pStmt = pArg->pStmt;
2599 char z[100];
2600 nCol = sqlite3_column_count(pStmt);
2601 raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
2602 for(i=0; i<nCol; i++){
2603 sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
2604 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
drh929cce82018-03-17 16:26:36 +00002605#ifndef SQLITE_OMIT_DECLTYPE
drh393344f2018-03-09 16:37:05 +00002606 sqlite3_snprintf(30, z+x, "declared type:");
2607 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
drh929cce82018-03-17 16:26:36 +00002608#endif
2609#ifdef SQLITE_ENABLE_COLUMN_METADATA
drh393344f2018-03-09 16:37:05 +00002610 sqlite3_snprintf(30, z+x, "database name:");
2611 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
2612 sqlite3_snprintf(30, z+x, "table name:");
2613 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
2614 sqlite3_snprintf(30, z+x, "origin name:");
2615 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
drh929cce82018-03-17 16:26:36 +00002616#endif
drh2ce15c32017-07-11 13:34:40 +00002617 }
drh929cce82018-03-17 16:26:36 +00002618 }
drh2ce15c32017-07-11 13:34:40 +00002619
drha6e6cf22021-01-09 19:10:04 +00002620 if( pArg->statsOn==3 ){
2621 if( pArg->pStmt ){
2622 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
2623 raw_printf(pArg->out, "VM-steps: %d\n", iCur);
2624 }
2625 return 0;
2626 }
2627
drh393344f2018-03-09 16:37:05 +00002628 displayStatLine(pArg, "Memory Used:",
2629 "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
2630 displayStatLine(pArg, "Number of Outstanding Allocations:",
2631 "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
2632 if( pArg->shellFlgs & SHFLG_Pagecache ){
2633 displayStatLine(pArg, "Number of Pcache Pages Used:",
2634 "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
2635 }
2636 displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
2637 "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
2638 displayStatLine(pArg, "Largest Allocation:",
2639 "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
2640 displayStatLine(pArg, "Largest Pcache Allocation:",
2641 "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
2642#ifdef YYTRACKMAXSTACKDEPTH
2643 displayStatLine(pArg, "Deepest Parser Stack:",
2644 "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
2645#endif
2646
2647 if( db ){
drh2ce15c32017-07-11 13:34:40 +00002648 if( pArg->shellFlgs & SHFLG_Lookaside ){
2649 iHiwtr = iCur = -1;
2650 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
2651 &iCur, &iHiwtr, bReset);
2652 raw_printf(pArg->out,
2653 "Lookaside Slots Used: %d (max %d)\n",
2654 iCur, iHiwtr);
2655 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
2656 &iCur, &iHiwtr, bReset);
2657 raw_printf(pArg->out, "Successful lookaside attempts: %d\n",
2658 iHiwtr);
2659 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
2660 &iCur, &iHiwtr, bReset);
2661 raw_printf(pArg->out, "Lookaside failures due to size: %d\n",
2662 iHiwtr);
2663 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
2664 &iCur, &iHiwtr, bReset);
2665 raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n",
2666 iHiwtr);
2667 }
2668 iHiwtr = iCur = -1;
2669 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
2670 raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n",
2671 iCur);
2672 iHiwtr = iCur = -1;
2673 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
2674 raw_printf(pArg->out, "Page cache hits: %d\n", iCur);
2675 iHiwtr = iCur = -1;
2676 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
2677 raw_printf(pArg->out, "Page cache misses: %d\n", iCur);
2678 iHiwtr = iCur = -1;
2679 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
2680 raw_printf(pArg->out, "Page cache writes: %d\n", iCur);
2681 iHiwtr = iCur = -1;
drhffc78a42018-03-14 14:53:50 +00002682 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
2683 raw_printf(pArg->out, "Page cache spills: %d\n", iCur);
2684 iHiwtr = iCur = -1;
drh2ce15c32017-07-11 13:34:40 +00002685 sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
2686 raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n",
2687 iCur);
2688 iHiwtr = iCur = -1;
2689 sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
2690 raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
2691 iCur);
2692 }
2693
drh393344f2018-03-09 16:37:05 +00002694 if( pArg->pStmt ){
drh2ce15c32017-07-11 13:34:40 +00002695 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
2696 bReset);
2697 raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
2698 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
2699 raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
2700 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
2701 raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
2702 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
2703 raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
drhe2754c12019-08-26 12:50:01 +00002704 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
drh393344f2018-03-09 16:37:05 +00002705 raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
2706 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
2707 raw_printf(pArg->out, "Number of times run: %d\n", iCur);
2708 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
2709 raw_printf(pArg->out, "Memory used by prepared stmt: %d\n", iCur);
drh2ce15c32017-07-11 13:34:40 +00002710 }
2711
2712#ifdef __linux__
2713 displayLinuxIoStats(pArg->out);
2714#endif
2715
2716 /* Do not remove this machine readable comment: extra-stats-output-here */
2717
2718 return 0;
2719}
2720
2721/*
2722** Display scan stats.
2723*/
2724static void display_scanstats(
2725 sqlite3 *db, /* Database to query */
2726 ShellState *pArg /* Pointer to ShellState */
2727){
2728#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
2729 UNUSED_PARAMETER(db);
2730 UNUSED_PARAMETER(pArg);
2731#else
2732 int i, k, n, mx;
2733 raw_printf(pArg->out, "-------- scanstats --------\n");
2734 mx = 0;
2735 for(k=0; k<=mx; k++){
2736 double rEstLoop = 1.0;
2737 for(i=n=0; 1; i++){
2738 sqlite3_stmt *p = pArg->pStmt;
2739 sqlite3_int64 nLoop, nVisit;
2740 double rEst;
2741 int iSid;
2742 const char *zExplain;
2743 if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){
2744 break;
2745 }
2746 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
2747 if( iSid>mx ) mx = iSid;
2748 if( iSid!=k ) continue;
2749 if( n==0 ){
2750 rEstLoop = (double)nLoop;
2751 if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k);
2752 }
2753 n++;
2754 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
2755 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
2756 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
2757 utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
2758 rEstLoop *= rEst;
2759 raw_printf(pArg->out,
2760 " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
2761 nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
2762 );
2763 }
2764 }
2765 raw_printf(pArg->out, "---------------------------\n");
2766#endif
2767}
2768
2769/*
2770** Parameter azArray points to a zero-terminated array of strings. zStr
2771** points to a single nul-terminated string. Return non-zero if zStr
2772** is equal, according to strcmp(), to any of the strings in the array.
2773** Otherwise, return zero.
2774*/
2775static int str_in_array(const char *zStr, const char **azArray){
2776 int i;
2777 for(i=0; azArray[i]; i++){
2778 if( 0==strcmp(zStr, azArray[i]) ) return 1;
2779 }
2780 return 0;
2781}
2782
2783/*
2784** If compiled statement pSql appears to be an EXPLAIN statement, allocate
2785** and populate the ShellState.aiIndent[] array with the number of
2786** spaces each opcode should be indented before it is output.
2787**
2788** The indenting rules are:
2789**
2790** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
2791** all opcodes that occur between the p2 jump destination and the opcode
2792** itself by 2 spaces.
2793**
2794** * For each "Goto", if the jump destination is earlier in the program
2795** and ends on one of:
2796** Yield SeekGt SeekLt RowSetRead Rewind
2797** or if the P1 parameter is one instead of zero,
2798** then indent all opcodes between the earlier instruction
2799** and "Goto" by 2 spaces.
2800*/
2801static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
2802 const char *zSql; /* The text of the SQL statement */
2803 const char *z; /* Used to check if this is an EXPLAIN */
2804 int *abYield = 0; /* True if op is an OP_Yield */
2805 int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
2806 int iOp; /* Index of operation in p->aiIndent[] */
2807
drhf1949b62018-06-07 17:32:59 +00002808 const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
drh2ce15c32017-07-11 13:34:40 +00002809 const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
2810 "Rewind", 0 };
2811 const char *azGoto[] = { "Goto", 0 };
2812
2813 /* Try to figure out if this is really an EXPLAIN statement. If this
2814 ** cannot be verified, return early. */
2815 if( sqlite3_column_count(pSql)!=8 ){
2816 p->cMode = p->mode;
2817 return;
2818 }
2819 zSql = sqlite3_sql(pSql);
2820 if( zSql==0 ) return;
2821 for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
2822 if( sqlite3_strnicmp(z, "explain", 7) ){
2823 p->cMode = p->mode;
2824 return;
2825 }
2826
2827 for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
2828 int i;
2829 int iAddr = sqlite3_column_int(pSql, 0);
2830 const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
2831
2832 /* Set p2 to the P2 field of the current opcode. Then, assuming that
2833 ** p2 is an instruction address, set variable p2op to the index of that
2834 ** instruction in the aiIndent[] array. p2 and p2op may be different if
2835 ** the current instruction is part of a sub-program generated by an
2836 ** SQL trigger or foreign key. */
2837 int p2 = sqlite3_column_int(pSql, 3);
2838 int p2op = (p2 + (iOp-iAddr));
2839
2840 /* Grow the p->aiIndent array as required */
2841 if( iOp>=nAlloc ){
2842 if( iOp==0 ){
2843 /* Do further verfication that this is explain output. Abort if
2844 ** it is not */
2845 static const char *explainCols[] = {
2846 "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" };
2847 int jj;
2848 for(jj=0; jj<ArraySize(explainCols); jj++){
2849 if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
2850 p->cMode = p->mode;
2851 sqlite3_reset(pSql);
2852 return;
2853 }
2854 }
2855 }
2856 nAlloc += 100;
2857 p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
drh884406b2018-07-29 18:56:35 +00002858 if( p->aiIndent==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00002859 abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
drh884406b2018-07-29 18:56:35 +00002860 if( abYield==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00002861 }
2862 abYield[iOp] = str_in_array(zOp, azYield);
2863 p->aiIndent[iOp] = 0;
2864 p->nIndent = iOp+1;
2865
2866 if( str_in_array(zOp, azNext) ){
2867 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
2868 }
2869 if( str_in_array(zOp, azGoto) && p2op<p->nIndent
2870 && (abYield[p2op] || sqlite3_column_int(pSql, 2))
2871 ){
2872 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
2873 }
2874 }
2875
2876 p->iIndent = 0;
2877 sqlite3_free(abYield);
2878 sqlite3_reset(pSql);
2879}
2880
2881/*
2882** Free the array allocated by explain_data_prepare().
2883*/
2884static void explain_data_delete(ShellState *p){
2885 sqlite3_free(p->aiIndent);
2886 p->aiIndent = 0;
2887 p->nIndent = 0;
2888 p->iIndent = 0;
2889}
2890
2891/*
2892** Disable and restore .wheretrace and .selecttrace settings.
2893*/
drhc0622a42020-12-04 01:17:57 +00002894static unsigned int savedSelectTrace;
2895static unsigned int savedWhereTrace;
drh2ce15c32017-07-11 13:34:40 +00002896static void disable_debug_trace_modes(void){
drh0a2fb792020-12-04 16:58:20 +00002897 unsigned int zero = 0;
drhc0622a42020-12-04 01:17:57 +00002898 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace);
drh0a2fb792020-12-04 16:58:20 +00002899 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero);
drhc0622a42020-12-04 01:17:57 +00002900 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace);
drh0a2fb792020-12-04 16:58:20 +00002901 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero);
drh2ce15c32017-07-11 13:34:40 +00002902}
2903static void restore_debug_trace_modes(void){
drhc0622a42020-12-04 01:17:57 +00002904 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &savedSelectTrace);
2905 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &savedWhereTrace);
drh2ce15c32017-07-11 13:34:40 +00002906}
2907
drh9cb02642019-02-28 20:10:52 +00002908/* Create the TEMP table used to store parameter bindings */
2909static void bind_table_init(ShellState *p){
drh346f4e22019-03-25 21:35:41 +00002910 int wrSchema = 0;
drh4b86e202020-01-19 20:37:26 +00002911 int defensiveMode = 0;
2912 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
2913 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
drh346f4e22019-03-25 21:35:41 +00002914 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
2915 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
drh9cb02642019-02-28 20:10:52 +00002916 sqlite3_exec(p->db,
drh65c29fd2019-03-25 21:56:26 +00002917 "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
drh9cb02642019-02-28 20:10:52 +00002918 " key TEXT PRIMARY KEY,\n"
larrybrdabada62021-04-04 12:52:58 +00002919 " value\n"
drh9cb02642019-02-28 20:10:52 +00002920 ") WITHOUT ROWID;",
2921 0, 0, 0);
drh346f4e22019-03-25 21:35:41 +00002922 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
drh4b86e202020-01-19 20:37:26 +00002923 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0);
drh9cb02642019-02-28 20:10:52 +00002924}
2925
drh8b738d02019-02-25 18:43:54 +00002926/*
2927** Bind parameters on a prepared statement.
2928**
2929** Parameter bindings are taken from a TEMP table of the form:
2930**
drh1cb02632019-03-25 22:05:22 +00002931** CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
drh8b738d02019-02-25 18:43:54 +00002932** WITHOUT ROWID;
2933**
drh91654b22020-04-02 13:21:10 +00002934** No bindings occur if this table does not exist. The name of the table
2935** begins with "sqlite_" so that it will not collide with ordinary application
2936** tables. The table must be in the TEMP schema.
drh8b738d02019-02-25 18:43:54 +00002937*/
2938static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
2939 int nVar;
2940 int i;
2941 int rc;
2942 sqlite3_stmt *pQ = 0;
2943
2944 nVar = sqlite3_bind_parameter_count(pStmt);
2945 if( nVar==0 ) return; /* Nothing to do */
drh65c29fd2019-03-25 21:56:26 +00002946 if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters",
drh8b738d02019-02-25 18:43:54 +00002947 "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
2948 return; /* Parameter table does not exist */
2949 }
2950 rc = sqlite3_prepare_v2(pArg->db,
drh65c29fd2019-03-25 21:56:26 +00002951 "SELECT value FROM temp.sqlite_parameters"
drh8b738d02019-02-25 18:43:54 +00002952 " WHERE key=?1", -1, &pQ, 0);
2953 if( rc || pQ==0 ) return;
2954 for(i=1; i<=nVar; i++){
2955 char zNum[30];
2956 const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
2957 if( zVar==0 ){
2958 sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
2959 zVar = zNum;
2960 }
2961 sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
2962 if( sqlite3_step(pQ)==SQLITE_ROW ){
2963 sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
2964 }else{
2965 sqlite3_bind_null(pStmt, i);
2966 }
2967 sqlite3_reset(pQ);
2968 }
2969 sqlite3_finalize(pQ);
2970}
2971
drh30c54a02020-05-28 23:49:50 +00002972/*
drh0908e382020-06-04 18:05:39 +00002973** UTF8 box-drawing characters. Imagine box lines like this:
2974**
2975** 1
2976** |
2977** 4 --+-- 2
2978** |
2979** 3
2980**
2981** Each box characters has between 2 and 4 of the lines leading from
2982** the center. The characters are here identified by the numbers of
2983** their corresponding lines.
2984*/
2985#define BOX_24 "\342\224\200" /* U+2500 --- */
2986#define BOX_13 "\342\224\202" /* U+2502 | */
2987#define BOX_23 "\342\224\214" /* U+250c ,- */
2988#define BOX_34 "\342\224\220" /* U+2510 -, */
2989#define BOX_12 "\342\224\224" /* U+2514 '- */
2990#define BOX_14 "\342\224\230" /* U+2518 -' */
2991#define BOX_123 "\342\224\234" /* U+251c |- */
2992#define BOX_134 "\342\224\244" /* U+2524 -| */
2993#define BOX_234 "\342\224\254" /* U+252c -,- */
2994#define BOX_124 "\342\224\264" /* U+2534 -'- */
2995#define BOX_1234 "\342\224\274" /* U+253c -|- */
2996
2997/* Draw horizontal line N characters long using unicode box
2998** characters
2999*/
3000static void print_box_line(FILE *out, int N){
3001 const char zDash[] =
3002 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
3003 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
3004 const int nDash = sizeof(zDash) - 1;
3005 N *= 3;
3006 while( N>nDash ){
3007 utf8_printf(out, zDash);
3008 N -= nDash;
3009 }
3010 utf8_printf(out, "%.*s", N, zDash);
3011}
3012
3013/*
3014** Draw a horizontal separator for a MODE_Box table.
3015*/
3016static void print_box_row_separator(
3017 ShellState *p,
3018 int nArg,
3019 const char *zSep1,
3020 const char *zSep2,
3021 const char *zSep3
3022){
3023 int i;
3024 if( nArg>0 ){
3025 utf8_printf(p->out, "%s", zSep1);
3026 print_box_line(p->out, p->actualWidth[0]+2);
3027 for(i=1; i<nArg; i++){
3028 utf8_printf(p->out, "%s", zSep2);
3029 print_box_line(p->out, p->actualWidth[i]+2);
3030 }
3031 utf8_printf(p->out, "%s", zSep3);
3032 }
3033 fputs("\n", p->out);
3034}
3035
3036
3037
3038/*
drh30c54a02020-05-28 23:49:50 +00003039** Run a prepared statement and output the result in one of the
drh0908e382020-06-04 18:05:39 +00003040** table-oriented formats: MODE_Column, MODE_Markdown, MODE_Table,
3041** or MODE_Box.
drh30c54a02020-05-28 23:49:50 +00003042**
3043** This is different from ordinary exec_prepared_stmt() in that
3044** it has to run the entire query and gather the results into memory
3045** first, in order to determine column widths, before providing
3046** any output.
3047*/
drh8c748632020-05-29 16:15:58 +00003048static void exec_prepared_stmt_columnar(
3049 ShellState *p, /* Pointer to ShellState */
3050 sqlite3_stmt *pStmt /* Statment to run */
drh30c54a02020-05-28 23:49:50 +00003051){
drhf82ce382020-08-06 16:45:22 +00003052 sqlite3_int64 nRow = 0;
drh8c748632020-05-29 16:15:58 +00003053 int nColumn = 0;
3054 char **azData = 0;
drhf82ce382020-08-06 16:45:22 +00003055 sqlite3_int64 nAlloc = 0;
drh8c748632020-05-29 16:15:58 +00003056 const char *z;
3057 int rc;
drhf82ce382020-08-06 16:45:22 +00003058 sqlite3_int64 i, nData;
3059 int j, nTotal, w, n;
drh0908e382020-06-04 18:05:39 +00003060 const char *colSep = 0;
3061 const char *rowSep = 0;
drh30c54a02020-05-28 23:49:50 +00003062
drhf82ce382020-08-06 16:45:22 +00003063 rc = sqlite3_step(pStmt);
3064 if( rc!=SQLITE_ROW ) return;
3065 nColumn = sqlite3_column_count(pStmt);
3066 nAlloc = nColumn*4;
drh01a8ad22021-03-20 23:15:52 +00003067 if( nAlloc<=0 ) nAlloc = 1;
drhf82ce382020-08-06 16:45:22 +00003068 azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
3069 if( azData==0 ) shell_out_of_memory();
3070 for(i=0; i<nColumn; i++){
3071 azData[i] = strdup(sqlite3_column_name(pStmt,i));
drh8c748632020-05-29 16:15:58 +00003072 }
drhf82ce382020-08-06 16:45:22 +00003073 do{
3074 if( (nRow+2)*nColumn >= nAlloc ){
3075 nAlloc *= 2;
3076 azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*));
3077 if( azData==0 ) shell_out_of_memory();
3078 }
3079 nRow++;
3080 for(i=0; i<nColumn; i++){
3081 z = (const char*)sqlite3_column_text(pStmt,i);
3082 azData[nRow*nColumn + i] = z ? strdup(z) : 0;
3083 }
3084 }while( (rc = sqlite3_step(pStmt))==SQLITE_ROW );
drh8c748632020-05-29 16:15:58 +00003085 if( nColumn>p->nWidth ){
3086 p->colWidth = realloc(p->colWidth, nColumn*2*sizeof(int));
3087 if( p->colWidth==0 ) shell_out_of_memory();
3088 for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0;
3089 p->nWidth = nColumn;
3090 p->actualWidth = &p->colWidth[nColumn];
3091 }
3092 memset(p->actualWidth, 0, nColumn*sizeof(int));
3093 for(i=0; i<nColumn; i++){
3094 w = p->colWidth[i];
3095 if( w<0 ) w = -w;
3096 p->actualWidth[i] = w;
3097 }
3098 nTotal = nColumn*(nRow+1);
3099 for(i=0; i<nTotal; i++){
3100 z = azData[i];
3101 if( z==0 ) z = p->nullValue;
3102 n = strlenChar(z);
3103 j = i%nColumn;
3104 if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
3105 }
drh99942982020-06-15 20:05:37 +00003106 if( seenInterrupt ) goto columnar_end;
drh01a8ad22021-03-20 23:15:52 +00003107 if( nColumn==0 ) goto columnar_end;
drh0908e382020-06-04 18:05:39 +00003108 switch( p->cMode ){
3109 case MODE_Column: {
3110 colSep = " ";
3111 rowSep = "\n";
3112 if( p->showHeader ){
3113 for(i=0; i<nColumn; i++){
3114 w = p->actualWidth[i];
3115 if( p->colWidth[i]<0 ) w = -w;
3116 utf8_width_print(p->out, w, azData[i]);
3117 fputs(i==nColumn-1?"\n":" ", p->out);
3118 }
3119 for(i=0; i<nColumn; i++){
3120 print_dashes(p->out, p->actualWidth[i]);
3121 fputs(i==nColumn-1?"\n":" ", p->out);
3122 }
3123 }
3124 break;
3125 }
3126 case MODE_Table: {
3127 colSep = " | ";
3128 rowSep = " |\n";
3129 print_row_separator(p, nColumn, "+");
3130 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003131 for(i=0; i<nColumn; i++){
3132 w = p->actualWidth[i];
drh0908e382020-06-04 18:05:39 +00003133 n = strlenChar(azData[i]);
3134 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
3135 fputs(i==nColumn-1?" |\n":" | ", p->out);
drh8c748632020-05-29 16:15:58 +00003136 }
drh0908e382020-06-04 18:05:39 +00003137 print_row_separator(p, nColumn, "+");
3138 break;
3139 }
3140 case MODE_Markdown: {
3141 colSep = " | ";
3142 rowSep = " |\n";
3143 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003144 for(i=0; i<nColumn; i++){
drh0908e382020-06-04 18:05:39 +00003145 w = p->actualWidth[i];
3146 n = strlenChar(azData[i]);
3147 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
3148 fputs(i==nColumn-1?" |\n":" | ", p->out);
drh8c748632020-05-29 16:15:58 +00003149 }
drh0908e382020-06-04 18:05:39 +00003150 print_row_separator(p, nColumn, "|");
3151 break;
drh8c748632020-05-29 16:15:58 +00003152 }
drh0908e382020-06-04 18:05:39 +00003153 case MODE_Box: {
3154 colSep = " " BOX_13 " ";
3155 rowSep = " " BOX_13 "\n";
3156 print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34);
3157 utf8_printf(p->out, BOX_13 " ");
3158 for(i=0; i<nColumn; i++){
3159 w = p->actualWidth[i];
3160 n = strlenChar(azData[i]);
3161 utf8_printf(p->out, "%*s%s%*s%s",
3162 (w-n)/2, "", azData[i], (w-n+1)/2, "",
3163 i==nColumn-1?" "BOX_13"\n":" "BOX_13" ");
3164 }
3165 print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
3166 break;
drh8c748632020-05-29 16:15:58 +00003167 }
drh8c748632020-05-29 16:15:58 +00003168 }
3169 for(i=nColumn, j=0; i<nTotal; i++, j++){
drh0908e382020-06-04 18:05:39 +00003170 if( j==0 && p->cMode!=MODE_Column ){
3171 utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| ");
3172 }
drh8c748632020-05-29 16:15:58 +00003173 z = azData[i];
3174 if( z==0 ) z = p->nullValue;
3175 w = p->actualWidth[j];
3176 if( p->colWidth[j]<0 ) w = -w;
3177 utf8_width_print(p->out, w, z);
3178 if( j==nColumn-1 ){
drh0908e382020-06-04 18:05:39 +00003179 utf8_printf(p->out, "%s", rowSep);
drh8c748632020-05-29 16:15:58 +00003180 j = -1;
drhdd853c32020-06-16 17:34:40 +00003181 if( seenInterrupt ) goto columnar_end;
drh8c748632020-05-29 16:15:58 +00003182 }else{
drh0908e382020-06-04 18:05:39 +00003183 utf8_printf(p->out, "%s", colSep);
drh8c748632020-05-29 16:15:58 +00003184 }
3185 }
3186 if( p->cMode==MODE_Table ){
3187 print_row_separator(p, nColumn, "+");
drh0908e382020-06-04 18:05:39 +00003188 }else if( p->cMode==MODE_Box ){
3189 print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14);
drh8c748632020-05-29 16:15:58 +00003190 }
drh99942982020-06-15 20:05:37 +00003191columnar_end:
drhdd853c32020-06-16 17:34:40 +00003192 if( seenInterrupt ){
3193 utf8_printf(p->out, "Interrupt\n");
3194 }
drhf82ce382020-08-06 16:45:22 +00003195 nData = (nRow+1)*nColumn;
3196 for(i=0; i<nData; i++) free(azData[i]);
3197 sqlite3_free(azData);
drh30c54a02020-05-28 23:49:50 +00003198}
drh30c54a02020-05-28 23:49:50 +00003199
drh2ce15c32017-07-11 13:34:40 +00003200/*
3201** Run a prepared statement
3202*/
3203static void exec_prepared_stmt(
3204 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003205 sqlite3_stmt *pStmt /* Statment to run */
drh2ce15c32017-07-11 13:34:40 +00003206){
3207 int rc;
3208
drh8c748632020-05-29 16:15:58 +00003209 if( pArg->cMode==MODE_Column
3210 || pArg->cMode==MODE_Table
drh0908e382020-06-04 18:05:39 +00003211 || pArg->cMode==MODE_Box
drh8c748632020-05-29 16:15:58 +00003212 || pArg->cMode==MODE_Markdown
3213 ){
3214 exec_prepared_stmt_columnar(pArg, pStmt);
3215 return;
3216 }
3217
drh2ce15c32017-07-11 13:34:40 +00003218 /* perform the first step. this will tell us if we
3219 ** have a result set or not and how wide it is.
3220 */
3221 rc = sqlite3_step(pStmt);
3222 /* if we have a result set... */
3223 if( SQLITE_ROW == rc ){
drha10b9992018-03-09 15:24:33 +00003224 /* allocate space for col name ptr, value ptr, and type */
3225 int nCol = sqlite3_column_count(pStmt);
3226 void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
3227 if( !pData ){
3228 rc = SQLITE_NOMEM;
drh2ce15c32017-07-11 13:34:40 +00003229 }else{
drha10b9992018-03-09 15:24:33 +00003230 char **azCols = (char **)pData; /* Names of result columns */
3231 char **azVals = &azCols[nCol]; /* Results */
3232 int *aiTypes = (int *)&azVals[nCol]; /* Result types */
3233 int i, x;
3234 assert(sizeof(int) <= sizeof(char *));
3235 /* save off ptrs to column names */
3236 for(i=0; i<nCol; i++){
3237 azCols[i] = (char *)sqlite3_column_name(pStmt, i);
3238 }
drh2ce15c32017-07-11 13:34:40 +00003239 do{
drha10b9992018-03-09 15:24:33 +00003240 /* extract the data and data types */
3241 for(i=0; i<nCol; i++){
3242 aiTypes[i] = x = sqlite3_column_type(pStmt, i);
3243 if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
3244 azVals[i] = "";
3245 }else{
3246 azVals[i] = (char*)sqlite3_column_text(pStmt, i);
3247 }
3248 if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
3249 rc = SQLITE_NOMEM;
3250 break; /* from for */
3251 }
3252 } /* end for */
3253
3254 /* if data and types extracted successfully... */
3255 if( SQLITE_ROW == rc ){
3256 /* call the supplied callback with the result row data */
3257 if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){
3258 rc = SQLITE_ABORT;
3259 }else{
3260 rc = sqlite3_step(pStmt);
3261 }
3262 }
3263 } while( SQLITE_ROW == rc );
3264 sqlite3_free(pData);
drh0908e382020-06-04 18:05:39 +00003265 if( pArg->cMode==MODE_Json ){
drh30c54a02020-05-28 23:49:50 +00003266 fputs("]\n", pArg->out);
3267 }
drh2ce15c32017-07-11 13:34:40 +00003268 }
3269 }
3270}
3271
dan6b046be2018-01-09 15:25:55 +00003272#ifndef SQLITE_OMIT_VIRTUALTABLE
drh2ce15c32017-07-11 13:34:40 +00003273/*
dan43efc182017-12-19 17:42:13 +00003274** This function is called to process SQL if the previous shell command
3275** was ".expert". It passes the SQL in the second argument directly to
3276** the sqlite3expert object.
3277**
3278** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3279** code. In this case, (*pzErr) may be set to point to a buffer containing
3280** an English language error message. It is the responsibility of the
3281** caller to eventually free this buffer using sqlite3_free().
3282*/
3283static int expertHandleSQL(
3284 ShellState *pState,
3285 const char *zSql,
3286 char **pzErr
3287){
3288 assert( pState->expert.pExpert );
3289 assert( pzErr==0 || *pzErr==0 );
3290 return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr);
3291}
3292
3293/*
3294** This function is called either to silently clean up the object
3295** created by the ".expert" command (if bCancel==1), or to generate a
3296** report from it and then clean it up (if bCancel==0).
3297**
3298** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3299** code. In this case, (*pzErr) may be set to point to a buffer containing
3300** an English language error message. It is the responsibility of the
3301** caller to eventually free this buffer using sqlite3_free().
3302*/
3303static int expertFinish(
3304 ShellState *pState,
3305 int bCancel,
3306 char **pzErr
3307){
3308 int rc = SQLITE_OK;
3309 sqlite3expert *p = pState->expert.pExpert;
3310 assert( p );
3311 assert( bCancel || pzErr==0 || *pzErr==0 );
3312 if( bCancel==0 ){
3313 FILE *out = pState->out;
3314 int bVerbose = pState->expert.bVerbose;
3315
3316 rc = sqlite3_expert_analyze(p, pzErr);
3317 if( rc==SQLITE_OK ){
3318 int nQuery = sqlite3_expert_count(p);
3319 int i;
3320
3321 if( bVerbose ){
3322 const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
3323 raw_printf(out, "-- Candidates -----------------------------\n");
3324 raw_printf(out, "%s\n", zCand);
3325 }
3326 for(i=0; i<nQuery; i++){
3327 const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
3328 const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
3329 const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
3330 if( zIdx==0 ) zIdx = "(no new indexes)\n";
3331 if( bVerbose ){
3332 raw_printf(out, "-- Query %d --------------------------------\n",i+1);
3333 raw_printf(out, "%s\n\n", zSql);
3334 }
3335 raw_printf(out, "%s\n", zIdx);
3336 raw_printf(out, "%s\n", zEQP);
3337 }
3338 }
3339 }
3340 sqlite3_expert_destroy(p);
3341 pState->expert.pExpert = 0;
3342 return rc;
3343}
3344
dan6b046be2018-01-09 15:25:55 +00003345/*
3346** Implementation of ".expert" dot command.
3347*/
3348static int expertDotCommand(
3349 ShellState *pState, /* Current shell tool state */
3350 char **azArg, /* Array of arguments passed to dot command */
3351 int nArg /* Number of entries in azArg[] */
3352){
3353 int rc = SQLITE_OK;
3354 char *zErr = 0;
3355 int i;
3356 int iSample = 0;
3357
3358 assert( pState->expert.pExpert==0 );
3359 memset(&pState->expert, 0, sizeof(ExpertInfo));
3360
3361 for(i=1; rc==SQLITE_OK && i<nArg; i++){
3362 char *z = azArg[i];
3363 int n;
3364 if( z[0]=='-' && z[1]=='-' ) z++;
3365 n = strlen30(z);
3366 if( n>=2 && 0==strncmp(z, "-verbose", n) ){
3367 pState->expert.bVerbose = 1;
3368 }
3369 else if( n>=2 && 0==strncmp(z, "-sample", n) ){
3370 if( i==(nArg-1) ){
3371 raw_printf(stderr, "option requires an argument: %s\n", z);
3372 rc = SQLITE_ERROR;
3373 }else{
3374 iSample = (int)integerValue(azArg[++i]);
3375 if( iSample<0 || iSample>100 ){
3376 raw_printf(stderr, "value out of range: %s\n", azArg[i]);
3377 rc = SQLITE_ERROR;
3378 }
3379 }
3380 }
3381 else{
3382 raw_printf(stderr, "unknown option: %s\n", z);
3383 rc = SQLITE_ERROR;
3384 }
3385 }
3386
3387 if( rc==SQLITE_OK ){
3388 pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
3389 if( pState->expert.pExpert==0 ){
3390 raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr);
3391 rc = SQLITE_ERROR;
3392 }else{
3393 sqlite3_expert_config(
3394 pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
3395 );
3396 }
3397 }
3398
3399 return rc;
3400}
3401#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
dan43efc182017-12-19 17:42:13 +00003402
3403/*
drh2ce15c32017-07-11 13:34:40 +00003404** Execute a statement or set of statements. Print
3405** any result rows/columns depending on the current mode
3406** set via the supplied callback.
3407**
3408** This is very similar to SQLite's built-in sqlite3_exec()
3409** function except it takes a slightly different callback
3410** and callback data argument.
3411*/
3412static int shell_exec(
drh2ce15c32017-07-11 13:34:40 +00003413 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003414 const char *zSql, /* SQL to be evaluated */
drh2ce15c32017-07-11 13:34:40 +00003415 char **pzErrMsg /* Error msg written here */
3416){
3417 sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
3418 int rc = SQLITE_OK; /* Return Code */
3419 int rc2;
3420 const char *zLeftover; /* Tail of unprocessed SQL */
drha10b9992018-03-09 15:24:33 +00003421 sqlite3 *db = pArg->db;
drh2ce15c32017-07-11 13:34:40 +00003422
3423 if( pzErrMsg ){
3424 *pzErrMsg = NULL;
3425 }
3426
dan6b046be2018-01-09 15:25:55 +00003427#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00003428 if( pArg->expert.pExpert ){
3429 rc = expertHandleSQL(pArg, zSql, pzErrMsg);
3430 return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
3431 }
dan6b046be2018-01-09 15:25:55 +00003432#endif
dan43efc182017-12-19 17:42:13 +00003433
drh2ce15c32017-07-11 13:34:40 +00003434 while( zSql[0] && (SQLITE_OK == rc) ){
3435 static const char *zStmtSql;
3436 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
3437 if( SQLITE_OK != rc ){
3438 if( pzErrMsg ){
3439 *pzErrMsg = save_err_msg(db);
3440 }
3441 }else{
3442 if( !pStmt ){
3443 /* this happens for a comment or white-space */
3444 zSql = zLeftover;
3445 while( IsSpace(zSql[0]) ) zSql++;
3446 continue;
3447 }
3448 zStmtSql = sqlite3_sql(pStmt);
3449 if( zStmtSql==0 ) zStmtSql = "";
3450 while( IsSpace(zStmtSql[0]) ) zStmtSql++;
3451
3452 /* save off the prepared statment handle and reset row count */
3453 if( pArg ){
3454 pArg->pStmt = pStmt;
3455 pArg->cnt = 0;
3456 }
3457
3458 /* echo the sql statement if echo on */
3459 if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
3460 utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
3461 }
3462
3463 /* Show the EXPLAIN QUERY PLAN if .eqp is on */
drh39c5c4a2019-03-06 14:53:27 +00003464 if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
drh2ce15c32017-07-11 13:34:40 +00003465 sqlite3_stmt *pExplain;
3466 char *zEQP;
drhada70452017-12-21 21:02:27 +00003467 int triggerEQP = 0;
drh2ce15c32017-07-11 13:34:40 +00003468 disable_debug_trace_modes();
drhada70452017-12-21 21:02:27 +00003469 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
3470 if( pArg->autoEQP>=AUTOEQP_trigger ){
3471 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
3472 }
drh2ce15c32017-07-11 13:34:40 +00003473 zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
3474 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3475 if( rc==SQLITE_OK ){
3476 while( sqlite3_step(pExplain)==SQLITE_ROW ){
drh4b5345c2018-04-24 13:07:40 +00003477 const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
drhe2ca99c2018-05-02 00:33:43 +00003478 int iEqpId = sqlite3_column_int(pExplain, 0);
3479 int iParentId = sqlite3_column_int(pExplain, 1);
drh7e088a62020-05-02 00:01:39 +00003480 if( zEQPLine==0 ) zEQPLine = "";
drh4b5345c2018-04-24 13:07:40 +00003481 if( zEQPLine[0]=='-' ) eqp_render(pArg);
drhe2ca99c2018-05-02 00:33:43 +00003482 eqp_append(pArg, iEqpId, iParentId, zEQPLine);
drh2ce15c32017-07-11 13:34:40 +00003483 }
drh4b5345c2018-04-24 13:07:40 +00003484 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003485 }
3486 sqlite3_finalize(pExplain);
3487 sqlite3_free(zEQP);
drhada70452017-12-21 21:02:27 +00003488 if( pArg->autoEQP>=AUTOEQP_full ){
drh2ce15c32017-07-11 13:34:40 +00003489 /* Also do an EXPLAIN for ".eqp full" mode */
3490 zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
3491 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3492 if( rc==SQLITE_OK ){
3493 pArg->cMode = MODE_Explain;
3494 explain_data_prepare(pArg, pExplain);
drha10b9992018-03-09 15:24:33 +00003495 exec_prepared_stmt(pArg, pExplain);
drh2ce15c32017-07-11 13:34:40 +00003496 explain_data_delete(pArg);
3497 }
3498 sqlite3_finalize(pExplain);
3499 sqlite3_free(zEQP);
3500 }
drh51efe092018-03-20 12:04:38 +00003501 if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
3502 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
3503 /* Reprepare pStmt before reactiving trace modes */
3504 sqlite3_finalize(pStmt);
3505 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
drh3c49eaf2018-06-07 15:23:43 +00003506 if( pArg ) pArg->pStmt = pStmt;
drh51efe092018-03-20 12:04:38 +00003507 }
drh2ce15c32017-07-11 13:34:40 +00003508 restore_debug_trace_modes();
3509 }
3510
3511 if( pArg ){
3512 pArg->cMode = pArg->mode;
drh4b5345c2018-04-24 13:07:40 +00003513 if( pArg->autoExplain ){
drh39c5c4a2019-03-06 14:53:27 +00003514 if( sqlite3_stmt_isexplain(pStmt)==1 ){
drh4b5345c2018-04-24 13:07:40 +00003515 pArg->cMode = MODE_Explain;
3516 }
drh39c5c4a2019-03-06 14:53:27 +00003517 if( sqlite3_stmt_isexplain(pStmt)==2 ){
drh4b5345c2018-04-24 13:07:40 +00003518 pArg->cMode = MODE_EQP;
3519 }
drh2ce15c32017-07-11 13:34:40 +00003520 }
3521
3522 /* If the shell is currently in ".explain" mode, gather the extra
3523 ** data required to add indents to the output.*/
3524 if( pArg->cMode==MODE_Explain ){
3525 explain_data_prepare(pArg, pStmt);
3526 }
3527 }
3528
drh8b738d02019-02-25 18:43:54 +00003529 bind_prepared_stmt(pArg, pStmt);
drha10b9992018-03-09 15:24:33 +00003530 exec_prepared_stmt(pArg, pStmt);
drh2ce15c32017-07-11 13:34:40 +00003531 explain_data_delete(pArg);
drh4b5345c2018-04-24 13:07:40 +00003532 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003533
3534 /* print usage stats if stats on */
3535 if( pArg && pArg->statsOn ){
3536 display_stats(db, pArg, 0);
3537 }
3538
3539 /* print loop-counters if required */
3540 if( pArg && pArg->scanstatsOn ){
3541 display_scanstats(db, pArg);
3542 }
3543
3544 /* Finalize the statement just executed. If this fails, save a
3545 ** copy of the error message. Otherwise, set zSql to point to the
3546 ** next statement to execute. */
3547 rc2 = sqlite3_finalize(pStmt);
3548 if( rc!=SQLITE_NOMEM ) rc = rc2;
3549 if( rc==SQLITE_OK ){
3550 zSql = zLeftover;
3551 while( IsSpace(zSql[0]) ) zSql++;
3552 }else if( pzErrMsg ){
3553 *pzErrMsg = save_err_msg(db);
3554 }
3555
3556 /* clear saved stmt handle */
3557 if( pArg ){
3558 pArg->pStmt = NULL;
3559 }
3560 }
3561 } /* end while */
3562
3563 return rc;
3564}
3565
3566/*
3567** Release memory previously allocated by tableColumnList().
3568*/
3569static void freeColumnList(char **azCol){
3570 int i;
3571 for(i=1; azCol[i]; i++){
3572 sqlite3_free(azCol[i]);
3573 }
3574 /* azCol[0] is a static string */
3575 sqlite3_free(azCol);
3576}
3577
3578/*
3579** Return a list of pointers to strings which are the names of all
3580** columns in table zTab. The memory to hold the names is dynamically
3581** allocated and must be released by the caller using a subsequent call
3582** to freeColumnList().
3583**
3584** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
3585** value that needs to be preserved, then azCol[0] is filled in with the
3586** name of the rowid column.
3587**
3588** The first regular column in the table is azCol[1]. The list is terminated
3589** by an entry with azCol[i]==0.
3590*/
3591static char **tableColumnList(ShellState *p, const char *zTab){
3592 char **azCol = 0;
3593 sqlite3_stmt *pStmt;
3594 char *zSql;
3595 int nCol = 0;
3596 int nAlloc = 0;
3597 int nPK = 0; /* Number of PRIMARY KEY columns seen */
3598 int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
3599 int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
3600 int rc;
3601
3602 zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
3603 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3604 sqlite3_free(zSql);
3605 if( rc ) return 0;
3606 while( sqlite3_step(pStmt)==SQLITE_ROW ){
3607 if( nCol>=nAlloc-2 ){
3608 nAlloc = nAlloc*2 + nCol + 10;
3609 azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
drh4b5345c2018-04-24 13:07:40 +00003610 if( azCol==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00003611 }
3612 azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
3613 if( sqlite3_column_int(pStmt, 5) ){
3614 nPK++;
3615 if( nPK==1
3616 && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
3617 "INTEGER")==0
3618 ){
3619 isIPK = 1;
3620 }else{
3621 isIPK = 0;
3622 }
3623 }
3624 }
3625 sqlite3_finalize(pStmt);
drh4c6cddc2017-10-12 10:28:30 +00003626 if( azCol==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00003627 azCol[0] = 0;
3628 azCol[nCol+1] = 0;
3629
3630 /* The decision of whether or not a rowid really needs to be preserved
3631 ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
3632 ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
3633 ** rowids on tables where the rowid is inaccessible because there are other
3634 ** columns in the table named "rowid", "_rowid_", and "oid".
3635 */
3636 if( preserveRowid && isIPK ){
3637 /* If a single PRIMARY KEY column with type INTEGER was seen, then it
3638 ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID
3639 ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
3640 ** ROWID aliases. To distinguish these cases, check to see if
3641 ** there is a "pk" entry in "PRAGMA index_list". There will be
3642 ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
3643 */
3644 zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
3645 " WHERE origin='pk'", zTab);
3646 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3647 sqlite3_free(zSql);
3648 if( rc ){
3649 freeColumnList(azCol);
3650 return 0;
3651 }
3652 rc = sqlite3_step(pStmt);
3653 sqlite3_finalize(pStmt);
3654 preserveRowid = rc==SQLITE_ROW;
3655 }
3656 if( preserveRowid ){
3657 /* Only preserve the rowid if we can find a name to use for the
3658 ** rowid */
3659 static char *azRowid[] = { "rowid", "_rowid_", "oid" };
3660 int i, j;
3661 for(j=0; j<3; j++){
3662 for(i=1; i<=nCol; i++){
3663 if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
3664 }
3665 if( i>nCol ){
3666 /* At this point, we know that azRowid[j] is not the name of any
3667 ** ordinary column in the table. Verify that azRowid[j] is a valid
3668 ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
3669 ** tables will fail this last check */
3670 rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
3671 if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
3672 break;
3673 }
3674 }
3675 }
3676 return azCol;
3677}
3678
3679/*
3680** Toggle the reverse_unordered_selects setting.
3681*/
3682static void toggleSelectOrder(sqlite3 *db){
3683 sqlite3_stmt *pStmt = 0;
3684 int iSetting = 0;
3685 char zStmt[100];
3686 sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0);
3687 if( sqlite3_step(pStmt)==SQLITE_ROW ){
3688 iSetting = sqlite3_column_int(pStmt, 0);
3689 }
3690 sqlite3_finalize(pStmt);
3691 sqlite3_snprintf(sizeof(zStmt), zStmt,
3692 "PRAGMA reverse_unordered_selects(%d)", !iSetting);
3693 sqlite3_exec(db, zStmt, 0, 0, 0);
3694}
3695
3696/*
3697** This is a different callback routine used for dumping the database.
3698** Each row received by this callback consists of a table name,
3699** the table type ("index" or "table") and SQL to create the table.
3700** This routine should print text sufficient to recreate the table.
3701*/
3702static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
3703 int rc;
3704 const char *zTable;
3705 const char *zType;
3706 const char *zSql;
3707 ShellState *p = (ShellState *)pArg;
mistachkina00a0162020-10-18 18:35:34 +00003708 int dataOnly;
3709 int noSys;
drh2ce15c32017-07-11 13:34:40 +00003710
3711 UNUSED_PARAMETER(azNotUsed);
drhb3c45232017-08-28 14:33:27 +00003712 if( nArg!=3 || azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00003713 zTable = azArg[0];
3714 zType = azArg[1];
3715 zSql = azArg[2];
mistachkina00a0162020-10-18 18:35:34 +00003716 dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
3717 noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
drh2ce15c32017-07-11 13:34:40 +00003718
drhc1962192020-10-12 16:54:28 +00003719 if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
3720 if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
3721 }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
3722 if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00003723 }else if( strncmp(zTable, "sqlite_", 7)==0 ){
3724 return 0;
drhc1962192020-10-12 16:54:28 +00003725 }else if( dataOnly ){
3726 /* no-op */
drh2ce15c32017-07-11 13:34:40 +00003727 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
3728 char *zIns;
3729 if( !p->writableSchema ){
3730 raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
3731 p->writableSchema = 1;
3732 }
3733 zIns = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00003734 "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
drh2ce15c32017-07-11 13:34:40 +00003735 "VALUES('table','%q','%q',0,'%q');",
3736 zTable, zTable, zSql);
3737 utf8_printf(p->out, "%s\n", zIns);
3738 sqlite3_free(zIns);
3739 return 0;
3740 }else{
3741 printSchemaLine(p->out, zSql, ";\n");
3742 }
3743
3744 if( strcmp(zType, "table")==0 ){
3745 ShellText sSelect;
3746 ShellText sTable;
3747 char **azCol;
3748 int i;
3749 char *savedDestTable;
3750 int savedMode;
3751
3752 azCol = tableColumnList(p, zTable);
3753 if( azCol==0 ){
3754 p->nErr++;
3755 return 0;
3756 }
3757
3758 /* Always quote the table name, even if it appears to be pure ascii,
3759 ** in case it is a keyword. Ex: INSERT INTO "table" ... */
3760 initText(&sTable);
3761 appendText(&sTable, zTable, quoteChar(zTable));
3762 /* If preserving the rowid, add a column list after the table name.
3763 ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
3764 ** instead of the usual "INSERT INTO tab VALUES(...)".
3765 */
3766 if( azCol[0] ){
3767 appendText(&sTable, "(", 0);
3768 appendText(&sTable, azCol[0], 0);
3769 for(i=1; azCol[i]; i++){
3770 appendText(&sTable, ",", 0);
3771 appendText(&sTable, azCol[i], quoteChar(azCol[i]));
3772 }
3773 appendText(&sTable, ")", 0);
3774 }
3775
3776 /* Build an appropriate SELECT statement */
3777 initText(&sSelect);
3778 appendText(&sSelect, "SELECT ", 0);
3779 if( azCol[0] ){
3780 appendText(&sSelect, azCol[0], 0);
3781 appendText(&sSelect, ",", 0);
3782 }
3783 for(i=1; azCol[i]; i++){
3784 appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
3785 if( azCol[i+1] ){
3786 appendText(&sSelect, ",", 0);
3787 }
3788 }
3789 freeColumnList(azCol);
3790 appendText(&sSelect, " FROM ", 0);
3791 appendText(&sSelect, zTable, quoteChar(zTable));
3792
3793 savedDestTable = p->zDestTable;
3794 savedMode = p->mode;
3795 p->zDestTable = sTable.z;
3796 p->mode = p->cMode = MODE_Insert;
drha10b9992018-03-09 15:24:33 +00003797 rc = shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00003798 if( (rc&0xff)==SQLITE_CORRUPT ){
3799 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
3800 toggleSelectOrder(p->db);
drha10b9992018-03-09 15:24:33 +00003801 shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00003802 toggleSelectOrder(p->db);
3803 }
3804 p->zDestTable = savedDestTable;
3805 p->mode = savedMode;
3806 freeText(&sTable);
3807 freeText(&sSelect);
3808 if( rc ) p->nErr++;
3809 }
3810 return 0;
3811}
3812
3813/*
3814** Run zQuery. Use dump_callback() as the callback routine so that
3815** the contents of the query are output as SQL statements.
3816**
3817** If we get a SQLITE_CORRUPT error, rerun the query after appending
3818** "ORDER BY rowid DESC" to the end.
3819*/
3820static int run_schema_dump_query(
3821 ShellState *p,
3822 const char *zQuery
3823){
3824 int rc;
3825 char *zErr = 0;
3826 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
3827 if( rc==SQLITE_CORRUPT ){
3828 char *zQ2;
3829 int len = strlen30(zQuery);
3830 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
3831 if( zErr ){
3832 utf8_printf(p->out, "/****** %s ******/\n", zErr);
3833 sqlite3_free(zErr);
3834 zErr = 0;
3835 }
3836 zQ2 = malloc( len+100 );
3837 if( zQ2==0 ) return rc;
3838 sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
3839 rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
3840 if( rc ){
3841 utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
3842 }else{
3843 rc = SQLITE_CORRUPT;
3844 }
3845 sqlite3_free(zErr);
3846 free(zQ2);
3847 }
3848 return rc;
3849}
3850
3851/*
drh98aa2ab2018-09-26 16:53:51 +00003852** Text of help messages.
3853**
3854** The help text for each individual command begins with a line that starts
3855** with ".". Subsequent lines are supplimental information.
3856**
3857** There must be two or more spaces between the end of the command and the
3858** start of the description of what that command does.
drh2ce15c32017-07-11 13:34:40 +00003859*/
drh98aa2ab2018-09-26 16:53:51 +00003860static const char *(azHelp[]) = {
drhe37c0e12018-01-06 19:19:50 +00003861#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drh98aa2ab2018-09-26 16:53:51 +00003862 ".archive ... Manage SQL archives",
3863 " Each command must have exactly one of the following options:",
3864 " -c, --create Create a new archive",
drhe2754c12019-08-26 12:50:01 +00003865 " -u, --update Add or update files with changed mtime",
3866 " -i, --insert Like -u but always add even if unchanged",
drh98aa2ab2018-09-26 16:53:51 +00003867 " -t, --list List contents of archive",
3868 " -x, --extract Extract files from archive",
3869 " Optional arguments:",
3870 " -v, --verbose Print each filename as it is processed",
drhe2754c12019-08-26 12:50:01 +00003871 " -f FILE, --file FILE Use archive FILE (default is current db)",
3872 " -a FILE, --append FILE Open FILE using the apndvfs VFS",
3873 " -C DIR, --directory DIR Read/extract files from directory DIR",
drh98aa2ab2018-09-26 16:53:51 +00003874 " -n, --dryrun Show the SQL that would have occurred",
3875 " Examples:",
drhe2754c12019-08-26 12:50:01 +00003876 " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
3877 " .ar -tf ARCHIVE # List members of ARCHIVE",
3878 " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE",
drh98aa2ab2018-09-26 16:53:51 +00003879 " See also:",
3880 " http://sqlite.org/cli.html#sqlar_archive_support",
drhe37c0e12018-01-06 19:19:50 +00003881#endif
drh2ce15c32017-07-11 13:34:40 +00003882#ifndef SQLITE_OMIT_AUTHORIZATION
drh98aa2ab2018-09-26 16:53:51 +00003883 ".auth ON|OFF Show authorizer callbacks",
drh2ce15c32017-07-11 13:34:40 +00003884#endif
drh98aa2ab2018-09-26 16:53:51 +00003885 ".backup ?DB? FILE Backup DB (default \"main\") to FILE",
3886 " --append Use the appendvfs",
drhe2754c12019-08-26 12:50:01 +00003887 " --async Write to FILE without journal and fsync()",
drh98aa2ab2018-09-26 16:53:51 +00003888 ".bail on|off Stop after hitting an error. Default OFF",
3889 ".binary on|off Turn binary output on or off. Default OFF",
3890 ".cd DIRECTORY Change the working directory to DIRECTORY",
3891 ".changes on|off Show number of rows changed by SQL",
3892 ".check GLOB Fail if output since .testcase does not match",
3893 ".clone NEWDB Clone data into NEWDB from the existing database",
3894 ".databases List names and files of attached databases",
3895 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
3896 ".dbinfo ?DB? Show status information about the database",
larrybr7bdbe592021-03-15 12:56:00 +00003897 ".dump ?OBJECTS? Render database content as SQL",
drheb7f2a02018-09-26 18:02:32 +00003898 " Options:",
drhc1962192020-10-12 16:54:28 +00003899 " --data-only Output only INSERT statements",
drheb7f2a02018-09-26 18:02:32 +00003900 " --newlines Allow unescaped newline characters in output",
drhc1962192020-10-12 16:54:28 +00003901 " --nosys Omit system tables (ex: \"sqlite_stat1\")",
3902 " --preserve-rowids Include ROWID values in the output",
larrybr7bdbe592021-03-15 12:56:00 +00003903 " OBJECTS is a LIKE pattern for tables, indexes, triggers or views to dump",
drh8e9297f2020-03-25 12:50:13 +00003904 " Additional LIKE patterns can be given in subsequent arguments",
drh98aa2ab2018-09-26 16:53:51 +00003905 ".echo on|off Turn command echo on or off",
drhb4e50392019-01-26 15:40:04 +00003906 ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
3907 " Other Modes:",
3908#ifdef SQLITE_DEBUG
3909 " test Show raw EXPLAIN QUERY PLAN output",
drhe2754c12019-08-26 12:50:01 +00003910 " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"",
drhb4e50392019-01-26 15:40:04 +00003911#endif
3912 " trigger Like \"full\" but also show trigger bytecode",
drhe2754c12019-08-26 12:50:01 +00003913 ".excel Display the output of next command in spreadsheet",
drh7a431002020-04-18 14:12:00 +00003914 " --bom Put a UTF8 byte-order mark on intermediate file",
drheb7f2a02018-09-26 18:02:32 +00003915 ".exit ?CODE? Exit this program with return-code CODE",
drhe2754c12019-08-26 12:50:01 +00003916 ".expert EXPERIMENTAL. Suggest indexes for queries",
drh978256f2019-11-02 00:00:14 +00003917 ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto",
drhd985f722019-06-05 14:29:53 +00003918 ".filectrl CMD ... Run various sqlite3_file_control() operations",
drh541ef2c2020-04-20 16:21:30 +00003919 " --schema SCHEMA Use SCHEMA instead of \"main\"",
3920 " --help Show CMD details",
drh98aa2ab2018-09-26 16:53:51 +00003921 ".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
3922 ".headers on|off Turn display of headers on or off",
3923 ".help ?-all? ?PATTERN? Show help text for PATTERN",
3924 ".import FILE TABLE Import data from FILE into TABLE",
drhccb37812020-03-09 15:39:39 +00003925 " Options:",
3926 " --ascii Use \\037 and \\036 as column and row separators",
3927 " --csv Use , and \\n as column and row separators",
3928 " --skip N Skip the first N rows of input",
3929 " -v \"Verbose\" - increase auxiliary output",
3930 " Notes:",
3931 " * If TABLE does not exist, it is created. The first row of input",
3932 " determines the column names.",
3933 " * If neither --csv or --ascii are used, the input mode is derived",
3934 " from the \".mode\" output mode",
3935 " * If FILE begins with \"|\" then it is a command that generates the",
3936 " input text.",
drh2ce15c32017-07-11 13:34:40 +00003937#ifndef SQLITE_OMIT_TEST_CONTROL
drh98aa2ab2018-09-26 16:53:51 +00003938 ".imposter INDEX TABLE Create imposter table TABLE on index INDEX",
drh2ce15c32017-07-11 13:34:40 +00003939#endif
drh98aa2ab2018-09-26 16:53:51 +00003940 ".indexes ?TABLE? Show names of indexes",
3941 " If TABLE is specified, only show indexes for",
3942 " tables matching TABLE using the LIKE operator.",
drh2ce15c32017-07-11 13:34:40 +00003943#ifdef SQLITE_ENABLE_IOTRACE
drh98aa2ab2018-09-26 16:53:51 +00003944 ".iotrace FILE Enable I/O diagnostic logging to FILE",
drh2ce15c32017-07-11 13:34:40 +00003945#endif
drh98aa2ab2018-09-26 16:53:51 +00003946 ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
3947 ".lint OPTIONS Report potential schema issues.",
3948 " Options:",
3949 " fkey-indexes Find missing foreign key indexes",
drh2ce15c32017-07-11 13:34:40 +00003950#ifndef SQLITE_OMIT_LOAD_EXTENSION
drh98aa2ab2018-09-26 16:53:51 +00003951 ".load FILE ?ENTRY? Load an extension library",
drh2ce15c32017-07-11 13:34:40 +00003952#endif
drh98aa2ab2018-09-26 16:53:51 +00003953 ".log FILE|off Turn logging on or off. FILE can be stderr/stdout",
3954 ".mode MODE ?TABLE? Set output mode",
3955 " MODE is one of:",
drh7da29a32020-05-29 19:17:20 +00003956 " ascii Columns/rows delimited by 0x1F and 0x1E",
drh0908e382020-06-04 18:05:39 +00003957 " box Tables using unicode box-drawing characters",
drh7da29a32020-05-29 19:17:20 +00003958 " csv Comma-separated values",
3959 " column Output in columns. (See .width)",
3960 " html HTML <table> code",
3961 " insert SQL insert statements for TABLE",
3962 " json Results in a JSON array",
3963 " line One value per line",
3964 " list Values delimited by \"|\"",
3965 " markdown Markdown table format",
3966 " quote Escape answers as for SQL",
3967 " table ASCII-art table",
3968 " tabs Tab-separated values",
3969 " tcl TCL list elements",
drh98aa2ab2018-09-26 16:53:51 +00003970 ".nullvalue STRING Use STRING in place of NULL values",
drh7a431002020-04-18 14:12:00 +00003971 ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE",
drh98aa2ab2018-09-26 16:53:51 +00003972 " If FILE begins with '|' then open as a pipe",
drh7a431002020-04-18 14:12:00 +00003973 " --bom Put a UTF8 byte-order mark at the beginning",
3974 " -e Send output to the system text editor",
3975 " -x Send output as CSV to a spreadsheet (same as \".excel\")",
drh4a3a3eb2020-02-29 15:53:48 +00003976#ifdef SQLITE_DEBUG
drhc0605082020-06-05 00:54:27 +00003977 ".oom ?--repeat M? ?N? Simulate an OOM error on the N-th allocation",
drh4a3a3eb2020-02-29 15:53:48 +00003978#endif
drh98aa2ab2018-09-26 16:53:51 +00003979 ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
3980 " Options:",
drh60f34ae2018-10-30 13:19:49 +00003981 " --append Use appendvfs to append database to the end of FILE",
drh8d889af2021-05-08 17:18:23 +00003982#ifndef SQLITE_OMIT_DESERIALIZE
drhd10c3ca2021-05-08 11:57:35 +00003983 " --deserialize Load into memory using sqlite3_deserialize()",
drhe2754c12019-08-26 12:50:01 +00003984 " --hexdb Load the output of \"dbtotxt\" as an in-memory db",
drh6ca64482019-01-22 16:06:20 +00003985 " --maxsize N Maximum size for --hexdb or --deserialized database",
drha751f392018-10-30 15:31:22 +00003986#endif
drh60f34ae2018-10-30 13:19:49 +00003987 " --new Initialize FILE to an empty database",
drh0933aad2019-11-18 17:46:38 +00003988 " --nofollow Do not follow symbolic links",
drh60f34ae2018-10-30 13:19:49 +00003989 " --readonly Open FILE readonly",
3990 " --zip FILE is a ZIP archive",
drh98aa2ab2018-09-26 16:53:51 +00003991 ".output ?FILE? Send output to FILE or stdout if FILE is omitted",
drh7a431002020-04-18 14:12:00 +00003992 " If FILE begins with '|' then open it as a pipe.",
3993 " Options:",
3994 " --bom Prefix output with a UTF8 byte-order mark",
3995 " -e Send output to the system text editor",
3996 " -x Send output as CSV to a spreadsheet",
drh9cb02642019-02-28 20:10:52 +00003997 ".parameter CMD ... Manage SQL parameter bindings",
3998 " clear Erase all bindings",
3999 " init Initialize the TEMP table that holds bindings",
4000 " list List the current parameter bindings",
4001 " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE",
drhe2754c12019-08-26 12:50:01 +00004002 " PARAMETER should start with one of: $ : @ ?",
drh9cb02642019-02-28 20:10:52 +00004003 " unset PARAMETER Remove PARAMETER from the binding table",
drh98aa2ab2018-09-26 16:53:51 +00004004 ".print STRING... Print literal STRING",
drh569b1d92019-02-05 20:51:41 +00004005#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh3f83f592019-02-04 14:53:18 +00004006 ".progress N Invoke progress handler after every N opcodes",
4007 " --limit N Interrupt after N progress callbacks",
4008 " --once Do no more than one progress interrupt",
4009 " --quiet|-q No output except at interrupts",
4010 " --reset Reset the count for each input and interrupt",
drh569b1d92019-02-05 20:51:41 +00004011#endif
drh98aa2ab2018-09-26 16:53:51 +00004012 ".prompt MAIN CONTINUE Replace the standard prompts",
4013 ".quit Exit this program",
4014 ".read FILE Read input from FILE",
dan1b162162019-04-27 20:15:15 +00004015#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan42ebb012019-04-27 18:47:03 +00004016 ".recover Recover as much data as possible from corrupt db.",
drhe2754c12019-08-26 12:50:01 +00004017 " --freelist-corrupt Assume the freelist is corrupt",
4018 " --recovery-db NAME Store recovery metadata in database file NAME",
4019 " --lost-and-found TABLE Alternative name for the lost-and-found table",
dan8cce6b82019-09-14 16:44:51 +00004020 " --no-rowids Do not attempt to recover rowid values",
4021 " that are not also INTEGER PRIMARY KEYs",
dan1b162162019-04-27 20:15:15 +00004022#endif
drh98aa2ab2018-09-26 16:53:51 +00004023 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
4024 ".save FILE Write in-memory database into FILE",
4025 ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
4026 ".schema ?PATTERN? Show the CREATE statements matching PATTERN",
drhbbb29ec2020-10-12 14:56:47 +00004027 " Options:",
4028 " --indent Try to pretty-print the schema",
4029 " --nosys Omit objects whose names start with \"sqlite_\"",
drheb7f2a02018-09-26 18:02:32 +00004030 ".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
4031 " Options:",
4032 " --init Create a new SELFTEST table",
4033 " -v Verbose output",
drh98aa2ab2018-09-26 16:53:51 +00004034 ".separator COL ?ROW? Change the column and row separators",
drh2ce15c32017-07-11 13:34:40 +00004035#if defined(SQLITE_ENABLE_SESSION)
drheb7f2a02018-09-26 18:02:32 +00004036 ".session ?NAME? CMD ... Create or control sessions",
4037 " Subcommands:",
4038 " attach TABLE Attach TABLE",
4039 " changeset FILE Write a changeset into FILE",
4040 " close Close one session",
4041 " enable ?BOOLEAN? Set or query the enable bit",
4042 " filter GLOB... Reject tables matching GLOBs",
4043 " indirect ?BOOLEAN? Mark or query the indirect status",
4044 " isempty Query whether the session is empty",
4045 " list List currently open session names",
4046 " open DB NAME Open a new session on DB",
4047 " patchset FILE Write a patchset into FILE",
4048 " If ?NAME? is omitted, the first defined session is used.",
drh2ce15c32017-07-11 13:34:40 +00004049#endif
drheb7f2a02018-09-26 18:02:32 +00004050 ".sha3sum ... Compute a SHA3 hash of database content",
4051 " Options:",
drh067b92b2020-06-19 15:24:12 +00004052 " --schema Also hash the sqlite_schema table",
drheb7f2a02018-09-26 18:02:32 +00004053 " --sha3-224 Use the sha3-224 algorithm",
drhe2754c12019-08-26 12:50:01 +00004054 " --sha3-256 Use the sha3-256 algorithm (default)",
drheb7f2a02018-09-26 18:02:32 +00004055 " --sha3-384 Use the sha3-384 algorithm",
4056 " --sha3-512 Use the sha3-512 algorithm",
4057 " Any other argument is a LIKE pattern for tables to hash",
drh04a28c32018-01-31 01:38:44 +00004058#ifndef SQLITE_NOHAVE_SYSTEM
drh98aa2ab2018-09-26 16:53:51 +00004059 ".shell CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004060#endif
drh98aa2ab2018-09-26 16:53:51 +00004061 ".show Show the current values for various settings",
drha6e6cf22021-01-09 19:10:04 +00004062 ".stats ?ARG? Show stats or turn stats on or off",
4063 " off Turn off automatic stat display",
4064 " on Turn on automatic stat display",
4065 " stmt Show statement stats",
4066 " vmstep Show the virtual machine step count only",
drh04a28c32018-01-31 01:38:44 +00004067#ifndef SQLITE_NOHAVE_SYSTEM
drh98aa2ab2018-09-26 16:53:51 +00004068 ".system CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004069#endif
drh98aa2ab2018-09-26 16:53:51 +00004070 ".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
4071 ".testcase NAME Begin redirecting output to 'testcase-out.txt'",
drhd985f722019-06-05 14:29:53 +00004072 ".testctrl CMD ... Run various sqlite3_test_control() operations",
4073 " Run \".testctrl\" with no arguments for details",
drh98aa2ab2018-09-26 16:53:51 +00004074 ".timeout MS Try opening locked tables for MS milliseconds",
4075 ".timer on|off Turn SQL timer on or off",
drh707821f2018-12-05 13:39:06 +00004076#ifndef SQLITE_OMIT_TRACE
4077 ".trace ?OPTIONS? Output each SQL statement as it is run",
4078 " FILE Send output to FILE",
4079 " stdout Send output to stdout",
4080 " stderr Send output to stderr",
4081 " off Disable tracing",
4082 " --expanded Expand query parameters",
4083#ifdef SQLITE_ENABLE_NORMALIZE
4084 " --normalized Normal the SQL statements",
4085#endif
4086 " --plain Show SQL as it is input",
4087 " --stmt Trace statement execution (SQLITE_TRACE_STMT)",
4088 " --profile Profile statements (SQLITE_TRACE_PROFILE)",
4089 " --row Trace each row (SQLITE_TRACE_ROW)",
4090 " --close Trace connection close (SQLITE_TRACE_CLOSE)",
4091#endif /* SQLITE_OMIT_TRACE */
drhcc5979d2019-08-16 22:58:29 +00004092#ifdef SQLITE_DEBUG
4093 ".unmodule NAME ... Unregister virtual table modules",
drh5df84282019-08-17 19:45:25 +00004094 " --allexcept Unregister everything except those named",
drhcc5979d2019-08-16 22:58:29 +00004095#endif
drh98aa2ab2018-09-26 16:53:51 +00004096 ".vfsinfo ?AUX? Information about the top-level VFS",
4097 ".vfslist List all available VFSes",
4098 ".vfsname ?AUX? Print the name of the VFS stack",
drh7da29a32020-05-29 19:17:20 +00004099 ".width NUM1 NUM2 ... Set minimum column widths for columnar output",
drh98aa2ab2018-09-26 16:53:51 +00004100 " Negative values right-justify",
4101};
4102
4103/*
4104** Output help text.
4105**
4106** zPattern describes the set of commands for which help text is provided.
4107** If zPattern is NULL, then show all commands, but only give a one-line
4108** description of each.
4109**
4110** Return the number of matches.
4111*/
4112static int showHelp(FILE *out, const char *zPattern){
drhe93f8262018-10-11 16:53:37 +00004113 int i = 0;
4114 int j = 0;
drh98aa2ab2018-09-26 16:53:51 +00004115 int n = 0;
4116 char *zPat;
drh488cddf2018-10-06 14:38:17 +00004117 if( zPattern==0
4118 || zPattern[0]=='0'
4119 || strcmp(zPattern,"-a")==0
4120 || strcmp(zPattern,"-all")==0
drh7a431002020-04-18 14:12:00 +00004121 || strcmp(zPattern,"--all")==0
drh488cddf2018-10-06 14:38:17 +00004122 ){
drh98aa2ab2018-09-26 16:53:51 +00004123 /* Show all commands, but only one line per command */
drh488cddf2018-10-06 14:38:17 +00004124 if( zPattern==0 ) zPattern = "";
drh98aa2ab2018-09-26 16:53:51 +00004125 for(i=0; i<ArraySize(azHelp); i++){
drh488cddf2018-10-06 14:38:17 +00004126 if( azHelp[i][0]=='.' || zPattern[0] ){
drh98aa2ab2018-09-26 16:53:51 +00004127 utf8_printf(out, "%s\n", azHelp[i]);
4128 n++;
4129 }
4130 }
4131 }else{
4132 /* Look for commands that for which zPattern is an exact prefix */
4133 zPat = sqlite3_mprintf(".%s*", zPattern);
4134 for(i=0; i<ArraySize(azHelp); i++){
4135 if( sqlite3_strglob(zPat, azHelp[i])==0 ){
4136 utf8_printf(out, "%s\n", azHelp[i]);
drheb7f2a02018-09-26 18:02:32 +00004137 j = i+1;
drh98aa2ab2018-09-26 16:53:51 +00004138 n++;
4139 }
4140 }
4141 sqlite3_free(zPat);
drheb7f2a02018-09-26 18:02:32 +00004142 if( n ){
4143 if( n==1 ){
4144 /* when zPattern is a prefix of exactly one command, then include the
4145 ** details of that command, which should begin at offset j */
4146 while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){
4147 utf8_printf(out, "%s\n", azHelp[j]);
4148 j++;
4149 }
4150 }
4151 return n;
4152 }
4153 /* Look for commands that contain zPattern anywhere. Show the complete
4154 ** text of all commands that match. */
drh98aa2ab2018-09-26 16:53:51 +00004155 zPat = sqlite3_mprintf("%%%s%%", zPattern);
4156 for(i=0; i<ArraySize(azHelp); i++){
4157 if( azHelp[i][0]=='.' ) j = i;
4158 if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
4159 utf8_printf(out, "%s\n", azHelp[j]);
4160 while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
4161 j++;
4162 utf8_printf(out, "%s\n", azHelp[j]);
4163 }
4164 i = j;
4165 n++;
4166 }
4167 }
4168 sqlite3_free(zPat);
4169 }
4170 return n;
4171}
drh2ce15c32017-07-11 13:34:40 +00004172
drh2ce15c32017-07-11 13:34:40 +00004173/* Forward reference */
drh60379d42018-12-13 18:30:01 +00004174static int process_input(ShellState *p);
drh2ce15c32017-07-11 13:34:40 +00004175
4176/*
4177** Read the content of file zName into memory obtained from sqlite3_malloc64()
4178** and return a pointer to the buffer. The caller is responsible for freeing
4179** the memory.
4180**
4181** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
4182** read.
4183**
4184** For convenience, a nul-terminator byte is always appended to the data read
4185** from the file before the buffer is returned. This byte is not included in
4186** the final value of (*pnByte), if applicable.
4187**
4188** NULL is returned if any error is encountered. The final value of *pnByte
4189** is undefined in this case.
4190*/
4191static char *readFile(const char *zName, int *pnByte){
4192 FILE *in = fopen(zName, "rb");
4193 long nIn;
4194 size_t nRead;
4195 char *pBuf;
4196 if( in==0 ) return 0;
4197 fseek(in, 0, SEEK_END);
4198 nIn = ftell(in);
4199 rewind(in);
4200 pBuf = sqlite3_malloc64( nIn+1 );
drh1dbb1472018-10-11 10:37:24 +00004201 if( pBuf==0 ){ fclose(in); return 0; }
drh2ce15c32017-07-11 13:34:40 +00004202 nRead = fread(pBuf, nIn, 1, in);
4203 fclose(in);
4204 if( nRead!=1 ){
4205 sqlite3_free(pBuf);
4206 return 0;
4207 }
4208 pBuf[nIn] = 0;
4209 if( pnByte ) *pnByte = nIn;
4210 return pBuf;
4211}
4212
4213#if defined(SQLITE_ENABLE_SESSION)
4214/*
4215** Close a single OpenSession object and release all of its associated
4216** resources.
4217*/
4218static void session_close(OpenSession *pSession){
4219 int i;
4220 sqlite3session_delete(pSession->p);
4221 sqlite3_free(pSession->zName);
4222 for(i=0; i<pSession->nFilter; i++){
4223 sqlite3_free(pSession->azFilter[i]);
4224 }
4225 sqlite3_free(pSession->azFilter);
4226 memset(pSession, 0, sizeof(OpenSession));
4227}
4228#endif
4229
4230/*
4231** Close all OpenSession objects and release all associated resources.
4232*/
4233#if defined(SQLITE_ENABLE_SESSION)
4234static void session_close_all(ShellState *p){
4235 int i;
4236 for(i=0; i<p->nSession; i++){
4237 session_close(&p->aSession[i]);
4238 }
4239 p->nSession = 0;
4240}
4241#else
4242# define session_close_all(X)
4243#endif
4244
4245/*
4246** Implementation of the xFilter function for an open session. Omit
4247** any tables named by ".session filter" but let all other table through.
4248*/
4249#if defined(SQLITE_ENABLE_SESSION)
4250static int session_filter(void *pCtx, const char *zTab){
4251 OpenSession *pSession = (OpenSession*)pCtx;
4252 int i;
4253 for(i=0; i<pSession->nFilter; i++){
4254 if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
4255 }
4256 return 1;
4257}
4258#endif
4259
4260/*
drh1fa6d9f2018-01-06 21:46:01 +00004261** Try to deduce the type of file for zName based on its content. Return
4262** one of the SHELL_OPEN_* constants.
drh1bf208c2018-03-09 21:54:01 +00004263**
4264** If the file does not exist or is empty but its name looks like a ZIP
4265** archive and the dfltZip flag is true, then assume it is a ZIP archive.
4266** Otherwise, assume an ordinary database regardless of the filename if
4267** the type cannot be determined from content.
drh1fa6d9f2018-01-06 21:46:01 +00004268*/
drhfc97c1c2018-05-14 00:41:12 +00004269int deduceDatabaseType(const char *zName, int dfltZip){
drh1fa6d9f2018-01-06 21:46:01 +00004270 FILE *f = fopen(zName, "rb");
4271 size_t n;
4272 int rc = SHELL_OPEN_UNSPEC;
4273 char zBuf[100];
drh1bf208c2018-03-09 21:54:01 +00004274 if( f==0 ){
drhbe4ccb22018-05-17 20:04:24 +00004275 if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
4276 return SHELL_OPEN_ZIPFILE;
4277 }else{
4278 return SHELL_OPEN_NORMAL;
4279 }
drh1bf208c2018-03-09 21:54:01 +00004280 }
drh2b3c4af2018-10-30 14:36:21 +00004281 n = fread(zBuf, 16, 1, f);
4282 if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
4283 fclose(f);
4284 return SHELL_OPEN_NORMAL;
4285 }
drh1fa6d9f2018-01-06 21:46:01 +00004286 fseek(f, -25, SEEK_END);
4287 n = fread(zBuf, 25, 1, f);
4288 if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
4289 rc = SHELL_OPEN_APPENDVFS;
4290 }else{
4291 fseek(f, -22, SEEK_END);
4292 n = fread(zBuf, 22, 1, f);
4293 if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
4294 && zBuf[3]==0x06 ){
4295 rc = SHELL_OPEN_ZIPFILE;
drh1bf208c2018-03-09 21:54:01 +00004296 }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
mistachkina3926f42018-05-14 12:23:04 +00004297 rc = SHELL_OPEN_ZIPFILE;
drh1fa6d9f2018-01-06 21:46:01 +00004298 }
4299 }
4300 fclose(f);
4301 return rc;
4302}
4303
drh8d889af2021-05-08 17:18:23 +00004304#ifndef SQLITE_OMIT_DESERIALIZE
drh33746482018-12-13 15:06:26 +00004305/*
4306** Reconstruct an in-memory database using the output from the "dbtotxt"
4307** program. Read content from the file in p->zDbFilename. If p->zDbFilename
4308** is 0, then read from standard input.
4309*/
4310static unsigned char *readHexDb(ShellState *p, int *pnData){
4311 unsigned char *a = 0;
drh2c8ee022018-12-13 18:59:30 +00004312 int nLine;
drh33746482018-12-13 15:06:26 +00004313 int n = 0;
4314 int pgsz = 0;
4315 int iOffset = 0;
4316 int j, k;
4317 int rc;
4318 FILE *in;
drh3ea557e2019-04-23 15:30:58 +00004319 unsigned int x[16];
drh2c8ee022018-12-13 18:59:30 +00004320 char zLine[1000];
drh33746482018-12-13 15:06:26 +00004321 if( p->zDbFilename ){
4322 in = fopen(p->zDbFilename, "r");
4323 if( in==0 ){
4324 utf8_printf(stderr, "cannot open \"%s\" for reading\n", p->zDbFilename);
4325 return 0;
4326 }
drh2c8ee022018-12-13 18:59:30 +00004327 nLine = 0;
drh33746482018-12-13 15:06:26 +00004328 }else{
drh60379d42018-12-13 18:30:01 +00004329 in = p->in;
drh2c8ee022018-12-13 18:59:30 +00004330 nLine = p->lineno;
drh5bf46442019-05-03 02:41:36 +00004331 if( in==0 ) in = stdin;
drh33746482018-12-13 15:06:26 +00004332 }
4333 *pnData = 0;
drh2c8ee022018-12-13 18:59:30 +00004334 nLine++;
drh33746482018-12-13 15:06:26 +00004335 if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
4336 rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
4337 if( rc!=2 ) goto readHexDb_error;
drh68feae52019-05-09 11:18:41 +00004338 if( n<0 ) goto readHexDb_error;
drh09ea1252019-07-17 15:05:16 +00004339 if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
4340 n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */
drh68feae52019-05-09 11:18:41 +00004341 a = sqlite3_malloc( n ? n : 1 );
drh33746482018-12-13 15:06:26 +00004342 if( a==0 ){
4343 utf8_printf(stderr, "Out of memory!\n");
4344 goto readHexDb_error;
4345 }
4346 memset(a, 0, n);
4347 if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
4348 utf8_printf(stderr, "invalid pagesize\n");
4349 goto readHexDb_error;
4350 }
drh2c8ee022018-12-13 18:59:30 +00004351 for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
drh33746482018-12-13 15:06:26 +00004352 rc = sscanf(zLine, "| page %d offset %d", &j, &k);
4353 if( rc==2 ){
4354 iOffset = k;
4355 continue;
4356 }
4357 if( strncmp(zLine, "| end ", 6)==0 ){
4358 break;
4359 }
drh3ea557e2019-04-23 15:30:58 +00004360 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 +00004361 &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
4362 &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
4363 if( rc==17 ){
4364 k = iOffset+j;
drhf354e772018-12-13 22:58:52 +00004365 if( k+16<=n ){
drh3ea557e2019-04-23 15:30:58 +00004366 int ii;
4367 for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
drh33746482018-12-13 15:06:26 +00004368 }
drh33746482018-12-13 15:06:26 +00004369 }
4370 }
4371 *pnData = n;
drh2c8ee022018-12-13 18:59:30 +00004372 if( in!=p->in ){
4373 fclose(in);
4374 }else{
4375 p->lineno = nLine;
4376 }
drh33746482018-12-13 15:06:26 +00004377 return a;
4378
4379readHexDb_error:
drh68feae52019-05-09 11:18:41 +00004380 if( in!=p->in ){
drh33746482018-12-13 15:06:26 +00004381 fclose(in);
4382 }else{
drh60379d42018-12-13 18:30:01 +00004383 while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
drh2c8ee022018-12-13 18:59:30 +00004384 nLine++;
drh33746482018-12-13 15:06:26 +00004385 if(strncmp(zLine, "| end ", 6)==0 ) break;
4386 }
drh2c8ee022018-12-13 18:59:30 +00004387 p->lineno = nLine;
drh33746482018-12-13 15:06:26 +00004388 }
4389 sqlite3_free(a);
4390 utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
4391 return 0;
4392}
drh8d889af2021-05-08 17:18:23 +00004393#endif /* SQLITE_OMIT_DESERIALIZE */
drh33746482018-12-13 15:06:26 +00004394
danb1825882019-04-23 20:48:32 +00004395/*
dan9c014f82019-04-25 19:23:15 +00004396** Scalar function "shell_int32". The first argument to this function
4397** must be a blob. The second a non-negative integer. This function
4398** reads and returns a 32-bit big-endian integer from byte
4399** offset (4*<arg2>) of the blob.
4400*/
4401static void shellInt32(
4402 sqlite3_context *context,
4403 int argc,
4404 sqlite3_value **argv
4405){
4406 const unsigned char *pBlob;
4407 int nBlob;
4408 int iInt;
drh9546c762019-05-10 17:50:33 +00004409
4410 UNUSED_PARAMETER(argc);
dan9c014f82019-04-25 19:23:15 +00004411 nBlob = sqlite3_value_bytes(argv[0]);
4412 pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
4413 iInt = sqlite3_value_int(argv[1]);
4414
4415 if( iInt>=0 && (iInt+1)*4<=nBlob ){
4416 const unsigned char *a = &pBlob[iInt*4];
4417 sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24)
4418 + ((sqlite3_int64)a[1]<<16)
4419 + ((sqlite3_int64)a[2]<< 8)
4420 + ((sqlite3_int64)a[3]<< 0);
4421 sqlite3_result_int64(context, iVal);
4422 }
4423}
4424
4425/*
drha2de66c2019-08-06 20:26:17 +00004426** Scalar function "shell_idquote(X)" returns string X quoted as an identifier,
4427** using "..." with internal double-quote characters doubled.
4428*/
4429static void shellIdQuote(
4430 sqlite3_context *context,
4431 int argc,
4432 sqlite3_value **argv
4433){
4434 const char *zName = (const char*)sqlite3_value_text(argv[0]);
drh51755a72019-08-08 19:40:29 +00004435 UNUSED_PARAMETER(argc);
drha2de66c2019-08-06 20:26:17 +00004436 if( zName ){
4437 char *z = sqlite3_mprintf("\"%w\"", zName);
4438 sqlite3_result_text(context, z, -1, sqlite3_free);
4439 }
4440}
4441
4442/*
drhddcfe922020-09-15 12:29:35 +00004443** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
4444*/
4445static void shellUSleepFunc(
4446 sqlite3_context *context,
drhd36f5882020-11-25 16:28:04 +00004447 int argcUnused,
drhddcfe922020-09-15 12:29:35 +00004448 sqlite3_value **argv
4449){
4450 int sleep = sqlite3_value_int(argv[0]);
drhd36f5882020-11-25 16:28:04 +00004451 (void)argcUnused;
drhddcfe922020-09-15 12:29:35 +00004452 sqlite3_sleep(sleep/1000);
4453 sqlite3_result_int(context, sleep);
4454}
4455
4456/*
danb1825882019-04-23 20:48:32 +00004457** Scalar function "shell_escape_crnl" used by the .recover command.
4458** The argument passed to this function is the output of built-in
4459** function quote(). If the first character of the input is "'",
4460** indicating that the value passed to quote() was a text value,
4461** then this function searches the input for "\n" and "\r" characters
4462** and adds a wrapper similar to the following:
4463**
4464** replace(replace(<input>, '\n', char(10), '\r', char(13));
4465**
4466** Or, if the first character of the input is not "'", then a copy
4467** of the input is returned.
4468*/
4469static void shellEscapeCrnl(
4470 sqlite3_context *context,
4471 int argc,
4472 sqlite3_value **argv
4473){
4474 const char *zText = (const char*)sqlite3_value_text(argv[0]);
drh9546c762019-05-10 17:50:33 +00004475 UNUSED_PARAMETER(argc);
danb1825882019-04-23 20:48:32 +00004476 if( zText[0]=='\'' ){
4477 int nText = sqlite3_value_bytes(argv[0]);
4478 int i;
4479 char zBuf1[20];
4480 char zBuf2[20];
4481 const char *zNL = 0;
4482 const char *zCR = 0;
4483 int nCR = 0;
4484 int nNL = 0;
4485
4486 for(i=0; zText[i]; i++){
4487 if( zNL==0 && zText[i]=='\n' ){
4488 zNL = unused_string(zText, "\\n", "\\012", zBuf1);
4489 nNL = (int)strlen(zNL);
4490 }
4491 if( zCR==0 && zText[i]=='\r' ){
4492 zCR = unused_string(zText, "\\r", "\\015", zBuf2);
4493 nCR = (int)strlen(zCR);
4494 }
4495 }
4496
4497 if( zNL || zCR ){
4498 int iOut = 0;
4499 i64 nMax = (nNL > nCR) ? nNL : nCR;
dan51f5ffa2019-04-29 11:41:46 +00004500 i64 nAlloc = nMax * nText + (nMax+64)*2;
danb1825882019-04-23 20:48:32 +00004501 char *zOut = (char*)sqlite3_malloc64(nAlloc);
4502 if( zOut==0 ){
4503 sqlite3_result_error_nomem(context);
4504 return;
4505 }
4506
4507 if( zNL && zCR ){
4508 memcpy(&zOut[iOut], "replace(replace(", 16);
4509 iOut += 16;
4510 }else{
4511 memcpy(&zOut[iOut], "replace(", 8);
4512 iOut += 8;
4513 }
4514 for(i=0; zText[i]; i++){
4515 if( zText[i]=='\n' ){
4516 memcpy(&zOut[iOut], zNL, nNL);
4517 iOut += nNL;
4518 }else if( zText[i]=='\r' ){
4519 memcpy(&zOut[iOut], zCR, nCR);
4520 iOut += nCR;
4521 }else{
4522 zOut[iOut] = zText[i];
4523 iOut++;
4524 }
4525 }
4526
4527 if( zNL ){
4528 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
4529 memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
4530 memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
4531 }
4532 if( zCR ){
4533 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
4534 memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
4535 memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
4536 }
4537
4538 sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
4539 sqlite3_free(zOut);
4540 return;
4541 }
4542 }
4543
4544 sqlite3_result_value(context, argv[0]);
4545}
4546
drhbe4ccb22018-05-17 20:04:24 +00004547/* Flags for open_db().
4548**
4549** The default behavior of open_db() is to exit(1) if the database fails to
4550** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
4551** but still returns without calling exit.
4552**
4553** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a
4554** ZIP archive if the file does not exist or is empty and its name matches
4555** the *.zip pattern.
4556*/
4557#define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */
4558#define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */
4559
drh1fa6d9f2018-01-06 21:46:01 +00004560/*
drh2ce15c32017-07-11 13:34:40 +00004561** Make sure the database is open. If it is not, then open it. If
4562** the database fails to open, print an error message and exit.
4563*/
drhbe4ccb22018-05-17 20:04:24 +00004564static void open_db(ShellState *p, int openFlags){
drh2ce15c32017-07-11 13:34:40 +00004565 if( p->db==0 ){
drhf2072d12018-05-11 15:10:11 +00004566 if( p->openMode==SHELL_OPEN_UNSPEC ){
4567 if( p->zDbFilename==0 || p->zDbFilename[0]==0 ){
4568 p->openMode = SHELL_OPEN_NORMAL;
drhbe4ccb22018-05-17 20:04:24 +00004569 }else{
4570 p->openMode = (u8)deduceDatabaseType(p->zDbFilename,
4571 (openFlags & OPEN_DB_ZIPFILE)!=0);
drhf2072d12018-05-11 15:10:11 +00004572 }
drh1fa6d9f2018-01-06 21:46:01 +00004573 }
4574 switch( p->openMode ){
4575 case SHELL_OPEN_APPENDVFS: {
4576 sqlite3_open_v2(p->zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004577 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
drh1fa6d9f2018-01-06 21:46:01 +00004578 break;
4579 }
drh33746482018-12-13 15:06:26 +00004580 case SHELL_OPEN_HEXDB:
drh60f34ae2018-10-30 13:19:49 +00004581 case SHELL_OPEN_DESERIALIZE: {
4582 sqlite3_open(0, &p->db);
4583 break;
4584 }
drh1fa6d9f2018-01-06 21:46:01 +00004585 case SHELL_OPEN_ZIPFILE: {
4586 sqlite3_open(":memory:", &p->db);
4587 break;
4588 }
drhee269a62018-02-14 23:27:43 +00004589 case SHELL_OPEN_READONLY: {
drh0933aad2019-11-18 17:46:38 +00004590 sqlite3_open_v2(p->zDbFilename, &p->db,
4591 SQLITE_OPEN_READONLY|p->openFlags, 0);
drhee269a62018-02-14 23:27:43 +00004592 break;
4593 }
drh1fa6d9f2018-01-06 21:46:01 +00004594 case SHELL_OPEN_UNSPEC:
4595 case SHELL_OPEN_NORMAL: {
drh0933aad2019-11-18 17:46:38 +00004596 sqlite3_open_v2(p->zDbFilename, &p->db,
4597 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
drh1fa6d9f2018-01-06 21:46:01 +00004598 break;
4599 }
4600 }
drh2ce15c32017-07-11 13:34:40 +00004601 globalDb = p->db;
4602 if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
4603 utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
4604 p->zDbFilename, sqlite3_errmsg(p->db));
drhf25cc4f2019-01-04 14:29:21 +00004605 if( openFlags & OPEN_DB_KEEPALIVE ){
4606 sqlite3_open(":memory:", &p->db);
4607 return;
4608 }
drh2ce15c32017-07-11 13:34:40 +00004609 exit(1);
4610 }
4611#ifndef SQLITE_OMIT_LOAD_EXTENSION
4612 sqlite3_enable_load_extension(p->db, 1);
4613#endif
4614 sqlite3_fileio_init(p->db, 0, 0);
4615 sqlite3_shathree_init(p->db, 0, 0);
drh56eb09b2017-07-11 13:59:07 +00004616 sqlite3_completion_init(p->db, 0, 0);
drhf05dd032020-04-14 15:53:58 +00004617 sqlite3_uint_init(p->db, 0, 0);
drhbeb9def2020-06-22 19:12:23 +00004618 sqlite3_decimal_init(p->db, 0, 0);
drh64689902021-06-03 13:51:31 +00004619 sqlite3_regexp_init(p->db, 0, 0);
drh8cda77d2020-06-24 15:06:29 +00004620 sqlite3_ieee_init(p->db, 0, 0);
mistachkin72c38d82020-08-28 18:47:39 +00004621 sqlite3_series_init(p->db, 0, 0);
dan1b162162019-04-27 20:15:15 +00004622#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00004623 sqlite3_dbdata_init(p->db, 0, 0);
dan1b162162019-04-27 20:15:15 +00004624#endif
dan72afc3c2017-12-05 18:32:40 +00004625#ifdef SQLITE_HAVE_ZLIB
dan9ebfaad2017-12-26 20:39:58 +00004626 sqlite3_zipfile_init(p->db, 0, 0);
dand1b51d42017-12-16 19:11:26 +00004627 sqlite3_sqlar_init(p->db, 0, 0);
dan72afc3c2017-12-05 18:32:40 +00004628#endif
drhceba7922018-01-01 21:28:25 +00004629 sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
drh2ce15c32017-07-11 13:34:40 +00004630 shellAddSchemaName, 0, 0);
drh667a2a22018-01-02 00:04:37 +00004631 sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
4632 shellModuleSchema, 0, 0);
drh634c70f2018-01-10 16:50:18 +00004633 sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
4634 shellPutsFunc, 0, 0);
danb1825882019-04-23 20:48:32 +00004635 sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0,
4636 shellEscapeCrnl, 0, 0);
dan9c014f82019-04-25 19:23:15 +00004637 sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
4638 shellInt32, 0, 0);
drha2de66c2019-08-06 20:26:17 +00004639 sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
4640 shellIdQuote, 0, 0);
drhddcfe922020-09-15 12:29:35 +00004641 sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
4642 shellUSleepFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00004643#ifndef SQLITE_NOHAVE_SYSTEM
drh97913132018-01-11 00:04:00 +00004644 sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
4645 editFunc, 0, 0);
4646 sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
4647 editFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00004648#endif
drh1fa6d9f2018-01-06 21:46:01 +00004649 if( p->openMode==SHELL_OPEN_ZIPFILE ){
4650 char *zSql = sqlite3_mprintf(
4651 "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename);
4652 sqlite3_exec(p->db, zSql, 0, 0, 0);
4653 sqlite3_free(zSql);
drha751f392018-10-30 15:31:22 +00004654 }
drh8d889af2021-05-08 17:18:23 +00004655#ifndef SQLITE_OMIT_DESERIALIZE
drh33746482018-12-13 15:06:26 +00004656 else
4657 if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
mistachkin99490932018-12-17 22:19:57 +00004658 int rc;
drh60f34ae2018-10-30 13:19:49 +00004659 int nData = 0;
drh33746482018-12-13 15:06:26 +00004660 unsigned char *aData;
4661 if( p->openMode==SHELL_OPEN_DESERIALIZE ){
4662 aData = (unsigned char*)readFile(p->zDbFilename, &nData);
4663 }else{
4664 aData = readHexDb(p, &nData);
4665 if( aData==0 ){
drh33746482018-12-13 15:06:26 +00004666 return;
4667 }
4668 }
mistachkin99490932018-12-17 22:19:57 +00004669 rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
drh60f34ae2018-10-30 13:19:49 +00004670 SQLITE_DESERIALIZE_RESIZEABLE |
4671 SQLITE_DESERIALIZE_FREEONCLOSE);
4672 if( rc ){
4673 utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
4674 }
drh6ca64482019-01-22 16:06:20 +00004675 if( p->szMax>0 ){
4676 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
4677 }
drh1fa6d9f2018-01-06 21:46:01 +00004678 }
drha751f392018-10-30 15:31:22 +00004679#endif
drh2ce15c32017-07-11 13:34:40 +00004680 }
4681}
4682
drh9e804032018-05-18 17:11:50 +00004683/*
4684** Attempt to close the databaes connection. Report errors.
4685*/
4686void close_db(sqlite3 *db){
4687 int rc = sqlite3_close(db);
4688 if( rc ){
4689 utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
4690 rc, sqlite3_errmsg(db));
4691 }
4692}
4693
drh56eb09b2017-07-11 13:59:07 +00004694#if HAVE_READLINE || HAVE_EDITLINE
4695/*
4696** Readline completion callbacks
4697*/
4698static char *readline_completion_generator(const char *text, int state){
4699 static sqlite3_stmt *pStmt = 0;
4700 char *zRet;
4701 if( state==0 ){
4702 char *zSql;
drh56eb09b2017-07-11 13:59:07 +00004703 sqlite3_finalize(pStmt);
4704 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
4705 " FROM completion(%Q) ORDER BY 1", text);
4706 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
4707 sqlite3_free(zSql);
4708 }
4709 if( sqlite3_step(pStmt)==SQLITE_ROW ){
drh968d8712017-07-14 00:28:28 +00004710 zRet = strdup((const char*)sqlite3_column_text(pStmt, 0));
drh56eb09b2017-07-11 13:59:07 +00004711 }else{
4712 sqlite3_finalize(pStmt);
4713 pStmt = 0;
4714 zRet = 0;
4715 }
4716 return zRet;
4717}
4718static char **readline_completion(const char *zText, int iStart, int iEnd){
4719 rl_attempted_completion_over = 1;
4720 return rl_completion_matches(zText, readline_completion_generator);
4721}
4722
4723#elif HAVE_LINENOISE
4724/*
4725** Linenoise completion callback
4726*/
4727static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
drhaf2770f2018-01-05 14:55:43 +00004728 int nLine = strlen30(zLine);
drh56eb09b2017-07-11 13:59:07 +00004729 int i, iStart;
4730 sqlite3_stmt *pStmt = 0;
4731 char *zSql;
4732 char zBuf[1000];
4733
4734 if( nLine>sizeof(zBuf)-30 ) return;
drh1615c372018-05-12 23:56:22 +00004735 if( zLine[0]=='.' || zLine[0]=='#') return;
drh56eb09b2017-07-11 13:59:07 +00004736 for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
4737 if( i==nLine-1 ) return;
4738 iStart = i+1;
4739 memcpy(zBuf, zLine, iStart);
4740 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
4741 " FROM completion(%Q,%Q) ORDER BY 1",
4742 &zLine[iStart], zLine);
4743 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
4744 sqlite3_free(zSql);
4745 sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
4746 while( sqlite3_step(pStmt)==SQLITE_ROW ){
4747 const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
4748 int nCompletion = sqlite3_column_bytes(pStmt, 0);
4749 if( iStart+nCompletion < sizeof(zBuf)-1 ){
4750 memcpy(zBuf+iStart, zCompletion, nCompletion+1);
4751 linenoiseAddCompletion(lc, zBuf);
4752 }
4753 }
4754 sqlite3_finalize(pStmt);
4755}
4756#endif
4757
drh2ce15c32017-07-11 13:34:40 +00004758/*
4759** Do C-language style dequoting.
4760**
4761** \a -> alarm
4762** \b -> backspace
4763** \t -> tab
4764** \n -> newline
4765** \v -> vertical tab
4766** \f -> form feed
4767** \r -> carriage return
4768** \s -> space
4769** \" -> "
4770** \' -> '
4771** \\ -> backslash
4772** \NNN -> ascii character NNN in octal
4773*/
4774static void resolve_backslashes(char *z){
4775 int i, j;
4776 char c;
4777 while( *z && *z!='\\' ) z++;
4778 for(i=j=0; (c = z[i])!=0; i++, j++){
4779 if( c=='\\' && z[i+1]!=0 ){
4780 c = z[++i];
4781 if( c=='a' ){
4782 c = '\a';
4783 }else if( c=='b' ){
4784 c = '\b';
4785 }else if( c=='t' ){
4786 c = '\t';
4787 }else if( c=='n' ){
4788 c = '\n';
4789 }else if( c=='v' ){
4790 c = '\v';
4791 }else if( c=='f' ){
4792 c = '\f';
4793 }else if( c=='r' ){
4794 c = '\r';
4795 }else if( c=='"' ){
4796 c = '"';
4797 }else if( c=='\'' ){
4798 c = '\'';
4799 }else if( c=='\\' ){
4800 c = '\\';
4801 }else if( c>='0' && c<='7' ){
4802 c -= '0';
4803 if( z[i+1]>='0' && z[i+1]<='7' ){
4804 i++;
4805 c = (c<<3) + z[i] - '0';
4806 if( z[i+1]>='0' && z[i+1]<='7' ){
4807 i++;
4808 c = (c<<3) + z[i] - '0';
4809 }
4810 }
4811 }
4812 }
4813 z[j] = c;
4814 }
4815 if( j<i ) z[j] = 0;
4816}
4817
4818/*
drh2ce15c32017-07-11 13:34:40 +00004819** Interpret zArg as either an integer or a boolean value. Return 1 or 0
4820** for TRUE and FALSE. Return the integer value if appropriate.
4821*/
4822static int booleanValue(const char *zArg){
4823 int i;
4824 if( zArg[0]=='0' && zArg[1]=='x' ){
4825 for(i=2; hexDigitValue(zArg[i])>=0; i++){}
4826 }else{
4827 for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
4828 }
4829 if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
4830 if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
4831 return 1;
4832 }
4833 if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
4834 return 0;
4835 }
4836 utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
4837 zArg);
4838 return 0;
4839}
4840
4841/*
4842** Set or clear a shell flag according to a boolean value.
4843*/
4844static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){
4845 if( booleanValue(zArg) ){
4846 ShellSetFlag(p, mFlag);
4847 }else{
4848 ShellClearFlag(p, mFlag);
4849 }
4850}
4851
4852/*
4853** Close an output file, assuming it is not stderr or stdout
4854*/
4855static void output_file_close(FILE *f){
4856 if( f && f!=stdout && f!=stderr ) fclose(f);
4857}
4858
4859/*
4860** Try to open an output file. The names "stdout" and "stderr" are
4861** recognized and do the right thing. NULL is returned if the output
4862** filename is "off".
4863*/
drha92a01a2018-01-10 22:15:37 +00004864static FILE *output_file_open(const char *zFile, int bTextMode){
drh2ce15c32017-07-11 13:34:40 +00004865 FILE *f;
4866 if( strcmp(zFile,"stdout")==0 ){
4867 f = stdout;
4868 }else if( strcmp(zFile, "stderr")==0 ){
4869 f = stderr;
4870 }else if( strcmp(zFile, "off")==0 ){
4871 f = 0;
4872 }else{
drha92a01a2018-01-10 22:15:37 +00004873 f = fopen(zFile, bTextMode ? "w" : "wb");
drh2ce15c32017-07-11 13:34:40 +00004874 if( f==0 ){
4875 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
4876 }
4877 }
4878 return f;
4879}
4880
drh707821f2018-12-05 13:39:06 +00004881#ifndef SQLITE_OMIT_TRACE
drh2ce15c32017-07-11 13:34:40 +00004882/*
4883** A routine for handling output from sqlite3_trace().
4884*/
4885static int sql_trace_callback(
drh707821f2018-12-05 13:39:06 +00004886 unsigned mType, /* The trace type */
4887 void *pArg, /* The ShellState pointer */
4888 void *pP, /* Usually a pointer to sqlite_stmt */
4889 void *pX /* Auxiliary output */
drh2ce15c32017-07-11 13:34:40 +00004890){
drh707821f2018-12-05 13:39:06 +00004891 ShellState *p = (ShellState*)pArg;
4892 sqlite3_stmt *pStmt;
4893 const char *zSql;
4894 int nSql;
4895 if( p->traceOut==0 ) return 0;
4896 if( mType==SQLITE_TRACE_CLOSE ){
4897 utf8_printf(p->traceOut, "-- closing database connection\n");
4898 return 0;
4899 }
4900 if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){
4901 zSql = (const char*)pX;
4902 }else{
4903 pStmt = (sqlite3_stmt*)pP;
4904 switch( p->eTraceType ){
4905 case SHELL_TRACE_EXPANDED: {
4906 zSql = sqlite3_expanded_sql(pStmt);
4907 break;
4908 }
4909#ifdef SQLITE_ENABLE_NORMALIZE
4910 case SHELL_TRACE_NORMALIZED: {
4911 zSql = sqlite3_normalized_sql(pStmt);
4912 break;
4913 }
4914#endif
4915 default: {
4916 zSql = sqlite3_sql(pStmt);
4917 break;
4918 }
4919 }
4920 }
4921 if( zSql==0 ) return 0;
4922 nSql = strlen30(zSql);
4923 while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
4924 switch( mType ){
4925 case SQLITE_TRACE_ROW:
4926 case SQLITE_TRACE_STMT: {
4927 utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql);
4928 break;
4929 }
4930 case SQLITE_TRACE_PROFILE: {
4931 sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
4932 utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec);
4933 break;
4934 }
drh2ce15c32017-07-11 13:34:40 +00004935 }
4936 return 0;
4937}
4938#endif
drh2ce15c32017-07-11 13:34:40 +00004939
4940/*
4941** A no-op routine that runs with the ".breakpoint" doc-command. This is
4942** a useful spot to set a debugger breakpoint.
4943*/
4944static void test_breakpoint(void){
4945 static int nCall = 0;
4946 nCall++;
4947}
4948
4949/*
4950** An object used to read a CSV and other files for import.
4951*/
4952typedef struct ImportCtx ImportCtx;
4953struct ImportCtx {
4954 const char *zFile; /* Name of the input file */
4955 FILE *in; /* Read the CSV text from this input stream */
drh97767842020-05-29 19:39:35 +00004956 int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */
drh2ce15c32017-07-11 13:34:40 +00004957 char *z; /* Accumulated text for a field */
4958 int n; /* Number of bytes in z */
4959 int nAlloc; /* Space allocated for z[] */
4960 int nLine; /* Current line number */
drhccb37812020-03-09 15:39:39 +00004961 int nRow; /* Number of rows imported */
4962 int nErr; /* Number of errors encountered */
drh2ce15c32017-07-11 13:34:40 +00004963 int bNotFirst; /* True if one or more bytes already read */
4964 int cTerm; /* Character that terminated the most recent field */
4965 int cColSep; /* The column separator character. (Usually ",") */
4966 int cRowSep; /* The row separator character. (Usually "\n") */
4967};
4968
drh97767842020-05-29 19:39:35 +00004969/* Clean up resourced used by an ImportCtx */
4970static void import_cleanup(ImportCtx *p){
drh42c2a042020-05-29 20:16:19 +00004971 if( p->in!=0 && p->xCloser!=0 ){
drh97767842020-05-29 19:39:35 +00004972 p->xCloser(p->in);
4973 p->in = 0;
4974 }
4975 sqlite3_free(p->z);
4976 p->z = 0;
4977}
4978
drh2ce15c32017-07-11 13:34:40 +00004979/* Append a single byte to z[] */
4980static void import_append_char(ImportCtx *p, int c){
4981 if( p->n+1>=p->nAlloc ){
4982 p->nAlloc += p->nAlloc + 100;
4983 p->z = sqlite3_realloc64(p->z, p->nAlloc);
drh4b5345c2018-04-24 13:07:40 +00004984 if( p->z==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00004985 }
4986 p->z[p->n++] = (char)c;
4987}
4988
4989/* Read a single field of CSV text. Compatible with rfc4180 and extended
4990** with the option of having a separator other than ",".
4991**
4992** + Input comes from p->in.
4993** + Store results in p->z of length p->n. Space to hold p->z comes
4994** from sqlite3_malloc64().
4995** + Use p->cSep as the column separator. The default is ",".
4996** + Use p->rSep as the row separator. The default is "\n".
4997** + Keep track of the line number in p->nLine.
4998** + Store the character that terminates the field in p->cTerm. Store
4999** EOF on end-of-file.
5000** + Report syntax errors on stderr
5001*/
5002static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
5003 int c;
5004 int cSep = p->cColSep;
5005 int rSep = p->cRowSep;
5006 p->n = 0;
5007 c = fgetc(p->in);
5008 if( c==EOF || seenInterrupt ){
5009 p->cTerm = EOF;
5010 return 0;
5011 }
5012 if( c=='"' ){
5013 int pc, ppc;
5014 int startLine = p->nLine;
5015 int cQuote = c;
5016 pc = ppc = 0;
5017 while( 1 ){
5018 c = fgetc(p->in);
5019 if( c==rSep ) p->nLine++;
5020 if( c==cQuote ){
5021 if( pc==cQuote ){
5022 pc = 0;
5023 continue;
5024 }
5025 }
5026 if( (c==cSep && pc==cQuote)
5027 || (c==rSep && pc==cQuote)
5028 || (c==rSep && pc=='\r' && ppc==cQuote)
5029 || (c==EOF && pc==cQuote)
5030 ){
5031 do{ p->n--; }while( p->z[p->n]!=cQuote );
5032 p->cTerm = c;
5033 break;
5034 }
5035 if( pc==cQuote && c!='\r' ){
5036 utf8_printf(stderr, "%s:%d: unescaped %c character\n",
5037 p->zFile, p->nLine, cQuote);
5038 }
5039 if( c==EOF ){
5040 utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
5041 p->zFile, startLine, cQuote);
5042 p->cTerm = c;
5043 break;
5044 }
5045 import_append_char(p, c);
5046 ppc = pc;
5047 pc = c;
5048 }
5049 }else{
5050 /* If this is the first field being parsed and it begins with the
5051 ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
5052 if( (c&0xff)==0xef && p->bNotFirst==0 ){
5053 import_append_char(p, c);
5054 c = fgetc(p->in);
5055 if( (c&0xff)==0xbb ){
5056 import_append_char(p, c);
5057 c = fgetc(p->in);
5058 if( (c&0xff)==0xbf ){
5059 p->bNotFirst = 1;
5060 p->n = 0;
5061 return csv_read_one_field(p);
5062 }
5063 }
5064 }
5065 while( c!=EOF && c!=cSep && c!=rSep ){
5066 import_append_char(p, c);
5067 c = fgetc(p->in);
5068 }
5069 if( c==rSep ){
5070 p->nLine++;
5071 if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
5072 }
5073 p->cTerm = c;
5074 }
5075 if( p->z ) p->z[p->n] = 0;
5076 p->bNotFirst = 1;
5077 return p->z;
5078}
5079
5080/* Read a single field of ASCII delimited text.
5081**
5082** + Input comes from p->in.
5083** + Store results in p->z of length p->n. Space to hold p->z comes
5084** from sqlite3_malloc64().
5085** + Use p->cSep as the column separator. The default is "\x1F".
5086** + Use p->rSep as the row separator. The default is "\x1E".
5087** + Keep track of the row number in p->nLine.
5088** + Store the character that terminates the field in p->cTerm. Store
5089** EOF on end-of-file.
5090** + Report syntax errors on stderr
5091*/
5092static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
5093 int c;
5094 int cSep = p->cColSep;
5095 int rSep = p->cRowSep;
5096 p->n = 0;
5097 c = fgetc(p->in);
5098 if( c==EOF || seenInterrupt ){
5099 p->cTerm = EOF;
5100 return 0;
5101 }
5102 while( c!=EOF && c!=cSep && c!=rSep ){
5103 import_append_char(p, c);
5104 c = fgetc(p->in);
5105 }
5106 if( c==rSep ){
5107 p->nLine++;
5108 }
5109 p->cTerm = c;
5110 if( p->z ) p->z[p->n] = 0;
5111 return p->z;
5112}
5113
5114/*
5115** Try to transfer data for table zTable. If an error is seen while
5116** moving forward, try to go backwards. The backwards movement won't
5117** work for WITHOUT ROWID tables.
5118*/
5119static void tryToCloneData(
5120 ShellState *p,
5121 sqlite3 *newDb,
5122 const char *zTable
5123){
5124 sqlite3_stmt *pQuery = 0;
5125 sqlite3_stmt *pInsert = 0;
5126 char *zQuery = 0;
5127 char *zInsert = 0;
5128 int rc;
5129 int i, j, n;
drhaf2770f2018-01-05 14:55:43 +00005130 int nTable = strlen30(zTable);
drh2ce15c32017-07-11 13:34:40 +00005131 int k = 0;
5132 int cnt = 0;
5133 const int spinRate = 10000;
5134
5135 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
5136 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5137 if( rc ){
5138 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5139 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5140 zQuery);
5141 goto end_data_xfer;
5142 }
5143 n = sqlite3_column_count(pQuery);
5144 zInsert = sqlite3_malloc64(200 + nTable + n*3);
drh4b5345c2018-04-24 13:07:40 +00005145 if( zInsert==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00005146 sqlite3_snprintf(200+nTable,zInsert,
5147 "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
drhaf2770f2018-01-05 14:55:43 +00005148 i = strlen30(zInsert);
drh2ce15c32017-07-11 13:34:40 +00005149 for(j=1; j<n; j++){
5150 memcpy(zInsert+i, ",?", 2);
5151 i += 2;
5152 }
5153 memcpy(zInsert+i, ");", 3);
5154 rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
5155 if( rc ){
5156 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5157 sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
5158 zQuery);
5159 goto end_data_xfer;
5160 }
5161 for(k=0; k<2; k++){
5162 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5163 for(i=0; i<n; i++){
5164 switch( sqlite3_column_type(pQuery, i) ){
5165 case SQLITE_NULL: {
5166 sqlite3_bind_null(pInsert, i+1);
5167 break;
5168 }
5169 case SQLITE_INTEGER: {
5170 sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
5171 break;
5172 }
5173 case SQLITE_FLOAT: {
5174 sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
5175 break;
5176 }
5177 case SQLITE_TEXT: {
5178 sqlite3_bind_text(pInsert, i+1,
5179 (const char*)sqlite3_column_text(pQuery,i),
5180 -1, SQLITE_STATIC);
5181 break;
5182 }
5183 case SQLITE_BLOB: {
5184 sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
5185 sqlite3_column_bytes(pQuery,i),
5186 SQLITE_STATIC);
5187 break;
5188 }
5189 }
5190 } /* End for */
5191 rc = sqlite3_step(pInsert);
5192 if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
5193 utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
5194 sqlite3_errmsg(newDb));
5195 }
5196 sqlite3_reset(pInsert);
5197 cnt++;
5198 if( (cnt%spinRate)==0 ){
5199 printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
5200 fflush(stdout);
5201 }
5202 } /* End while */
5203 if( rc==SQLITE_DONE ) break;
5204 sqlite3_finalize(pQuery);
5205 sqlite3_free(zQuery);
5206 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
5207 zTable);
5208 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5209 if( rc ){
5210 utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
5211 break;
5212 }
5213 } /* End for(k=0...) */
5214
5215end_data_xfer:
5216 sqlite3_finalize(pQuery);
5217 sqlite3_finalize(pInsert);
5218 sqlite3_free(zQuery);
5219 sqlite3_free(zInsert);
5220}
5221
5222
5223/*
5224** Try to transfer all rows of the schema that match zWhere. For
5225** each row, invoke xForEach() on the object defined by that row.
5226** If an error is encountered while moving forward through the
drh067b92b2020-06-19 15:24:12 +00005227** sqlite_schema table, try again moving backwards.
drh2ce15c32017-07-11 13:34:40 +00005228*/
5229static void tryToCloneSchema(
5230 ShellState *p,
5231 sqlite3 *newDb,
5232 const char *zWhere,
5233 void (*xForEach)(ShellState*,sqlite3*,const char*)
5234){
5235 sqlite3_stmt *pQuery = 0;
5236 char *zQuery = 0;
5237 int rc;
5238 const unsigned char *zName;
5239 const unsigned char *zSql;
5240 char *zErrMsg = 0;
5241
drh067b92b2020-06-19 15:24:12 +00005242 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005243 " WHERE %s", zWhere);
5244 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5245 if( rc ){
5246 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5247 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5248 zQuery);
5249 goto end_schema_xfer;
5250 }
5251 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5252 zName = sqlite3_column_text(pQuery, 0);
5253 zSql = sqlite3_column_text(pQuery, 1);
5254 printf("%s... ", zName); fflush(stdout);
5255 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5256 if( zErrMsg ){
5257 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5258 sqlite3_free(zErrMsg);
5259 zErrMsg = 0;
5260 }
5261 if( xForEach ){
5262 xForEach(p, newDb, (const char*)zName);
5263 }
5264 printf("done\n");
5265 }
5266 if( rc!=SQLITE_DONE ){
5267 sqlite3_finalize(pQuery);
5268 sqlite3_free(zQuery);
drh067b92b2020-06-19 15:24:12 +00005269 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005270 " WHERE %s ORDER BY rowid DESC", zWhere);
5271 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5272 if( rc ){
5273 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5274 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5275 zQuery);
5276 goto end_schema_xfer;
5277 }
5278 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5279 zName = sqlite3_column_text(pQuery, 0);
5280 zSql = sqlite3_column_text(pQuery, 1);
5281 printf("%s... ", zName); fflush(stdout);
5282 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5283 if( zErrMsg ){
5284 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5285 sqlite3_free(zErrMsg);
5286 zErrMsg = 0;
5287 }
5288 if( xForEach ){
5289 xForEach(p, newDb, (const char*)zName);
5290 }
5291 printf("done\n");
5292 }
5293 }
5294end_schema_xfer:
5295 sqlite3_finalize(pQuery);
5296 sqlite3_free(zQuery);
5297}
5298
5299/*
5300** Open a new database file named "zNewDb". Try to recover as much information
5301** as possible out of the main database (which might be corrupt) and write it
5302** into zNewDb.
5303*/
5304static void tryToClone(ShellState *p, const char *zNewDb){
5305 int rc;
5306 sqlite3 *newDb = 0;
5307 if( access(zNewDb,0)==0 ){
5308 utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
5309 return;
5310 }
5311 rc = sqlite3_open(zNewDb, &newDb);
5312 if( rc ){
5313 utf8_printf(stderr, "Cannot create output database: %s\n",
5314 sqlite3_errmsg(newDb));
5315 }else{
5316 sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
5317 sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
5318 tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
5319 tryToCloneSchema(p, newDb, "type!='table'", 0);
5320 sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
5321 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
5322 }
drh9e804032018-05-18 17:11:50 +00005323 close_db(newDb);
drh2ce15c32017-07-11 13:34:40 +00005324}
5325
5326/*
drh13c20932018-01-10 21:41:55 +00005327** Change the output file back to stdout.
5328**
5329** If the p->doXdgOpen flag is set, that means the output was being
5330** redirected to a temporary file named by p->zTempFile. In that case,
5331** launch start/open/xdg-open on that temporary file.
drh2ce15c32017-07-11 13:34:40 +00005332*/
5333static void output_reset(ShellState *p){
5334 if( p->outfile[0]=='|' ){
5335#ifndef SQLITE_OMIT_POPEN
5336 pclose(p->out);
5337#endif
5338 }else{
5339 output_file_close(p->out);
drh04a28c32018-01-31 01:38:44 +00005340#ifndef SQLITE_NOHAVE_SYSTEM
drh13c20932018-01-10 21:41:55 +00005341 if( p->doXdgOpen ){
5342 const char *zXdgOpenCmd =
5343#if defined(_WIN32)
5344 "start";
5345#elif defined(__APPLE__)
5346 "open";
5347#else
5348 "xdg-open";
5349#endif
5350 char *zCmd;
5351 zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
drha92a01a2018-01-10 22:15:37 +00005352 if( system(zCmd) ){
5353 utf8_printf(stderr, "Failed: [%s]\n", zCmd);
drh1d9ea272020-04-17 23:46:54 +00005354 }else{
5355 /* Give the start/open/xdg-open command some time to get
5356 ** going before we continue, and potential delete the
5357 ** p->zTempFile data file out from under it */
5358 sqlite3_sleep(2000);
drha92a01a2018-01-10 22:15:37 +00005359 }
drh13c20932018-01-10 21:41:55 +00005360 sqlite3_free(zCmd);
drh3c484e82018-01-10 22:27:21 +00005361 outputModePop(p);
drh13c20932018-01-10 21:41:55 +00005362 p->doXdgOpen = 0;
5363 }
drh04a28c32018-01-31 01:38:44 +00005364#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
drh2ce15c32017-07-11 13:34:40 +00005365 }
5366 p->outfile[0] = 0;
5367 p->out = stdout;
5368}
5369
5370/*
5371** Run an SQL command and return the single integer result.
5372*/
5373static int db_int(ShellState *p, const char *zSql){
5374 sqlite3_stmt *pStmt;
5375 int res = 0;
5376 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
5377 if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
5378 res = sqlite3_column_int(pStmt,0);
5379 }
5380 sqlite3_finalize(pStmt);
5381 return res;
5382}
5383
5384/*
5385** Convert a 2-byte or 4-byte big-endian integer into a native integer
5386*/
5387static unsigned int get2byteInt(unsigned char *a){
5388 return (a[0]<<8) + a[1];
5389}
5390static unsigned int get4byteInt(unsigned char *a){
5391 return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
5392}
5393
5394/*
drh76c12062020-01-14 13:13:19 +00005395** Implementation of the ".dbinfo" command.
drh2ce15c32017-07-11 13:34:40 +00005396**
5397** Return 1 on error, 2 to exit, and 0 otherwise.
5398*/
5399static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
5400 static const struct { const char *zName; int ofst; } aField[] = {
5401 { "file change counter:", 24 },
5402 { "database page count:", 28 },
5403 { "freelist page count:", 36 },
5404 { "schema cookie:", 40 },
5405 { "schema format:", 44 },
5406 { "default cache size:", 48 },
5407 { "autovacuum top root:", 52 },
5408 { "incremental vacuum:", 64 },
5409 { "text encoding:", 56 },
5410 { "user version:", 60 },
5411 { "application id:", 68 },
5412 { "software version:", 96 },
5413 };
5414 static const struct { const char *zName; const char *zSql; } aQuery[] = {
5415 { "number of tables:",
5416 "SELECT count(*) FROM %s WHERE type='table'" },
5417 { "number of indexes:",
5418 "SELECT count(*) FROM %s WHERE type='index'" },
5419 { "number of triggers:",
5420 "SELECT count(*) FROM %s WHERE type='trigger'" },
5421 { "number of views:",
5422 "SELECT count(*) FROM %s WHERE type='view'" },
5423 { "schema size:",
5424 "SELECT total(length(sql)) FROM %s" },
5425 };
drh87c889c2019-03-20 18:22:51 +00005426 int i, rc;
drhea99a312018-07-18 19:09:07 +00005427 unsigned iDataVersion;
drh2ce15c32017-07-11 13:34:40 +00005428 char *zSchemaTab;
5429 char *zDb = nArg>=2 ? azArg[1] : "main";
drh512e6c32017-10-11 17:51:08 +00005430 sqlite3_stmt *pStmt = 0;
drh2ce15c32017-07-11 13:34:40 +00005431 unsigned char aHdr[100];
5432 open_db(p, 0);
5433 if( p->db==0 ) return 1;
drh87c889c2019-03-20 18:22:51 +00005434 rc = sqlite3_prepare_v2(p->db,
5435 "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
5436 -1, &pStmt, 0);
5437 if( rc ){
drh451f89a2020-04-28 23:09:56 +00005438 utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
drh87c889c2019-03-20 18:22:51 +00005439 sqlite3_finalize(pStmt);
5440 return 1;
5441 }
drh512e6c32017-10-11 17:51:08 +00005442 sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
5443 if( sqlite3_step(pStmt)==SQLITE_ROW
5444 && sqlite3_column_bytes(pStmt,0)>100
5445 ){
5446 memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
5447 sqlite3_finalize(pStmt);
5448 }else{
drh2ce15c32017-07-11 13:34:40 +00005449 raw_printf(stderr, "unable to read database header\n");
drh512e6c32017-10-11 17:51:08 +00005450 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00005451 return 1;
5452 }
5453 i = get2byteInt(aHdr+16);
5454 if( i==1 ) i = 65536;
5455 utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
5456 utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
5457 utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
5458 utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
5459 for(i=0; i<ArraySize(aField); i++){
5460 int ofst = aField[i].ofst;
5461 unsigned int val = get4byteInt(aHdr + ofst);
5462 utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
5463 switch( ofst ){
5464 case 56: {
5465 if( val==1 ) raw_printf(p->out, " (utf8)");
5466 if( val==2 ) raw_printf(p->out, " (utf16le)");
5467 if( val==3 ) raw_printf(p->out, " (utf16be)");
5468 }
5469 }
5470 raw_printf(p->out, "\n");
5471 }
5472 if( zDb==0 ){
drh067b92b2020-06-19 15:24:12 +00005473 zSchemaTab = sqlite3_mprintf("main.sqlite_schema");
drh2ce15c32017-07-11 13:34:40 +00005474 }else if( strcmp(zDb,"temp")==0 ){
drh067b92b2020-06-19 15:24:12 +00005475 zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
drh2ce15c32017-07-11 13:34:40 +00005476 }else{
drh067b92b2020-06-19 15:24:12 +00005477 zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
drh2ce15c32017-07-11 13:34:40 +00005478 }
5479 for(i=0; i<ArraySize(aQuery); i++){
5480 char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
5481 int val = db_int(p, zSql);
5482 sqlite3_free(zSql);
5483 utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
5484 }
5485 sqlite3_free(zSchemaTab);
drhea99a312018-07-18 19:09:07 +00005486 sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
5487 utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
drh2ce15c32017-07-11 13:34:40 +00005488 return 0;
5489}
5490
5491/*
5492** Print the current sqlite3_errmsg() value to stderr and return 1.
5493*/
5494static int shellDatabaseError(sqlite3 *db){
5495 const char *zErr = sqlite3_errmsg(db);
5496 utf8_printf(stderr, "Error: %s\n", zErr);
5497 return 1;
5498}
5499
5500/*
drh2ce15c32017-07-11 13:34:40 +00005501** Compare the pattern in zGlob[] against the text in z[]. Return TRUE
5502** if they match and FALSE (0) if they do not match.
5503**
5504** Globbing rules:
5505**
5506** '*' Matches any sequence of zero or more characters.
5507**
5508** '?' Matches exactly one character.
5509**
5510** [...] Matches one character from the enclosed list of
5511** characters.
5512**
5513** [^...] Matches one character not in the enclosed list.
5514**
5515** '#' Matches any sequence of one or more digits with an
5516** optional + or - sign in front
5517**
5518** ' ' Any span of whitespace matches any other span of
5519** whitespace.
5520**
5521** Extra whitespace at the end of z[] is ignored.
5522*/
5523static int testcase_glob(const char *zGlob, const char *z){
5524 int c, c2;
5525 int invert;
5526 int seen;
5527
5528 while( (c = (*(zGlob++)))!=0 ){
5529 if( IsSpace(c) ){
5530 if( !IsSpace(*z) ) return 0;
5531 while( IsSpace(*zGlob) ) zGlob++;
5532 while( IsSpace(*z) ) z++;
5533 }else if( c=='*' ){
5534 while( (c=(*(zGlob++))) == '*' || c=='?' ){
5535 if( c=='?' && (*(z++))==0 ) return 0;
5536 }
5537 if( c==0 ){
5538 return 1;
5539 }else if( c=='[' ){
5540 while( *z && testcase_glob(zGlob-1,z)==0 ){
5541 z++;
5542 }
5543 return (*z)!=0;
5544 }
5545 while( (c2 = (*(z++)))!=0 ){
5546 while( c2!=c ){
5547 c2 = *(z++);
5548 if( c2==0 ) return 0;
5549 }
5550 if( testcase_glob(zGlob,z) ) return 1;
5551 }
5552 return 0;
5553 }else if( c=='?' ){
5554 if( (*(z++))==0 ) return 0;
5555 }else if( c=='[' ){
5556 int prior_c = 0;
5557 seen = 0;
5558 invert = 0;
5559 c = *(z++);
5560 if( c==0 ) return 0;
5561 c2 = *(zGlob++);
5562 if( c2=='^' ){
5563 invert = 1;
5564 c2 = *(zGlob++);
5565 }
5566 if( c2==']' ){
5567 if( c==']' ) seen = 1;
5568 c2 = *(zGlob++);
5569 }
5570 while( c2 && c2!=']' ){
5571 if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
5572 c2 = *(zGlob++);
5573 if( c>=prior_c && c<=c2 ) seen = 1;
5574 prior_c = 0;
5575 }else{
5576 if( c==c2 ){
5577 seen = 1;
5578 }
5579 prior_c = c2;
5580 }
5581 c2 = *(zGlob++);
5582 }
5583 if( c2==0 || (seen ^ invert)==0 ) return 0;
5584 }else if( c=='#' ){
5585 if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++;
5586 if( !IsDigit(z[0]) ) return 0;
5587 z++;
5588 while( IsDigit(z[0]) ){ z++; }
5589 }else{
5590 if( c!=(*(z++)) ) return 0;
5591 }
5592 }
5593 while( IsSpace(*z) ){ z++; }
5594 return *z==0;
5595}
5596
5597
5598/*
5599** Compare the string as a command-line option with either one or two
5600** initial "-" characters.
5601*/
5602static int optionMatch(const char *zStr, const char *zOpt){
5603 if( zStr[0]!='-' ) return 0;
5604 zStr++;
5605 if( zStr[0]=='-' ) zStr++;
5606 return strcmp(zStr, zOpt)==0;
5607}
5608
5609/*
5610** Delete a file.
5611*/
5612int shellDeleteFile(const char *zFilename){
5613 int rc;
5614#ifdef _WIN32
5615 wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
5616 rc = _wunlink(z);
5617 sqlite3_free(z);
5618#else
5619 rc = unlink(zFilename);
5620#endif
5621 return rc;
5622}
5623
drh13c20932018-01-10 21:41:55 +00005624/*
5625** Try to delete the temporary file (if there is one) and free the
5626** memory used to hold the name of the temp file.
5627*/
5628static void clearTempFile(ShellState *p){
5629 if( p->zTempFile==0 ) return;
drh536c3452018-01-11 00:38:39 +00005630 if( p->doXdgOpen ) return;
drh13c20932018-01-10 21:41:55 +00005631 if( shellDeleteFile(p->zTempFile) ) return;
5632 sqlite3_free(p->zTempFile);
5633 p->zTempFile = 0;
5634}
5635
5636/*
5637** Create a new temp file name with the given suffix.
5638*/
5639static void newTempFile(ShellState *p, const char *zSuffix){
5640 clearTempFile(p);
5641 sqlite3_free(p->zTempFile);
5642 p->zTempFile = 0;
drh7f3bf8a2018-01-10 21:50:08 +00005643 if( p->db ){
5644 sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
5645 }
drh13c20932018-01-10 21:41:55 +00005646 if( p->zTempFile==0 ){
drh1d9ea272020-04-17 23:46:54 +00005647 /* If p->db is an in-memory database then the TEMPFILENAME file-control
5648 ** will not work and we will need to fallback to guessing */
5649 char *zTemp;
drh13c20932018-01-10 21:41:55 +00005650 sqlite3_uint64 r;
5651 sqlite3_randomness(sizeof(r), &r);
drh1d9ea272020-04-17 23:46:54 +00005652 zTemp = getenv("TEMP");
5653 if( zTemp==0 ) zTemp = getenv("TMP");
5654 if( zTemp==0 ){
5655#ifdef _WIN32
5656 zTemp = "\\tmp";
5657#else
5658 zTemp = "/tmp";
5659#endif
5660 }
5661 p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix);
drh13c20932018-01-10 21:41:55 +00005662 }else{
5663 p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
5664 }
5665 if( p->zTempFile==0 ){
5666 raw_printf(stderr, "out of memory\n");
5667 exit(1);
5668 }
5669}
5670
drh2ce15c32017-07-11 13:34:40 +00005671
5672/*
5673** The implementation of SQL scalar function fkey_collate_clause(), used
5674** by the ".lint fkey-indexes" command. This scalar function is always
5675** called with four arguments - the parent table name, the parent column name,
5676** the child table name and the child column name.
5677**
5678** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
5679**
5680** If either of the named tables or columns do not exist, this function
5681** returns an empty string. An empty string is also returned if both tables
5682** and columns exist but have the same default collation sequence. Or,
5683** if both exist but the default collation sequences are different, this
5684** function returns the string " COLLATE <parent-collation>", where
5685** <parent-collation> is the default collation sequence of the parent column.
5686*/
5687static void shellFkeyCollateClause(
5688 sqlite3_context *pCtx,
5689 int nVal,
5690 sqlite3_value **apVal
5691){
5692 sqlite3 *db = sqlite3_context_db_handle(pCtx);
5693 const char *zParent;
5694 const char *zParentCol;
5695 const char *zParentSeq;
5696 const char *zChild;
5697 const char *zChildCol;
5698 const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */
5699 int rc;
5700
5701 assert( nVal==4 );
5702 zParent = (const char*)sqlite3_value_text(apVal[0]);
5703 zParentCol = (const char*)sqlite3_value_text(apVal[1]);
5704 zChild = (const char*)sqlite3_value_text(apVal[2]);
5705 zChildCol = (const char*)sqlite3_value_text(apVal[3]);
5706
5707 sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
5708 rc = sqlite3_table_column_metadata(
5709 db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0
5710 );
5711 if( rc==SQLITE_OK ){
5712 rc = sqlite3_table_column_metadata(
5713 db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0
5714 );
5715 }
5716
5717 if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){
5718 char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq);
5719 sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
5720 sqlite3_free(z);
5721 }
5722}
5723
5724
5725/*
5726** The implementation of dot-command ".lint fkey-indexes".
5727*/
5728static int lintFkeyIndexes(
5729 ShellState *pState, /* Current shell tool state */
5730 char **azArg, /* Array of arguments passed to dot command */
5731 int nArg /* Number of entries in azArg[] */
5732){
5733 sqlite3 *db = pState->db; /* Database handle to query "main" db of */
5734 FILE *out = pState->out; /* Stream to write non-error output to */
5735 int bVerbose = 0; /* If -verbose is present */
5736 int bGroupByParent = 0; /* If -groupbyparent is present */
5737 int i; /* To iterate through azArg[] */
5738 const char *zIndent = ""; /* How much to indent CREATE INDEX by */
5739 int rc; /* Return code */
5740 sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */
5741
5742 /*
5743 ** This SELECT statement returns one row for each foreign key constraint
5744 ** in the schema of the main database. The column values are:
5745 **
5746 ** 0. The text of an SQL statement similar to:
5747 **
danf9679312017-12-01 18:40:18 +00005748 ** "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?"
drh2ce15c32017-07-11 13:34:40 +00005749 **
danf9679312017-12-01 18:40:18 +00005750 ** This SELECT is similar to the one that the foreign keys implementation
5751 ** needs to run internally on child tables. If there is an index that can
drh2ce15c32017-07-11 13:34:40 +00005752 ** be used to optimize this query, then it can also be used by the FK
5753 ** implementation to optimize DELETE or UPDATE statements on the parent
5754 ** table.
5755 **
5756 ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by
5757 ** the EXPLAIN QUERY PLAN command matches this pattern, then the schema
5758 ** contains an index that can be used to optimize the query.
5759 **
5760 ** 2. Human readable text that describes the child table and columns. e.g.
5761 **
5762 ** "child_table(child_key1, child_key2)"
5763 **
5764 ** 3. Human readable text that describes the parent table and columns. e.g.
5765 **
5766 ** "parent_table(parent_key1, parent_key2)"
5767 **
5768 ** 4. A full CREATE INDEX statement for an index that could be used to
5769 ** optimize DELETE or UPDATE statements on the parent table. e.g.
5770 **
5771 ** "CREATE INDEX child_table_child_key ON child_table(child_key)"
5772 **
5773 ** 5. The name of the parent table.
5774 **
5775 ** These six values are used by the C logic below to generate the report.
5776 */
5777 const char *zSql =
5778 "SELECT "
danf9679312017-12-01 18:40:18 +00005779 " 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
drh2ce15c32017-07-11 13:34:40 +00005780 " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
5781 " || fkey_collate_clause("
5782 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
5783 ", "
drh82102332021-03-20 15:11:29 +00005784 " 'SEARCH ' || s.name || ' USING COVERING INDEX*('"
drh2ce15c32017-07-11 13:34:40 +00005785 " || group_concat('*=?', ' AND ') || ')'"
5786 ", "
5787 " s.name || '(' || group_concat(f.[from], ', ') || ')'"
5788 ", "
5789 " f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
5790 ", "
5791 " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
5792 " || ' ON ' || quote(s.name) || '('"
5793 " || group_concat(quote(f.[from]) ||"
5794 " fkey_collate_clause("
5795 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
5796 " || ');'"
5797 ", "
5798 " f.[table] "
drh067b92b2020-06-19 15:24:12 +00005799 "FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f "
drh2ce15c32017-07-11 13:34:40 +00005800 "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
5801 "GROUP BY s.name, f.id "
5802 "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
5803 ;
drh82102332021-03-20 15:11:29 +00005804 const char *zGlobIPK = "SEARCH * USING INTEGER PRIMARY KEY (rowid=?)";
drh2ce15c32017-07-11 13:34:40 +00005805
5806 for(i=2; i<nArg; i++){
drhaf2770f2018-01-05 14:55:43 +00005807 int n = strlen30(azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00005808 if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
5809 bVerbose = 1;
5810 }
5811 else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
5812 bGroupByParent = 1;
5813 zIndent = " ";
5814 }
5815 else{
5816 raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
5817 azArg[0], azArg[1]
5818 );
5819 return SQLITE_ERROR;
5820 }
5821 }
5822
5823 /* Register the fkey_collate_clause() SQL function */
5824 rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
5825 0, shellFkeyCollateClause, 0, 0
5826 );
5827
5828
5829 if( rc==SQLITE_OK ){
5830 rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
5831 }
5832 if( rc==SQLITE_OK ){
5833 sqlite3_bind_int(pSql, 1, bGroupByParent);
5834 }
5835
5836 if( rc==SQLITE_OK ){
5837 int rc2;
5838 char *zPrev = 0;
5839 while( SQLITE_ROW==sqlite3_step(pSql) ){
5840 int res = -1;
5841 sqlite3_stmt *pExplain = 0;
5842 const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
5843 const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
5844 const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
5845 const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
5846 const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
5847 const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
5848
5849 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
5850 if( rc!=SQLITE_OK ) break;
5851 if( SQLITE_ROW==sqlite3_step(pExplain) ){
5852 const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
5853 res = (
5854 0==sqlite3_strglob(zGlob, zPlan)
5855 || 0==sqlite3_strglob(zGlobIPK, zPlan)
5856 );
5857 }
5858 rc = sqlite3_finalize(pExplain);
5859 if( rc!=SQLITE_OK ) break;
5860
5861 if( res<0 ){
5862 raw_printf(stderr, "Error: internal error");
5863 break;
5864 }else{
5865 if( bGroupByParent
5866 && (bVerbose || res==0)
5867 && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
5868 ){
5869 raw_printf(out, "-- Parent table %s\n", zParent);
5870 sqlite3_free(zPrev);
5871 zPrev = sqlite3_mprintf("%s", zParent);
5872 }
5873
5874 if( res==0 ){
5875 raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
5876 }else if( bVerbose ){
5877 raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
5878 zIndent, zFrom, zTarget
5879 );
5880 }
5881 }
5882 }
5883 sqlite3_free(zPrev);
5884
5885 if( rc!=SQLITE_OK ){
5886 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
5887 }
5888
5889 rc2 = sqlite3_finalize(pSql);
5890 if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
5891 rc = rc2;
5892 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
5893 }
5894 }else{
5895 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
5896 }
5897
5898 return rc;
5899}
5900
5901/*
5902** Implementation of ".lint" dot command.
5903*/
5904static int lintDotCommand(
5905 ShellState *pState, /* Current shell tool state */
5906 char **azArg, /* Array of arguments passed to dot command */
5907 int nArg /* Number of entries in azArg[] */
5908){
5909 int n;
drhaf2770f2018-01-05 14:55:43 +00005910 n = (nArg>=2 ? strlen30(azArg[1]) : 0);
drh2ce15c32017-07-11 13:34:40 +00005911 if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
5912 return lintFkeyIndexes(pState, azArg, nArg);
5913
5914 usage:
5915 raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
5916 raw_printf(stderr, "Where sub-commands are:\n");
5917 raw_printf(stderr, " fkey-indexes\n");
5918 return SQLITE_ERROR;
5919}
5920
dan1b162162019-04-27 20:15:15 +00005921#if !defined SQLITE_OMIT_VIRTUALTABLE
danfd0245d2017-12-07 15:44:29 +00005922static void shellPrepare(
dand4b56e52017-12-12 20:04:59 +00005923 sqlite3 *db,
danfd0245d2017-12-07 15:44:29 +00005924 int *pRc,
5925 const char *zSql,
5926 sqlite3_stmt **ppStmt
5927){
5928 *ppStmt = 0;
5929 if( *pRc==SQLITE_OK ){
dand4b56e52017-12-12 20:04:59 +00005930 int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
danfd0245d2017-12-07 15:44:29 +00005931 if( rc!=SQLITE_OK ){
5932 raw_printf(stderr, "sql error: %s (%d)\n",
dand4b56e52017-12-12 20:04:59 +00005933 sqlite3_errmsg(db), sqlite3_errcode(db)
danfd0245d2017-12-07 15:44:29 +00005934 );
5935 *pRc = rc;
5936 }
5937 }
5938}
5939
drh9546c762019-05-10 17:50:33 +00005940/*
5941** Create a prepared statement using printf-style arguments for the SQL.
5942**
5943** This routine is could be marked "static". But it is not always used,
5944** depending on compile-time options. By omitting the "static", we avoid
5945** nuisance compiler warnings about "defined but not used".
5946*/
5947void shellPreparePrintf(
dan3f67ddf2017-12-13 20:04:53 +00005948 sqlite3 *db,
5949 int *pRc,
danac15e2d2017-12-14 19:15:07 +00005950 sqlite3_stmt **ppStmt,
5951 const char *zFmt,
5952 ...
dan3f67ddf2017-12-13 20:04:53 +00005953){
danac15e2d2017-12-14 19:15:07 +00005954 *ppStmt = 0;
5955 if( *pRc==SQLITE_OK ){
5956 va_list ap;
5957 char *z;
5958 va_start(ap, zFmt);
5959 z = sqlite3_vmprintf(zFmt, ap);
drh1dbb1472018-10-11 10:37:24 +00005960 va_end(ap);
dan3f67ddf2017-12-13 20:04:53 +00005961 if( z==0 ){
5962 *pRc = SQLITE_NOMEM;
5963 }else{
5964 shellPrepare(db, pRc, z, ppStmt);
5965 sqlite3_free(z);
5966 }
dan3f67ddf2017-12-13 20:04:53 +00005967 }
5968}
5969
drh9546c762019-05-10 17:50:33 +00005970/* Finalize the prepared statement created using shellPreparePrintf().
5971**
5972** This routine is could be marked "static". But it is not always used,
5973** depending on compile-time options. By omitting the "static", we avoid
5974** nuisance compiler warnings about "defined but not used".
5975*/
5976void shellFinalize(
danfd0245d2017-12-07 15:44:29 +00005977 int *pRc,
5978 sqlite3_stmt *pStmt
5979){
dan25c12182017-12-07 21:03:33 +00005980 if( pStmt ){
5981 sqlite3 *db = sqlite3_db_handle(pStmt);
5982 int rc = sqlite3_finalize(pStmt);
5983 if( *pRc==SQLITE_OK ){
5984 if( rc!=SQLITE_OK ){
5985 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
5986 }
5987 *pRc = rc;
5988 }
5989 }
danfd0245d2017-12-07 15:44:29 +00005990}
5991
drh9546c762019-05-10 17:50:33 +00005992/* Reset the prepared statement created using shellPreparePrintf().
5993**
5994** This routine is could be marked "static". But it is not always used,
5995** depending on compile-time options. By omitting the "static", we avoid
5996** nuisance compiler warnings about "defined but not used".
5997*/
5998void shellReset(
danfd0245d2017-12-07 15:44:29 +00005999 int *pRc,
6000 sqlite3_stmt *pStmt
6001){
6002 int rc = sqlite3_reset(pStmt);
dan5a78b812017-12-27 18:54:11 +00006003 if( *pRc==SQLITE_OK ){
6004 if( rc!=SQLITE_OK ){
6005 sqlite3 *db = sqlite3_db_handle(pStmt);
6006 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
6007 }
6008 *pRc = rc;
6009 }
danfd0245d2017-12-07 15:44:29 +00006010}
dan1b162162019-04-27 20:15:15 +00006011#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
6012
6013#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drhe2754c12019-08-26 12:50:01 +00006014/******************************************************************************
dan1b162162019-04-27 20:15:15 +00006015** The ".archive" or ".ar" command.
6016*/
drhe37c0e12018-01-06 19:19:50 +00006017/*
dan88be0202017-12-09 17:58:02 +00006018** Structure representing a single ".ar" command.
6019*/
6020typedef struct ArCommand ArCommand;
6021struct ArCommand {
drhb376b3d2018-01-10 13:11:51 +00006022 u8 eCmd; /* An AR_CMD_* value */
6023 u8 bVerbose; /* True if --verbose */
drha5676c42018-01-10 15:17:34 +00006024 u8 bZip; /* True if the archive is a ZIP */
drhb376b3d2018-01-10 13:11:51 +00006025 u8 bDryRun; /* True if --dry-run */
drha5676c42018-01-10 15:17:34 +00006026 u8 bAppend; /* True if --append */
drhd0f9cdc2018-05-17 14:09:06 +00006027 u8 fromCmdLine; /* Run from -A instead of .archive */
drhb376b3d2018-01-10 13:11:51 +00006028 int nArg; /* Number of command arguments */
drha5676c42018-01-10 15:17:34 +00006029 char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
dan88be0202017-12-09 17:58:02 +00006030 const char *zFile; /* --file argument, or NULL */
6031 const char *zDir; /* --directory argument, or NULL */
dan88be0202017-12-09 17:58:02 +00006032 char **azArg; /* Array of command arguments */
drhb376b3d2018-01-10 13:11:51 +00006033 ShellState *p; /* Shell state */
6034 sqlite3 *db; /* Database containing the archive */
dan88be0202017-12-09 17:58:02 +00006035};
6036
6037/*
6038** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
6039*/
dan0d0547f2017-12-14 15:40:42 +00006040static int arUsage(FILE *f){
drh98aa2ab2018-09-26 16:53:51 +00006041 showHelp(f,"archive");
dan0d0547f2017-12-14 15:40:42 +00006042 return SQLITE_ERROR;
6043}
6044
6045/*
6046** Print an error message for the .ar command to stderr and return
6047** SQLITE_ERROR.
6048*/
drhd0f9cdc2018-05-17 14:09:06 +00006049static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
dan0d0547f2017-12-14 15:40:42 +00006050 va_list ap;
6051 char *z;
6052 va_start(ap, zFmt);
6053 z = sqlite3_vmprintf(zFmt, ap);
6054 va_end(ap);
drhd0f9cdc2018-05-17 14:09:06 +00006055 utf8_printf(stderr, "Error: %s\n", z);
6056 if( pAr->fromCmdLine ){
6057 utf8_printf(stderr, "Use \"-A\" for more help\n");
6058 }else{
6059 utf8_printf(stderr, "Use \".archive --help\" for more help\n");
6060 }
dan0d0547f2017-12-14 15:40:42 +00006061 sqlite3_free(z);
dan88be0202017-12-09 17:58:02 +00006062 return SQLITE_ERROR;
6063}
6064
6065/*
6066** Values for ArCommand.eCmd.
6067*/
dand4b56e52017-12-12 20:04:59 +00006068#define AR_CMD_CREATE 1
drhb17ea912019-03-25 14:24:19 +00006069#define AR_CMD_UPDATE 2
6070#define AR_CMD_INSERT 3
6071#define AR_CMD_EXTRACT 4
6072#define AR_CMD_LIST 5
6073#define AR_CMD_HELP 6
dand4b56e52017-12-12 20:04:59 +00006074
6075/*
6076** Other (non-command) switches.
6077*/
drhb17ea912019-03-25 14:24:19 +00006078#define AR_SWITCH_VERBOSE 7
6079#define AR_SWITCH_FILE 8
6080#define AR_SWITCH_DIRECTORY 9
6081#define AR_SWITCH_APPEND 10
6082#define AR_SWITCH_DRYRUN 11
dand4b56e52017-12-12 20:04:59 +00006083
6084static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
6085 switch( eSwitch ){
6086 case AR_CMD_CREATE:
6087 case AR_CMD_EXTRACT:
6088 case AR_CMD_LIST:
6089 case AR_CMD_UPDATE:
drhb17ea912019-03-25 14:24:19 +00006090 case AR_CMD_INSERT:
dan0d0547f2017-12-14 15:40:42 +00006091 case AR_CMD_HELP:
6092 if( pAr->eCmd ){
drhd0f9cdc2018-05-17 14:09:06 +00006093 return arErrorMsg(pAr, "multiple command options");
dan0d0547f2017-12-14 15:40:42 +00006094 }
dand4b56e52017-12-12 20:04:59 +00006095 pAr->eCmd = eSwitch;
6096 break;
6097
drhb376b3d2018-01-10 13:11:51 +00006098 case AR_SWITCH_DRYRUN:
6099 pAr->bDryRun = 1;
6100 break;
dand4b56e52017-12-12 20:04:59 +00006101 case AR_SWITCH_VERBOSE:
6102 pAr->bVerbose = 1;
6103 break;
drha5676c42018-01-10 15:17:34 +00006104 case AR_SWITCH_APPEND:
6105 pAr->bAppend = 1;
drhca7733b2018-01-10 18:09:20 +00006106 /* Fall thru into --file */
dand4b56e52017-12-12 20:04:59 +00006107 case AR_SWITCH_FILE:
6108 pAr->zFile = zArg;
6109 break;
6110 case AR_SWITCH_DIRECTORY:
6111 pAr->zDir = zArg;
6112 break;
6113 }
6114
6115 return SQLITE_OK;
6116}
dan88be0202017-12-09 17:58:02 +00006117
6118/*
6119** Parse the command line for an ".ar" command. The results are written into
6120** structure (*pAr). SQLITE_OK is returned if the command line is parsed
6121** successfully, otherwise an error message is written to stderr and
6122** SQLITE_ERROR returned.
6123*/
6124static int arParseCommand(
6125 char **azArg, /* Array of arguments passed to dot command */
6126 int nArg, /* Number of entries in azArg[] */
6127 ArCommand *pAr /* Populate this object */
6128){
dand4b56e52017-12-12 20:04:59 +00006129 struct ArSwitch {
dand4b56e52017-12-12 20:04:59 +00006130 const char *zLong;
drhb376b3d2018-01-10 13:11:51 +00006131 char cShort;
6132 u8 eSwitch;
6133 u8 bArg;
dand4b56e52017-12-12 20:04:59 +00006134 } aSwitch[] = {
drhb376b3d2018-01-10 13:11:51 +00006135 { "create", 'c', AR_CMD_CREATE, 0 },
6136 { "extract", 'x', AR_CMD_EXTRACT, 0 },
drhb17ea912019-03-25 14:24:19 +00006137 { "insert", 'i', AR_CMD_INSERT, 0 },
drhb376b3d2018-01-10 13:11:51 +00006138 { "list", 't', AR_CMD_LIST, 0 },
6139 { "update", 'u', AR_CMD_UPDATE, 0 },
6140 { "help", 'h', AR_CMD_HELP, 0 },
6141 { "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
6142 { "file", 'f', AR_SWITCH_FILE, 1 },
drhca7733b2018-01-10 18:09:20 +00006143 { "append", 'a', AR_SWITCH_APPEND, 1 },
drhb376b3d2018-01-10 13:11:51 +00006144 { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
drhb376b3d2018-01-10 13:11:51 +00006145 { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
dand4b56e52017-12-12 20:04:59 +00006146 };
6147 int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
6148 struct ArSwitch *pEnd = &aSwitch[nSwitch];
6149
dan88be0202017-12-09 17:58:02 +00006150 if( nArg<=1 ){
drh98aa2ab2018-09-26 16:53:51 +00006151 utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
dan0d0547f2017-12-14 15:40:42 +00006152 return arUsage(stderr);
dan88be0202017-12-09 17:58:02 +00006153 }else{
6154 char *z = azArg[1];
dan88be0202017-12-09 17:58:02 +00006155 if( z[0]!='-' ){
6156 /* Traditional style [tar] invocation */
6157 int i;
6158 int iArg = 2;
6159 for(i=0; z[i]; i++){
dand4b56e52017-12-12 20:04:59 +00006160 const char *zArg = 0;
6161 struct ArSwitch *pOpt;
6162 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6163 if( z[i]==pOpt->cShort ) break;
dan88be0202017-12-09 17:58:02 +00006164 }
dan0d0547f2017-12-14 15:40:42 +00006165 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006166 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006167 }
dand4b56e52017-12-12 20:04:59 +00006168 if( pOpt->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006169 if( iArg>=nArg ){
drhd0f9cdc2018-05-17 14:09:06 +00006170 return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
dan0d0547f2017-12-14 15:40:42 +00006171 }
dand4b56e52017-12-12 20:04:59 +00006172 zArg = azArg[iArg++];
6173 }
6174 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
dan88be0202017-12-09 17:58:02 +00006175 }
dan88be0202017-12-09 17:58:02 +00006176 pAr->nArg = nArg-iArg;
6177 if( pAr->nArg>0 ){
6178 pAr->azArg = &azArg[iArg];
6179 }
dand4b56e52017-12-12 20:04:59 +00006180 }else{
6181 /* Non-traditional invocation */
6182 int iArg;
6183 for(iArg=1; iArg<nArg; iArg++){
6184 int n;
6185 z = azArg[iArg];
6186 if( z[0]!='-' ){
6187 /* All remaining command line words are command arguments. */
6188 pAr->azArg = &azArg[iArg];
6189 pAr->nArg = nArg-iArg;
6190 break;
6191 }
drhaf2770f2018-01-05 14:55:43 +00006192 n = strlen30(z);
dand4b56e52017-12-12 20:04:59 +00006193
6194 if( z[1]!='-' ){
6195 int i;
6196 /* One or more short options */
6197 for(i=1; i<n; i++){
6198 const char *zArg = 0;
6199 struct ArSwitch *pOpt;
6200 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6201 if( z[i]==pOpt->cShort ) break;
6202 }
dan0d0547f2017-12-14 15:40:42 +00006203 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006204 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006205 }
dand4b56e52017-12-12 20:04:59 +00006206 if( pOpt->bArg ){
6207 if( i<(n-1) ){
6208 zArg = &z[i+1];
6209 i = n;
6210 }else{
dan0d0547f2017-12-14 15:40:42 +00006211 if( iArg>=(nArg-1) ){
drhe2754c12019-08-26 12:50:01 +00006212 return arErrorMsg(pAr, "option requires an argument: %c",
6213 z[i]);
dan0d0547f2017-12-14 15:40:42 +00006214 }
dand4b56e52017-12-12 20:04:59 +00006215 zArg = azArg[++iArg];
6216 }
6217 }
6218 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
6219 }
6220 }else if( z[2]=='\0' ){
6221 /* A -- option, indicating that all remaining command line words
6222 ** are command arguments. */
6223 pAr->azArg = &azArg[iArg+1];
6224 pAr->nArg = nArg-iArg-1;
6225 break;
6226 }else{
6227 /* A long option */
6228 const char *zArg = 0; /* Argument for option, if any */
6229 struct ArSwitch *pMatch = 0; /* Matching option */
6230 struct ArSwitch *pOpt; /* Iterator */
6231 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6232 const char *zLong = pOpt->zLong;
drhaf2770f2018-01-05 14:55:43 +00006233 if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
dand4b56e52017-12-12 20:04:59 +00006234 if( pMatch ){
drhd0f9cdc2018-05-17 14:09:06 +00006235 return arErrorMsg(pAr, "ambiguous option: %s",z);
dand4b56e52017-12-12 20:04:59 +00006236 }else{
6237 pMatch = pOpt;
6238 }
6239 }
6240 }
6241
6242 if( pMatch==0 ){
drhd0f9cdc2018-05-17 14:09:06 +00006243 return arErrorMsg(pAr, "unrecognized option: %s", z);
dand4b56e52017-12-12 20:04:59 +00006244 }
6245 if( pMatch->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006246 if( iArg>=(nArg-1) ){
drhd0f9cdc2018-05-17 14:09:06 +00006247 return arErrorMsg(pAr, "option requires an argument: %s", z);
dan0d0547f2017-12-14 15:40:42 +00006248 }
dand4b56e52017-12-12 20:04:59 +00006249 zArg = azArg[++iArg];
6250 }
6251 if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
6252 }
6253 }
dan88be0202017-12-09 17:58:02 +00006254 }
6255 }
6256
6257 return SQLITE_OK;
6258}
6259
6260/*
dan3f67ddf2017-12-13 20:04:53 +00006261** This function assumes that all arguments within the ArCommand.azArg[]
6262** array refer to archive members, as for the --extract or --list commands.
6263** It checks that each of them are present. If any specified file is not
6264** present in the archive, an error is printed to stderr and an error
6265** code returned. Otherwise, if all specified arguments are present in
6266** the archive, SQLITE_OK is returned.
6267**
6268** This function strips any trailing '/' characters from each argument.
6269** This is consistent with the way the [tar] command seems to work on
6270** Linux.
6271*/
drhb376b3d2018-01-10 13:11:51 +00006272static int arCheckEntries(ArCommand *pAr){
dan3f67ddf2017-12-13 20:04:53 +00006273 int rc = SQLITE_OK;
6274 if( pAr->nArg ){
drhb376b3d2018-01-10 13:11:51 +00006275 int i, j;
dan3f67ddf2017-12-13 20:04:53 +00006276 sqlite3_stmt *pTest = 0;
6277
drhb376b3d2018-01-10 13:11:51 +00006278 shellPreparePrintf(pAr->db, &rc, &pTest,
6279 "SELECT name FROM %s WHERE name=$name",
6280 pAr->zSrcTable
dan5a78b812017-12-27 18:54:11 +00006281 );
drhb376b3d2018-01-10 13:11:51 +00006282 j = sqlite3_bind_parameter_index(pTest, "$name");
dan3f67ddf2017-12-13 20:04:53 +00006283 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
6284 char *z = pAr->azArg[i];
drhaf2770f2018-01-05 14:55:43 +00006285 int n = strlen30(z);
dan3f67ddf2017-12-13 20:04:53 +00006286 int bOk = 0;
6287 while( n>0 && z[n-1]=='/' ) n--;
6288 z[n] = '\0';
drhb376b3d2018-01-10 13:11:51 +00006289 sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
dan3f67ddf2017-12-13 20:04:53 +00006290 if( SQLITE_ROW==sqlite3_step(pTest) ){
6291 bOk = 1;
6292 }
6293 shellReset(&rc, pTest);
6294 if( rc==SQLITE_OK && bOk==0 ){
drhb376b3d2018-01-10 13:11:51 +00006295 utf8_printf(stderr, "not found in archive: %s\n", z);
dan3f67ddf2017-12-13 20:04:53 +00006296 rc = SQLITE_ERROR;
6297 }
6298 }
6299 shellFinalize(&rc, pTest);
6300 }
dan3f67ddf2017-12-13 20:04:53 +00006301 return rc;
6302}
6303
6304/*
6305** Format a WHERE clause that can be used against the "sqlar" table to
6306** identify all archive members that match the command arguments held
6307** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
6308** The caller is responsible for eventually calling sqlite3_free() on
6309** any non-NULL (*pzWhere) value.
6310*/
6311static void arWhereClause(
6312 int *pRc,
6313 ArCommand *pAr,
danac15e2d2017-12-14 19:15:07 +00006314 char **pzWhere /* OUT: New WHERE clause */
dan3f67ddf2017-12-13 20:04:53 +00006315){
6316 char *zWhere = 0;
6317 if( *pRc==SQLITE_OK ){
danac15e2d2017-12-14 19:15:07 +00006318 if( pAr->nArg==0 ){
6319 zWhere = sqlite3_mprintf("1");
6320 }else{
6321 int i;
6322 const char *zSep = "";
6323 for(i=0; i<pAr->nArg; i++){
6324 const char *z = pAr->azArg[i];
6325 zWhere = sqlite3_mprintf(
drhb376b3d2018-01-10 13:11:51 +00006326 "%z%s name = '%q' OR substr(name,1,%d) = '%q/'",
6327 zWhere, zSep, z, strlen30(z)+1, z
6328 );
danac15e2d2017-12-14 19:15:07 +00006329 if( zWhere==0 ){
6330 *pRc = SQLITE_NOMEM;
6331 break;
6332 }
6333 zSep = " OR ";
dan3f67ddf2017-12-13 20:04:53 +00006334 }
dan3f67ddf2017-12-13 20:04:53 +00006335 }
6336 }
6337 *pzWhere = zWhere;
6338}
6339
6340/*
dan88be0202017-12-09 17:58:02 +00006341** Implementation of .ar "lisT" command.
6342*/
drhb376b3d2018-01-10 13:11:51 +00006343static int arListCommand(ArCommand *pAr){
danb5090e42017-12-27 21:13:21 +00006344 const char *zSql = "SELECT %s FROM %s WHERE %s";
danb5090e42017-12-27 21:13:21 +00006345 const char *azCols[] = {
6346 "name",
drh410cad92018-01-10 17:19:16 +00006347 "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
danb5090e42017-12-27 21:13:21 +00006348 };
dan5a78b812017-12-27 18:54:11 +00006349
dan3f67ddf2017-12-13 20:04:53 +00006350 char *zWhere = 0;
6351 sqlite3_stmt *pSql = 0;
6352 int rc;
6353
drhb376b3d2018-01-10 13:11:51 +00006354 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006355 arWhereClause(&rc, pAr, &zWhere);
6356
drhb376b3d2018-01-10 13:11:51 +00006357 shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
6358 pAr->zSrcTable, zWhere);
drhb376b3d2018-01-10 13:11:51 +00006359 if( pAr->bDryRun ){
6360 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
6361 }else{
6362 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
6363 if( pAr->bVerbose ){
drh410cad92018-01-10 17:19:16 +00006364 utf8_printf(pAr->p->out, "%s % 10d %s %s\n",
6365 sqlite3_column_text(pSql, 0),
drhb376b3d2018-01-10 13:11:51 +00006366 sqlite3_column_int(pSql, 1),
6367 sqlite3_column_text(pSql, 2),
6368 sqlite3_column_text(pSql, 3)
6369 );
6370 }else{
6371 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
6372 }
danb5090e42017-12-27 21:13:21 +00006373 }
dan3f67ddf2017-12-13 20:04:53 +00006374 }
dan5a78b812017-12-27 18:54:11 +00006375 shellFinalize(&rc, pSql);
drhd0f9cdc2018-05-17 14:09:06 +00006376 sqlite3_free(zWhere);
dan3f67ddf2017-12-13 20:04:53 +00006377 return rc;
dan88be0202017-12-09 17:58:02 +00006378}
6379
6380
danfd0245d2017-12-07 15:44:29 +00006381/*
6382** Implementation of .ar "eXtract" command.
6383*/
drhb376b3d2018-01-10 13:11:51 +00006384static int arExtractCommand(ArCommand *pAr){
dan25c12182017-12-07 21:03:33 +00006385 const char *zSql1 =
dand1b51d42017-12-16 19:11:26 +00006386 "SELECT "
drhb376b3d2018-01-10 13:11:51 +00006387 " ($dir || name),"
6388 " writefile(($dir || name), %s, mode, mtime) "
drh0cfd46a2018-06-06 01:18:01 +00006389 "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
6390 " AND name NOT GLOB '*..[/\\]*'";
dan5a78b812017-12-27 18:54:11 +00006391
6392 const char *azExtraArg[] = {
6393 "sqlar_uncompress(data, sz)",
dan7c15ac12018-01-08 19:59:59 +00006394 "data"
dan5a78b812017-12-27 18:54:11 +00006395 };
dan5a78b812017-12-27 18:54:11 +00006396
danfd0245d2017-12-07 15:44:29 +00006397 sqlite3_stmt *pSql = 0;
6398 int rc = SQLITE_OK;
dan2ad09492017-12-09 18:28:22 +00006399 char *zDir = 0;
dan3f67ddf2017-12-13 20:04:53 +00006400 char *zWhere = 0;
drhb376b3d2018-01-10 13:11:51 +00006401 int i, j;
dan2ad09492017-12-09 18:28:22 +00006402
dan3f67ddf2017-12-13 20:04:53 +00006403 /* If arguments are specified, check that they actually exist within
6404 ** the archive before proceeding. And formulate a WHERE clause to
6405 ** match them. */
drhb376b3d2018-01-10 13:11:51 +00006406 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006407 arWhereClause(&rc, pAr, &zWhere);
6408
6409 if( rc==SQLITE_OK ){
6410 if( pAr->zDir ){
6411 zDir = sqlite3_mprintf("%s/", pAr->zDir);
6412 }else{
6413 zDir = sqlite3_mprintf("");
6414 }
6415 if( zDir==0 ) rc = SQLITE_NOMEM;
dan2ad09492017-12-09 18:28:22 +00006416 }
danfd0245d2017-12-07 15:44:29 +00006417
drhb376b3d2018-01-10 13:11:51 +00006418 shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
6419 azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
dan5a78b812017-12-27 18:54:11 +00006420 );
6421
dan2ad09492017-12-09 18:28:22 +00006422 if( rc==SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00006423 j = sqlite3_bind_parameter_index(pSql, "$dir");
6424 sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
dan25c12182017-12-07 21:03:33 +00006425
danac15e2d2017-12-14 19:15:07 +00006426 /* Run the SELECT statement twice. The first time, writefile() is called
6427 ** for all archive members that should be extracted. The second time,
6428 ** only for the directories. This is because the timestamps for
6429 ** extracted directories must be reset after they are populated (as
6430 ** populating them changes the timestamp). */
6431 for(i=0; i<2; i++){
drhb376b3d2018-01-10 13:11:51 +00006432 j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
6433 sqlite3_bind_int(pSql, j, i);
6434 if( pAr->bDryRun ){
6435 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
6436 }else{
6437 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
6438 if( i==0 && pAr->bVerbose ){
6439 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
6440 }
danac15e2d2017-12-14 19:15:07 +00006441 }
6442 }
6443 shellReset(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00006444 }
danac15e2d2017-12-14 19:15:07 +00006445 shellFinalize(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00006446 }
dan25c12182017-12-07 21:03:33 +00006447
dan2ad09492017-12-09 18:28:22 +00006448 sqlite3_free(zDir);
dan3f67ddf2017-12-13 20:04:53 +00006449 sqlite3_free(zWhere);
danfd0245d2017-12-07 15:44:29 +00006450 return rc;
6451}
6452
drhb376b3d2018-01-10 13:11:51 +00006453/*
6454** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out.
6455*/
6456static int arExecSql(ArCommand *pAr, const char *zSql){
6457 int rc;
6458 if( pAr->bDryRun ){
6459 utf8_printf(pAr->p->out, "%s\n", zSql);
6460 rc = SQLITE_OK;
6461 }else{
drh410cad92018-01-10 17:19:16 +00006462 char *zErr = 0;
6463 rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
6464 if( zErr ){
6465 utf8_printf(stdout, "ERROR: %s\n", zErr);
6466 sqlite3_free(zErr);
6467 }
drhb376b3d2018-01-10 13:11:51 +00006468 }
6469 return rc;
6470}
6471
dan1ad3f612017-12-11 20:22:02 +00006472
danfd0245d2017-12-07 15:44:29 +00006473/*
drhb17ea912019-03-25 14:24:19 +00006474** Implementation of .ar "create", "insert", and "update" commands.
6475**
6476** create -> Create a new SQL archive
6477** insert -> Insert or reinsert all files listed
6478** update -> Insert files that have changed or that were not
6479** previously in the archive
danfd0245d2017-12-07 15:44:29 +00006480**
6481** Create the "sqlar" table in the database if it does not already exist.
6482** Then add each file in the azFile[] array to the archive. Directories
6483** are added recursively. If argument bVerbose is non-zero, a message is
6484** printed on stdout for each file archived.
dan06741a32017-12-13 20:17:18 +00006485**
6486** The create command is the same as update, except that it drops
drhb17ea912019-03-25 14:24:19 +00006487** any existing "sqlar" table before beginning. The "insert" command
6488** always overwrites every file named on the command-line, where as
6489** "update" only overwrites if the size or mtime or mode has changed.
danfd0245d2017-12-07 15:44:29 +00006490*/
drhb376b3d2018-01-10 13:11:51 +00006491static int arCreateOrUpdateCommand(
dan06741a32017-12-13 20:17:18 +00006492 ArCommand *pAr, /* Command arguments and options */
drhb17ea912019-03-25 14:24:19 +00006493 int bUpdate, /* true for a --create. */
6494 int bOnlyIfChanged /* Only update if file has changed */
danfd0245d2017-12-07 15:44:29 +00006495){
dand4b56e52017-12-12 20:04:59 +00006496 const char *zCreate =
drhafba1802018-01-06 15:49:57 +00006497 "CREATE TABLE IF NOT EXISTS sqlar(\n"
6498 " name TEXT PRIMARY KEY, -- name of the file\n"
6499 " mode INT, -- access permissions\n"
6500 " mtime INT, -- last modification time\n"
6501 " sz INT, -- original file size\n"
6502 " data BLOB -- compressed content\n"
6503 ")";
dand4b56e52017-12-12 20:04:59 +00006504 const char *zDrop = "DROP TABLE IF EXISTS sqlar";
drh1bf208c2018-03-09 21:54:01 +00006505 const char *zInsertFmt[2] = {
6506 "REPLACE INTO %s(name,mode,mtime,sz,data)\n"
drh634c70f2018-01-10 16:50:18 +00006507 " SELECT\n"
6508 " %s,\n"
6509 " mode,\n"
6510 " mtime,\n"
drh410cad92018-01-10 17:19:16 +00006511 " CASE substr(lsmode(mode),1,1)\n"
6512 " WHEN '-' THEN length(data)\n"
6513 " WHEN 'd' THEN 0\n"
drh634c70f2018-01-10 16:50:18 +00006514 " ELSE -1 END,\n"
drh69d2d352018-03-09 22:18:53 +00006515 " sqlar_compress(data)\n"
drhb17ea912019-03-25 14:24:19 +00006516 " FROM fsdir(%Q,%Q) AS disk\n"
6517 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
6518 ,
drh1bf208c2018-03-09 21:54:01 +00006519 "REPLACE INTO %s(name,mode,mtime,data)\n"
6520 " SELECT\n"
6521 " %s,\n"
6522 " mode,\n"
6523 " mtime,\n"
6524 " data\n"
drhb17ea912019-03-25 14:24:19 +00006525 " FROM fsdir(%Q,%Q) AS disk\n"
6526 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
drh1bf208c2018-03-09 21:54:01 +00006527 };
danfd0245d2017-12-07 15:44:29 +00006528 int i; /* For iterating through azFile[] */
6529 int rc; /* Return code */
drh1bf208c2018-03-09 21:54:01 +00006530 const char *zTab = 0; /* SQL table into which to insert */
6531 char *zSql;
6532 char zTemp[50];
drhb17ea912019-03-25 14:24:19 +00006533 char *zExists = 0;
danfd0245d2017-12-07 15:44:29 +00006534
drh1bf208c2018-03-09 21:54:01 +00006535 arExecSql(pAr, "PRAGMA page_size=512");
drhb376b3d2018-01-10 13:11:51 +00006536 rc = arExecSql(pAr, "SAVEPOINT ar;");
danfd0245d2017-12-07 15:44:29 +00006537 if( rc!=SQLITE_OK ) return rc;
drh1bf208c2018-03-09 21:54:01 +00006538 zTemp[0] = 0;
6539 if( pAr->bZip ){
6540 /* Initialize the zipfile virtual table, if necessary */
6541 if( pAr->zFile ){
6542 sqlite3_uint64 r;
6543 sqlite3_randomness(sizeof(r),&r);
6544 sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
6545 zTab = zTemp;
6546 zSql = sqlite3_mprintf(
6547 "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)",
6548 zTab, pAr->zFile
6549 );
6550 rc = arExecSql(pAr, zSql);
6551 sqlite3_free(zSql);
6552 }else{
6553 zTab = "zip";
6554 }
6555 }else{
6556 /* Initialize the table for an SQLAR */
6557 zTab = "sqlar";
6558 if( bUpdate==0 ){
6559 rc = arExecSql(pAr, zDrop);
6560 if( rc!=SQLITE_OK ) goto end_ar_transaction;
6561 }
6562 rc = arExecSql(pAr, zCreate);
dan06741a32017-12-13 20:17:18 +00006563 }
drhb17ea912019-03-25 14:24:19 +00006564 if( bOnlyIfChanged ){
6565 zExists = sqlite3_mprintf(
6566 " AND NOT EXISTS("
6567 "SELECT 1 FROM %s AS mem"
6568 " WHERE mem.name=disk.name"
6569 " AND mem.mtime=disk.mtime"
6570 " AND mem.mode=disk.mode)", zTab);
6571 }else{
6572 zExists = sqlite3_mprintf("");
6573 }
6574 if( zExists==0 ) rc = SQLITE_NOMEM;
dan88be0202017-12-09 17:58:02 +00006575 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
mistachkince2052b2018-03-23 00:31:53 +00006576 char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
drh634c70f2018-01-10 16:50:18 +00006577 pAr->bVerbose ? "shell_putsnl(name)" : "name",
drhb17ea912019-03-25 14:24:19 +00006578 pAr->azArg[i], pAr->zDir, zExists);
mistachkince2052b2018-03-23 00:31:53 +00006579 rc = arExecSql(pAr, zSql2);
6580 sqlite3_free(zSql2);
danfd0245d2017-12-07 15:44:29 +00006581 }
drh1bf208c2018-03-09 21:54:01 +00006582end_ar_transaction:
danfd0245d2017-12-07 15:44:29 +00006583 if( rc!=SQLITE_OK ){
drh2bd207f2019-01-11 17:19:59 +00006584 sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
danfd0245d2017-12-07 15:44:29 +00006585 }else{
drhb376b3d2018-01-10 13:11:51 +00006586 rc = arExecSql(pAr, "RELEASE ar;");
drh1bf208c2018-03-09 21:54:01 +00006587 if( pAr->bZip && pAr->zFile ){
6588 zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
6589 arExecSql(pAr, zSql);
6590 sqlite3_free(zSql);
6591 }
danfd0245d2017-12-07 15:44:29 +00006592 }
drhb17ea912019-03-25 14:24:19 +00006593 sqlite3_free(zExists);
danfd0245d2017-12-07 15:44:29 +00006594 return rc;
6595}
6596
6597/*
6598** Implementation of ".ar" dot command.
6599*/
6600static int arDotCommand(
drhe2754c12019-08-26 12:50:01 +00006601 ShellState *pState, /* Current shell tool state */
6602 int fromCmdLine, /* True if -A command-line option, not .ar cmd */
6603 char **azArg, /* Array of arguments passed to dot command */
6604 int nArg /* Number of entries in azArg[] */
danfd0245d2017-12-07 15:44:29 +00006605){
dan88be0202017-12-09 17:58:02 +00006606 ArCommand cmd;
6607 int rc;
drh34660642018-01-10 17:39:54 +00006608 memset(&cmd, 0, sizeof(cmd));
drhd0f9cdc2018-05-17 14:09:06 +00006609 cmd.fromCmdLine = fromCmdLine;
dan88be0202017-12-09 17:58:02 +00006610 rc = arParseCommand(azArg, nArg, &cmd);
6611 if( rc==SQLITE_OK ){
drha5676c42018-01-10 15:17:34 +00006612 int eDbType = SHELL_OPEN_UNSPEC;
drhb376b3d2018-01-10 13:11:51 +00006613 cmd.p = pState;
6614 cmd.db = pState->db;
drha5676c42018-01-10 15:17:34 +00006615 if( cmd.zFile ){
drh1bf208c2018-03-09 21:54:01 +00006616 eDbType = deduceDatabaseType(cmd.zFile, 1);
drha5676c42018-01-10 15:17:34 +00006617 }else{
6618 eDbType = pState->openMode;
6619 }
6620 if( eDbType==SHELL_OPEN_ZIPFILE ){
drh1bf208c2018-03-09 21:54:01 +00006621 if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){
6622 if( cmd.zFile==0 ){
6623 cmd.zSrcTable = sqlite3_mprintf("zip");
6624 }else{
6625 cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
6626 }
dan5a78b812017-12-27 18:54:11 +00006627 }
drha5676c42018-01-10 15:17:34 +00006628 cmd.bZip = 1;
dan5a78b812017-12-27 18:54:11 +00006629 }else if( cmd.zFile ){
dand4b56e52017-12-12 20:04:59 +00006630 int flags;
drha5676c42018-01-10 15:17:34 +00006631 if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
drhb17ea912019-03-25 14:24:19 +00006632 if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
6633 || cmd.eCmd==AR_CMD_UPDATE ){
dand4b56e52017-12-12 20:04:59 +00006634 flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
6635 }else{
6636 flags = SQLITE_OPEN_READONLY;
6637 }
drha82c95b2018-01-10 14:00:00 +00006638 cmd.db = 0;
drha5676c42018-01-10 15:17:34 +00006639 if( cmd.bDryRun ){
6640 utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
6641 eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
6642 }
6643 rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
6644 eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
dand4b56e52017-12-12 20:04:59 +00006645 if( rc!=SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00006646 utf8_printf(stderr, "cannot open file: %s (%s)\n",
6647 cmd.zFile, sqlite3_errmsg(cmd.db)
dand4b56e52017-12-12 20:04:59 +00006648 );
drha5676c42018-01-10 15:17:34 +00006649 goto end_ar_command;
dand4b56e52017-12-12 20:04:59 +00006650 }
drhb376b3d2018-01-10 13:11:51 +00006651 sqlite3_fileio_init(cmd.db, 0, 0);
drhb376b3d2018-01-10 13:11:51 +00006652 sqlite3_sqlar_init(cmd.db, 0, 0);
drh34660642018-01-10 17:39:54 +00006653 sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
6654 shellPutsFunc, 0, 0);
6655
dand4b56e52017-12-12 20:04:59 +00006656 }
drhd0f9cdc2018-05-17 14:09:06 +00006657 if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
drh634c70f2018-01-10 16:50:18 +00006658 if( cmd.eCmd!=AR_CMD_CREATE
6659 && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
6660 ){
drha5676c42018-01-10 15:17:34 +00006661 utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
6662 rc = SQLITE_ERROR;
6663 goto end_ar_command;
6664 }
6665 cmd.zSrcTable = sqlite3_mprintf("sqlar");
6666 }
dand4b56e52017-12-12 20:04:59 +00006667
dan88be0202017-12-09 17:58:02 +00006668 switch( cmd.eCmd ){
6669 case AR_CMD_CREATE:
drhb17ea912019-03-25 14:24:19 +00006670 rc = arCreateOrUpdateCommand(&cmd, 0, 0);
dan88be0202017-12-09 17:58:02 +00006671 break;
danfd0245d2017-12-07 15:44:29 +00006672
dan88be0202017-12-09 17:58:02 +00006673 case AR_CMD_EXTRACT:
drhb376b3d2018-01-10 13:11:51 +00006674 rc = arExtractCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00006675 break;
6676
6677 case AR_CMD_LIST:
drhb376b3d2018-01-10 13:11:51 +00006678 rc = arListCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00006679 break;
6680
dan0d0547f2017-12-14 15:40:42 +00006681 case AR_CMD_HELP:
6682 arUsage(pState->out);
6683 break;
6684
drhb17ea912019-03-25 14:24:19 +00006685 case AR_CMD_INSERT:
6686 rc = arCreateOrUpdateCommand(&cmd, 1, 0);
6687 break;
6688
dan88be0202017-12-09 17:58:02 +00006689 default:
6690 assert( cmd.eCmd==AR_CMD_UPDATE );
drhb17ea912019-03-25 14:24:19 +00006691 rc = arCreateOrUpdateCommand(&cmd, 1, 1);
dan88be0202017-12-09 17:58:02 +00006692 break;
danfd0245d2017-12-07 15:44:29 +00006693 }
6694 }
drha5676c42018-01-10 15:17:34 +00006695end_ar_command:
6696 if( cmd.db!=pState->db ){
drh9e804032018-05-18 17:11:50 +00006697 close_db(cmd.db);
drha5676c42018-01-10 15:17:34 +00006698 }
6699 sqlite3_free(cmd.zSrcTable);
danfd0245d2017-12-07 15:44:29 +00006700
dan88be0202017-12-09 17:58:02 +00006701 return rc;
danfd0245d2017-12-07 15:44:29 +00006702}
drhe37c0e12018-01-06 19:19:50 +00006703/* End of the ".archive" or ".ar" command logic
drhe2754c12019-08-26 12:50:01 +00006704*******************************************************************************/
drhe37c0e12018-01-06 19:19:50 +00006705#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
danfd0245d2017-12-07 15:44:29 +00006706
dan1b162162019-04-27 20:15:15 +00006707#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan42ebb012019-04-27 18:47:03 +00006708/*
6709** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
6710** Otherwise, the SQL statement or statements in zSql are executed using
6711** database connection db and the error code written to *pRc before
6712** this function returns.
6713*/
dan68cb86e2019-04-20 20:57:28 +00006714static void shellExec(sqlite3 *db, int *pRc, const char *zSql){
6715 int rc = *pRc;
6716 if( rc==SQLITE_OK ){
6717 char *zErr = 0;
6718 rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
6719 if( rc!=SQLITE_OK ){
6720 raw_printf(stderr, "SQL error: %s\n", zErr);
6721 }
drhf83d5012021-05-03 13:35:00 +00006722 sqlite3_free(zErr);
dan68cb86e2019-04-20 20:57:28 +00006723 *pRc = rc;
6724 }
6725}
6726
dan42ebb012019-04-27 18:47:03 +00006727/*
6728** Like shellExec(), except that zFmt is a printf() style format string.
6729*/
danc0b42432019-04-26 15:14:53 +00006730static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){
6731 char *z = 0;
6732 if( *pRc==SQLITE_OK ){
6733 va_list ap;
6734 va_start(ap, zFmt);
6735 z = sqlite3_vmprintf(zFmt, ap);
6736 va_end(ap);
6737 if( z==0 ){
6738 *pRc = SQLITE_NOMEM;
6739 }else{
6740 shellExec(db, pRc, z);
6741 }
6742 sqlite3_free(z);
6743 }
6744}
6745
dan42ebb012019-04-27 18:47:03 +00006746/*
6747** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
6748** Otherwise, an attempt is made to allocate, zero and return a pointer
6749** to a buffer nByte bytes in size. If an OOM error occurs, *pRc is set
6750** to SQLITE_NOMEM and NULL returned.
6751*/
dan68cb86e2019-04-20 20:57:28 +00006752static void *shellMalloc(int *pRc, sqlite3_int64 nByte){
6753 void *pRet = 0;
6754 if( *pRc==SQLITE_OK ){
6755 pRet = sqlite3_malloc64(nByte);
6756 if( pRet==0 ){
6757 *pRc = SQLITE_NOMEM;
6758 }else{
6759 memset(pRet, 0, nByte);
6760 }
6761 }
6762 return pRet;
6763}
6764
dan42ebb012019-04-27 18:47:03 +00006765/*
6766** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
6767** Otherwise, zFmt is treated as a printf() style string. The result of
6768** formatting it along with any trailing arguments is written into a
6769** buffer obtained from sqlite3_malloc(), and pointer to which is returned.
6770** It is the responsibility of the caller to eventually free this buffer
6771** using a call to sqlite3_free().
6772**
6773** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL
6774** pointer returned.
6775*/
dan68cb86e2019-04-20 20:57:28 +00006776static char *shellMPrintf(int *pRc, const char *zFmt, ...){
6777 char *z = 0;
6778 if( *pRc==SQLITE_OK ){
6779 va_list ap;
6780 va_start(ap, zFmt);
6781 z = sqlite3_vmprintf(zFmt, ap);
6782 va_end(ap);
6783 if( z==0 ){
6784 *pRc = SQLITE_NOMEM;
6785 }
6786 }
6787 return z;
6788}
6789
dan42ebb012019-04-27 18:47:03 +00006790/*
6791** When running the ".recover" command, each output table, and the special
6792** orphaned row table if it is required, is represented by an instance
6793** of the following struct.
6794*/
dan68cb86e2019-04-20 20:57:28 +00006795typedef struct RecoverTable RecoverTable;
6796struct RecoverTable {
dan42ebb012019-04-27 18:47:03 +00006797 char *zQuoted; /* Quoted version of table name */
dan68cb86e2019-04-20 20:57:28 +00006798 int nCol; /* Number of columns in table */
6799 char **azlCol; /* Array of column lists */
dan42ebb012019-04-27 18:47:03 +00006800 int iPk; /* Index of IPK column */
dan68cb86e2019-04-20 20:57:28 +00006801};
6802
6803/*
dan42ebb012019-04-27 18:47:03 +00006804** Free a RecoverTable object allocated by recoverFindTable() or
6805** recoverOrphanTable().
dan68cb86e2019-04-20 20:57:28 +00006806*/
6807static void recoverFreeTable(RecoverTable *pTab){
6808 if( pTab ){
dan68cb86e2019-04-20 20:57:28 +00006809 sqlite3_free(pTab->zQuoted);
dan68cb86e2019-04-20 20:57:28 +00006810 if( pTab->azlCol ){
6811 int i;
dan98c5ad32019-04-26 21:11:37 +00006812 for(i=0; i<=pTab->nCol; i++){
dan68cb86e2019-04-20 20:57:28 +00006813 sqlite3_free(pTab->azlCol[i]);
6814 }
6815 sqlite3_free(pTab->azlCol);
6816 }
6817 sqlite3_free(pTab);
6818 }
6819}
6820
dan42ebb012019-04-27 18:47:03 +00006821/*
6822** This function is a no-op if (*pRc) is not SQLITE_OK when it is called.
6823** Otherwise, it allocates and returns a RecoverTable object based on the
6824** final four arguments passed to this function. It is the responsibility
6825** of the caller to eventually free the returned object using
6826** recoverFreeTable().
6827*/
6828static RecoverTable *recoverNewTable(
danb40af492019-04-22 20:52:12 +00006829 int *pRc, /* IN/OUT: Error code */
danb40af492019-04-22 20:52:12 +00006830 const char *zName, /* Name of table */
6831 const char *zSql, /* CREATE TABLE statement */
6832 int bIntkey,
6833 int nCol
6834){
6835 sqlite3 *dbtmp = 0; /* sqlite3 handle for testing CREATE TABLE */
6836 int rc = *pRc;
dan98c5ad32019-04-26 21:11:37 +00006837 RecoverTable *pTab = 0;
danb40af492019-04-22 20:52:12 +00006838
dan98c5ad32019-04-26 21:11:37 +00006839 pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable));
danb40af492019-04-22 20:52:12 +00006840 if( rc==SQLITE_OK ){
6841 int nSqlCol = 0;
6842 int bSqlIntkey = 0;
6843 sqlite3_stmt *pStmt = 0;
dan98c5ad32019-04-26 21:11:37 +00006844
danb40af492019-04-22 20:52:12 +00006845 rc = sqlite3_open("", &dbtmp);
6846 if( rc==SQLITE_OK ){
drha2de66c2019-08-06 20:26:17 +00006847 sqlite3_create_function(dbtmp, "shell_idquote", 1, SQLITE_UTF8, 0,
6848 shellIdQuote, 0, 0);
6849 }
6850 if( rc==SQLITE_OK ){
dan38f9c712019-04-23 18:03:02 +00006851 rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
6852 }
6853 if( rc==SQLITE_OK ){
danb40af492019-04-22 20:52:12 +00006854 rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0);
6855 if( rc==SQLITE_ERROR ){
6856 rc = SQLITE_OK;
6857 goto finished;
6858 }
6859 }
6860 shellPreparePrintf(dbtmp, &rc, &pStmt,
6861 "SELECT count(*) FROM pragma_table_info(%Q)", zName
6862 );
6863 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
6864 nSqlCol = sqlite3_column_int(pStmt, 0);
6865 }
6866 shellFinalize(&rc, pStmt);
6867
6868 if( rc!=SQLITE_OK || nSqlCol<nCol ){
6869 goto finished;
6870 }
6871
6872 shellPreparePrintf(dbtmp, &rc, &pStmt,
6873 "SELECT ("
6874 " SELECT substr(data,1,1)==X'0D' FROM sqlite_dbpage WHERE pgno=rootpage"
drh067b92b2020-06-19 15:24:12 +00006875 ") FROM sqlite_schema WHERE name = %Q", zName
danb40af492019-04-22 20:52:12 +00006876 );
6877 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
6878 bSqlIntkey = sqlite3_column_int(pStmt, 0);
6879 }
6880 shellFinalize(&rc, pStmt);
6881
6882 if( bIntkey==bSqlIntkey ){
dan98c5ad32019-04-26 21:11:37 +00006883 int i;
danb40af492019-04-22 20:52:12 +00006884 const char *zPk = "_rowid_";
6885 sqlite3_stmt *pPkFinder = 0;
6886
danf57bea32019-04-27 15:35:45 +00006887 /* If this is an intkey table and there is an INTEGER PRIMARY KEY,
6888 ** set zPk to the name of the PK column, and pTab->iPk to the index
6889 ** of the column, where columns are 0-numbered from left to right.
6890 ** Or, if this is a WITHOUT ROWID table or if there is no IPK column,
6891 ** leave zPk as "_rowid_" and pTab->iPk at -2. */
dan98c5ad32019-04-26 21:11:37 +00006892 pTab->iPk = -2;
6893 if( bIntkey ){
6894 shellPreparePrintf(dbtmp, &rc, &pPkFinder,
danb40af492019-04-22 20:52:12 +00006895 "SELECT cid, name FROM pragma_table_info(%Q) "
6896 " WHERE pk=1 AND type='integer' COLLATE nocase"
dan98c5ad32019-04-26 21:11:37 +00006897 " AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
6898 , zName, zName
6899 );
6900 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){
6901 pTab->iPk = sqlite3_column_int(pPkFinder, 0);
6902 zPk = (const char*)sqlite3_column_text(pPkFinder, 1);
6903 }
danb40af492019-04-22 20:52:12 +00006904 }
6905
drha2de66c2019-08-06 20:26:17 +00006906 pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName);
dan98c5ad32019-04-26 21:11:37 +00006907 pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
danb40af492019-04-22 20:52:12 +00006908 pTab->nCol = nSqlCol;
6909
dan98c5ad32019-04-26 21:11:37 +00006910 if( bIntkey ){
drha2de66c2019-08-06 20:26:17 +00006911 pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk);
danb40af492019-04-22 20:52:12 +00006912 }else{
dan98c5ad32019-04-26 21:11:37 +00006913 pTab->azlCol[0] = shellMPrintf(&rc, "");
danb40af492019-04-22 20:52:12 +00006914 }
dan98c5ad32019-04-26 21:11:37 +00006915 i = 1;
6916 shellPreparePrintf(dbtmp, &rc, &pStmt,
drha2de66c2019-08-06 20:26:17 +00006917 "SELECT %Q || group_concat(shell_idquote(name), ', ') "
danf57bea32019-04-27 15:35:45 +00006918 " FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
dan98c5ad32019-04-26 21:11:37 +00006919 "FROM pragma_table_info(%Q)",
danf57bea32019-04-27 15:35:45 +00006920 bIntkey ? ", " : "", pTab->iPk,
6921 bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ",
6922 zName
dan98c5ad32019-04-26 21:11:37 +00006923 );
6924 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
6925 const char *zText = (const char*)sqlite3_column_text(pStmt, 0);
6926 pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText);
6927 i++;
6928 }
6929 shellFinalize(&rc, pStmt);
6930
danb40af492019-04-22 20:52:12 +00006931 shellFinalize(&rc, pPkFinder);
6932 }
6933 }
6934
6935 finished:
6936 sqlite3_close(dbtmp);
6937 *pRc = rc;
dan98779652019-05-09 14:15:19 +00006938 if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){
dan98c5ad32019-04-26 21:11:37 +00006939 recoverFreeTable(pTab);
6940 pTab = 0;
6941 }
6942 return pTab;
danb40af492019-04-22 20:52:12 +00006943}
6944
dan0aa01ee2019-04-27 19:36:49 +00006945/*
6946** This function is called to search the schema recovered from the
drh067b92b2020-06-19 15:24:12 +00006947** sqlite_schema table of the (possibly) corrupt database as part
dan0aa01ee2019-04-27 19:36:49 +00006948** of a ".recover" command. Specifically, for a table with root page
6949** iRoot and at least nCol columns. Additionally, if bIntkey is 0, the
6950** table must be a WITHOUT ROWID table, or if non-zero, not one of
6951** those.
6952**
6953** If a table is found, a (RecoverTable*) object is returned. Or, if
6954** no such table is found, but bIntkey is false and iRoot is the
6955** root page of an index in the recovered schema, then (*pbNoop) is
6956** set to true and NULL returned. Or, if there is no such table or
6957** index, NULL is returned and (*pbNoop) set to 0, indicating that
6958** the caller should write data to the orphans table.
6959*/
dan42ebb012019-04-27 18:47:03 +00006960static RecoverTable *recoverFindTable(
dan0aa01ee2019-04-27 19:36:49 +00006961 ShellState *pState, /* Shell state object */
6962 int *pRc, /* IN/OUT: Error code */
6963 int iRoot, /* Root page of table */
6964 int bIntkey, /* True for an intkey table */
6965 int nCol, /* Number of columns in table */
6966 int *pbNoop /* OUT: True if iRoot is root of index */
dan68cb86e2019-04-20 20:57:28 +00006967){
danb40af492019-04-22 20:52:12 +00006968 sqlite3_stmt *pStmt = 0;
dan68cb86e2019-04-20 20:57:28 +00006969 RecoverTable *pRet = 0;
danb40af492019-04-22 20:52:12 +00006970 int bNoop = 0;
6971 const char *zSql = 0;
6972 const char *zName = 0;
dan68cb86e2019-04-20 20:57:28 +00006973
danb40af492019-04-22 20:52:12 +00006974 /* Search the recovered schema for an object with root page iRoot. */
6975 shellPreparePrintf(pState->db, pRc, &pStmt,
6976 "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot
6977 );
6978 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
6979 const char *zType = (const char*)sqlite3_column_text(pStmt, 0);
6980 if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){
6981 bNoop = 1;
6982 break;
6983 }
6984 if( sqlite3_stricmp(zType, "table")==0 ){
6985 zName = (const char*)sqlite3_column_text(pStmt, 1);
6986 zSql = (const char*)sqlite3_column_text(pStmt, 2);
dan42ebb012019-04-27 18:47:03 +00006987 pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol);
danb40af492019-04-22 20:52:12 +00006988 break;
6989 }
6990 }
dan98c5ad32019-04-26 21:11:37 +00006991
danb40af492019-04-22 20:52:12 +00006992 shellFinalize(pRc, pStmt);
dan98c5ad32019-04-26 21:11:37 +00006993 *pbNoop = bNoop;
6994 return pRet;
6995}
danb40af492019-04-22 20:52:12 +00006996
dan0aa01ee2019-04-27 19:36:49 +00006997/*
6998** Return a RecoverTable object representing the orphans table.
6999*/
dan98c5ad32019-04-26 21:11:37 +00007000static RecoverTable *recoverOrphanTable(
dan0aa01ee2019-04-27 19:36:49 +00007001 ShellState *pState, /* Shell state object */
7002 int *pRc, /* IN/OUT: Error code */
7003 const char *zLostAndFound, /* Base name for orphans table */
7004 int nCol /* Number of user data columns */
dan98c5ad32019-04-26 21:11:37 +00007005){
7006 RecoverTable *pTab = 0;
7007 if( nCol>=0 && *pRc==SQLITE_OK ){
7008 int i;
dan42ebb012019-04-27 18:47:03 +00007009
7010 /* This block determines the name of the orphan table. The prefered
7011 ** name is zLostAndFound. But if that clashes with another name
7012 ** in the recovered schema, try zLostAndFound_0, zLostAndFound_1
7013 ** and so on until a non-clashing name is found. */
7014 int iTab = 0;
7015 char *zTab = shellMPrintf(pRc, "%s", zLostAndFound);
7016 sqlite3_stmt *pTest = 0;
7017 shellPrepare(pState->db, pRc,
7018 "SELECT 1 FROM recovery.schema WHERE name=?", &pTest
dan68cb86e2019-04-20 20:57:28 +00007019 );
dan42ebb012019-04-27 18:47:03 +00007020 if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
7021 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){
7022 shellReset(pRc, pTest);
7023 sqlite3_free(zTab);
7024 zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++);
7025 sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
dan68cb86e2019-04-20 20:57:28 +00007026 }
dan42ebb012019-04-27 18:47:03 +00007027 shellFinalize(pRc, pTest);
dan68cb86e2019-04-20 20:57:28 +00007028
dan98c5ad32019-04-26 21:11:37 +00007029 pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
7030 if( pTab ){
drha2de66c2019-08-06 20:26:17 +00007031 pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab);
dan98c5ad32019-04-26 21:11:37 +00007032 pTab->nCol = nCol;
7033 pTab->iPk = -2;
7034 if( nCol>0 ){
7035 pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1));
7036 if( pTab->azlCol ){
7037 pTab->azlCol[nCol] = shellMPrintf(pRc, "");
7038 for(i=nCol-1; i>=0; i--){
7039 pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]);
7040 }
7041 }
danb40af492019-04-22 20:52:12 +00007042 }
dan68cb86e2019-04-20 20:57:28 +00007043
dan42ebb012019-04-27 18:47:03 +00007044 if( *pRc!=SQLITE_OK ){
7045 recoverFreeTable(pTab);
7046 pTab = 0;
7047 }else{
7048 raw_printf(pState->out,
7049 "CREATE TABLE %s(rootpgno INTEGER, "
7050 "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted
7051 );
7052 for(i=0; i<nCol; i++){
7053 raw_printf(pState->out, ", c%d", i);
7054 }
7055 raw_printf(pState->out, ");\n");
7056 }
dan98c5ad32019-04-26 21:11:37 +00007057 }
dan42ebb012019-04-27 18:47:03 +00007058 sqlite3_free(zTab);
dan68cb86e2019-04-20 20:57:28 +00007059 }
dan98c5ad32019-04-26 21:11:37 +00007060 return pTab;
dan68cb86e2019-04-20 20:57:28 +00007061}
7062
7063/*
7064** This function is called to recover data from the database. A script
7065** to construct a new database containing all recovered data is output
7066** on stream pState->out.
7067*/
danb9b71db2019-04-25 16:20:40 +00007068static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
dan68cb86e2019-04-20 20:57:28 +00007069 int rc = SQLITE_OK;
7070 sqlite3_stmt *pLoop = 0; /* Loop through all root pages */
danefa363b2019-04-24 20:48:55 +00007071 sqlite3_stmt *pPages = 0; /* Loop through all pages in a group */
7072 sqlite3_stmt *pCells = 0; /* Loop through all cells in a page */
danc0b42432019-04-26 15:14:53 +00007073 const char *zRecoveryDb = ""; /* Name of "recovery" database */
dan42ebb012019-04-27 18:47:03 +00007074 const char *zLostAndFound = "lost_and_found";
dan9c014f82019-04-25 19:23:15 +00007075 int i;
dan98c5ad32019-04-26 21:11:37 +00007076 int nOrphan = -1;
7077 RecoverTable *pOrphan = 0;
dan9c014f82019-04-25 19:23:15 +00007078
7079 int bFreelist = 1; /* 0 if --freelist-corrupt is specified */
dan8cce6b82019-09-14 16:44:51 +00007080 int bRowids = 1; /* 0 if --no-rowids */
dan9c014f82019-04-25 19:23:15 +00007081 for(i=1; i<nArg; i++){
7082 char *z = azArg[i];
7083 int n;
7084 if( z[0]=='-' && z[1]=='-' ) z++;
drh4245e042019-06-13 13:52:46 +00007085 n = strlen30(z);
dan9c014f82019-04-25 19:23:15 +00007086 if( n<=17 && memcmp("-freelist-corrupt", z, n)==0 ){
7087 bFreelist = 0;
dan42ebb012019-04-27 18:47:03 +00007088 }else
danc0b42432019-04-26 15:14:53 +00007089 if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
7090 i++;
7091 zRecoveryDb = azArg[i];
dan42ebb012019-04-27 18:47:03 +00007092 }else
7093 if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
7094 i++;
7095 zLostAndFound = azArg[i];
dan8cce6b82019-09-14 16:44:51 +00007096 }else
7097 if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
7098 bRowids = 0;
danc0b42432019-04-26 15:14:53 +00007099 }
dan9c014f82019-04-25 19:23:15 +00007100 else{
drhe2754c12019-08-26 12:50:01 +00007101 utf8_printf(stderr, "unexpected option: %s\n", azArg[i]);
7102 showHelp(pState->out, azArg[0]);
dan9c014f82019-04-25 19:23:15 +00007103 return 1;
7104 }
7105 }
dan68cb86e2019-04-20 20:57:28 +00007106
danc0b42432019-04-26 15:14:53 +00007107 shellExecPrintf(pState->db, &rc,
dan68cb86e2019-04-20 20:57:28 +00007108 /* Attach an in-memory database named 'recovery'. Create an indexed
7109 ** cache of the sqlite_dbptr virtual table. */
dan01c08bc2019-07-24 19:20:30 +00007110 "PRAGMA writable_schema = on;"
danc0b42432019-04-26 15:14:53 +00007111 "ATTACH %Q AS recovery;"
7112 "DROP TABLE IF EXISTS recovery.dbptr;"
7113 "DROP TABLE IF EXISTS recovery.freelist;"
7114 "DROP TABLE IF EXISTS recovery.map;"
7115 "DROP TABLE IF EXISTS recovery.schema;"
danc0b42432019-04-26 15:14:53 +00007116 "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb
dan9c014f82019-04-25 19:23:15 +00007117 );
7118
7119 if( bFreelist ){
7120 shellExec(pState->db, &rc,
7121 "WITH trunk(pgno) AS ("
7122 " SELECT shell_int32("
7123 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x "
7124 " WHERE x>0"
7125 " UNION"
7126 " SELECT shell_int32("
7127 " (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x "
7128 " FROM trunk WHERE x>0"
7129 "),"
7130 "freelist(data, n, freepgno) AS ("
danf6099e92019-05-09 16:57:39 +00007131 " SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno "
dan9c014f82019-04-25 19:23:15 +00007132 " FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno"
7133 " UNION ALL"
7134 " SELECT data, n-1, shell_int32(data, 2+n) "
7135 " FROM freelist WHERE n>=0"
7136 ")"
7137 "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;"
7138 );
7139 }
7140
dan95063c22019-07-24 08:15:09 +00007141 /* If this is an auto-vacuum database, add all pointer-map pages to
7142 ** the freelist table. Do this regardless of whether or not
7143 ** --freelist-corrupt was specified. */
7144 shellExec(pState->db, &rc,
7145 "WITH ptrmap(pgno) AS ("
7146 " SELECT 2 WHERE shell_int32("
7147 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 13"
7148 " )"
7149 " UNION ALL "
7150 " SELECT pgno+1+(SELECT page_size FROM pragma_page_size)/5 AS pp "
7151 " FROM ptrmap WHERE pp<=(SELECT page_count FROM pragma_page_count)"
7152 ")"
7153 "REPLACE INTO recovery.freelist SELECT pgno FROM ptrmap"
7154 );
7155
dan9c014f82019-04-25 19:23:15 +00007156 shellExec(pState->db, &rc,
danca424382019-04-26 15:40:27 +00007157 "CREATE TABLE recovery.dbptr("
7158 " pgno, child, PRIMARY KEY(child, pgno)"
7159 ") WITHOUT ROWID;"
7160 "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) "
7161 " SELECT * FROM sqlite_dbptr"
7162 " WHERE pgno NOT IN freelist AND child NOT IN freelist;"
7163
7164 /* Delete any pointer to page 1. This ensures that page 1 is considered
7165 ** a root page, regardless of how corrupt the db is. */
7166 "DELETE FROM recovery.dbptr WHERE child = 1;"
7167
7168 /* Delete all pointers to any pages that have more than one pointer
7169 ** to them. Such pages will be treated as root pages when recovering
7170 ** data. */
7171 "DELETE FROM recovery.dbptr WHERE child IN ("
7172 " SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1"
7173 ");"
7174
dan68cb86e2019-04-20 20:57:28 +00007175 /* Create the "map" table that will (eventually) contain instructions
7176 ** for dealing with each page in the db that contains one or more
7177 ** records. */
danb40af492019-04-22 20:52:12 +00007178 "CREATE TABLE recovery.map("
7179 "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT"
7180 ");"
dan68cb86e2019-04-20 20:57:28 +00007181
7182 /* Populate table [map]. If there are circular loops of pages in the
7183 ** database, the following adds all pages in such a loop to the map
7184 ** as individual root pages. This could be handled better. */
7185 "WITH pages(i, maxlen) AS ("
danb9b71db2019-04-25 16:20:40 +00007186 " SELECT page_count, ("
7187 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count"
dan13b87672019-05-09 11:45:21 +00007188 " ) FROM pragma_page_count WHERE page_count>0"
dan68cb86e2019-04-20 20:57:28 +00007189 " UNION ALL"
danb40af492019-04-22 20:52:12 +00007190 " SELECT i-1, ("
7191 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1"
7192 " ) FROM pages WHERE i>=2"
dan68cb86e2019-04-20 20:57:28 +00007193 ")"
danb40af492019-04-22 20:52:12 +00007194 "INSERT INTO recovery.map(pgno, maxlen, intkey, root) "
7195 " SELECT i, maxlen, NULL, ("
dan68cb86e2019-04-20 20:57:28 +00007196 " WITH p(orig, pgno, parent) AS ("
7197 " SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)"
dan39e04f82019-05-09 18:33:32 +00007198 " UNION "
dan68cb86e2019-04-20 20:57:28 +00007199 " SELECT i, p.parent, "
7200 " (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p"
7201 " )"
7202 " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
7203 ") "
dand790c9a2019-08-26 14:57:58 +00007204 "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;"
danb40af492019-04-22 20:52:12 +00007205 "UPDATE recovery.map AS o SET intkey = ("
7206 " SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
7207 ");"
dan68cb86e2019-04-20 20:57:28 +00007208
7209 /* Extract data from page 1 and any linked pages into table
drh067b92b2020-06-19 15:24:12 +00007210 ** recovery.schema. With the same schema as an sqlite_schema table. */
dan68cb86e2019-04-20 20:57:28 +00007211 "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
7212 "INSERT INTO recovery.schema SELECT "
7213 " max(CASE WHEN field=0 THEN value ELSE NULL END),"
7214 " max(CASE WHEN field=1 THEN value ELSE NULL END),"
7215 " max(CASE WHEN field=2 THEN value ELSE NULL END),"
7216 " max(CASE WHEN field=3 THEN value ELSE NULL END),"
7217 " max(CASE WHEN field=4 THEN value ELSE NULL END)"
7218 "FROM sqlite_dbdata WHERE pgno IN ("
7219 " SELECT pgno FROM recovery.map WHERE root=1"
7220 ")"
7221 "GROUP BY pgno, cell;"
dan98c5ad32019-04-26 21:11:37 +00007222 "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);"
dan68cb86e2019-04-20 20:57:28 +00007223 );
7224
danb40af492019-04-22 20:52:12 +00007225 /* Open a transaction, then print out all non-virtual, non-"sqlite_%"
7226 ** CREATE TABLE statements that extracted from the existing schema. */
7227 if( rc==SQLITE_OK ){
7228 sqlite3_stmt *pStmt = 0;
danf3210572019-08-06 18:40:36 +00007229 /* ".recover" might output content in an order which causes immediate
7230 ** foreign key constraints to be violated. So disable foreign-key
7231 ** constraint enforcement to prevent problems when running the output
7232 ** script. */
7233 raw_printf(pState->out, "PRAGMA foreign_keys=OFF;\n");
danb40af492019-04-22 20:52:12 +00007234 raw_printf(pState->out, "BEGIN;\n");
dan38f9c712019-04-23 18:03:02 +00007235 raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
7236 shellPrepare(pState->db, &rc,
danb40af492019-04-22 20:52:12 +00007237 "SELECT sql FROM recovery.schema "
dan38f9c712019-04-23 18:03:02 +00007238 "WHERE type='table' AND sql LIKE 'create table%'", &pStmt
danb40af492019-04-22 20:52:12 +00007239 );
7240 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7241 const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0);
dan38f9c712019-04-23 18:03:02 +00007242 raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n",
7243 &zCreateTable[12]
7244 );
danb40af492019-04-22 20:52:12 +00007245 }
7246 shellFinalize(&rc, pStmt);
7247 }
7248
dan98c5ad32019-04-26 21:11:37 +00007249 /* Figure out if an orphan table will be required. And if so, how many
7250 ** user columns it should contain */
7251 shellPrepare(pState->db, &rc,
dan98779652019-05-09 14:15:19 +00007252 "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1"
dan98c5ad32019-04-26 21:11:37 +00007253 , &pLoop
7254 );
7255 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
7256 nOrphan = sqlite3_column_int(pLoop, 0);
7257 }
7258 shellFinalize(&rc, pLoop);
7259 pLoop = 0;
dan98c5ad32019-04-26 21:11:37 +00007260
danefa363b2019-04-24 20:48:55 +00007261 shellPrepare(pState->db, &rc,
7262 "SELECT pgno FROM recovery.map WHERE root=?", &pPages
7263 );
dan8cce6b82019-09-14 16:44:51 +00007264
danefa363b2019-04-24 20:48:55 +00007265 shellPrepare(pState->db, &rc,
dan8cce6b82019-09-14 16:44:51 +00007266 "SELECT max(field), group_concat(shell_escape_crnl(quote"
7267 "(case when (? AND field<0) then NULL else value end)"
7268 "), ', ')"
dan9443dbc2019-07-24 20:10:27 +00007269 ", min(field) "
danefa363b2019-04-24 20:48:55 +00007270 "FROM sqlite_dbdata WHERE pgno = ? AND field != ?"
7271 "GROUP BY cell", &pCells
7272 );
7273
dan68cb86e2019-04-20 20:57:28 +00007274 /* Loop through each root page. */
danb40af492019-04-22 20:52:12 +00007275 shellPrepare(pState->db, &rc,
7276 "SELECT root, intkey, max(maxlen) FROM recovery.map"
dan38f9c712019-04-23 18:03:02 +00007277 " WHERE root>1 GROUP BY root, intkey ORDER BY root=("
7278 " SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'"
7279 ")", &pLoop
danb40af492019-04-22 20:52:12 +00007280 );
dan68cb86e2019-04-20 20:57:28 +00007281 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
7282 int iRoot = sqlite3_column_int(pLoop, 0);
danb40af492019-04-22 20:52:12 +00007283 int bIntkey = sqlite3_column_int(pLoop, 1);
7284 int nCol = sqlite3_column_int(pLoop, 2);
dan98c5ad32019-04-26 21:11:37 +00007285 int bNoop = 0;
dan68cb86e2019-04-20 20:57:28 +00007286 RecoverTable *pTab;
7287
dan9443dbc2019-07-24 20:10:27 +00007288 assert( bIntkey==0 || bIntkey==1 );
dan42ebb012019-04-27 18:47:03 +00007289 pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);
dan98c5ad32019-04-26 21:11:37 +00007290 if( bNoop || rc ) continue;
dan98779652019-05-09 14:15:19 +00007291 if( pTab==0 ){
7292 if( pOrphan==0 ){
7293 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
7294 }
7295 pTab = pOrphan;
7296 if( pTab==0 ) break;
7297 }
dan98c5ad32019-04-26 21:11:37 +00007298
drha2de66c2019-08-06 20:26:17 +00007299 if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){
dan98c5ad32019-04-26 21:11:37 +00007300 raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
7301 }
7302 sqlite3_bind_int(pPages, 1, iRoot);
dan8cce6b82019-09-14 16:44:51 +00007303 if( bRowids==0 && pTab->iPk<0 ){
7304 sqlite3_bind_int(pCells, 1, 1);
7305 }else{
7306 sqlite3_bind_int(pCells, 1, 0);
7307 }
7308 sqlite3_bind_int(pCells, 3, pTab->iPk);
dan98c5ad32019-04-26 21:11:37 +00007309
7310 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){
7311 int iPgno = sqlite3_column_int(pPages, 0);
dan8cce6b82019-09-14 16:44:51 +00007312 sqlite3_bind_int(pCells, 2, iPgno);
dan98c5ad32019-04-26 21:11:37 +00007313 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){
7314 int nField = sqlite3_column_int(pCells, 0);
dan9443dbc2019-07-24 20:10:27 +00007315 int iMin = sqlite3_column_int(pCells, 2);
dan98c5ad32019-04-26 21:11:37 +00007316 const char *zVal = (const char*)sqlite3_column_text(pCells, 1);
7317
dan9443dbc2019-07-24 20:10:27 +00007318 RecoverTable *pTab2 = pTab;
7319 if( pTab!=pOrphan && (iMin<0)!=bIntkey ){
7320 if( pOrphan==0 ){
7321 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
7322 }
7323 pTab2 = pOrphan;
7324 if( pTab2==0 ) break;
7325 }
7326
dan98c5ad32019-04-26 21:11:37 +00007327 nField = nField+1;
dan9443dbc2019-07-24 20:10:27 +00007328 if( pTab2==pOrphan ){
dan98c5ad32019-04-26 21:11:37 +00007329 raw_printf(pState->out,
7330 "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",
dan9443dbc2019-07-24 20:10:27 +00007331 pTab2->zQuoted, iRoot, iPgno, nField,
7332 iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField]
dan98c5ad32019-04-26 21:11:37 +00007333 );
7334 }else{
danefa363b2019-04-24 20:48:55 +00007335 raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n",
dan9443dbc2019-07-24 20:10:27 +00007336 pTab2->zQuoted, pTab2->azlCol[nField], zVal
danefa363b2019-04-24 20:48:55 +00007337 );
7338 }
dan68cb86e2019-04-20 20:57:28 +00007339 }
dan98c5ad32019-04-26 21:11:37 +00007340 shellReset(&rc, pCells);
dan68cb86e2019-04-20 20:57:28 +00007341 }
dan98c5ad32019-04-26 21:11:37 +00007342 shellReset(&rc, pPages);
7343 if( pTab!=pOrphan ) recoverFreeTable(pTab);
dan68cb86e2019-04-20 20:57:28 +00007344 }
7345 shellFinalize(&rc, pLoop);
danefa363b2019-04-24 20:48:55 +00007346 shellFinalize(&rc, pPages);
7347 shellFinalize(&rc, pCells);
dan98c5ad32019-04-26 21:11:37 +00007348 recoverFreeTable(pOrphan);
dan68cb86e2019-04-20 20:57:28 +00007349
dan38f9c712019-04-23 18:03:02 +00007350 /* The rest of the schema */
danb40af492019-04-22 20:52:12 +00007351 if( rc==SQLITE_OK ){
dan38f9c712019-04-23 18:03:02 +00007352 sqlite3_stmt *pStmt = 0;
7353 shellPrepare(pState->db, &rc,
7354 "SELECT sql, name FROM recovery.schema "
danb1825882019-04-23 20:48:32 +00007355 "WHERE sql NOT LIKE 'create table%'", &pStmt
dan38f9c712019-04-23 18:03:02 +00007356 );
7357 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7358 const char *zSql = (const char*)sqlite3_column_text(pStmt, 0);
7359 if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){
7360 const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
7361 char *zPrint = shellMPrintf(&rc,
drh067b92b2020-06-19 15:24:12 +00007362 "INSERT INTO sqlite_schema VALUES('table', %Q, %Q, 0, %Q)",
dan38f9c712019-04-23 18:03:02 +00007363 zName, zName, zSql
7364 );
7365 raw_printf(pState->out, "%s;\n", zPrint);
7366 sqlite3_free(zPrint);
7367 }else{
7368 raw_printf(pState->out, "%s;\n", zSql);
7369 }
7370 }
7371 shellFinalize(&rc, pStmt);
7372 }
7373
7374 if( rc==SQLITE_OK ){
7375 raw_printf(pState->out, "PRAGMA writable_schema = off;\n");
danb40af492019-04-22 20:52:12 +00007376 raw_printf(pState->out, "COMMIT;\n");
7377 }
dan68cb86e2019-04-20 20:57:28 +00007378 sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
7379 return rc;
7380}
dan1b162162019-04-27 20:15:15 +00007381#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
dan68cb86e2019-04-20 20:57:28 +00007382
drh2ce15c32017-07-11 13:34:40 +00007383
7384/*
7385** If an input line begins with "." then invoke this routine to
7386** process that line.
7387**
7388** Return 1 on error, 2 to exit, and 0 otherwise.
7389*/
7390static int do_meta_command(char *zLine, ShellState *p){
7391 int h = 1;
7392 int nArg = 0;
7393 int n, c;
7394 int rc = 0;
drh5df84282019-08-17 19:45:25 +00007395 char *azArg[52];
drh2ce15c32017-07-11 13:34:40 +00007396
dan6b046be2018-01-09 15:25:55 +00007397#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00007398 if( p->expert.pExpert ){
7399 expertFinish(p, 1, 0);
7400 }
dan6b046be2018-01-09 15:25:55 +00007401#endif
dan43efc182017-12-19 17:42:13 +00007402
drh2ce15c32017-07-11 13:34:40 +00007403 /* Parse the input line into tokens.
7404 */
drh5df84282019-08-17 19:45:25 +00007405 while( zLine[h] && nArg<ArraySize(azArg)-1 ){
drh2ce15c32017-07-11 13:34:40 +00007406 while( IsSpace(zLine[h]) ){ h++; }
7407 if( zLine[h]==0 ) break;
7408 if( zLine[h]=='\'' || zLine[h]=='"' ){
7409 int delim = zLine[h++];
7410 azArg[nArg++] = &zLine[h];
7411 while( zLine[h] && zLine[h]!=delim ){
7412 if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
7413 h++;
7414 }
7415 if( zLine[h]==delim ){
7416 zLine[h++] = 0;
7417 }
7418 if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
7419 }else{
7420 azArg[nArg++] = &zLine[h];
7421 while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
7422 if( zLine[h] ) zLine[h++] = 0;
7423 resolve_backslashes(azArg[nArg-1]);
7424 }
7425 }
drh5df84282019-08-17 19:45:25 +00007426 azArg[nArg] = 0;
drh2ce15c32017-07-11 13:34:40 +00007427
7428 /* Process the input line.
7429 */
7430 if( nArg==0 ) return 0; /* no tokens, no error */
7431 n = strlen30(azArg[0]);
7432 c = azArg[0][0];
drh13c20932018-01-10 21:41:55 +00007433 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +00007434
7435#ifndef SQLITE_OMIT_AUTHORIZATION
7436 if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
7437 if( nArg!=2 ){
7438 raw_printf(stderr, "Usage: .auth ON|OFF\n");
7439 rc = 1;
7440 goto meta_command_exit;
7441 }
7442 open_db(p, 0);
7443 if( booleanValue(azArg[1]) ){
7444 sqlite3_set_authorizer(p->db, shellAuth, p);
7445 }else{
7446 sqlite3_set_authorizer(p->db, 0, 0);
7447 }
7448 }else
7449#endif
7450
drhe37c0e12018-01-06 19:19:50 +00007451#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
7452 if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
danfd0245d2017-12-07 15:44:29 +00007453 open_db(p, 0);
drhd0f9cdc2018-05-17 14:09:06 +00007454 rc = arDotCommand(p, 0, azArg, nArg);
danfd0245d2017-12-07 15:44:29 +00007455 }else
7456#endif
7457
drh2ce15c32017-07-11 13:34:40 +00007458 if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
7459 || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
7460 ){
7461 const char *zDestFile = 0;
7462 const char *zDb = 0;
7463 sqlite3 *pDest;
7464 sqlite3_backup *pBackup;
7465 int j;
drha50bffb2018-12-08 01:09:14 +00007466 int bAsync = 0;
drh69ed38a2018-05-14 00:23:08 +00007467 const char *zVfs = 0;
drh2ce15c32017-07-11 13:34:40 +00007468 for(j=1; j<nArg; j++){
7469 const char *z = azArg[j];
7470 if( z[0]=='-' ){
drh69ed38a2018-05-14 00:23:08 +00007471 if( z[1]=='-' ) z++;
7472 if( strcmp(z, "-append")==0 ){
7473 zVfs = "apndvfs";
7474 }else
drha50bffb2018-12-08 01:09:14 +00007475 if( strcmp(z, "-async")==0 ){
7476 bAsync = 1;
7477 }else
drh2ce15c32017-07-11 13:34:40 +00007478 {
7479 utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
7480 return 1;
7481 }
7482 }else if( zDestFile==0 ){
7483 zDestFile = azArg[j];
7484 }else if( zDb==0 ){
7485 zDb = zDestFile;
7486 zDestFile = azArg[j];
7487 }else{
drha50bffb2018-12-08 01:09:14 +00007488 raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
drh2ce15c32017-07-11 13:34:40 +00007489 return 1;
7490 }
7491 }
7492 if( zDestFile==0 ){
7493 raw_printf(stderr, "missing FILENAME argument on .backup\n");
7494 return 1;
7495 }
7496 if( zDb==0 ) zDb = "main";
drh69ed38a2018-05-14 00:23:08 +00007497 rc = sqlite3_open_v2(zDestFile, &pDest,
7498 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
drh2ce15c32017-07-11 13:34:40 +00007499 if( rc!=SQLITE_OK ){
7500 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
drh9e804032018-05-18 17:11:50 +00007501 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007502 return 1;
7503 }
drha50bffb2018-12-08 01:09:14 +00007504 if( bAsync ){
7505 sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
7506 0, 0, 0);
7507 }
drh2ce15c32017-07-11 13:34:40 +00007508 open_db(p, 0);
7509 pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
7510 if( pBackup==0 ){
7511 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
drh9e804032018-05-18 17:11:50 +00007512 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007513 return 1;
7514 }
7515 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
7516 sqlite3_backup_finish(pBackup);
7517 if( rc==SQLITE_DONE ){
7518 rc = 0;
7519 }else{
7520 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
7521 rc = 1;
7522 }
drh9e804032018-05-18 17:11:50 +00007523 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007524 }else
7525
7526 if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
7527 if( nArg==2 ){
7528 bail_on_error = booleanValue(azArg[1]);
7529 }else{
7530 raw_printf(stderr, "Usage: .bail on|off\n");
7531 rc = 1;
7532 }
7533 }else
7534
7535 if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
7536 if( nArg==2 ){
7537 if( booleanValue(azArg[1]) ){
7538 setBinaryMode(p->out, 1);
7539 }else{
7540 setTextMode(p->out, 1);
7541 }
7542 }else{
7543 raw_printf(stderr, "Usage: .binary on|off\n");
7544 rc = 1;
7545 }
7546 }else
7547
7548 if( c=='c' && strcmp(azArg[0],"cd")==0 ){
7549 if( nArg==2 ){
7550#if defined(_WIN32) || defined(WIN32)
7551 wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
7552 rc = !SetCurrentDirectoryW(z);
7553 sqlite3_free(z);
7554#else
7555 rc = chdir(azArg[1]);
7556#endif
7557 if( rc ){
7558 utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
7559 rc = 1;
7560 }
7561 }else{
7562 raw_printf(stderr, "Usage: .cd DIRECTORY\n");
7563 rc = 1;
7564 }
7565 }else
7566
7567 /* The undocumented ".breakpoint" command causes a call to the no-op
7568 ** routine named test_breakpoint().
7569 */
7570 if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
7571 test_breakpoint();
7572 }else
7573
7574 if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
7575 if( nArg==2 ){
7576 setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
7577 }else{
7578 raw_printf(stderr, "Usage: .changes on|off\n");
7579 rc = 1;
7580 }
7581 }else
7582
7583 /* Cancel output redirection, if it is currently set (by .testcase)
7584 ** Then read the content of the testcase-out.txt file and compare against
7585 ** azArg[1]. If there are differences, report an error and exit.
7586 */
7587 if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
7588 char *zRes = 0;
7589 output_reset(p);
7590 if( nArg!=2 ){
7591 raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
7592 rc = 2;
7593 }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
7594 raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
7595 rc = 2;
7596 }else if( testcase_glob(azArg[1],zRes)==0 ){
7597 utf8_printf(stderr,
7598 "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
7599 p->zTestcase, azArg[1], zRes);
drhf30d3452017-10-17 13:44:46 +00007600 rc = 1;
drh2ce15c32017-07-11 13:34:40 +00007601 }else{
7602 utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
7603 p->nCheck++;
7604 }
7605 sqlite3_free(zRes);
7606 }else
7607
7608 if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
7609 if( nArg==2 ){
7610 tryToClone(p, azArg[1]);
7611 }else{
7612 raw_printf(stderr, "Usage: .clone FILENAME\n");
7613 rc = 1;
7614 }
7615 }else
7616
7617 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
drh60081a02020-08-26 19:07:18 +00007618 char **azName = 0;
7619 int nName = 0;
7620 sqlite3_stmt *pStmt;
drh60081a02020-08-26 19:07:18 +00007621 int i;
drh2ce15c32017-07-11 13:34:40 +00007622 open_db(p, 0);
drh60081a02020-08-26 19:07:18 +00007623 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
7624 if( rc ){
7625 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh2ce15c32017-07-11 13:34:40 +00007626 rc = 1;
drh60081a02020-08-26 19:07:18 +00007627 }else{
7628 while( sqlite3_step(pStmt)==SQLITE_ROW ){
7629 const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
7630 const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
7631 azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
7632 if( azName==0 ){ shell_out_of_memory(); /* Does not return */ }
7633 azName[nName*2] = strdup(zSchema);
7634 azName[nName*2+1] = strdup(zFile);
7635 nName++;
7636 }
drh2ce15c32017-07-11 13:34:40 +00007637 }
drh60081a02020-08-26 19:07:18 +00007638 sqlite3_finalize(pStmt);
7639 for(i=0; i<nName; i++){
7640 int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
7641 int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
7642 const char *z = azName[i*2+1];
7643 utf8_printf(p->out, "%s: %s %s%s\n",
7644 azName[i*2],
7645 z && z[0] ? z : "\"\"",
7646 bRdonly ? "r/o" : "r/w",
7647 eTxn==SQLITE_TXN_NONE ? "" :
7648 eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
7649 free(azName[i*2]);
7650 free(azName[i*2+1]);
7651 }
7652 sqlite3_free(azName);
drh2ce15c32017-07-11 13:34:40 +00007653 }else
7654
drh7df01192018-04-28 12:43:16 +00007655 if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
drheb7f2a02018-09-26 18:02:32 +00007656 static const struct DbConfigChoices {
7657 const char *zName;
7658 int op;
7659 } aDbConfig[] = {
drhb945bcd2019-12-31 22:52:10 +00007660 { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
7661 { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL },
7662 { "dqs_dml", SQLITE_DBCONFIG_DQS_DML },
drh0a6873b2019-06-14 21:25:25 +00007663 { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
drhb945bcd2019-12-31 22:52:10 +00007664 { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
drh0a6873b2019-06-14 21:25:25 +00007665 { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
drh11d88e62019-08-15 21:27:20 +00007666 { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
drh0a6873b2019-06-14 21:25:25 +00007667 { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
drhb945bcd2019-12-31 22:52:10 +00007668 { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
7669 { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
drh0a6873b2019-06-14 21:25:25 +00007670 { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
7671 { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
drh0a6873b2019-06-14 21:25:25 +00007672 { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
drhb945bcd2019-12-31 22:52:10 +00007673 { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
drhb77da372020-01-07 16:09:11 +00007674 { "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA },
dan07312a62019-06-21 14:05:27 +00007675 { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA },
drh7df01192018-04-28 12:43:16 +00007676 };
7677 int ii, v;
7678 open_db(p, 0);
7679 for(ii=0; ii<ArraySize(aDbConfig); ii++){
7680 if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
7681 if( nArg>=3 ){
7682 sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
7683 }
7684 sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
drhb945bcd2019-12-31 22:52:10 +00007685 utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
drh7df01192018-04-28 12:43:16 +00007686 if( nArg>1 ) break;
7687 }
7688 if( nArg>1 && ii==ArraySize(aDbConfig) ){
7689 utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
7690 utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
7691 }
7692 }else
7693
7694 if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00007695 rc = shell_dbinfo_command(p, nArg, azArg);
7696 }else
7697
dan1b162162019-04-27 20:15:15 +00007698#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00007699 if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){
7700 open_db(p, 0);
danb9b71db2019-04-25 16:20:40 +00007701 rc = recoverDatabaseCmd(p, nArg, azArg);
dan68cb86e2019-04-20 20:57:28 +00007702 }else
dan1b162162019-04-27 20:15:15 +00007703#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
dan68cb86e2019-04-20 20:57:28 +00007704
drh2ce15c32017-07-11 13:34:40 +00007705 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
drh8e9297f2020-03-25 12:50:13 +00007706 char *zLike = 0;
7707 char *zSql;
drh2ce15c32017-07-11 13:34:40 +00007708 int i;
7709 int savedShowHeader = p->showHeader;
drhf213b332018-07-05 17:35:46 +00007710 int savedShellFlags = p->shellFlgs;
drhc1962192020-10-12 16:54:28 +00007711 ShellClearFlag(p,
7712 SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
7713 |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
drh2ce15c32017-07-11 13:34:40 +00007714 for(i=1; i<nArg; i++){
7715 if( azArg[i][0]=='-' ){
7716 const char *z = azArg[i]+1;
7717 if( z[0]=='-' ) z++;
7718 if( strcmp(z,"preserve-rowids")==0 ){
7719#ifdef SQLITE_OMIT_VIRTUALTABLE
7720 raw_printf(stderr, "The --preserve-rowids option is not compatible"
7721 " with SQLITE_OMIT_VIRTUALTABLE\n");
7722 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00007723 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00007724 goto meta_command_exit;
7725#else
7726 ShellSetFlag(p, SHFLG_PreserveRowid);
7727#endif
7728 }else
7729 if( strcmp(z,"newlines")==0 ){
7730 ShellSetFlag(p, SHFLG_Newlines);
7731 }else
drhc1962192020-10-12 16:54:28 +00007732 if( strcmp(z,"data-only")==0 ){
7733 ShellSetFlag(p, SHFLG_DumpDataOnly);
7734 }else
7735 if( strcmp(z,"nosys")==0 ){
7736 ShellSetFlag(p, SHFLG_DumpNoSys);
7737 }else
drh2ce15c32017-07-11 13:34:40 +00007738 {
7739 raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
7740 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00007741 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00007742 goto meta_command_exit;
7743 }
drh2ce15c32017-07-11 13:34:40 +00007744 }else{
dan78a9d752021-05-25 11:39:14 +00007745 /* azArg[i] contains a LIKE pattern. This ".dump" request should
7746 ** only dump data for tables for which either the table name matches
7747 ** the LIKE pattern, or the table appears to be a shadow table of
7748 ** a virtual table for which the name matches the LIKE pattern.
7749 */
7750 char *zExpr = sqlite3_mprintf(
7751 "name LIKE %Q ESCAPE '\\' OR EXISTS ("
7752 " SELECT 1 FROM sqlite_schema WHERE "
7753 " name LIKE %Q ESCAPE '\\' AND"
7754 " sql LIKE 'CREATE VIRTUAL TABLE%%' AND"
7755 " substr(o.name, 1, length(name)+1) == (name||'_')"
7756 ")", azArg[i], azArg[i]
7757 );
7758
7759 if( zLike ){
7760 zLike = sqlite3_mprintf("%z OR %z", zLike, zExpr);
7761 }else{
7762 zLike = zExpr;
7763 }
drh2ce15c32017-07-11 13:34:40 +00007764 }
7765 }
dan68cb86e2019-04-20 20:57:28 +00007766
drh2ce15c32017-07-11 13:34:40 +00007767 open_db(p, 0);
dan68cb86e2019-04-20 20:57:28 +00007768
drhc1962192020-10-12 16:54:28 +00007769 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
7770 /* When playing back a "dump", the content might appear in an order
7771 ** which causes immediate foreign key constraints to be violated.
7772 ** So disable foreign-key constraint enforcement to prevent problems. */
7773 raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
7774 raw_printf(p->out, "BEGIN TRANSACTION;\n");
7775 }
drh2ce15c32017-07-11 13:34:40 +00007776 p->writableSchema = 0;
7777 p->showHeader = 0;
7778 /* Set writable_schema=ON since doing so forces SQLite to initialize
drh067b92b2020-06-19 15:24:12 +00007779 ** as much of the schema as it can even if the sqlite_schema table is
drh2ce15c32017-07-11 13:34:40 +00007780 ** corrupt. */
7781 sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
7782 p->nErr = 0;
drh8e9297f2020-03-25 12:50:13 +00007783 if( zLike==0 ) zLike = sqlite3_mprintf("true");
7784 zSql = sqlite3_mprintf(
dan78a9d752021-05-25 11:39:14 +00007785 "SELECT name, type, sql FROM sqlite_schema AS o "
drh8e9297f2020-03-25 12:50:13 +00007786 "WHERE (%s) AND type=='table'"
7787 " AND sql NOT NULL"
7788 " ORDER BY tbl_name='sqlite_sequence', rowid",
7789 zLike
7790 );
7791 run_schema_dump_query(p,zSql);
7792 sqlite3_free(zSql);
drhc1962192020-10-12 16:54:28 +00007793 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
7794 zSql = sqlite3_mprintf(
dan78a9d752021-05-25 11:39:14 +00007795 "SELECT sql FROM sqlite_schema AS o "
drhc1962192020-10-12 16:54:28 +00007796 "WHERE (%s) AND sql NOT NULL"
7797 " AND type IN ('index','trigger','view')",
7798 zLike
7799 );
7800 run_table_dump_query(p, zSql);
7801 sqlite3_free(zSql);
7802 }
drh8e9297f2020-03-25 12:50:13 +00007803 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00007804 if( p->writableSchema ){
7805 raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
7806 p->writableSchema = 0;
7807 }
7808 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
7809 sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
drhc1962192020-10-12 16:54:28 +00007810 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
7811 raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
7812 }
drh2ce15c32017-07-11 13:34:40 +00007813 p->showHeader = savedShowHeader;
drhf213b332018-07-05 17:35:46 +00007814 p->shellFlgs = savedShellFlags;
drh2ce15c32017-07-11 13:34:40 +00007815 }else
7816
7817 if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
7818 if( nArg==2 ){
7819 setOrClearFlag(p, SHFLG_Echo, azArg[1]);
7820 }else{
7821 raw_printf(stderr, "Usage: .echo on|off\n");
7822 rc = 1;
7823 }
7824 }else
7825
7826 if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
7827 if( nArg==2 ){
drhe2ca99c2018-05-02 00:33:43 +00007828 p->autoEQPtest = 0;
drhb4e50392019-01-26 15:40:04 +00007829 if( p->autoEQPtrace ){
7830 if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
7831 p->autoEQPtrace = 0;
7832 }
drh2ce15c32017-07-11 13:34:40 +00007833 if( strcmp(azArg[1],"full")==0 ){
drhada70452017-12-21 21:02:27 +00007834 p->autoEQP = AUTOEQP_full;
7835 }else if( strcmp(azArg[1],"trigger")==0 ){
7836 p->autoEQP = AUTOEQP_trigger;
drhb4e50392019-01-26 15:40:04 +00007837#ifdef SQLITE_DEBUG
drhe2ca99c2018-05-02 00:33:43 +00007838 }else if( strcmp(azArg[1],"test")==0 ){
7839 p->autoEQP = AUTOEQP_on;
7840 p->autoEQPtest = 1;
drhb4e50392019-01-26 15:40:04 +00007841 }else if( strcmp(azArg[1],"trace")==0 ){
7842 p->autoEQP = AUTOEQP_full;
7843 p->autoEQPtrace = 1;
7844 open_db(p, 0);
drh067b92b2020-06-19 15:24:12 +00007845 sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0);
drhb4e50392019-01-26 15:40:04 +00007846 sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
7847#endif
drh2ce15c32017-07-11 13:34:40 +00007848 }else{
mistachkinb71aa092018-01-23 00:05:18 +00007849 p->autoEQP = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00007850 }
7851 }else{
drhb4e50392019-01-26 15:40:04 +00007852 raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
drh2ce15c32017-07-11 13:34:40 +00007853 rc = 1;
7854 }
7855 }else
7856
7857 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
7858 if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
7859 rc = 2;
7860 }else
7861
7862 /* The ".explain" command is automatic now. It is largely pointless. It
7863 ** retained purely for backwards compatibility */
7864 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
7865 int val = 1;
7866 if( nArg>=2 ){
7867 if( strcmp(azArg[1],"auto")==0 ){
7868 val = 99;
7869 }else{
7870 val = booleanValue(azArg[1]);
7871 }
7872 }
7873 if( val==1 && p->mode!=MODE_Explain ){
7874 p->normalMode = p->mode;
7875 p->mode = MODE_Explain;
7876 p->autoExplain = 0;
7877 }else if( val==0 ){
7878 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
7879 p->autoExplain = 0;
7880 }else if( val==99 ){
7881 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
7882 p->autoExplain = 1;
7883 }
7884 }else
7885
dan6b046be2018-01-09 15:25:55 +00007886#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00007887 if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
7888 open_db(p, 0);
7889 expertDotCommand(p, azArg, nArg);
7890 }else
dan6b046be2018-01-09 15:25:55 +00007891#endif
dan43efc182017-12-19 17:42:13 +00007892
drhd985f722019-06-05 14:29:53 +00007893 if( c=='f' && strncmp(azArg[0], "filectrl", n)==0 ){
7894 static const struct {
7895 const char *zCtrlName; /* Name of a test-control option */
7896 int ctrlCode; /* Integer code for that option */
7897 const char *zUsage; /* Usage notes */
7898 } aCtrl[] = {
drhd985f722019-06-05 14:29:53 +00007899 { "chunk_size", SQLITE_FCNTL_CHUNK_SIZE, "SIZE" },
drh18a4bbd2020-12-17 15:17:42 +00007900 { "data_version", SQLITE_FCNTL_DATA_VERSION, "" },
drhd985f722019-06-05 14:29:53 +00007901 { "has_moved", SQLITE_FCNTL_HAS_MOVED, "" },
7902 { "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" },
drh18a4bbd2020-12-17 15:17:42 +00007903 { "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" },
7904 /* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/
7905 { "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" },
drh541ef2c2020-04-20 16:21:30 +00007906 { "reserve_bytes", SQLITE_FCNTL_RESERVE_BYTES, "[N]" },
drh18a4bbd2020-12-17 15:17:42 +00007907 { "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" },
7908 { "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" },
7909 /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/
drhd985f722019-06-05 14:29:53 +00007910 };
7911 int filectrl = -1;
7912 int iCtrl = -1;
drh4245e042019-06-13 13:52:46 +00007913 sqlite3_int64 iRes = 0; /* Integer result to display if rc2==1 */
7914 int isOk = 0; /* 0: usage 1: %lld 2: no-result */
drhd985f722019-06-05 14:29:53 +00007915 int n2, i;
7916 const char *zCmd = 0;
drh541ef2c2020-04-20 16:21:30 +00007917 const char *zSchema = 0;
drhd985f722019-06-05 14:29:53 +00007918
7919 open_db(p, 0);
7920 zCmd = nArg>=2 ? azArg[1] : "help";
7921
drh541ef2c2020-04-20 16:21:30 +00007922 if( zCmd[0]=='-'
7923 && (strcmp(zCmd,"--schema")==0 || strcmp(zCmd,"-schema")==0)
7924 && nArg>=4
7925 ){
7926 zSchema = azArg[2];
7927 for(i=3; i<nArg; i++) azArg[i-2] = azArg[i];
7928 nArg -= 2;
7929 zCmd = azArg[1];
7930 }
7931
drhd985f722019-06-05 14:29:53 +00007932 /* The argument can optionally begin with "-" or "--" */
7933 if( zCmd[0]=='-' && zCmd[1] ){
7934 zCmd++;
7935 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
7936 }
7937
7938 /* --help lists all file-controls */
7939 if( strcmp(zCmd,"help")==0 ){
7940 utf8_printf(p->out, "Available file-controls:\n");
7941 for(i=0; i<ArraySize(aCtrl); i++){
7942 utf8_printf(p->out, " .filectrl %s %s\n",
7943 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
7944 }
7945 rc = 1;
7946 goto meta_command_exit;
7947 }
7948
7949 /* convert filectrl text option to value. allow any unique prefix
7950 ** of the option name, or a numerical value. */
7951 n2 = strlen30(zCmd);
7952 for(i=0; i<ArraySize(aCtrl); i++){
7953 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
7954 if( filectrl<0 ){
7955 filectrl = aCtrl[i].ctrlCode;
7956 iCtrl = i;
7957 }else{
7958 utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n"
7959 "Use \".filectrl --help\" for help\n", zCmd);
7960 rc = 1;
7961 goto meta_command_exit;
7962 }
7963 }
7964 }
7965 if( filectrl<0 ){
7966 utf8_printf(stderr,"Error: unknown file-control: %s\n"
7967 "Use \".filectrl --help\" for help\n", zCmd);
7968 }else{
7969 switch(filectrl){
7970 case SQLITE_FCNTL_SIZE_LIMIT: {
7971 if( nArg!=2 && nArg!=3 ) break;
7972 iRes = nArg==3 ? integerValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00007973 sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
drhd985f722019-06-05 14:29:53 +00007974 isOk = 1;
7975 break;
7976 }
7977 case SQLITE_FCNTL_LOCK_TIMEOUT:
7978 case SQLITE_FCNTL_CHUNK_SIZE: {
7979 int x;
7980 if( nArg!=3 ) break;
7981 x = (int)integerValue(azArg[2]);
drh541ef2c2020-04-20 16:21:30 +00007982 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00007983 isOk = 2;
7984 break;
7985 }
7986 case SQLITE_FCNTL_PERSIST_WAL:
7987 case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
7988 int x;
7989 if( nArg!=2 && nArg!=3 ) break;
7990 x = nArg==3 ? booleanValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00007991 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00007992 iRes = x;
7993 isOk = 1;
7994 break;
7995 }
drh18a4bbd2020-12-17 15:17:42 +00007996 case SQLITE_FCNTL_DATA_VERSION:
drhd985f722019-06-05 14:29:53 +00007997 case SQLITE_FCNTL_HAS_MOVED: {
7998 int x;
7999 if( nArg!=2 ) break;
drh541ef2c2020-04-20 16:21:30 +00008000 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008001 iRes = x;
8002 isOk = 1;
8003 break;
8004 }
8005 case SQLITE_FCNTL_TEMPFILENAME: {
8006 char *z = 0;
8007 if( nArg!=2 ) break;
drh541ef2c2020-04-20 16:21:30 +00008008 sqlite3_file_control(p->db, zSchema, filectrl, &z);
drhd985f722019-06-05 14:29:53 +00008009 if( z ){
8010 utf8_printf(p->out, "%s\n", z);
8011 sqlite3_free(z);
8012 }
8013 isOk = 2;
8014 break;
8015 }
drh541ef2c2020-04-20 16:21:30 +00008016 case SQLITE_FCNTL_RESERVE_BYTES: {
8017 int x;
8018 if( nArg>=3 ){
8019 x = atoi(azArg[2]);
8020 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8021 }
8022 x = -1;
8023 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8024 utf8_printf(p->out,"%d\n", x);
8025 isOk = 2;
8026 break;
8027 }
drhd985f722019-06-05 14:29:53 +00008028 }
8029 }
8030 if( isOk==0 && iCtrl>=0 ){
8031 utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
8032 rc = 1;
8033 }else if( isOk==1 ){
drhe2500762019-06-13 14:07:41 +00008034 char zBuf[100];
8035 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
8036 raw_printf(p->out, "%s\n", zBuf);
drhd985f722019-06-05 14:29:53 +00008037 }
8038 }else
8039
drh2ce15c32017-07-11 13:34:40 +00008040 if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
8041 ShellState data;
drh2ce15c32017-07-11 13:34:40 +00008042 int doStats = 0;
8043 memcpy(&data, p, sizeof(data));
8044 data.showHeader = 0;
8045 data.cMode = data.mode = MODE_Semi;
8046 if( nArg==2 && optionMatch(azArg[1], "indent") ){
8047 data.cMode = data.mode = MODE_Pretty;
8048 nArg = 1;
8049 }
8050 if( nArg!=1 ){
8051 raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
8052 rc = 1;
8053 goto meta_command_exit;
8054 }
8055 open_db(p, 0);
8056 rc = sqlite3_exec(p->db,
8057 "SELECT sql FROM"
8058 " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
drh067b92b2020-06-19 15:24:12 +00008059 " FROM sqlite_schema UNION ALL"
8060 " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
drh2ce15c32017-07-11 13:34:40 +00008061 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
8062 "ORDER BY rowid",
drhf83d5012021-05-03 13:35:00 +00008063 callback, &data, 0
drh2ce15c32017-07-11 13:34:40 +00008064 );
8065 if( rc==SQLITE_OK ){
8066 sqlite3_stmt *pStmt;
8067 rc = sqlite3_prepare_v2(p->db,
drh067b92b2020-06-19 15:24:12 +00008068 "SELECT rowid FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00008069 " WHERE name GLOB 'sqlite_stat[134]'",
8070 -1, &pStmt, 0);
8071 doStats = sqlite3_step(pStmt)==SQLITE_ROW;
8072 sqlite3_finalize(pStmt);
8073 }
8074 if( doStats==0 ){
8075 raw_printf(p->out, "/* No STAT tables available */\n");
8076 }else{
drh067b92b2020-06-19 15:24:12 +00008077 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
8078 sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_schema'",
drhf83d5012021-05-03 13:35:00 +00008079 callback, &data, 0);
drh2ce15c32017-07-11 13:34:40 +00008080 data.cMode = data.mode = MODE_Insert;
8081 data.zDestTable = "sqlite_stat1";
drhf83d5012021-05-03 13:35:00 +00008082 shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
drh2ce15c32017-07-11 13:34:40 +00008083 data.zDestTable = "sqlite_stat4";
drhf83d5012021-05-03 13:35:00 +00008084 shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
drh067b92b2020-06-19 15:24:12 +00008085 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00008086 }
8087 }else
8088
8089 if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
8090 if( nArg==2 ){
8091 p->showHeader = booleanValue(azArg[1]);
drhc0605082020-06-05 00:54:27 +00008092 p->shellFlgs |= SHFLG_HeaderSet;
drh2ce15c32017-07-11 13:34:40 +00008093 }else{
8094 raw_printf(stderr, "Usage: .headers on|off\n");
8095 rc = 1;
8096 }
8097 }else
8098
8099 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
drh98aa2ab2018-09-26 16:53:51 +00008100 if( nArg>=2 ){
drhe93f8262018-10-11 16:53:37 +00008101 n = showHelp(p->out, azArg[1]);
drh98aa2ab2018-09-26 16:53:51 +00008102 if( n==0 ){
8103 utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
8104 }
8105 }else{
8106 showHelp(p->out, 0);
8107 }
drh2ce15c32017-07-11 13:34:40 +00008108 }else
8109
8110 if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
drhccb37812020-03-09 15:39:39 +00008111 char *zTable = 0; /* Insert data into this table */
8112 char *zFile = 0; /* Name of file to extra content from */
drh2ce15c32017-07-11 13:34:40 +00008113 sqlite3_stmt *pStmt = NULL; /* A statement */
8114 int nCol; /* Number of columns in the table */
8115 int nByte; /* Number of bytes in an SQL string */
8116 int i, j; /* Loop counters */
8117 int needCommit; /* True to COMMIT or ROLLBACK at end */
8118 int nSep; /* Number of bytes in p->colSeparator[] */
8119 char *zSql; /* An SQL statement */
8120 ImportCtx sCtx; /* Reader context */
8121 char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
drhccb37812020-03-09 15:39:39 +00008122 int eVerbose = 0; /* Larger for more console output */
8123 int nSkip = 0; /* Initial lines to skip */
8124 int useOutputMode = 1; /* Use output mode to determine separators */
drh2ce15c32017-07-11 13:34:40 +00008125
drhccb37812020-03-09 15:39:39 +00008126 memset(&sCtx, 0, sizeof(sCtx));
8127 if( p->mode==MODE_Ascii ){
8128 xRead = ascii_read_one_field;
8129 }else{
8130 xRead = csv_read_one_field;
8131 }
8132 for(i=1; i<nArg; i++){
8133 char *z = azArg[i];
8134 if( z[0]=='-' && z[1]=='-' ) z++;
8135 if( z[0]!='-' ){
8136 if( zFile==0 ){
8137 zFile = z;
8138 }else if( zTable==0 ){
8139 zTable = z;
8140 }else{
8141 utf8_printf(p->out, "ERROR: extra argument: \"%s\". Usage:\n", z);
8142 showHelp(p->out, "import");
8143 rc = 1;
8144 goto meta_command_exit;
8145 }
8146 }else if( strcmp(z,"-v")==0 ){
8147 eVerbose++;
8148 }else if( strcmp(z,"-skip")==0 && i<nArg-1 ){
8149 nSkip = integerValue(azArg[++i]);
8150 }else if( strcmp(z,"-ascii")==0 ){
8151 sCtx.cColSep = SEP_Unit[0];
8152 sCtx.cRowSep = SEP_Record[0];
8153 xRead = ascii_read_one_field;
8154 useOutputMode = 0;
8155 }else if( strcmp(z,"-csv")==0 ){
8156 sCtx.cColSep = ',';
8157 sCtx.cRowSep = '\n';
8158 xRead = csv_read_one_field;
8159 useOutputMode = 0;
8160 }else{
8161 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", z);
8162 showHelp(p->out, "import");
8163 rc = 1;
8164 goto meta_command_exit;
8165 }
8166 }
8167 if( zTable==0 ){
8168 utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
8169 zFile==0 ? "FILE" : "TABLE");
8170 showHelp(p->out, "import");
8171 rc = 1;
drh2ce15c32017-07-11 13:34:40 +00008172 goto meta_command_exit;
8173 }
drh2ce15c32017-07-11 13:34:40 +00008174 seenInterrupt = 0;
drh2ce15c32017-07-11 13:34:40 +00008175 open_db(p, 0);
drhccb37812020-03-09 15:39:39 +00008176 if( useOutputMode ){
8177 /* If neither the --csv or --ascii options are specified, then set
8178 ** the column and row separator characters from the output mode. */
8179 nSep = strlen30(p->colSeparator);
8180 if( nSep==0 ){
8181 raw_printf(stderr,
8182 "Error: non-null column separator required for import\n");
8183 rc = 1;
8184 goto meta_command_exit;
8185 }
8186 if( nSep>1 ){
8187 raw_printf(stderr,
8188 "Error: multi-character column separators not allowed"
8189 " for import\n");
8190 rc = 1;
8191 goto meta_command_exit;
8192 }
drh2ce15c32017-07-11 13:34:40 +00008193 nSep = strlen30(p->rowSeparator);
drhccb37812020-03-09 15:39:39 +00008194 if( nSep==0 ){
8195 raw_printf(stderr,
8196 "Error: non-null row separator required for import\n");
8197 rc = 1;
8198 goto meta_command_exit;
8199 }
8200 if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator,SEP_CrLf)==0 ){
8201 /* When importing CSV (only), if the row separator is set to the
8202 ** default output row separator, change it to the default input
8203 ** row separator. This avoids having to maintain different input
8204 ** and output row separators. */
8205 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8206 nSep = strlen30(p->rowSeparator);
8207 }
8208 if( nSep>1 ){
8209 raw_printf(stderr, "Error: multi-character row separators not allowed"
8210 " for import\n");
8211 rc = 1;
8212 goto meta_command_exit;
8213 }
8214 sCtx.cColSep = p->colSeparator[0];
8215 sCtx.cRowSep = p->rowSeparator[0];
drh2ce15c32017-07-11 13:34:40 +00008216 }
8217 sCtx.zFile = zFile;
8218 sCtx.nLine = 1;
8219 if( sCtx.zFile[0]=='|' ){
8220#ifdef SQLITE_OMIT_POPEN
8221 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
drhccb37812020-03-09 15:39:39 +00008222 rc = 1;
8223 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008224#else
8225 sCtx.in = popen(sCtx.zFile+1, "r");
8226 sCtx.zFile = "<pipe>";
drh97767842020-05-29 19:39:35 +00008227 sCtx.xCloser = pclose;
drh2ce15c32017-07-11 13:34:40 +00008228#endif
8229 }else{
8230 sCtx.in = fopen(sCtx.zFile, "rb");
drh97767842020-05-29 19:39:35 +00008231 sCtx.xCloser = fclose;
drh2ce15c32017-07-11 13:34:40 +00008232 }
drh2ce15c32017-07-11 13:34:40 +00008233 if( sCtx.in==0 ){
8234 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
drhccb37812020-03-09 15:39:39 +00008235 rc = 1;
8236 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008237 }
drhccb37812020-03-09 15:39:39 +00008238 if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
8239 char zSep[2];
8240 zSep[1] = 0;
8241 zSep[0] = sCtx.cColSep;
8242 utf8_printf(p->out, "Column separator ");
8243 output_c_string(p->out, zSep);
8244 utf8_printf(p->out, ", row separator ");
8245 zSep[0] = sCtx.cRowSep;
8246 output_c_string(p->out, zSep);
8247 utf8_printf(p->out, "\n");
8248 }
8249 while( (nSkip--)>0 ){
8250 while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
drhccb37812020-03-09 15:39:39 +00008251 }
drhc6712642020-10-12 17:57:29 +00008252 zSql = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
drh2ce15c32017-07-11 13:34:40 +00008253 if( zSql==0 ){
drh97767842020-05-29 19:39:35 +00008254 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00008255 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00008256 }
8257 nByte = strlen30(zSql);
8258 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8259 import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
8260 if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
drhc6712642020-10-12 17:57:29 +00008261 char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"", zTable);
drh2ce15c32017-07-11 13:34:40 +00008262 char cSep = '(';
8263 while( xRead(&sCtx) ){
8264 zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z);
8265 cSep = ',';
8266 if( sCtx.cTerm!=sCtx.cColSep ) break;
8267 }
8268 if( cSep=='(' ){
8269 sqlite3_free(zCreate);
drh97767842020-05-29 19:39:35 +00008270 import_cleanup(&sCtx);
drh2ce15c32017-07-11 13:34:40 +00008271 utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
drhccb37812020-03-09 15:39:39 +00008272 rc = 1;
8273 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008274 }
8275 zCreate = sqlite3_mprintf("%z\n)", zCreate);
drhccb37812020-03-09 15:39:39 +00008276 if( eVerbose>=1 ){
8277 utf8_printf(p->out, "%s\n", zCreate);
8278 }
drh2ce15c32017-07-11 13:34:40 +00008279 rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
8280 sqlite3_free(zCreate);
8281 if( rc ){
drhc6712642020-10-12 17:57:29 +00008282 utf8_printf(stderr, "CREATE TABLE \"%s\"(...) failed: %s\n", zTable,
drh2ce15c32017-07-11 13:34:40 +00008283 sqlite3_errmsg(p->db));
drh97767842020-05-29 19:39:35 +00008284 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008285 rc = 1;
8286 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008287 }
8288 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8289 }
8290 sqlite3_free(zSql);
8291 if( rc ){
8292 if (pStmt) sqlite3_finalize(pStmt);
8293 utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
drh97767842020-05-29 19:39:35 +00008294 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008295 rc = 1;
8296 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008297 }
8298 nCol = sqlite3_column_count(pStmt);
8299 sqlite3_finalize(pStmt);
8300 pStmt = 0;
8301 if( nCol==0 ) return 0; /* no columns, no error */
8302 zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
8303 if( zSql==0 ){
drh97767842020-05-29 19:39:35 +00008304 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00008305 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00008306 }
8307 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
8308 j = strlen30(zSql);
8309 for(i=1; i<nCol; i++){
8310 zSql[j++] = ',';
8311 zSql[j++] = '?';
8312 }
8313 zSql[j++] = ')';
8314 zSql[j] = 0;
drhccb37812020-03-09 15:39:39 +00008315 if( eVerbose>=2 ){
8316 utf8_printf(p->out, "Insert using: %s\n", zSql);
8317 }
drh2ce15c32017-07-11 13:34:40 +00008318 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8319 sqlite3_free(zSql);
8320 if( rc ){
8321 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
8322 if (pStmt) sqlite3_finalize(pStmt);
drh97767842020-05-29 19:39:35 +00008323 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008324 rc = 1;
8325 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008326 }
8327 needCommit = sqlite3_get_autocommit(p->db);
8328 if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
8329 do{
8330 int startLine = sCtx.nLine;
8331 for(i=0; i<nCol; i++){
8332 char *z = xRead(&sCtx);
8333 /*
8334 ** Did we reach end-of-file before finding any columns?
8335 ** If so, stop instead of NULL filling the remaining columns.
8336 */
8337 if( z==0 && i==0 ) break;
8338 /*
8339 ** Did we reach end-of-file OR end-of-line before finding any
8340 ** columns in ASCII mode? If so, stop instead of NULL filling
8341 ** the remaining columns.
8342 */
8343 if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
8344 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
8345 if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
8346 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
8347 "filling the rest with NULL\n",
8348 sCtx.zFile, startLine, nCol, i+1);
8349 i += 2;
8350 while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
8351 }
8352 }
8353 if( sCtx.cTerm==sCtx.cColSep ){
8354 do{
8355 xRead(&sCtx);
8356 i++;
8357 }while( sCtx.cTerm==sCtx.cColSep );
8358 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
8359 "extras ignored\n",
8360 sCtx.zFile, startLine, nCol, i);
8361 }
8362 if( i>=nCol ){
8363 sqlite3_step(pStmt);
8364 rc = sqlite3_reset(pStmt);
8365 if( rc!=SQLITE_OK ){
8366 utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
8367 startLine, sqlite3_errmsg(p->db));
drhccb37812020-03-09 15:39:39 +00008368 sCtx.nErr++;
8369 }else{
8370 sCtx.nRow++;
drh2ce15c32017-07-11 13:34:40 +00008371 }
8372 }
8373 }while( sCtx.cTerm!=EOF );
8374
drh97767842020-05-29 19:39:35 +00008375 import_cleanup(&sCtx);
drh2ce15c32017-07-11 13:34:40 +00008376 sqlite3_finalize(pStmt);
8377 if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
drhccb37812020-03-09 15:39:39 +00008378 if( eVerbose>0 ){
8379 utf8_printf(p->out,
8380 "Added %d rows with %d errors using %d lines of input\n",
8381 sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
8382 }
drh2ce15c32017-07-11 13:34:40 +00008383 }else
8384
8385#ifndef SQLITE_UNTESTABLE
8386 if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
8387 char *zSql;
8388 char *zCollist = 0;
8389 sqlite3_stmt *pStmt;
8390 int tnum = 0;
drh491c5be2019-10-18 15:58:50 +00008391 int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */
8392 int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
drh2ce15c32017-07-11 13:34:40 +00008393 int i;
drh48d219a2018-04-23 18:38:48 +00008394 if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
8395 utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
8396 " .imposter off\n");
drh491c5be2019-10-18 15:58:50 +00008397 /* Also allowed, but not documented:
8398 **
8399 ** .imposter TABLE IMPOSTER
8400 **
8401 ** where TABLE is a WITHOUT ROWID table. In that case, the
8402 ** imposter is another WITHOUT ROWID table with the columns in
8403 ** storage order. */
drh2ce15c32017-07-11 13:34:40 +00008404 rc = 1;
8405 goto meta_command_exit;
8406 }
8407 open_db(p, 0);
drh48d219a2018-04-23 18:38:48 +00008408 if( nArg==2 ){
8409 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
8410 goto meta_command_exit;
8411 }
drh491c5be2019-10-18 15:58:50 +00008412 zSql = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00008413 "SELECT rootpage, 0 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00008414 " WHERE name='%q' AND type='index'"
8415 "UNION ALL "
drh067b92b2020-06-19 15:24:12 +00008416 "SELECT rootpage, 1 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00008417 " WHERE name='%q' AND type='table'"
8418 " AND sql LIKE '%%without%%rowid%%'",
8419 azArg[1], azArg[1]
8420 );
drh2ce15c32017-07-11 13:34:40 +00008421 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8422 sqlite3_free(zSql);
8423 if( sqlite3_step(pStmt)==SQLITE_ROW ){
8424 tnum = sqlite3_column_int(pStmt, 0);
drh491c5be2019-10-18 15:58:50 +00008425 isWO = sqlite3_column_int(pStmt, 1);
drh2ce15c32017-07-11 13:34:40 +00008426 }
8427 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00008428 zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
8429 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8430 sqlite3_free(zSql);
8431 i = 0;
8432 while( sqlite3_step(pStmt)==SQLITE_ROW ){
8433 char zLabel[20];
8434 const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
8435 i++;
8436 if( zCol==0 ){
8437 if( sqlite3_column_int(pStmt,1)==-1 ){
8438 zCol = "_ROWID_";
8439 }else{
8440 sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
8441 zCol = zLabel;
8442 }
8443 }
drh491c5be2019-10-18 15:58:50 +00008444 if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){
8445 lenPK = (int)strlen(zCollist);
8446 }
drh2ce15c32017-07-11 13:34:40 +00008447 if( zCollist==0 ){
8448 zCollist = sqlite3_mprintf("\"%w\"", zCol);
8449 }else{
8450 zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
8451 }
8452 }
8453 sqlite3_finalize(pStmt);
drh491c5be2019-10-18 15:58:50 +00008454 if( i==0 || tnum==0 ){
8455 utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
8456 rc = 1;
8457 sqlite3_free(zCollist);
8458 goto meta_command_exit;
8459 }
8460 if( lenPK==0 ) lenPK = 100000;
drh2ce15c32017-07-11 13:34:40 +00008461 zSql = sqlite3_mprintf(
drh491c5be2019-10-18 15:58:50 +00008462 "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
8463 azArg[2], zCollist, lenPK, zCollist);
drh2ce15c32017-07-11 13:34:40 +00008464 sqlite3_free(zCollist);
8465 rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
8466 if( rc==SQLITE_OK ){
8467 rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
8468 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
8469 if( rc ){
8470 utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
8471 }else{
8472 utf8_printf(stdout, "%s;\n", zSql);
8473 raw_printf(stdout,
drh491c5be2019-10-18 15:58:50 +00008474 "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
8475 azArg[1], isWO ? "table" : "index"
drh2ce15c32017-07-11 13:34:40 +00008476 );
8477 }
8478 }else{
8479 raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
8480 rc = 1;
8481 }
8482 sqlite3_free(zSql);
8483 }else
8484#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
8485
8486#ifdef SQLITE_ENABLE_IOTRACE
8487 if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
8488 SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
8489 if( iotrace && iotrace!=stdout ) fclose(iotrace);
8490 iotrace = 0;
8491 if( nArg<2 ){
8492 sqlite3IoTrace = 0;
8493 }else if( strcmp(azArg[1], "-")==0 ){
8494 sqlite3IoTrace = iotracePrintf;
8495 iotrace = stdout;
8496 }else{
8497 iotrace = fopen(azArg[1], "w");
8498 if( iotrace==0 ){
8499 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
8500 sqlite3IoTrace = 0;
8501 rc = 1;
8502 }else{
8503 sqlite3IoTrace = iotracePrintf;
8504 }
8505 }
8506 }else
8507#endif
8508
8509 if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
8510 static const struct {
8511 const char *zLimitName; /* Name of a limit */
8512 int limitCode; /* Integer code for that limit */
8513 } aLimit[] = {
8514 { "length", SQLITE_LIMIT_LENGTH },
8515 { "sql_length", SQLITE_LIMIT_SQL_LENGTH },
8516 { "column", SQLITE_LIMIT_COLUMN },
8517 { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
8518 { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
8519 { "vdbe_op", SQLITE_LIMIT_VDBE_OP },
8520 { "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
8521 { "attached", SQLITE_LIMIT_ATTACHED },
8522 { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
8523 { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER },
8524 { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
8525 { "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
8526 };
8527 int i, n2;
8528 open_db(p, 0);
8529 if( nArg==1 ){
8530 for(i=0; i<ArraySize(aLimit); i++){
8531 printf("%20s %d\n", aLimit[i].zLimitName,
8532 sqlite3_limit(p->db, aLimit[i].limitCode, -1));
8533 }
8534 }else if( nArg>3 ){
8535 raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
8536 rc = 1;
8537 goto meta_command_exit;
8538 }else{
8539 int iLimit = -1;
8540 n2 = strlen30(azArg[1]);
8541 for(i=0; i<ArraySize(aLimit); i++){
8542 if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
8543 if( iLimit<0 ){
8544 iLimit = i;
8545 }else{
8546 utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
8547 rc = 1;
8548 goto meta_command_exit;
8549 }
8550 }
8551 }
8552 if( iLimit<0 ){
8553 utf8_printf(stderr, "unknown limit: \"%s\"\n"
8554 "enter \".limits\" with no arguments for a list.\n",
8555 azArg[1]);
8556 rc = 1;
8557 goto meta_command_exit;
8558 }
8559 if( nArg==3 ){
8560 sqlite3_limit(p->db, aLimit[iLimit].limitCode,
8561 (int)integerValue(azArg[2]));
8562 }
8563 printf("%20s %d\n", aLimit[iLimit].zLimitName,
8564 sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
8565 }
8566 }else
8567
8568 if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
8569 open_db(p, 0);
8570 lintDotCommand(p, azArg, nArg);
8571 }else
8572
8573#ifndef SQLITE_OMIT_LOAD_EXTENSION
8574 if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
8575 const char *zFile, *zProc;
8576 char *zErrMsg = 0;
8577 if( nArg<2 ){
8578 raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
8579 rc = 1;
8580 goto meta_command_exit;
8581 }
8582 zFile = azArg[1];
8583 zProc = nArg>=3 ? azArg[2] : 0;
8584 open_db(p, 0);
8585 rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
8586 if( rc!=SQLITE_OK ){
8587 utf8_printf(stderr, "Error: %s\n", zErrMsg);
8588 sqlite3_free(zErrMsg);
8589 rc = 1;
8590 }
8591 }else
8592#endif
8593
8594 if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
8595 if( nArg!=2 ){
8596 raw_printf(stderr, "Usage: .log FILENAME\n");
8597 rc = 1;
8598 }else{
8599 const char *zFile = azArg[1];
8600 output_file_close(p->pLog);
drha92a01a2018-01-10 22:15:37 +00008601 p->pLog = output_file_open(zFile, 0);
drh2ce15c32017-07-11 13:34:40 +00008602 }
8603 }else
8604
8605 if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
8606 const char *zMode = nArg>=2 ? azArg[1] : "";
drhaf2770f2018-01-05 14:55:43 +00008607 int n2 = strlen30(zMode);
drh2ce15c32017-07-11 13:34:40 +00008608 int c2 = zMode[0];
8609 if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){
8610 p->mode = MODE_Line;
8611 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8612 }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
8613 p->mode = MODE_Column;
drhc0605082020-06-05 00:54:27 +00008614 if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){
8615 p->showHeader = 1;
8616 }
drh2ce15c32017-07-11 13:34:40 +00008617 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8618 }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
8619 p->mode = MODE_List;
8620 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
8621 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8622 }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){
8623 p->mode = MODE_Html;
8624 }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
8625 p->mode = MODE_Tcl;
8626 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
8627 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8628 }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
8629 p->mode = MODE_Csv;
8630 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
8631 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
8632 }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
8633 p->mode = MODE_List;
8634 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
8635 }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
8636 p->mode = MODE_Insert;
8637 set_table_name(p, nArg>=3 ? azArg[2] : "table");
8638 }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
8639 p->mode = MODE_Quote;
drhc6835732020-05-28 20:37:17 +00008640 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
8641 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +00008642 }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
8643 p->mode = MODE_Ascii;
8644 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
8645 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
drh30c54a02020-05-28 23:49:50 +00008646 }else if( c2=='m' && strncmp(azArg[1],"markdown",n2)==0 ){
8647 p->mode = MODE_Markdown;
8648 }else if( c2=='t' && strncmp(azArg[1],"table",n2)==0 ){
8649 p->mode = MODE_Table;
drh0908e382020-06-04 18:05:39 +00008650 }else if( c2=='b' && strncmp(azArg[1],"box",n2)==0 ){
8651 p->mode = MODE_Box;
drh30c54a02020-05-28 23:49:50 +00008652 }else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){
8653 p->mode = MODE_Json;
drh2ce15c32017-07-11 13:34:40 +00008654 }else if( nArg==1 ){
8655 raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
8656 }else{
8657 raw_printf(stderr, "Error: mode should be one of: "
drh0908e382020-06-04 18:05:39 +00008658 "ascii box column csv html insert json line list markdown "
drh30c54a02020-05-28 23:49:50 +00008659 "quote table tabs tcl\n");
drh2ce15c32017-07-11 13:34:40 +00008660 rc = 1;
8661 }
8662 p->cMode = p->mode;
8663 }else
8664
8665 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
8666 if( nArg==2 ){
8667 sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
8668 "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
8669 }else{
8670 raw_printf(stderr, "Usage: .nullvalue STRING\n");
8671 rc = 1;
8672 }
8673 }else
8674
drh4a3a3eb2020-02-29 15:53:48 +00008675#ifdef SQLITE_DEBUG
8676 if( c=='o' && strcmp(azArg[0],"oom")==0 ){
8677 int i;
8678 for(i=1; i<nArg; i++){
8679 const char *z = azArg[i];
8680 if( z[0]=='-' && z[1]=='-' ) z++;
8681 if( strcmp(z,"-repeat")==0 ){
8682 if( i==nArg-1 ){
8683 raw_printf(p->out, "missing argument on \"%s\"\n", azArg[i]);
8684 rc = 1;
8685 }else{
8686 oomRepeat = (int)integerValue(azArg[++i]);
8687 }
8688 }else if( IsDigit(z[0]) ){
8689 oomCounter = (int)integerValue(azArg[i]);
8690 }else{
8691 raw_printf(p->out, "unknown argument: \"%s\"\n", azArg[i]);
8692 raw_printf(p->out, "Usage: .oom [--repeat N] [M]\n");
8693 rc = 1;
8694 }
8695 }
8696 if( rc==0 ){
8697 raw_printf(p->out, "oomCounter = %d\n", oomCounter);
8698 raw_printf(p->out, "oomRepeat = %d\n", oomRepeat);
8699 }
8700 }else
8701#endif /* SQLITE_DEBUG */
8702
drh2ce15c32017-07-11 13:34:40 +00008703 if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
drhf30bbce2020-12-02 18:27:48 +00008704 char *zNewFilename = 0; /* Name of the database file to open */
8705 int iName = 1; /* Index in azArg[] of the filename */
8706 int newFlag = 0; /* True to delete file before opening */
drh2ce15c32017-07-11 13:34:40 +00008707 /* Close the existing database */
8708 session_close_all(p);
drh9e804032018-05-18 17:11:50 +00008709 close_db(p->db);
drh2ce15c32017-07-11 13:34:40 +00008710 p->db = 0;
8711 p->zDbFilename = 0;
8712 sqlite3_free(p->zFreeOnClose);
8713 p->zFreeOnClose = 0;
drh1fa6d9f2018-01-06 21:46:01 +00008714 p->openMode = SHELL_OPEN_UNSPEC;
drh0933aad2019-11-18 17:46:38 +00008715 p->openFlags = 0;
drh6ca64482019-01-22 16:06:20 +00008716 p->szMax = 0;
drh2ce15c32017-07-11 13:34:40 +00008717 /* Check for command-line arguments */
drhf30bbce2020-12-02 18:27:48 +00008718 for(iName=1; iName<nArg; iName++){
drh2ce15c32017-07-11 13:34:40 +00008719 const char *z = azArg[iName];
8720 if( optionMatch(z,"new") ){
8721 newFlag = 1;
drh3baed312018-03-08 18:14:41 +00008722#ifdef SQLITE_HAVE_ZLIB
drh1fa6d9f2018-01-06 21:46:01 +00008723 }else if( optionMatch(z, "zip") ){
8724 p->openMode = SHELL_OPEN_ZIPFILE;
8725#endif
8726 }else if( optionMatch(z, "append") ){
8727 p->openMode = SHELL_OPEN_APPENDVFS;
drhee269a62018-02-14 23:27:43 +00008728 }else if( optionMatch(z, "readonly") ){
8729 p->openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +00008730 }else if( optionMatch(z, "nofollow") ){
8731 p->openFlags |= SQLITE_OPEN_NOFOLLOW;
drh8d889af2021-05-08 17:18:23 +00008732#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +00008733 }else if( optionMatch(z, "deserialize") ){
8734 p->openMode = SHELL_OPEN_DESERIALIZE;
drh33746482018-12-13 15:06:26 +00008735 }else if( optionMatch(z, "hexdb") ){
8736 p->openMode = SHELL_OPEN_HEXDB;
drh6ca64482019-01-22 16:06:20 +00008737 }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
8738 p->szMax = integerValue(azArg[++iName]);
drh8d889af2021-05-08 17:18:23 +00008739#endif /* SQLITE_OMIT_DESERIALIZE */
drh2ce15c32017-07-11 13:34:40 +00008740 }else if( z[0]=='-' ){
8741 utf8_printf(stderr, "unknown option: %s\n", z);
8742 rc = 1;
8743 goto meta_command_exit;
drhf30bbce2020-12-02 18:27:48 +00008744 }else if( zNewFilename ){
8745 utf8_printf(stderr, "extra argument: \"%s\"\n", z);
8746 rc = 1;
8747 goto meta_command_exit;
8748 }else{
8749 zNewFilename = sqlite3_mprintf("%s", z);
drh2ce15c32017-07-11 13:34:40 +00008750 }
8751 }
8752 /* If a filename is specified, try to open it first */
drh33746482018-12-13 15:06:26 +00008753 if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
drh2ce15c32017-07-11 13:34:40 +00008754 if( newFlag ) shellDeleteFile(zNewFilename);
8755 p->zDbFilename = zNewFilename;
drhbe4ccb22018-05-17 20:04:24 +00008756 open_db(p, OPEN_DB_KEEPALIVE);
drh2ce15c32017-07-11 13:34:40 +00008757 if( p->db==0 ){
8758 utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
8759 sqlite3_free(zNewFilename);
8760 }else{
8761 p->zFreeOnClose = zNewFilename;
8762 }
8763 }
8764 if( p->db==0 ){
8765 /* As a fall-back open a TEMP database */
8766 p->zDbFilename = 0;
8767 open_db(p, 0);
8768 }
8769 }else
8770
drh13c20932018-01-10 21:41:55 +00008771 if( (c=='o'
8772 && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
8773 || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
drh2ce15c32017-07-11 13:34:40 +00008774 ){
drh4b0229a2021-02-17 13:19:22 +00008775 char *zFile = 0;
drha92a01a2018-01-10 22:15:37 +00008776 int bTxtMode = 0;
drh7a431002020-04-18 14:12:00 +00008777 int i;
8778 int eMode = 0;
8779 int bBOM = 0;
drh5415ab42020-04-23 20:45:46 +00008780 int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */
drh7a431002020-04-18 14:12:00 +00008781
8782 if( c=='e' ){
8783 eMode = 'x';
8784 bOnce = 2;
8785 }else if( strncmp(azArg[0],"once",n)==0 ){
8786 bOnce = 1;
drh13c20932018-01-10 21:41:55 +00008787 }
drh7a431002020-04-18 14:12:00 +00008788 for(i=1; i<nArg; i++){
8789 char *z = azArg[i];
8790 if( z[0]=='-' ){
8791 if( z[1]=='-' ) z++;
8792 if( strcmp(z,"-bom")==0 ){
8793 bBOM = 1;
8794 }else if( c!='e' && strcmp(z,"-x")==0 ){
8795 eMode = 'x'; /* spreadsheet */
8796 }else if( c!='e' && strcmp(z,"-e")==0 ){
8797 eMode = 'e'; /* text editor */
8798 }else{
8799 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n",
8800 azArg[i]);
8801 showHelp(p->out, azArg[0]);
8802 rc = 1;
8803 goto meta_command_exit;
8804 }
drh4b0229a2021-02-17 13:19:22 +00008805 }else if( zFile==0 && eMode!='e' && eMode!='x' ){
8806 zFile = sqlite3_mprintf("%s", z);
8807 if( zFile[0]=='|' ){
8808 while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]);
8809 break;
8810 }
drh7a431002020-04-18 14:12:00 +00008811 }else{
8812 utf8_printf(p->out,"ERROR: extra parameter: \"%s\". Usage:\n",
8813 azArg[i]);
8814 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00008815 rc = 1;
drh4b0229a2021-02-17 13:19:22 +00008816 sqlite3_free(zFile);
drh2ce15c32017-07-11 13:34:40 +00008817 goto meta_command_exit;
8818 }
drh7a431002020-04-18 14:12:00 +00008819 }
drh4b0229a2021-02-17 13:19:22 +00008820 if( zFile==0 ) zFile = sqlite3_mprintf("stdout");
drh7a431002020-04-18 14:12:00 +00008821 if( bOnce ){
drh2ce15c32017-07-11 13:34:40 +00008822 p->outCount = 2;
8823 }else{
8824 p->outCount = 0;
8825 }
8826 output_reset(p);
drh04a28c32018-01-31 01:38:44 +00008827#ifndef SQLITE_NOHAVE_SYSTEM
drh7a431002020-04-18 14:12:00 +00008828 if( eMode=='e' || eMode=='x' ){
drh3c484e82018-01-10 22:27:21 +00008829 p->doXdgOpen = 1;
8830 outputModePush(p);
drh7a431002020-04-18 14:12:00 +00008831 if( eMode=='x' ){
8832 /* spreadsheet mode. Output as CSV. */
drh13c20932018-01-10 21:41:55 +00008833 newTempFile(p, "csv");
drh7a431002020-04-18 14:12:00 +00008834 ShellClearFlag(p, SHFLG_Echo);
drh13c20932018-01-10 21:41:55 +00008835 p->mode = MODE_Csv;
8836 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
8837 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
8838 }else{
drh7a431002020-04-18 14:12:00 +00008839 /* text editor mode */
drh13c20932018-01-10 21:41:55 +00008840 newTempFile(p, "txt");
drha92a01a2018-01-10 22:15:37 +00008841 bTxtMode = 1;
drh13c20932018-01-10 21:41:55 +00008842 }
drh4b0229a2021-02-17 13:19:22 +00008843 sqlite3_free(zFile);
8844 zFile = sqlite3_mprintf("%s", p->zTempFile);
drh13c20932018-01-10 21:41:55 +00008845 }
drh04a28c32018-01-31 01:38:44 +00008846#endif /* SQLITE_NOHAVE_SYSTEM */
drh2ce15c32017-07-11 13:34:40 +00008847 if( zFile[0]=='|' ){
8848#ifdef SQLITE_OMIT_POPEN
8849 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
8850 rc = 1;
8851 p->out = stdout;
8852#else
8853 p->out = popen(zFile + 1, "w");
8854 if( p->out==0 ){
8855 utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
8856 p->out = stdout;
8857 rc = 1;
8858 }else{
drh7a431002020-04-18 14:12:00 +00008859 if( bBOM ) fprintf(p->out,"\357\273\277");
drh2ce15c32017-07-11 13:34:40 +00008860 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
8861 }
8862#endif
8863 }else{
drha92a01a2018-01-10 22:15:37 +00008864 p->out = output_file_open(zFile, bTxtMode);
drh2ce15c32017-07-11 13:34:40 +00008865 if( p->out==0 ){
8866 if( strcmp(zFile,"off")!=0 ){
8867 utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
8868 }
8869 p->out = stdout;
8870 rc = 1;
8871 } else {
drh7a431002020-04-18 14:12:00 +00008872 if( bBOM ) fprintf(p->out,"\357\273\277");
drh2ce15c32017-07-11 13:34:40 +00008873 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
8874 }
8875 }
drh4b0229a2021-02-17 13:19:22 +00008876 sqlite3_free(zFile);
drh2ce15c32017-07-11 13:34:40 +00008877 }else
8878
drh9cb02642019-02-28 20:10:52 +00008879 if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
8880 open_db(p,0);
8881 if( nArg<=1 ) goto parameter_syntax_error;
8882
8883 /* .parameter clear
8884 ** Clear all bind parameters by dropping the TEMP table that holds them.
8885 */
8886 if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
drh65c29fd2019-03-25 21:56:26 +00008887 sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
drh9cb02642019-02-28 20:10:52 +00008888 0, 0, 0);
8889 }else
8890
8891 /* .parameter list
8892 ** List all bind parameters.
8893 */
8894 if( nArg==2 && strcmp(azArg[1],"list")==0 ){
8895 sqlite3_stmt *pStmt = 0;
8896 int rx;
8897 int len = 0;
8898 rx = sqlite3_prepare_v2(p->db,
8899 "SELECT max(length(key)) "
drh65c29fd2019-03-25 21:56:26 +00008900 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drh9cb02642019-02-28 20:10:52 +00008901 if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
8902 len = sqlite3_column_int(pStmt, 0);
8903 if( len>40 ) len = 40;
8904 }
8905 sqlite3_finalize(pStmt);
8906 pStmt = 0;
8907 if( len ){
8908 rx = sqlite3_prepare_v2(p->db,
8909 "SELECT key, quote(value) "
drh65c29fd2019-03-25 21:56:26 +00008910 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drh9cb02642019-02-28 20:10:52 +00008911 while( sqlite3_step(pStmt)==SQLITE_ROW ){
8912 utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
8913 sqlite3_column_text(pStmt,1));
8914 }
8915 sqlite3_finalize(pStmt);
8916 }
8917 }else
8918
8919 /* .parameter init
8920 ** Make sure the TEMP table used to hold bind parameters exists.
8921 ** Create it if necessary.
8922 */
8923 if( nArg==2 && strcmp(azArg[1],"init")==0 ){
8924 bind_table_init(p);
8925 }else
8926
8927 /* .parameter set NAME VALUE
8928 ** Set or reset a bind parameter. NAME should be the full parameter
8929 ** name exactly as it appears in the query. (ex: $abc, @def). The
8930 ** VALUE can be in either SQL literal notation, or if not it will be
8931 ** understood to be a text string.
8932 */
8933 if( nArg==4 && strcmp(azArg[1],"set")==0 ){
8934 int rx;
8935 char *zSql;
8936 sqlite3_stmt *pStmt;
8937 const char *zKey = azArg[2];
8938 const char *zValue = azArg[3];
8939 bind_table_init(p);
8940 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00008941 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00008942 "VALUES(%Q,%s);", zKey, zValue);
8943 if( zSql==0 ) shell_out_of_memory();
8944 pStmt = 0;
8945 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8946 sqlite3_free(zSql);
8947 if( rx!=SQLITE_OK ){
8948 sqlite3_finalize(pStmt);
8949 pStmt = 0;
8950 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00008951 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00008952 "VALUES(%Q,%Q);", zKey, zValue);
8953 if( zSql==0 ) shell_out_of_memory();
8954 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8955 sqlite3_free(zSql);
8956 if( rx!=SQLITE_OK ){
8957 utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
8958 sqlite3_finalize(pStmt);
8959 pStmt = 0;
8960 rc = 1;
8961 }
8962 }
8963 sqlite3_step(pStmt);
8964 sqlite3_finalize(pStmt);
8965 }else
8966
8967 /* .parameter unset NAME
8968 ** Remove the NAME binding from the parameter binding table, if it
8969 ** exists.
8970 */
8971 if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
8972 char *zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00008973 "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
drh9cb02642019-02-28 20:10:52 +00008974 if( zSql==0 ) shell_out_of_memory();
8975 sqlite3_exec(p->db, zSql, 0, 0, 0);
8976 sqlite3_free(zSql);
8977 }else
8978 /* If no command name matches, show a syntax error */
8979 parameter_syntax_error:
8980 showHelp(p->out, "parameter");
8981 }else
8982
drh2ce15c32017-07-11 13:34:40 +00008983 if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
8984 int i;
8985 for(i=1; i<nArg; i++){
8986 if( i>1 ) raw_printf(p->out, " ");
8987 utf8_printf(p->out, "%s", azArg[i]);
8988 }
8989 raw_printf(p->out, "\n");
8990 }else
8991
drh569b1d92019-02-05 20:51:41 +00008992#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh3f83f592019-02-04 14:53:18 +00008993 if( c=='p' && n>=3 && strncmp(azArg[0], "progress", n)==0 ){
8994 int i;
drhfc4eeef2019-02-05 19:48:46 +00008995 int nn = 0;
drh3f83f592019-02-04 14:53:18 +00008996 p->flgProgress = 0;
8997 p->mxProgress = 0;
8998 p->nProgress = 0;
8999 for(i=1; i<nArg; i++){
9000 const char *z = azArg[i];
9001 if( z[0]=='-' ){
9002 z++;
9003 if( z[0]=='-' ) z++;
9004 if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009005 p->flgProgress |= SHELL_PROGRESS_QUIET;
drh3f83f592019-02-04 14:53:18 +00009006 continue;
9007 }
9008 if( strcmp(z,"reset")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009009 p->flgProgress |= SHELL_PROGRESS_RESET;
drh3f83f592019-02-04 14:53:18 +00009010 continue;
9011 }
9012 if( strcmp(z,"once")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009013 p->flgProgress |= SHELL_PROGRESS_ONCE;
drh3f83f592019-02-04 14:53:18 +00009014 continue;
9015 }
9016 if( strcmp(z,"limit")==0 ){
9017 if( i+1>=nArg ){
9018 utf8_printf(stderr, "Error: missing argument on --limit\n");
9019 rc = 1;
9020 goto meta_command_exit;
9021 }else{
9022 p->mxProgress = (int)integerValue(azArg[++i]);
9023 }
9024 continue;
9025 }
9026 utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
9027 rc = 1;
9028 goto meta_command_exit;
9029 }else{
drhfc4eeef2019-02-05 19:48:46 +00009030 nn = (int)integerValue(z);
drh3f83f592019-02-04 14:53:18 +00009031 }
9032 }
9033 open_db(p, 0);
drhfc4eeef2019-02-05 19:48:46 +00009034 sqlite3_progress_handler(p->db, nn, progress_handler, p);
drh3f83f592019-02-04 14:53:18 +00009035 }else
drh569b1d92019-02-05 20:51:41 +00009036#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
drh3f83f592019-02-04 14:53:18 +00009037
drh2ce15c32017-07-11 13:34:40 +00009038 if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
9039 if( nArg >= 2) {
9040 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
9041 }
9042 if( nArg >= 3) {
9043 strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
9044 }
9045 }else
9046
9047 if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
9048 rc = 2;
9049 }else
9050
9051 if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
drh60379d42018-12-13 18:30:01 +00009052 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +00009053 int savedLineno = p->lineno;
drh2ce15c32017-07-11 13:34:40 +00009054 if( nArg!=2 ){
9055 raw_printf(stderr, "Usage: .read FILE\n");
9056 rc = 1;
9057 goto meta_command_exit;
9058 }
drh30497f42020-08-26 10:50:48 +00009059 if( azArg[1][0]=='|' ){
drh9d59e3b2021-03-12 01:49:08 +00009060#ifdef SQLITE_OMIT_POPEN
9061 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
9062 rc = 1;
9063 p->out = stdout;
9064#else
drh30497f42020-08-26 10:50:48 +00009065 p->in = popen(azArg[1]+1, "r");
9066 if( p->in==0 ){
9067 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
9068 rc = 1;
9069 }else{
9070 rc = process_input(p);
9071 pclose(p->in);
9072 }
drh9d59e3b2021-03-12 01:49:08 +00009073#endif
drh30497f42020-08-26 10:50:48 +00009074 }else if( notNormalFile(azArg[1]) || (p->in = fopen(azArg[1], "rb"))==0 ){
drh2ce15c32017-07-11 13:34:40 +00009075 utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
9076 rc = 1;
9077 }else{
drh60379d42018-12-13 18:30:01 +00009078 rc = process_input(p);
9079 fclose(p->in);
drh2ce15c32017-07-11 13:34:40 +00009080 }
drh60379d42018-12-13 18:30:01 +00009081 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +00009082 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +00009083 }else
9084
9085 if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
9086 const char *zSrcFile;
9087 const char *zDb;
9088 sqlite3 *pSrc;
9089 sqlite3_backup *pBackup;
9090 int nTimeout = 0;
9091
9092 if( nArg==2 ){
9093 zSrcFile = azArg[1];
9094 zDb = "main";
9095 }else if( nArg==3 ){
9096 zSrcFile = azArg[2];
9097 zDb = azArg[1];
9098 }else{
9099 raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
9100 rc = 1;
9101 goto meta_command_exit;
9102 }
9103 rc = sqlite3_open(zSrcFile, &pSrc);
9104 if( rc!=SQLITE_OK ){
9105 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
drh9e804032018-05-18 17:11:50 +00009106 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009107 return 1;
9108 }
9109 open_db(p, 0);
9110 pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
9111 if( pBackup==0 ){
9112 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh9e804032018-05-18 17:11:50 +00009113 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009114 return 1;
9115 }
9116 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
9117 || rc==SQLITE_BUSY ){
9118 if( rc==SQLITE_BUSY ){
9119 if( nTimeout++ >= 3 ) break;
9120 sqlite3_sleep(100);
9121 }
9122 }
9123 sqlite3_backup_finish(pBackup);
9124 if( rc==SQLITE_DONE ){
9125 rc = 0;
9126 }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
9127 raw_printf(stderr, "Error: source database is busy\n");
9128 rc = 1;
9129 }else{
9130 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9131 rc = 1;
9132 }
drh9e804032018-05-18 17:11:50 +00009133 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009134 }else
9135
drh2ce15c32017-07-11 13:34:40 +00009136 if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
9137 if( nArg==2 ){
mistachkinb71aa092018-01-23 00:05:18 +00009138 p->scanstatsOn = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00009139#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
9140 raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
9141#endif
9142 }else{
9143 raw_printf(stderr, "Usage: .scanstats on|off\n");
9144 rc = 1;
9145 }
9146 }else
9147
9148 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
9149 ShellText sSelect;
9150 ShellState data;
9151 char *zErrMsg = 0;
drh667a2a22018-01-02 00:04:37 +00009152 const char *zDiv = "(";
drhceba7922018-01-01 21:28:25 +00009153 const char *zName = 0;
drh2ce15c32017-07-11 13:34:40 +00009154 int iSchema = 0;
drhceba7922018-01-01 21:28:25 +00009155 int bDebug = 0;
drhbbb29ec2020-10-12 14:56:47 +00009156 int bNoSystemTabs = 0;
drhceba7922018-01-01 21:28:25 +00009157 int ii;
drh2ce15c32017-07-11 13:34:40 +00009158
9159 open_db(p, 0);
9160 memcpy(&data, p, sizeof(data));
9161 data.showHeader = 0;
9162 data.cMode = data.mode = MODE_Semi;
9163 initText(&sSelect);
drhceba7922018-01-01 21:28:25 +00009164 for(ii=1; ii<nArg; ii++){
9165 if( optionMatch(azArg[ii],"indent") ){
9166 data.cMode = data.mode = MODE_Pretty;
9167 }else if( optionMatch(azArg[ii],"debug") ){
9168 bDebug = 1;
drhbbb29ec2020-10-12 14:56:47 +00009169 }else if( optionMatch(azArg[ii],"nosys") ){
9170 bNoSystemTabs = 1;
9171 }else if( azArg[ii][0]=='-' ){
9172 utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
9173 rc = 1;
9174 goto meta_command_exit;
drhceba7922018-01-01 21:28:25 +00009175 }else if( zName==0 ){
9176 zName = azArg[ii];
drh2ce15c32017-07-11 13:34:40 +00009177 }else{
drhbbb29ec2020-10-12 14:56:47 +00009178 raw_printf(stderr, "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
drhceba7922018-01-01 21:28:25 +00009179 rc = 1;
9180 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00009181 }
drh2ce15c32017-07-11 13:34:40 +00009182 }
drhceba7922018-01-01 21:28:25 +00009183 if( zName!=0 ){
drh067b92b2020-06-19 15:24:12 +00009184 int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0
drh346a70c2020-06-15 20:27:35 +00009185 || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
9186 || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
9187 || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
drh067b92b2020-06-19 15:24:12 +00009188 if( isSchema ){
drh2ce15c32017-07-11 13:34:40 +00009189 char *new_argv[2], *new_colv[2];
drhc22b7162018-01-01 20:11:23 +00009190 new_argv[0] = sqlite3_mprintf(
9191 "CREATE TABLE %s (\n"
drh2ce15c32017-07-11 13:34:40 +00009192 " type text,\n"
9193 " name text,\n"
9194 " tbl_name text,\n"
9195 " rootpage integer,\n"
9196 " sql text\n"
drh346a70c2020-06-15 20:27:35 +00009197 ")", zName);
drh2ce15c32017-07-11 13:34:40 +00009198 new_argv[1] = 0;
9199 new_colv[0] = "sql";
9200 new_colv[1] = 0;
9201 callback(&data, 1, new_argv, new_colv);
drhc22b7162018-01-01 20:11:23 +00009202 sqlite3_free(new_argv[0]);
drh2ce15c32017-07-11 13:34:40 +00009203 }
drh2ce15c32017-07-11 13:34:40 +00009204 }
9205 if( zDiv ){
9206 sqlite3_stmt *pStmt = 0;
9207 rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
9208 -1, &pStmt, 0);
9209 if( rc ){
9210 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9211 sqlite3_finalize(pStmt);
9212 rc = 1;
9213 goto meta_command_exit;
9214 }
9215 appendText(&sSelect, "SELECT sql FROM", 0);
9216 iSchema = 0;
9217 while( sqlite3_step(pStmt)==SQLITE_ROW ){
9218 const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
9219 char zScNum[30];
9220 sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
9221 appendText(&sSelect, zDiv, 0);
9222 zDiv = " UNION ALL ";
drhceba7922018-01-01 21:28:25 +00009223 appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
9224 if( sqlite3_stricmp(zDb, "main")!=0 ){
drhea38f4f2019-07-13 17:21:47 +00009225 appendText(&sSelect, zDb, '\'');
drh2ce15c32017-07-11 13:34:40 +00009226 }else{
drhceba7922018-01-01 21:28:25 +00009227 appendText(&sSelect, "NULL", 0);
drh2ce15c32017-07-11 13:34:40 +00009228 }
drhceba7922018-01-01 21:28:25 +00009229 appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0);
9230 appendText(&sSelect, zScNum, 0);
9231 appendText(&sSelect, " AS snum, ", 0);
9232 appendText(&sSelect, zDb, '\'');
9233 appendText(&sSelect, " AS sname FROM ", 0);
drhea38f4f2019-07-13 17:21:47 +00009234 appendText(&sSelect, zDb, quoteChar(zDb));
drh067b92b2020-06-19 15:24:12 +00009235 appendText(&sSelect, ".sqlite_schema", 0);
drh2ce15c32017-07-11 13:34:40 +00009236 }
9237 sqlite3_finalize(pStmt);
drhcc3f3d12019-08-17 15:27:58 +00009238#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
drh667a2a22018-01-02 00:04:37 +00009239 if( zName ){
9240 appendText(&sSelect,
9241 " UNION ALL SELECT shell_module_schema(name),"
drhe2754c12019-08-26 12:50:01 +00009242 " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
9243 0);
drh667a2a22018-01-02 00:04:37 +00009244 }
drhcde7b772018-01-02 12:50:40 +00009245#endif
drh2ce15c32017-07-11 13:34:40 +00009246 appendText(&sSelect, ") WHERE ", 0);
drhceba7922018-01-01 21:28:25 +00009247 if( zName ){
9248 char *zQarg = sqlite3_mprintf("%Q", zName);
mistachkin9d107262018-03-23 14:24:34 +00009249 int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
9250 strchr(zName, '[') != 0;
drhceba7922018-01-01 21:28:25 +00009251 if( strchr(zName, '.') ){
drh2ce15c32017-07-11 13:34:40 +00009252 appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
9253 }else{
9254 appendText(&sSelect, "lower(tbl_name)", 0);
9255 }
mistachkin9d107262018-03-23 14:24:34 +00009256 appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0);
drh2ce15c32017-07-11 13:34:40 +00009257 appendText(&sSelect, zQarg, 0);
mistachkin9d107262018-03-23 14:24:34 +00009258 if( !bGlob ){
9259 appendText(&sSelect, " ESCAPE '\\' ", 0);
9260 }
drh2ce15c32017-07-11 13:34:40 +00009261 appendText(&sSelect, " AND ", 0);
9262 sqlite3_free(zQarg);
9263 }
drhbbb29ec2020-10-12 14:56:47 +00009264 if( bNoSystemTabs ){
9265 appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
9266 }
9267 appendText(&sSelect, "sql IS NOT NULL"
drh2ce15c32017-07-11 13:34:40 +00009268 " ORDER BY snum, rowid", 0);
drhceba7922018-01-01 21:28:25 +00009269 if( bDebug ){
9270 utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
9271 }else{
9272 rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
9273 }
drh2ce15c32017-07-11 13:34:40 +00009274 freeText(&sSelect);
9275 }
9276 if( zErrMsg ){
9277 utf8_printf(stderr,"Error: %s\n", zErrMsg);
9278 sqlite3_free(zErrMsg);
9279 rc = 1;
9280 }else if( rc != SQLITE_OK ){
9281 raw_printf(stderr,"Error: querying schema information\n");
9282 rc = 1;
9283 }else{
9284 rc = 0;
9285 }
9286 }else
9287
drh2ce15c32017-07-11 13:34:40 +00009288 if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
drhfda8e492020-12-04 16:04:45 +00009289 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
drhc0622a42020-12-04 01:17:57 +00009290 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
drh2ce15c32017-07-11 13:34:40 +00009291 }else
drh2ce15c32017-07-11 13:34:40 +00009292
9293#if defined(SQLITE_ENABLE_SESSION)
9294 if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
9295 OpenSession *pSession = &p->aSession[0];
9296 char **azCmd = &azArg[1];
9297 int iSes = 0;
9298 int nCmd = nArg - 1;
9299 int i;
9300 if( nArg<=1 ) goto session_syntax_error;
9301 open_db(p, 0);
9302 if( nArg>=3 ){
9303 for(iSes=0; iSes<p->nSession; iSes++){
9304 if( strcmp(p->aSession[iSes].zName, azArg[1])==0 ) break;
9305 }
9306 if( iSes<p->nSession ){
9307 pSession = &p->aSession[iSes];
9308 azCmd++;
9309 nCmd--;
9310 }else{
9311 pSession = &p->aSession[0];
9312 iSes = 0;
9313 }
9314 }
9315
9316 /* .session attach TABLE
9317 ** Invoke the sqlite3session_attach() interface to attach a particular
9318 ** table so that it is never filtered.
9319 */
9320 if( strcmp(azCmd[0],"attach")==0 ){
9321 if( nCmd!=2 ) goto session_syntax_error;
9322 if( pSession->p==0 ){
9323 session_not_open:
9324 raw_printf(stderr, "ERROR: No sessions are open\n");
9325 }else{
9326 rc = sqlite3session_attach(pSession->p, azCmd[1]);
9327 if( rc ){
9328 raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
9329 rc = 0;
9330 }
9331 }
9332 }else
9333
9334 /* .session changeset FILE
9335 ** .session patchset FILE
9336 ** Write a changeset or patchset into a file. The file is overwritten.
9337 */
9338 if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
9339 FILE *out = 0;
9340 if( nCmd!=2 ) goto session_syntax_error;
9341 if( pSession->p==0 ) goto session_not_open;
9342 out = fopen(azCmd[1], "wb");
9343 if( out==0 ){
drhe2754c12019-08-26 12:50:01 +00009344 utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
9345 azCmd[1]);
drh2ce15c32017-07-11 13:34:40 +00009346 }else{
9347 int szChng;
9348 void *pChng;
9349 if( azCmd[0][0]=='c' ){
9350 rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
9351 }else{
9352 rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
9353 }
9354 if( rc ){
9355 printf("Error: error code %d\n", rc);
9356 rc = 0;
9357 }
9358 if( pChng
9359 && fwrite(pChng, szChng, 1, out)!=1 ){
9360 raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
9361 szChng);
9362 }
9363 sqlite3_free(pChng);
9364 fclose(out);
9365 }
9366 }else
9367
9368 /* .session close
9369 ** Close the identified session
9370 */
9371 if( strcmp(azCmd[0], "close")==0 ){
9372 if( nCmd!=1 ) goto session_syntax_error;
9373 if( p->nSession ){
9374 session_close(pSession);
9375 p->aSession[iSes] = p->aSession[--p->nSession];
9376 }
9377 }else
9378
9379 /* .session enable ?BOOLEAN?
9380 ** Query or set the enable flag
9381 */
9382 if( strcmp(azCmd[0], "enable")==0 ){
9383 int ii;
9384 if( nCmd>2 ) goto session_syntax_error;
9385 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
9386 if( p->nSession ){
9387 ii = sqlite3session_enable(pSession->p, ii);
9388 utf8_printf(p->out, "session %s enable flag = %d\n",
9389 pSession->zName, ii);
9390 }
9391 }else
9392
9393 /* .session filter GLOB ....
9394 ** Set a list of GLOB patterns of table names to be excluded.
9395 */
9396 if( strcmp(azCmd[0], "filter")==0 ){
9397 int ii, nByte;
9398 if( nCmd<2 ) goto session_syntax_error;
9399 if( p->nSession ){
9400 for(ii=0; ii<pSession->nFilter; ii++){
9401 sqlite3_free(pSession->azFilter[ii]);
9402 }
9403 sqlite3_free(pSession->azFilter);
9404 nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
9405 pSession->azFilter = sqlite3_malloc( nByte );
9406 if( pSession->azFilter==0 ){
9407 raw_printf(stderr, "Error: out or memory\n");
9408 exit(1);
9409 }
9410 for(ii=1; ii<nCmd; ii++){
9411 pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
9412 }
9413 pSession->nFilter = ii-1;
9414 }
9415 }else
9416
9417 /* .session indirect ?BOOLEAN?
9418 ** Query or set the indirect flag
9419 */
9420 if( strcmp(azCmd[0], "indirect")==0 ){
9421 int ii;
9422 if( nCmd>2 ) goto session_syntax_error;
9423 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
9424 if( p->nSession ){
9425 ii = sqlite3session_indirect(pSession->p, ii);
9426 utf8_printf(p->out, "session %s indirect flag = %d\n",
9427 pSession->zName, ii);
9428 }
9429 }else
9430
9431 /* .session isempty
9432 ** Determine if the session is empty
9433 */
9434 if( strcmp(azCmd[0], "isempty")==0 ){
9435 int ii;
9436 if( nCmd!=1 ) goto session_syntax_error;
9437 if( p->nSession ){
9438 ii = sqlite3session_isempty(pSession->p);
9439 utf8_printf(p->out, "session %s isempty flag = %d\n",
9440 pSession->zName, ii);
9441 }
9442 }else
9443
9444 /* .session list
9445 ** List all currently open sessions
9446 */
9447 if( strcmp(azCmd[0],"list")==0 ){
9448 for(i=0; i<p->nSession; i++){
9449 utf8_printf(p->out, "%d %s\n", i, p->aSession[i].zName);
9450 }
9451 }else
9452
9453 /* .session open DB NAME
9454 ** Open a new session called NAME on the attached database DB.
9455 ** DB is normally "main".
9456 */
9457 if( strcmp(azCmd[0],"open")==0 ){
9458 char *zName;
9459 if( nCmd!=3 ) goto session_syntax_error;
9460 zName = azCmd[2];
9461 if( zName[0]==0 ) goto session_syntax_error;
9462 for(i=0; i<p->nSession; i++){
9463 if( strcmp(p->aSession[i].zName,zName)==0 ){
9464 utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
9465 goto meta_command_exit;
9466 }
9467 }
9468 if( p->nSession>=ArraySize(p->aSession) ){
9469 raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(p->aSession));
9470 goto meta_command_exit;
9471 }
9472 pSession = &p->aSession[p->nSession];
9473 rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
9474 if( rc ){
9475 raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
9476 rc = 0;
9477 goto meta_command_exit;
9478 }
9479 pSession->nFilter = 0;
9480 sqlite3session_table_filter(pSession->p, session_filter, pSession);
9481 p->nSession++;
9482 pSession->zName = sqlite3_mprintf("%s", zName);
9483 }else
9484 /* If no command name matches, show a syntax error */
9485 session_syntax_error:
drheb7f2a02018-09-26 18:02:32 +00009486 showHelp(p->out, "session");
drh2ce15c32017-07-11 13:34:40 +00009487 }else
9488#endif
9489
9490#ifdef SQLITE_DEBUG
9491 /* Undocumented commands for internal testing. Subject to change
9492 ** without notice. */
9493 if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
9494 if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
9495 int i, v;
9496 for(i=1; i<nArg; i++){
9497 v = booleanValue(azArg[i]);
9498 utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
9499 }
9500 }
9501 if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
9502 int i; sqlite3_int64 v;
9503 for(i=1; i<nArg; i++){
9504 char zBuf[200];
9505 v = integerValue(azArg[i]);
9506 sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
9507 utf8_printf(p->out, "%s", zBuf);
9508 }
9509 }
9510 }else
9511#endif
9512
9513 if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){
9514 int bIsInit = 0; /* True to initialize the SELFTEST table */
9515 int bVerbose = 0; /* Verbose output */
9516 int bSelftestExists; /* True if SELFTEST already exists */
9517 int i, k; /* Loop counters */
9518 int nTest = 0; /* Number of tests runs */
9519 int nErr = 0; /* Number of errors seen */
9520 ShellText str; /* Answer for a query */
9521 sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
9522
9523 open_db(p,0);
9524 for(i=1; i<nArg; i++){
9525 const char *z = azArg[i];
9526 if( z[0]=='-' && z[1]=='-' ) z++;
9527 if( strcmp(z,"-init")==0 ){
9528 bIsInit = 1;
9529 }else
9530 if( strcmp(z,"-v")==0 ){
9531 bVerbose++;
9532 }else
9533 {
9534 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
9535 azArg[i], azArg[0]);
9536 raw_printf(stderr, "Should be one of: --init -v\n");
9537 rc = 1;
9538 goto meta_command_exit;
9539 }
9540 }
9541 if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
9542 != SQLITE_OK ){
9543 bSelftestExists = 0;
9544 }else{
9545 bSelftestExists = 1;
9546 }
9547 if( bIsInit ){
9548 createSelftestTable(p);
9549 bSelftestExists = 1;
9550 }
9551 initText(&str);
9552 appendText(&str, "x", 0);
9553 for(k=bSelftestExists; k>=0; k--){
9554 if( k==1 ){
9555 rc = sqlite3_prepare_v2(p->db,
9556 "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
9557 -1, &pStmt, 0);
9558 }else{
9559 rc = sqlite3_prepare_v2(p->db,
9560 "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
9561 " (1,'run','PRAGMA integrity_check','ok')",
9562 -1, &pStmt, 0);
9563 }
9564 if( rc ){
9565 raw_printf(stderr, "Error querying the selftest table\n");
9566 rc = 1;
9567 sqlite3_finalize(pStmt);
9568 goto meta_command_exit;
9569 }
9570 for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
9571 int tno = sqlite3_column_int(pStmt, 0);
9572 const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
9573 const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
9574 const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
9575
9576 k = 0;
9577 if( bVerbose>0 ){
9578 char *zQuote = sqlite3_mprintf("%q", zSql);
9579 printf("%d: %s %s\n", tno, zOp, zSql);
9580 sqlite3_free(zQuote);
9581 }
9582 if( strcmp(zOp,"memo")==0 ){
9583 utf8_printf(p->out, "%s\n", zSql);
9584 }else
9585 if( strcmp(zOp,"run")==0 ){
9586 char *zErrMsg = 0;
9587 str.n = 0;
9588 str.z[0] = 0;
9589 rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
9590 nTest++;
9591 if( bVerbose ){
9592 utf8_printf(p->out, "Result: %s\n", str.z);
9593 }
9594 if( rc || zErrMsg ){
9595 nErr++;
9596 rc = 1;
9597 utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
9598 sqlite3_free(zErrMsg);
9599 }else if( strcmp(zAns,str.z)!=0 ){
9600 nErr++;
9601 rc = 1;
9602 utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
9603 utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z);
9604 }
9605 }else
9606 {
9607 utf8_printf(stderr,
9608 "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
9609 rc = 1;
9610 break;
9611 }
9612 } /* End loop over rows of content from SELFTEST */
9613 sqlite3_finalize(pStmt);
9614 } /* End loop over k */
9615 freeText(&str);
9616 utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
9617 }else
9618
9619 if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
9620 if( nArg<2 || nArg>3 ){
9621 raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
9622 rc = 1;
9623 }
9624 if( nArg>=2 ){
9625 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
9626 "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
9627 }
9628 if( nArg>=3 ){
9629 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator,
9630 "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]);
9631 }
9632 }else
9633
9634 if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){
9635 const char *zLike = 0; /* Which table to checksum. 0 means everything */
9636 int i; /* Loop counter */
9637 int bSchema = 0; /* Also hash the schema */
9638 int bSeparate = 0; /* Hash each table separately */
9639 int iSize = 224; /* Hash algorithm to use */
9640 int bDebug = 0; /* Only show the query that would have run */
9641 sqlite3_stmt *pStmt; /* For querying tables names */
9642 char *zSql; /* SQL to be run */
9643 char *zSep; /* Separator */
9644 ShellText sSql; /* Complete SQL for the query to run the hash */
9645 ShellText sQuery; /* Set of queries used to read all content */
9646 open_db(p, 0);
9647 for(i=1; i<nArg; i++){
9648 const char *z = azArg[i];
9649 if( z[0]=='-' ){
9650 z++;
9651 if( z[0]=='-' ) z++;
9652 if( strcmp(z,"schema")==0 ){
9653 bSchema = 1;
9654 }else
9655 if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
9656 || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
9657 ){
9658 iSize = atoi(&z[5]);
9659 }else
9660 if( strcmp(z,"debug")==0 ){
9661 bDebug = 1;
9662 }else
9663 {
9664 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
9665 azArg[i], azArg[0]);
drhe2754c12019-08-26 12:50:01 +00009666 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00009667 rc = 1;
9668 goto meta_command_exit;
9669 }
9670 }else if( zLike ){
9671 raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
9672 rc = 1;
9673 goto meta_command_exit;
9674 }else{
9675 zLike = z;
9676 bSeparate = 1;
drhcedfecf2018-03-23 12:59:10 +00009677 if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1;
drh2ce15c32017-07-11 13:34:40 +00009678 }
9679 }
9680 if( bSchema ){
drh067b92b2020-06-19 15:24:12 +00009681 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00009682 " WHERE type='table' AND coalesce(rootpage,0)>1"
drh067b92b2020-06-19 15:24:12 +00009683 " UNION ALL SELECT 'sqlite_schema'"
drh2ce15c32017-07-11 13:34:40 +00009684 " ORDER BY 1 collate nocase";
9685 }else{
drh067b92b2020-06-19 15:24:12 +00009686 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00009687 " WHERE type='table' AND coalesce(rootpage,0)>1"
9688 " AND name NOT LIKE 'sqlite_%'"
9689 " ORDER BY 1 collate nocase";
9690 }
9691 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9692 initText(&sQuery);
9693 initText(&sSql);
9694 appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
9695 zSep = "VALUES(";
9696 while( SQLITE_ROW==sqlite3_step(pStmt) ){
9697 const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
9698 if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
9699 if( strncmp(zTab, "sqlite_",7)!=0 ){
9700 appendText(&sQuery,"SELECT * FROM ", 0);
9701 appendText(&sQuery,zTab,'"');
9702 appendText(&sQuery," NOT INDEXED;", 0);
drh067b92b2020-06-19 15:24:12 +00009703 }else if( strcmp(zTab, "sqlite_schema")==0 ){
9704 appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00009705 " ORDER BY name;", 0);
9706 }else if( strcmp(zTab, "sqlite_sequence")==0 ){
9707 appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
9708 " ORDER BY name;", 0);
9709 }else if( strcmp(zTab, "sqlite_stat1")==0 ){
9710 appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
9711 " ORDER BY tbl,idx;", 0);
drh175b8f02019-08-08 15:24:17 +00009712 }else if( strcmp(zTab, "sqlite_stat4")==0 ){
drh2ce15c32017-07-11 13:34:40 +00009713 appendText(&sQuery, "SELECT * FROM ", 0);
9714 appendText(&sQuery, zTab, 0);
9715 appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
9716 }
9717 appendText(&sSql, zSep, 0);
9718 appendText(&sSql, sQuery.z, '\'');
9719 sQuery.n = 0;
9720 appendText(&sSql, ",", 0);
9721 appendText(&sSql, zTab, '\'');
9722 zSep = "),(";
9723 }
9724 sqlite3_finalize(pStmt);
9725 if( bSeparate ){
9726 zSql = sqlite3_mprintf(
9727 "%s))"
9728 " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
9729 " FROM [sha3sum$query]",
9730 sSql.z, iSize);
9731 }else{
9732 zSql = sqlite3_mprintf(
9733 "%s))"
9734 " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
9735 " FROM [sha3sum$query]",
9736 sSql.z, iSize);
9737 }
9738 freeText(&sQuery);
9739 freeText(&sSql);
9740 if( bDebug ){
9741 utf8_printf(p->out, "%s\n", zSql);
9742 }else{
drha10b9992018-03-09 15:24:33 +00009743 shell_exec(p, zSql, 0);
drh2ce15c32017-07-11 13:34:40 +00009744 }
9745 sqlite3_free(zSql);
9746 }else
9747
drh04a28c32018-01-31 01:38:44 +00009748#ifndef SQLITE_NOHAVE_SYSTEM
drh2ce15c32017-07-11 13:34:40 +00009749 if( c=='s'
9750 && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
9751 ){
9752 char *zCmd;
9753 int i, x;
9754 if( nArg<2 ){
9755 raw_printf(stderr, "Usage: .system COMMAND\n");
9756 rc = 1;
9757 goto meta_command_exit;
9758 }
9759 zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
9760 for(i=2; i<nArg; i++){
9761 zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
9762 zCmd, azArg[i]);
9763 }
9764 x = system(zCmd);
9765 sqlite3_free(zCmd);
9766 if( x ) raw_printf(stderr, "System command returns %d\n", x);
9767 }else
drh04a28c32018-01-31 01:38:44 +00009768#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
drh2ce15c32017-07-11 13:34:40 +00009769
9770 if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
drhada70452017-12-21 21:02:27 +00009771 static const char *azBool[] = { "off", "on", "trigger", "full"};
drha6e6cf22021-01-09 19:10:04 +00009772 const char *zOut;
drh2ce15c32017-07-11 13:34:40 +00009773 int i;
9774 if( nArg!=1 ){
9775 raw_printf(stderr, "Usage: .show\n");
9776 rc = 1;
9777 goto meta_command_exit;
9778 }
9779 utf8_printf(p->out, "%12.12s: %s\n","echo",
9780 azBool[ShellHasFlag(p, SHFLG_Echo)]);
9781 utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
9782 utf8_printf(p->out, "%12.12s: %s\n","explain",
9783 p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
9784 utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
9785 utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
9786 utf8_printf(p->out, "%12.12s: ", "nullvalue");
9787 output_c_string(p->out, p->nullValue);
9788 raw_printf(p->out, "\n");
9789 utf8_printf(p->out,"%12.12s: %s\n","output",
9790 strlen30(p->outfile) ? p->outfile : "stdout");
9791 utf8_printf(p->out,"%12.12s: ", "colseparator");
9792 output_c_string(p->out, p->colSeparator);
9793 raw_printf(p->out, "\n");
9794 utf8_printf(p->out,"%12.12s: ", "rowseparator");
9795 output_c_string(p->out, p->rowSeparator);
9796 raw_printf(p->out, "\n");
drha6e6cf22021-01-09 19:10:04 +00009797 switch( p->statsOn ){
9798 case 0: zOut = "off"; break;
9799 default: zOut = "on"; break;
9800 case 2: zOut = "stmt"; break;
9801 case 3: zOut = "vmstep"; break;
9802 }
9803 utf8_printf(p->out, "%12.12s: %s\n","stats", zOut);
drh2ce15c32017-07-11 13:34:40 +00009804 utf8_printf(p->out, "%12.12s: ", "width");
drh0285d982020-05-29 14:38:43 +00009805 for (i=0;i<p->nWidth;i++) {
drh2ce15c32017-07-11 13:34:40 +00009806 raw_printf(p->out, "%d ", p->colWidth[i]);
9807 }
9808 raw_printf(p->out, "\n");
9809 utf8_printf(p->out, "%12.12s: %s\n", "filename",
9810 p->zDbFilename ? p->zDbFilename : "");
9811 }else
9812
9813 if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
9814 if( nArg==2 ){
drha6e6cf22021-01-09 19:10:04 +00009815 if( strcmp(azArg[1],"stmt")==0 ){
9816 p->statsOn = 2;
9817 }else if( strcmp(azArg[1],"vmstep")==0 ){
9818 p->statsOn = 3;
9819 }else{
9820 p->statsOn = (u8)booleanValue(azArg[1]);
9821 }
drh2ce15c32017-07-11 13:34:40 +00009822 }else if( nArg==1 ){
9823 display_stats(p->db, p, 0);
9824 }else{
drha6e6cf22021-01-09 19:10:04 +00009825 raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n");
drh2ce15c32017-07-11 13:34:40 +00009826 rc = 1;
9827 }
9828 }else
9829
9830 if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0)
9831 || (c=='i' && (strncmp(azArg[0], "indices", n)==0
9832 || strncmp(azArg[0], "indexes", n)==0) )
9833 ){
9834 sqlite3_stmt *pStmt;
9835 char **azResult;
9836 int nRow, nAlloc;
9837 int ii;
9838 ShellText s;
9839 initText(&s);
9840 open_db(p, 0);
9841 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
drh9e804032018-05-18 17:11:50 +00009842 if( rc ){
9843 sqlite3_finalize(pStmt);
9844 return shellDatabaseError(p->db);
9845 }
drh2ce15c32017-07-11 13:34:40 +00009846
9847 if( nArg>2 && c=='i' ){
9848 /* It is an historical accident that the .indexes command shows an error
9849 ** when called with the wrong number of arguments whereas the .tables
9850 ** command does not. */
9851 raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
9852 rc = 1;
drh9e804032018-05-18 17:11:50 +00009853 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00009854 goto meta_command_exit;
9855 }
9856 for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
9857 const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
9858 if( zDbName==0 ) continue;
9859 if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0);
9860 if( sqlite3_stricmp(zDbName, "main")==0 ){
9861 appendText(&s, "SELECT name FROM ", 0);
9862 }else{
9863 appendText(&s, "SELECT ", 0);
9864 appendText(&s, zDbName, '\'');
9865 appendText(&s, "||'.'||name FROM ", 0);
9866 }
9867 appendText(&s, zDbName, '"');
drh067b92b2020-06-19 15:24:12 +00009868 appendText(&s, ".sqlite_schema ", 0);
drh2ce15c32017-07-11 13:34:40 +00009869 if( c=='t' ){
9870 appendText(&s," WHERE type IN ('table','view')"
9871 " AND name NOT LIKE 'sqlite_%'"
9872 " AND name LIKE ?1", 0);
9873 }else{
9874 appendText(&s," WHERE type='index'"
9875 " AND tbl_name LIKE ?1", 0);
9876 }
9877 }
9878 rc = sqlite3_finalize(pStmt);
9879 appendText(&s, " ORDER BY 1", 0);
9880 rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
9881 freeText(&s);
9882 if( rc ) return shellDatabaseError(p->db);
9883
9884 /* Run the SQL statement prepared by the above block. Store the results
9885 ** as an array of nul-terminated strings in azResult[]. */
9886 nRow = nAlloc = 0;
9887 azResult = 0;
9888 if( nArg>1 ){
9889 sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
9890 }else{
9891 sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
9892 }
9893 while( sqlite3_step(pStmt)==SQLITE_ROW ){
9894 if( nRow>=nAlloc ){
9895 char **azNew;
9896 int n2 = nAlloc*2 + 10;
9897 azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
drh4b5345c2018-04-24 13:07:40 +00009898 if( azNew==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00009899 nAlloc = n2;
9900 azResult = azNew;
9901 }
9902 azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
drh4b5345c2018-04-24 13:07:40 +00009903 if( 0==azResult[nRow] ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00009904 nRow++;
9905 }
9906 if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
9907 rc = shellDatabaseError(p->db);
9908 }
9909
9910 /* Pretty-print the contents of array azResult[] to the output */
9911 if( rc==0 && nRow>0 ){
9912 int len, maxlen = 0;
9913 int i, j;
9914 int nPrintCol, nPrintRow;
9915 for(i=0; i<nRow; i++){
9916 len = strlen30(azResult[i]);
9917 if( len>maxlen ) maxlen = len;
9918 }
9919 nPrintCol = 80/(maxlen+2);
9920 if( nPrintCol<1 ) nPrintCol = 1;
9921 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
9922 for(i=0; i<nPrintRow; i++){
9923 for(j=i; j<nRow; j+=nPrintRow){
9924 char *zSp = j<nPrintRow ? "" : " ";
9925 utf8_printf(p->out, "%s%-*s", zSp, maxlen,
9926 azResult[j] ? azResult[j]:"");
9927 }
9928 raw_printf(p->out, "\n");
9929 }
9930 }
9931
9932 for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
9933 sqlite3_free(azResult);
9934 }else
9935
9936 /* Begin redirecting output to the file "testcase-out.txt" */
9937 if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
9938 output_reset(p);
drha92a01a2018-01-10 22:15:37 +00009939 p->out = output_file_open("testcase-out.txt", 0);
drh2ce15c32017-07-11 13:34:40 +00009940 if( p->out==0 ){
9941 raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
9942 }
9943 if( nArg>=2 ){
9944 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
9945 }else{
9946 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
9947 }
9948 }else
9949
9950#ifndef SQLITE_UNTESTABLE
drh35f51a42017-11-15 17:07:22 +00009951 if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009952 static const struct {
9953 const char *zCtrlName; /* Name of a test-control option */
9954 int ctrlCode; /* Integer code for that option */
drhef302e82017-11-15 19:14:08 +00009955 const char *zUsage; /* Usage notes */
drh2ce15c32017-07-11 13:34:40 +00009956 } aCtrl[] = {
drhe2754c12019-08-26 12:50:01 +00009957 { "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" },
9958 { "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" },
9959 /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/
9960 /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/
9961 { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" },
9962 { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN" },
9963 /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" },*/
9964 { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
drh171c50e2020-01-01 15:43:30 +00009965 { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "" },
drhe2754c12019-08-26 12:50:01 +00009966 { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" },
9967 { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" },
9968 { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" },
drh0d9de992017-12-26 18:04:23 +00009969#ifdef YYCOVERAGE
drhe2754c12019-08-26 12:50:01 +00009970 { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" },
drh0d9de992017-12-26 18:04:23 +00009971#endif
drhe2754c12019-08-26 12:50:01 +00009972 { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " },
9973 { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
9974 { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
9975 { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
drh37ccfcf2020-08-31 18:49:04 +00009976 { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, "" },
drhf3c12562021-06-04 13:16:46 +00009977 { "tune", SQLITE_TESTCTRL_TUNE, "ID VALUE" },
drh2ce15c32017-07-11 13:34:40 +00009978 };
9979 int testctrl = -1;
drhef302e82017-11-15 19:14:08 +00009980 int iCtrl = -1;
9981 int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */
9982 int isOk = 0;
drh2ce15c32017-07-11 13:34:40 +00009983 int i, n2;
mistachkinc6bc15a2017-11-21 21:14:32 +00009984 const char *zCmd = 0;
9985
drh2ce15c32017-07-11 13:34:40 +00009986 open_db(p, 0);
mistachkinc6bc15a2017-11-21 21:14:32 +00009987 zCmd = nArg>=2 ? azArg[1] : "help";
drh35f51a42017-11-15 17:07:22 +00009988
9989 /* The argument can optionally begin with "-" or "--" */
9990 if( zCmd[0]=='-' && zCmd[1] ){
9991 zCmd++;
9992 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
9993 }
9994
9995 /* --help lists all test-controls */
9996 if( strcmp(zCmd,"help")==0 ){
9997 utf8_printf(p->out, "Available test-controls:\n");
9998 for(i=0; i<ArraySize(aCtrl); i++){
drhef302e82017-11-15 19:14:08 +00009999 utf8_printf(p->out, " .testctrl %s %s\n",
10000 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
drh35f51a42017-11-15 17:07:22 +000010001 }
10002 rc = 1;
10003 goto meta_command_exit;
10004 }
drh2ce15c32017-07-11 13:34:40 +000010005
10006 /* convert testctrl text option to value. allow any unique prefix
10007 ** of the option name, or a numerical value. */
drh35f51a42017-11-15 17:07:22 +000010008 n2 = strlen30(zCmd);
drh2ce15c32017-07-11 13:34:40 +000010009 for(i=0; i<ArraySize(aCtrl); i++){
drh35f51a42017-11-15 17:07:22 +000010010 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010011 if( testctrl<0 ){
10012 testctrl = aCtrl[i].ctrlCode;
drhef302e82017-11-15 19:14:08 +000010013 iCtrl = i;
drh2ce15c32017-07-11 13:34:40 +000010014 }else{
drh35f51a42017-11-15 17:07:22 +000010015 utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
10016 "Use \".testctrl --help\" for help\n", zCmd);
10017 rc = 1;
10018 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +000010019 }
10020 }
10021 }
drhef302e82017-11-15 19:14:08 +000010022 if( testctrl<0 ){
drh35f51a42017-11-15 17:07:22 +000010023 utf8_printf(stderr,"Error: unknown test-control: %s\n"
10024 "Use \".testctrl --help\" for help\n", zCmd);
drh2ce15c32017-07-11 13:34:40 +000010025 }else{
10026 switch(testctrl){
10027
10028 /* sqlite3_test_control(int, db, int) */
10029 case SQLITE_TESTCTRL_OPTIMIZATIONS:
drh2ce15c32017-07-11 13:34:40 +000010030 if( nArg==3 ){
drhaf7b7652021-01-13 19:28:17 +000010031 unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
drh2ce15c32017-07-11 13:34:40 +000010032 rc2 = sqlite3_test_control(testctrl, p->db, opt);
drhef302e82017-11-15 19:14:08 +000010033 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010034 }
10035 break;
10036
10037 /* sqlite3_test_control(int) */
10038 case SQLITE_TESTCTRL_PRNG_SAVE:
10039 case SQLITE_TESTCTRL_PRNG_RESTORE:
drh2ce15c32017-07-11 13:34:40 +000010040 case SQLITE_TESTCTRL_BYTEORDER:
10041 if( nArg==2 ){
10042 rc2 = sqlite3_test_control(testctrl);
drhef302e82017-11-15 19:14:08 +000010043 isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
drh2ce15c32017-07-11 13:34:40 +000010044 }
10045 break;
10046
10047 /* sqlite3_test_control(int, uint) */
10048 case SQLITE_TESTCTRL_PENDING_BYTE:
10049 if( nArg==3 ){
10050 unsigned int opt = (unsigned int)integerValue(azArg[2]);
10051 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010052 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010053 }
10054 break;
10055
drh2e6d83b2019-08-03 01:39:20 +000010056 /* sqlite3_test_control(int, int, sqlite3*) */
10057 case SQLITE_TESTCTRL_PRNG_SEED:
10058 if( nArg==3 || nArg==4 ){
drh51755a72019-08-08 19:40:29 +000010059 int ii = (int)integerValue(azArg[2]);
drh2e6d83b2019-08-03 01:39:20 +000010060 sqlite3 *db;
drh41428a92019-08-12 16:25:11 +000010061 if( ii==0 && strcmp(azArg[2],"random")==0 ){
10062 sqlite3_randomness(sizeof(ii),&ii);
10063 printf("-- random seed: %d\n", ii);
10064 }
drh2e6d83b2019-08-03 01:39:20 +000010065 if( nArg==3 ){
10066 db = 0;
10067 }else{
10068 db = p->db;
10069 /* Make sure the schema has been loaded */
10070 sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);
10071 }
drh51755a72019-08-08 19:40:29 +000010072 rc2 = sqlite3_test_control(testctrl, ii, db);
drh2e6d83b2019-08-03 01:39:20 +000010073 isOk = 3;
10074 }
10075 break;
10076
drh2ce15c32017-07-11 13:34:40 +000010077 /* sqlite3_test_control(int, int) */
10078 case SQLITE_TESTCTRL_ASSERT:
10079 case SQLITE_TESTCTRL_ALWAYS:
drhef302e82017-11-15 19:14:08 +000010080 if( nArg==3 ){
10081 int opt = booleanValue(azArg[2]);
10082 rc2 = sqlite3_test_control(testctrl, opt);
10083 isOk = 1;
10084 }
10085 break;
10086
10087 /* sqlite3_test_control(int, int) */
10088 case SQLITE_TESTCTRL_LOCALTIME_FAULT:
drh2ce15c32017-07-11 13:34:40 +000010089 case SQLITE_TESTCTRL_NEVER_CORRUPT:
10090 if( nArg==3 ){
10091 int opt = booleanValue(azArg[2]);
10092 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010093 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010094 }
10095 break;
10096
drh171c50e2020-01-01 15:43:30 +000010097 /* sqlite3_test_control(sqlite3*) */
10098 case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
10099 rc2 = sqlite3_test_control(testctrl, p->db);
drh2a83c102020-01-01 23:02:35 +000010100 isOk = 3;
drh171c50e2020-01-01 15:43:30 +000010101 break;
10102
drh2ce15c32017-07-11 13:34:40 +000010103 case SQLITE_TESTCTRL_IMPOSTER:
10104 if( nArg==5 ){
10105 rc2 = sqlite3_test_control(testctrl, p->db,
10106 azArg[2],
10107 integerValue(azArg[3]),
10108 integerValue(azArg[4]));
drhef302e82017-11-15 19:14:08 +000010109 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010110 }
10111 break;
drh0d9de992017-12-26 18:04:23 +000010112
drh37ccfcf2020-08-31 18:49:04 +000010113 case SQLITE_TESTCTRL_SEEK_COUNT: {
10114 u64 x = 0;
10115 rc2 = sqlite3_test_control(testctrl, p->db, &x);
10116 utf8_printf(p->out, "%llu\n", x);
10117 isOk = 3;
10118 break;
10119 }
10120
drh0d9de992017-12-26 18:04:23 +000010121#ifdef YYCOVERAGE
drhf3c12562021-06-04 13:16:46 +000010122 case SQLITE_TESTCTRL_PARSER_COVERAGE: {
drh0d9de992017-12-26 18:04:23 +000010123 if( nArg==2 ){
10124 sqlite3_test_control(testctrl, p->out);
10125 isOk = 3;
10126 }
drhf3c12562021-06-04 13:16:46 +000010127 break;
10128 }
10129#endif
10130#ifdef SQLITE_DEBUG
10131 case SQLITE_TESTCTRL_TUNE: {
10132 if( nArg==4 ){
10133 int id = (int)integerValue(azArg[2]);
drh2d26cfc2021-06-04 13:40:26 +000010134 int val = (int)integerValue(azArg[3]);
10135 sqlite3_test_control(testctrl, id, &val);
10136 isOk = 3;
10137 }else if( nArg==3 ){
10138 int id = (int)integerValue(azArg[2]);
10139 sqlite3_test_control(testctrl, -id, &rc2);
10140 isOk = 1;
10141 }else if( nArg==2 ){
10142 int id = 1;
10143 while(1){
10144 int val = 0;
10145 rc2 = sqlite3_test_control(testctrl, -id, &val);
10146 if( rc2!=SQLITE_OK ) break;
10147 if( id>1 ) utf8_printf(p->out, " ");
10148 utf8_printf(p->out, "%d: %d", id, val);
10149 id++;
10150 }
10151 if( id>1 ) utf8_printf(p->out, "\n");
drhf3c12562021-06-04 13:16:46 +000010152 isOk = 3;
10153 }
10154 break;
10155 }
drh0d9de992017-12-26 18:04:23 +000010156#endif
drh2ce15c32017-07-11 13:34:40 +000010157 }
10158 }
drhef302e82017-11-15 19:14:08 +000010159 if( isOk==0 && iCtrl>=0 ){
drhe2754c12019-08-26 12:50:01 +000010160 utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
drhef302e82017-11-15 19:14:08 +000010161 rc = 1;
10162 }else if( isOk==1 ){
10163 raw_printf(p->out, "%d\n", rc2);
10164 }else if( isOk==2 ){
10165 raw_printf(p->out, "0x%08x\n", rc2);
10166 }
drh2ce15c32017-07-11 13:34:40 +000010167 }else
10168#endif /* !defined(SQLITE_UNTESTABLE) */
10169
10170 if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
10171 open_db(p, 0);
10172 sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
10173 }else
10174
10175 if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
10176 if( nArg==2 ){
10177 enableTimer = booleanValue(azArg[1]);
10178 if( enableTimer && !HAS_TIMER ){
10179 raw_printf(stderr, "Error: timer not available on this system.\n");
10180 enableTimer = 0;
10181 }
10182 }else{
10183 raw_printf(stderr, "Usage: .timer on|off\n");
10184 rc = 1;
10185 }
10186 }else
10187
drh707821f2018-12-05 13:39:06 +000010188#ifndef SQLITE_OMIT_TRACE
drh2ce15c32017-07-11 13:34:40 +000010189 if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
drh707821f2018-12-05 13:39:06 +000010190 int mType = 0;
10191 int jj;
drh2ce15c32017-07-11 13:34:40 +000010192 open_db(p, 0);
drh707821f2018-12-05 13:39:06 +000010193 for(jj=1; jj<nArg; jj++){
10194 const char *z = azArg[jj];
10195 if( z[0]=='-' ){
10196 if( optionMatch(z, "expanded") ){
10197 p->eTraceType = SHELL_TRACE_EXPANDED;
10198 }
10199#ifdef SQLITE_ENABLE_NORMALIZE
10200 else if( optionMatch(z, "normalized") ){
10201 p->eTraceType = SHELL_TRACE_NORMALIZED;
10202 }
10203#endif
10204 else if( optionMatch(z, "plain") ){
10205 p->eTraceType = SHELL_TRACE_PLAIN;
10206 }
10207 else if( optionMatch(z, "profile") ){
10208 mType |= SQLITE_TRACE_PROFILE;
10209 }
10210 else if( optionMatch(z, "row") ){
10211 mType |= SQLITE_TRACE_ROW;
10212 }
10213 else if( optionMatch(z, "stmt") ){
10214 mType |= SQLITE_TRACE_STMT;
10215 }
10216 else if( optionMatch(z, "close") ){
10217 mType |= SQLITE_TRACE_CLOSE;
10218 }
10219 else {
10220 raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
10221 rc = 1;
10222 goto meta_command_exit;
10223 }
10224 }else{
10225 output_file_close(p->traceOut);
10226 p->traceOut = output_file_open(azArg[1], 0);
10227 }
drh2ce15c32017-07-11 13:34:40 +000010228 }
drh2ce15c32017-07-11 13:34:40 +000010229 if( p->traceOut==0 ){
10230 sqlite3_trace_v2(p->db, 0, 0, 0);
10231 }else{
drh707821f2018-12-05 13:39:06 +000010232 if( mType==0 ) mType = SQLITE_TRACE_STMT;
10233 sqlite3_trace_v2(p->db, mType, sql_trace_callback, p);
drh2ce15c32017-07-11 13:34:40 +000010234 }
drh2ce15c32017-07-11 13:34:40 +000010235 }else
drh707821f2018-12-05 13:39:06 +000010236#endif /* !defined(SQLITE_OMIT_TRACE) */
drh2ce15c32017-07-11 13:34:40 +000010237
drhe2b7a762019-10-02 00:25:08 +000010238#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhcc5979d2019-08-16 22:58:29 +000010239 if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){
10240 int ii;
drh8c754a32019-08-19 20:35:30 +000010241 int lenOpt;
drh5df84282019-08-17 19:45:25 +000010242 char *zOpt;
drhcc5979d2019-08-16 22:58:29 +000010243 if( nArg<2 ){
drh5df84282019-08-17 19:45:25 +000010244 raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
drhcc5979d2019-08-16 22:58:29 +000010245 rc = 1;
10246 goto meta_command_exit;
10247 }
10248 open_db(p, 0);
drh5df84282019-08-17 19:45:25 +000010249 zOpt = azArg[1];
10250 if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
drh8c754a32019-08-19 20:35:30 +000010251 lenOpt = (int)strlen(zOpt);
10252 if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){
drh5df84282019-08-17 19:45:25 +000010253 assert( azArg[nArg]==0 );
drh8c754a32019-08-19 20:35:30 +000010254 sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0);
drh5df84282019-08-17 19:45:25 +000010255 }else{
10256 for(ii=1; ii<nArg; ii++){
10257 sqlite3_create_module(p->db, azArg[ii], 0, 0);
10258 }
drhcc5979d2019-08-16 22:58:29 +000010259 }
10260 }else
10261#endif
10262
drh2ce15c32017-07-11 13:34:40 +000010263#if SQLITE_USER_AUTHENTICATION
10264 if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
10265 if( nArg<2 ){
10266 raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
10267 rc = 1;
10268 goto meta_command_exit;
10269 }
10270 open_db(p, 0);
10271 if( strcmp(azArg[1],"login")==0 ){
10272 if( nArg!=4 ){
10273 raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
10274 rc = 1;
10275 goto meta_command_exit;
10276 }
drhe2754c12019-08-26 12:50:01 +000010277 rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
10278 strlen30(azArg[3]));
drh2ce15c32017-07-11 13:34:40 +000010279 if( rc ){
10280 utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
10281 rc = 1;
10282 }
10283 }else if( strcmp(azArg[1],"add")==0 ){
10284 if( nArg!=5 ){
10285 raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
10286 rc = 1;
10287 goto meta_command_exit;
10288 }
drhaf2770f2018-01-05 14:55:43 +000010289 rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000010290 booleanValue(azArg[4]));
10291 if( rc ){
10292 raw_printf(stderr, "User-Add failed: %d\n", rc);
10293 rc = 1;
10294 }
10295 }else if( strcmp(azArg[1],"edit")==0 ){
10296 if( nArg!=5 ){
10297 raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
10298 rc = 1;
10299 goto meta_command_exit;
10300 }
drhaf2770f2018-01-05 14:55:43 +000010301 rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000010302 booleanValue(azArg[4]));
10303 if( rc ){
10304 raw_printf(stderr, "User-Edit failed: %d\n", rc);
10305 rc = 1;
10306 }
10307 }else if( strcmp(azArg[1],"delete")==0 ){
10308 if( nArg!=3 ){
10309 raw_printf(stderr, "Usage: .user delete USER\n");
10310 rc = 1;
10311 goto meta_command_exit;
10312 }
10313 rc = sqlite3_user_delete(p->db, azArg[2]);
10314 if( rc ){
10315 raw_printf(stderr, "User-Delete failed: %d\n", rc);
10316 rc = 1;
10317 }
10318 }else{
10319 raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
10320 rc = 1;
10321 goto meta_command_exit;
10322 }
10323 }else
10324#endif /* SQLITE_USER_AUTHENTICATION */
10325
10326 if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
10327 utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
10328 sqlite3_libversion(), sqlite3_sourceid());
drh0ed2fd82018-01-16 20:05:27 +000010329#if SQLITE_HAVE_ZLIB
10330 utf8_printf(p->out, "zlib version %s\n", zlibVersion());
10331#endif
10332#define CTIMEOPT_VAL_(opt) #opt
10333#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
10334#if defined(__clang__) && defined(__clang_major__)
10335 utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
10336 CTIMEOPT_VAL(__clang_minor__) "."
10337 CTIMEOPT_VAL(__clang_patchlevel__) "\n");
10338#elif defined(_MSC_VER)
10339 utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n");
10340#elif defined(__GNUC__) && defined(__VERSION__)
10341 utf8_printf(p->out, "gcc-" __VERSION__ "\n");
10342#endif
drh2ce15c32017-07-11 13:34:40 +000010343 }else
10344
10345 if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
10346 const char *zDbName = nArg==2 ? azArg[1] : "main";
10347 sqlite3_vfs *pVfs = 0;
10348 if( p->db ){
10349 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
10350 if( pVfs ){
10351 utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
10352 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
10353 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
10354 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
10355 }
10356 }
10357 }else
10358
10359 if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){
10360 sqlite3_vfs *pVfs;
10361 sqlite3_vfs *pCurrent = 0;
10362 if( p->db ){
10363 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
10364 }
10365 for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
10366 utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName,
10367 pVfs==pCurrent ? " <--- CURRENT" : "");
10368 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
10369 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
10370 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
10371 if( pVfs->pNext ){
10372 raw_printf(p->out, "-----------------------------------\n");
10373 }
10374 }
10375 }else
10376
10377 if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
10378 const char *zDbName = nArg==2 ? azArg[1] : "main";
10379 char *zVfsName = 0;
10380 if( p->db ){
10381 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
10382 if( zVfsName ){
10383 utf8_printf(p->out, "%s\n", zVfsName);
10384 sqlite3_free(zVfsName);
10385 }
10386 }
10387 }else
10388
drh2ce15c32017-07-11 13:34:40 +000010389 if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
drhc0622a42020-12-04 01:17:57 +000010390 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
10391 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x);
drh2ce15c32017-07-11 13:34:40 +000010392 }else
drh2ce15c32017-07-11 13:34:40 +000010393
10394 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
10395 int j;
10396 assert( nArg<=ArraySize(azArg) );
drh0285d982020-05-29 14:38:43 +000010397 p->nWidth = nArg-1;
10398 p->colWidth = realloc(p->colWidth, p->nWidth*sizeof(int)*2);
10399 if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory();
10400 if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
10401 for(j=1; j<nArg; j++){
drh2ce15c32017-07-11 13:34:40 +000010402 p->colWidth[j-1] = (int)integerValue(azArg[j]);
10403 }
10404 }else
10405
10406 {
10407 utf8_printf(stderr, "Error: unknown command or invalid arguments: "
10408 " \"%s\". Enter \".help\" for help\n", azArg[0]);
10409 rc = 1;
10410 }
10411
10412meta_command_exit:
10413 if( p->outCount ){
10414 p->outCount--;
10415 if( p->outCount==0 ) output_reset(p);
10416 }
10417 return rc;
10418}
10419
10420/*
10421** Return TRUE if a semicolon occurs anywhere in the first N characters
10422** of string z[].
10423*/
10424static int line_contains_semicolon(const char *z, int N){
10425 int i;
10426 for(i=0; i<N; i++){ if( z[i]==';' ) return 1; }
10427 return 0;
10428}
10429
10430/*
10431** Test to see if a line consists entirely of whitespace.
10432*/
10433static int _all_whitespace(const char *z){
10434 for(; *z; z++){
10435 if( IsSpace(z[0]) ) continue;
10436 if( *z=='/' && z[1]=='*' ){
10437 z += 2;
10438 while( *z && (*z!='*' || z[1]!='/') ){ z++; }
10439 if( *z==0 ) return 0;
10440 z++;
10441 continue;
10442 }
10443 if( *z=='-' && z[1]=='-' ){
10444 z += 2;
10445 while( *z && *z!='\n' ){ z++; }
10446 if( *z==0 ) return 1;
10447 continue;
10448 }
10449 return 0;
10450 }
10451 return 1;
10452}
10453
10454/*
10455** Return TRUE if the line typed in is an SQL command terminator other
10456** than a semi-colon. The SQL Server style "go" command is understood
10457** as is the Oracle "/".
10458*/
10459static int line_is_command_terminator(const char *zLine){
10460 while( IsSpace(zLine[0]) ){ zLine++; };
10461 if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ){
10462 return 1; /* Oracle */
10463 }
10464 if( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o'
10465 && _all_whitespace(&zLine[2]) ){
10466 return 1; /* SQL Server */
10467 }
10468 return 0;
10469}
10470
10471/*
drh56f17742018-01-24 01:58:49 +000010472** We need a default sqlite3_complete() implementation to use in case
10473** the shell is compiled with SQLITE_OMIT_COMPLETE. The default assumes
10474** any arbitrary text is a complete SQL statement. This is not very
10475** user-friendly, but it does seem to work.
10476*/
10477#ifdef SQLITE_OMIT_COMPLETE
danc86b23b2018-11-16 14:36:42 +000010478#define sqlite3_complete(x) 1
drh56f17742018-01-24 01:58:49 +000010479#endif
10480
10481/*
drh2ce15c32017-07-11 13:34:40 +000010482** Return true if zSql is a complete SQL statement. Return false if it
10483** ends in the middle of a string literal or C-style comment.
10484*/
10485static int line_is_complete(char *zSql, int nSql){
10486 int rc;
10487 if( zSql==0 ) return 1;
10488 zSql[nSql] = ';';
10489 zSql[nSql+1] = 0;
10490 rc = sqlite3_complete(zSql);
10491 zSql[nSql] = 0;
10492 return rc;
10493}
10494
10495/*
drhfc29a862018-05-11 19:11:18 +000010496** Run a single line of SQL. Return the number of errors.
drh2ce15c32017-07-11 13:34:40 +000010497*/
10498static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
10499 int rc;
10500 char *zErrMsg = 0;
10501
10502 open_db(p, 0);
10503 if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
drhfc4eeef2019-02-05 19:48:46 +000010504 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
drh2ce15c32017-07-11 13:34:40 +000010505 BEGIN_TIMER;
drha10b9992018-03-09 15:24:33 +000010506 rc = shell_exec(p, zSql, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000010507 END_TIMER;
10508 if( rc || zErrMsg ){
10509 char zPrefix[100];
10510 if( in!=0 || !stdin_is_interactive ){
10511 sqlite3_snprintf(sizeof(zPrefix), zPrefix,
10512 "Error: near line %d:", startline);
10513 }else{
10514 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
10515 }
10516 if( zErrMsg!=0 ){
10517 utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
10518 sqlite3_free(zErrMsg);
10519 zErrMsg = 0;
10520 }else{
10521 utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
10522 }
10523 return 1;
10524 }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
10525 raw_printf(p->out, "changes: %3d total_changes: %d\n",
10526 sqlite3_changes(p->db), sqlite3_total_changes(p->db));
10527 }
10528 return 0;
10529}
10530
10531
10532/*
10533** Read input from *in and process it. If *in==0 then input
10534** is interactive - the user is typing it it. Otherwise, input
10535** is coming from a file or device. A prompt is issued and history
10536** is saved only if input is interactive. An interrupt signal will
10537** cause this routine to exit immediately, unless input is interactive.
10538**
10539** Return the number of errors.
10540*/
drh60379d42018-12-13 18:30:01 +000010541static int process_input(ShellState *p){
drh2ce15c32017-07-11 13:34:40 +000010542 char *zLine = 0; /* A single input line */
10543 char *zSql = 0; /* Accumulated SQL text */
10544 int nLine; /* Length of current line */
10545 int nSql = 0; /* Bytes of zSql[] used */
10546 int nAlloc = 0; /* Allocated zSql[] space */
10547 int nSqlPrior = 0; /* Bytes of zSql[] used by prior line */
10548 int rc; /* Error code */
10549 int errCnt = 0; /* Number of errors seen */
drh2ce15c32017-07-11 13:34:40 +000010550 int startline = 0; /* Line number for start of current input */
10551
drh2c8ee022018-12-13 18:59:30 +000010552 p->lineno = 0;
drh60379d42018-12-13 18:30:01 +000010553 while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
drh2ce15c32017-07-11 13:34:40 +000010554 fflush(p->out);
drh60379d42018-12-13 18:30:01 +000010555 zLine = one_input_line(p->in, zLine, nSql>0);
drh2ce15c32017-07-11 13:34:40 +000010556 if( zLine==0 ){
10557 /* End of input */
drh60379d42018-12-13 18:30:01 +000010558 if( p->in==0 && stdin_is_interactive ) printf("\n");
drh2ce15c32017-07-11 13:34:40 +000010559 break;
10560 }
10561 if( seenInterrupt ){
drh60379d42018-12-13 18:30:01 +000010562 if( p->in!=0 ) break;
drh2ce15c32017-07-11 13:34:40 +000010563 seenInterrupt = 0;
10564 }
drh2c8ee022018-12-13 18:59:30 +000010565 p->lineno++;
drh2ce15c32017-07-11 13:34:40 +000010566 if( nSql==0 && _all_whitespace(zLine) ){
10567 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
10568 continue;
10569 }
drh1615c372018-05-12 23:56:22 +000010570 if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
drh2ce15c32017-07-11 13:34:40 +000010571 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
drh1615c372018-05-12 23:56:22 +000010572 if( zLine[0]=='.' ){
10573 rc = do_meta_command(zLine, p);
10574 if( rc==2 ){ /* exit requested */
10575 break;
10576 }else if( rc ){
10577 errCnt++;
10578 }
drh2ce15c32017-07-11 13:34:40 +000010579 }
10580 continue;
10581 }
10582 if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){
10583 memcpy(zLine,";",2);
10584 }
10585 nLine = strlen30(zLine);
10586 if( nSql+nLine+2>=nAlloc ){
10587 nAlloc = nSql+nLine+100;
10588 zSql = realloc(zSql, nAlloc);
drh4b5345c2018-04-24 13:07:40 +000010589 if( zSql==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +000010590 }
10591 nSqlPrior = nSql;
10592 if( nSql==0 ){
10593 int i;
10594 for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
10595 assert( nAlloc>0 && zSql!=0 );
10596 memcpy(zSql, zLine+i, nLine+1-i);
drh2c8ee022018-12-13 18:59:30 +000010597 startline = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000010598 nSql = nLine-i;
10599 }else{
10600 zSql[nSql++] = '\n';
10601 memcpy(zSql+nSql, zLine, nLine+1);
10602 nSql += nLine;
10603 }
10604 if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
10605 && sqlite3_complete(zSql) ){
drh60379d42018-12-13 18:30:01 +000010606 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000010607 nSql = 0;
10608 if( p->outCount ){
10609 output_reset(p);
10610 p->outCount = 0;
drh13c20932018-01-10 21:41:55 +000010611 }else{
10612 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +000010613 }
10614 }else if( nSql && _all_whitespace(zSql) ){
10615 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
10616 nSql = 0;
10617 }
10618 }
10619 if( nSql && !_all_whitespace(zSql) ){
drh60379d42018-12-13 18:30:01 +000010620 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000010621 }
10622 free(zSql);
10623 free(zLine);
10624 return errCnt>0;
10625}
10626
10627/*
10628** Return a pathname which is the user's home directory. A
10629** 0 return indicates an error of some kind.
10630*/
10631static char *find_home_dir(int clearFlag){
10632 static char *home_dir = NULL;
10633 if( clearFlag ){
10634 free(home_dir);
10635 home_dir = 0;
10636 return 0;
10637 }
10638 if( home_dir ) return home_dir;
10639
10640#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
10641 && !defined(__RTP__) && !defined(_WRS_KERNEL)
10642 {
10643 struct passwd *pwent;
10644 uid_t uid = getuid();
10645 if( (pwent=getpwuid(uid)) != NULL) {
10646 home_dir = pwent->pw_dir;
10647 }
10648 }
10649#endif
10650
10651#if defined(_WIN32_WCE)
10652 /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
10653 */
10654 home_dir = "/";
10655#else
10656
10657#if defined(_WIN32) || defined(WIN32)
10658 if (!home_dir) {
10659 home_dir = getenv("USERPROFILE");
10660 }
10661#endif
10662
10663 if (!home_dir) {
10664 home_dir = getenv("HOME");
10665 }
10666
10667#if defined(_WIN32) || defined(WIN32)
10668 if (!home_dir) {
10669 char *zDrive, *zPath;
10670 int n;
10671 zDrive = getenv("HOMEDRIVE");
10672 zPath = getenv("HOMEPATH");
10673 if( zDrive && zPath ){
10674 n = strlen30(zDrive) + strlen30(zPath) + 1;
10675 home_dir = malloc( n );
10676 if( home_dir==0 ) return 0;
10677 sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
10678 return home_dir;
10679 }
10680 home_dir = "c:\\";
10681 }
10682#endif
10683
10684#endif /* !_WIN32_WCE */
10685
10686 if( home_dir ){
10687 int n = strlen30(home_dir) + 1;
10688 char *z = malloc( n );
10689 if( z ) memcpy(z, home_dir, n);
10690 home_dir = z;
10691 }
10692
10693 return home_dir;
10694}
10695
10696/*
10697** Read input from the file given by sqliterc_override. Or if that
10698** parameter is NULL, take input from ~/.sqliterc
10699**
10700** Returns the number of errors.
10701*/
10702static void process_sqliterc(
10703 ShellState *p, /* Configuration data */
10704 const char *sqliterc_override /* Name of config file. NULL to use default */
10705){
10706 char *home_dir = NULL;
10707 const char *sqliterc = sqliterc_override;
10708 char *zBuf = 0;
drh60379d42018-12-13 18:30:01 +000010709 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +000010710 int savedLineno = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000010711
10712 if (sqliterc == NULL) {
10713 home_dir = find_home_dir(0);
10714 if( home_dir==0 ){
10715 raw_printf(stderr, "-- warning: cannot find home directory;"
10716 " cannot read ~/.sqliterc\n");
10717 return;
10718 }
drh2ce15c32017-07-11 13:34:40 +000010719 zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
10720 sqliterc = zBuf;
10721 }
drh60379d42018-12-13 18:30:01 +000010722 p->in = fopen(sqliterc,"rb");
10723 if( p->in ){
drh2ce15c32017-07-11 13:34:40 +000010724 if( stdin_is_interactive ){
10725 utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
10726 }
drhb7c46aa2020-11-25 13:59:47 +000010727 if( process_input(p) && bail_on_error ) exit(1);
drh60379d42018-12-13 18:30:01 +000010728 fclose(p->in);
drhb7c46aa2020-11-25 13:59:47 +000010729 }else if( sqliterc_override!=0 ){
10730 utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
10731 if( bail_on_error ) exit(1);
drh2ce15c32017-07-11 13:34:40 +000010732 }
drh60379d42018-12-13 18:30:01 +000010733 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +000010734 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +000010735 sqlite3_free(zBuf);
10736}
10737
10738/*
10739** Show available command line options
10740*/
10741static const char zOptions[] =
drhda57d962018-03-05 19:34:05 +000010742#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhad7fd5d2018-03-05 20:21:50 +000010743 " -A ARGS... run \".archive ARGS\" and exit\n"
drhda57d962018-03-05 19:34:05 +000010744#endif
drh3baed312018-03-08 18:14:41 +000010745 " -append append the database to the end of the file\n"
drh2ce15c32017-07-11 13:34:40 +000010746 " -ascii set output mode to 'ascii'\n"
10747 " -bail stop after hitting an error\n"
10748 " -batch force batch I/O\n"
drh0908e382020-06-04 18:05:39 +000010749 " -box set output mode to 'box'\n"
drh2ce15c32017-07-11 13:34:40 +000010750 " -column set output mode to 'column'\n"
10751 " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
10752 " -csv set output mode to 'csv'\n"
drh8d889af2021-05-08 17:18:23 +000010753#if !defined(SQLITE_OMIT_DESERIALIZE)
drh6ca64482019-01-22 16:06:20 +000010754 " -deserialize open the database using sqlite3_deserialize()\n"
10755#endif
drh2ce15c32017-07-11 13:34:40 +000010756 " -echo print commands before execution\n"
10757 " -init FILENAME read/process named file\n"
10758 " -[no]header turn headers on or off\n"
10759#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
10760 " -heap SIZE Size of heap for memsys3 or memsys5\n"
10761#endif
10762 " -help show this message\n"
10763 " -html set output mode to HTML\n"
10764 " -interactive force interactive I/O\n"
drh30c54a02020-05-28 23:49:50 +000010765 " -json set output mode to 'json'\n"
drh2ce15c32017-07-11 13:34:40 +000010766 " -line set output mode to 'line'\n"
10767 " -list set output mode to 'list'\n"
10768 " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
drh30c54a02020-05-28 23:49:50 +000010769 " -markdown set output mode to 'markdown'\n"
drh8d889af2021-05-08 17:18:23 +000010770#if !defined(SQLITE_OMIT_DESERIALIZE)
drh6ca64482019-01-22 16:06:20 +000010771 " -maxsize N maximum size for a --deserialize database\n"
10772#endif
drhaf482572019-02-04 19:52:39 +000010773 " -memtrace trace all memory allocations and deallocations\n"
drh2ce15c32017-07-11 13:34:40 +000010774 " -mmap N default mmap size set to N\n"
10775#ifdef SQLITE_ENABLE_MULTIPLEX
10776 " -multiplex enable the multiplexor VFS\n"
10777#endif
10778 " -newline SEP set output row separator. Default: '\\n'\n"
drh0933aad2019-11-18 17:46:38 +000010779 " -nofollow refuse to open symbolic links to database files\n"
drh2ce15c32017-07-11 13:34:40 +000010780 " -nullvalue TEXT set text string for NULL values. Default ''\n"
10781 " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
10782 " -quote set output mode to 'quote'\n"
drhee269a62018-02-14 23:27:43 +000010783 " -readonly open the database read-only\n"
drh2ce15c32017-07-11 13:34:40 +000010784 " -separator SEP set output column separator. Default: '|'\n"
drha90d84f2018-04-18 15:21:13 +000010785#ifdef SQLITE_ENABLE_SORTER_REFERENCES
10786 " -sorterref SIZE sorter references threshold size\n"
10787#endif
drh2ce15c32017-07-11 13:34:40 +000010788 " -stats print memory stats before each finalize\n"
drh30c54a02020-05-28 23:49:50 +000010789 " -table set output mode to 'table'\n"
drh2fa78182020-10-31 18:58:37 +000010790 " -tabs set output mode to 'tabs'\n"
drh2ce15c32017-07-11 13:34:40 +000010791 " -version show SQLite version\n"
10792 " -vfs NAME use NAME as the default VFS\n"
10793#ifdef SQLITE_ENABLE_VFSTRACE
10794 " -vfstrace enable tracing of all VFS calls\n"
10795#endif
drh3baed312018-03-08 18:14:41 +000010796#ifdef SQLITE_HAVE_ZLIB
10797 " -zip open the file as a ZIP Archive\n"
10798#endif
drh2ce15c32017-07-11 13:34:40 +000010799;
10800static void usage(int showDetail){
10801 utf8_printf(stderr,
10802 "Usage: %s [OPTIONS] FILENAME [SQL]\n"
10803 "FILENAME is the name of an SQLite database. A new database is created\n"
10804 "if the file does not previously exist.\n", Argv0);
10805 if( showDetail ){
10806 utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
10807 }else{
10808 raw_printf(stderr, "Use the -help option for additional information\n");
10809 }
10810 exit(1);
10811}
10812
10813/*
drhe7df8922018-04-18 10:44:58 +000010814** Internal check: Verify that the SQLite is uninitialized. Print a
10815** error message if it is initialized.
10816*/
10817static void verify_uninitialized(void){
10818 if( sqlite3_config(-1)==SQLITE_MISUSE ){
drh8e02a182018-05-30 07:24:41 +000010819 utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
drhe7df8922018-04-18 10:44:58 +000010820 " initialization.\n");
10821 }
10822}
10823
10824/*
drh2ce15c32017-07-11 13:34:40 +000010825** Initialize the state information in data
10826*/
10827static void main_init(ShellState *data) {
10828 memset(data, 0, sizeof(*data));
10829 data->normalMode = data->cMode = data->mode = MODE_List;
10830 data->autoExplain = 1;
10831 memcpy(data->colSeparator,SEP_Column, 2);
10832 memcpy(data->rowSeparator,SEP_Row, 2);
10833 data->showHeader = 0;
10834 data->shellFlgs = SHFLG_Lookaside;
drhe7df8922018-04-18 10:44:58 +000010835 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000010836 sqlite3_config(SQLITE_CONFIG_URI, 1);
10837 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
10838 sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
10839 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
10840 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
10841}
10842
10843/*
10844** Output text to the console in a font that attracts extra attention.
10845*/
10846#ifdef _WIN32
10847static void printBold(const char *zText){
mistachkin43e86272020-04-09 15:31:22 +000010848#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000010849 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
10850 CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
10851 GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
10852 SetConsoleTextAttribute(out,
10853 FOREGROUND_RED|FOREGROUND_INTENSITY
10854 );
mistachkin43e86272020-04-09 15:31:22 +000010855#endif
drh2ce15c32017-07-11 13:34:40 +000010856 printf("%s", zText);
mistachkin43e86272020-04-09 15:31:22 +000010857#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000010858 SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
mistachkin43e86272020-04-09 15:31:22 +000010859#endif
drh2ce15c32017-07-11 13:34:40 +000010860}
10861#else
10862static void printBold(const char *zText){
10863 printf("\033[1m%s\033[0m", zText);
10864}
10865#endif
10866
10867/*
10868** Get the argument to an --option. Throw an error and die if no argument
10869** is available.
10870*/
10871static char *cmdline_option_value(int argc, char **argv, int i){
10872 if( i==argc ){
10873 utf8_printf(stderr, "%s: Error: missing argument to %s\n",
10874 argv[0], argv[argc-1]);
10875 exit(1);
10876 }
10877 return argv[i];
10878}
10879
10880#ifndef SQLITE_SHELL_IS_UTF8
dan39b6bd52021-03-04 18:31:07 +000010881# if (defined(_WIN32) || defined(WIN32)) \
10882 && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
drh2ce15c32017-07-11 13:34:40 +000010883# define SQLITE_SHELL_IS_UTF8 (0)
10884# else
10885# define SQLITE_SHELL_IS_UTF8 (1)
10886# endif
10887#endif
10888
10889#if SQLITE_SHELL_IS_UTF8
10890int SQLITE_CDECL main(int argc, char **argv){
10891#else
10892int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
10893 char **argv;
10894#endif
10895 char *zErrMsg = 0;
10896 ShellState data;
10897 const char *zInitFile = 0;
10898 int i;
10899 int rc = 0;
10900 int warnInmemoryDb = 0;
10901 int readStdin = 1;
10902 int nCmd = 0;
10903 char **azCmd = 0;
dan16a47422018-04-18 09:16:11 +000010904 const char *zVfs = 0; /* Value of -vfs command-line option */
drh1f22f622018-05-17 13:29:14 +000010905#if !SQLITE_SHELL_IS_UTF8
10906 char **argvToFree = 0;
10907 int argcToFree = 0;
10908#endif
drh2ce15c32017-07-11 13:34:40 +000010909
10910 setBinaryMode(stdin, 0);
10911 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
10912 stdin_is_interactive = isatty(0);
10913 stdout_is_console = isatty(1);
10914
drh4a3a3eb2020-02-29 15:53:48 +000010915#ifdef SQLITE_DEBUG
10916 registerOomSimulator();
10917#endif
10918
mistachkin1e8487d2018-07-22 06:25:35 +000010919#if !defined(_WIN32_WCE)
10920 if( getenv("SQLITE_DEBUG_BREAK") ){
10921 if( isatty(0) && isatty(2) ){
10922 fprintf(stderr,
10923 "attach debugger to process %d and press any key to continue.\n",
10924 GETPID());
10925 fgetc(stdin);
10926 }else{
10927#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +000010928#if SQLITE_OS_WINRT
10929 __debugbreak();
10930#else
mistachkin1e8487d2018-07-22 06:25:35 +000010931 DebugBreak();
mistachkin43e86272020-04-09 15:31:22 +000010932#endif
mistachkin1e8487d2018-07-22 06:25:35 +000010933#elif defined(SIGTRAP)
10934 raise(SIGTRAP);
10935#endif
10936 }
10937 }
10938#endif
10939
drh2ce15c32017-07-11 13:34:40 +000010940#if USE_SYSTEM_SQLITE+0!=1
drhb3c45232017-08-28 14:33:27 +000010941 if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
drh2ce15c32017-07-11 13:34:40 +000010942 utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
10943 sqlite3_sourceid(), SQLITE_SOURCE_ID);
10944 exit(1);
10945 }
10946#endif
10947 main_init(&data);
drh501ea052018-02-15 01:03:37 +000010948
10949 /* On Windows, we must translate command-line arguments into UTF-8.
10950 ** The SQLite memory allocator subsystem has to be enabled in order to
10951 ** do this. But we want to run an sqlite3_shutdown() afterwards so that
10952 ** subsequent sqlite3_config() calls will work. So copy all results into
10953 ** memory that does not come from the SQLite memory allocator.
10954 */
drh4b18c1d2018-02-04 20:33:13 +000010955#if !SQLITE_SHELL_IS_UTF8
drh501ea052018-02-15 01:03:37 +000010956 sqlite3_initialize();
drh1f22f622018-05-17 13:29:14 +000010957 argvToFree = malloc(sizeof(argv[0])*argc*2);
10958 argcToFree = argc;
10959 argv = argvToFree + argc;
drh4b5345c2018-04-24 13:07:40 +000010960 if( argv==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +000010961 for(i=0; i<argc; i++){
drh501ea052018-02-15 01:03:37 +000010962 char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
10963 int n;
drh4b5345c2018-04-24 13:07:40 +000010964 if( z==0 ) shell_out_of_memory();
drh501ea052018-02-15 01:03:37 +000010965 n = (int)strlen(z);
10966 argv[i] = malloc( n+1 );
drh4b5345c2018-04-24 13:07:40 +000010967 if( argv[i]==0 ) shell_out_of_memory();
drh501ea052018-02-15 01:03:37 +000010968 memcpy(argv[i], z, n+1);
drh1f22f622018-05-17 13:29:14 +000010969 argvToFree[i] = argv[i];
drh501ea052018-02-15 01:03:37 +000010970 sqlite3_free(z);
drh2ce15c32017-07-11 13:34:40 +000010971 }
drh501ea052018-02-15 01:03:37 +000010972 sqlite3_shutdown();
drh2ce15c32017-07-11 13:34:40 +000010973#endif
drh501ea052018-02-15 01:03:37 +000010974
drh2ce15c32017-07-11 13:34:40 +000010975 assert( argc>=1 && argv && argv[0] );
10976 Argv0 = argv[0];
10977
10978 /* Make sure we have a valid signal handler early, before anything
10979 ** else is done.
10980 */
10981#ifdef SIGINT
10982 signal(SIGINT, interrupt_handler);
mistachkinb4bab902017-10-27 17:09:44 +000010983#elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
10984 SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
drh2ce15c32017-07-11 13:34:40 +000010985#endif
10986
10987#ifdef SQLITE_SHELL_DBNAME_PROC
10988 {
10989 /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
10990 ** of a C-function that will provide the name of the database file. Use
10991 ** this compile-time option to embed this shell program in larger
10992 ** applications. */
10993 extern void SQLITE_SHELL_DBNAME_PROC(const char**);
10994 SQLITE_SHELL_DBNAME_PROC(&data.zDbFilename);
10995 warnInmemoryDb = 0;
10996 }
10997#endif
10998
10999 /* Do an initial pass through the command-line argument to locate
11000 ** the name of the database file, the name of the initialization file,
11001 ** the size of the alternative malloc heap,
11002 ** and the first command to execute.
11003 */
drhe7df8922018-04-18 10:44:58 +000011004 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000011005 for(i=1; i<argc; i++){
11006 char *z;
11007 z = argv[i];
11008 if( z[0]!='-' ){
11009 if( data.zDbFilename==0 ){
11010 data.zDbFilename = z;
11011 }else{
11012 /* Excesss arguments are interpreted as SQL (or dot-commands) and
11013 ** mean that nothing is read from stdin */
11014 readStdin = 0;
11015 nCmd++;
11016 azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
drh4b5345c2018-04-24 13:07:40 +000011017 if( azCmd==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +000011018 azCmd[nCmd-1] = z;
11019 }
11020 }
11021 if( z[1]=='-' ) z++;
11022 if( strcmp(z,"-separator")==0
11023 || strcmp(z,"-nullvalue")==0
11024 || strcmp(z,"-newline")==0
11025 || strcmp(z,"-cmd")==0
11026 ){
11027 (void)cmdline_option_value(argc, argv, ++i);
11028 }else if( strcmp(z,"-init")==0 ){
11029 zInitFile = cmdline_option_value(argc, argv, ++i);
11030 }else if( strcmp(z,"-batch")==0 ){
11031 /* Need to check for batch mode here to so we can avoid printing
11032 ** informational messages (like from process_sqliterc) before
11033 ** we do the actual processing of arguments later in a second pass.
11034 */
11035 stdin_is_interactive = 0;
11036 }else if( strcmp(z,"-heap")==0 ){
11037#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
11038 const char *zSize;
11039 sqlite3_int64 szHeap;
11040
11041 zSize = cmdline_option_value(argc, argv, ++i);
11042 szHeap = integerValue(zSize);
11043 if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
11044 sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
11045#else
11046 (void)cmdline_option_value(argc, argv, ++i);
11047#endif
drh2ce15c32017-07-11 13:34:40 +000011048 }else if( strcmp(z,"-pagecache")==0 ){
drhf573b4f2020-09-28 13:34:05 +000011049 sqlite3_int64 n, sz;
11050 sz = integerValue(cmdline_option_value(argc,argv,++i));
drh2ce15c32017-07-11 13:34:40 +000011051 if( sz>70000 ) sz = 70000;
11052 if( sz<0 ) sz = 0;
drhf573b4f2020-09-28 13:34:05 +000011053 n = integerValue(cmdline_option_value(argc,argv,++i));
11054 if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
11055 n = 0xffffffffffffLL/sz;
11056 }
drh2ce15c32017-07-11 13:34:40 +000011057 sqlite3_config(SQLITE_CONFIG_PAGECACHE,
11058 (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
11059 data.shellFlgs |= SHFLG_Pagecache;
11060 }else if( strcmp(z,"-lookaside")==0 ){
11061 int n, sz;
11062 sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
11063 if( sz<0 ) sz = 0;
11064 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
11065 if( n<0 ) n = 0;
11066 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
11067 if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
11068#ifdef SQLITE_ENABLE_VFSTRACE
11069 }else if( strcmp(z,"-vfstrace")==0 ){
11070 extern int vfstrace_register(
11071 const char *zTraceName,
11072 const char *zOldVfsName,
11073 int (*xOut)(const char*,void*),
11074 void *pOutArg,
11075 int makeDefault
11076 );
11077 vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
11078#endif
11079#ifdef SQLITE_ENABLE_MULTIPLEX
11080 }else if( strcmp(z,"-multiplex")==0 ){
11081 extern int sqlite3_multiple_initialize(const char*,int);
11082 sqlite3_multiplex_initialize(0, 1);
11083#endif
11084 }else if( strcmp(z,"-mmap")==0 ){
11085 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
11086 sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
drha90d84f2018-04-18 15:21:13 +000011087#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11088 }else if( strcmp(z,"-sorterref")==0 ){
11089 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
11090 sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz);
11091#endif
drh2ce15c32017-07-11 13:34:40 +000011092 }else if( strcmp(z,"-vfs")==0 ){
dan16a47422018-04-18 09:16:11 +000011093 zVfs = cmdline_option_value(argc, argv, ++i);
drh3baed312018-03-08 18:14:41 +000011094#ifdef SQLITE_HAVE_ZLIB
drh8682e122018-01-07 20:38:10 +000011095 }else if( strcmp(z,"-zip")==0 ){
11096 data.openMode = SHELL_OPEN_ZIPFILE;
11097#endif
11098 }else if( strcmp(z,"-append")==0 ){
11099 data.openMode = SHELL_OPEN_APPENDVFS;
drh8d889af2021-05-08 17:18:23 +000011100#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +000011101 }else if( strcmp(z,"-deserialize")==0 ){
11102 data.openMode = SHELL_OPEN_DESERIALIZE;
drh6ca64482019-01-22 16:06:20 +000011103 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
11104 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000011105#endif
drhee269a62018-02-14 23:27:43 +000011106 }else if( strcmp(z,"-readonly")==0 ){
11107 data.openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +000011108 }else if( strcmp(z,"-nofollow")==0 ){
11109 data.openFlags = SQLITE_OPEN_NOFOLLOW;
drhda57d962018-03-05 19:34:05 +000011110#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drh93b77312018-03-05 20:20:22 +000011111 }else if( strncmp(z, "-A",2)==0 ){
drhda57d962018-03-05 19:34:05 +000011112 /* All remaining command-line arguments are passed to the ".archive"
11113 ** command, so ignore them */
11114 break;
11115#endif
drh50b910a2019-01-21 14:55:03 +000011116 }else if( strcmp(z, "-memtrace")==0 ){
11117 sqlite3MemTraceActivate(stderr);
drhb7c46aa2020-11-25 13:59:47 +000011118 }else if( strcmp(z,"-bail")==0 ){
11119 bail_on_error = 1;
drh2ce15c32017-07-11 13:34:40 +000011120 }
11121 }
drhe7df8922018-04-18 10:44:58 +000011122 verify_uninitialized();
11123
dan16a47422018-04-18 09:16:11 +000011124
drhd11b8f62018-04-25 13:27:07 +000011125#ifdef SQLITE_SHELL_INIT_PROC
11126 {
11127 /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name
11128 ** of a C-function that will perform initialization actions on SQLite that
11129 ** occur just before or after sqlite3_initialize(). Use this compile-time
11130 ** option to embed this shell program in larger applications. */
11131 extern void SQLITE_SHELL_INIT_PROC(void);
11132 SQLITE_SHELL_INIT_PROC();
11133 }
11134#else
dan16a47422018-04-18 09:16:11 +000011135 /* All the sqlite3_config() calls have now been made. So it is safe
11136 ** to call sqlite3_initialize() and process any command line -vfs option. */
11137 sqlite3_initialize();
drhd11b8f62018-04-25 13:27:07 +000011138#endif
11139
dan16a47422018-04-18 09:16:11 +000011140 if( zVfs ){
11141 sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
11142 if( pVfs ){
11143 sqlite3_vfs_register(pVfs, 1);
11144 }else{
11145 utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
11146 exit(1);
11147 }
11148 }
11149
drh2ce15c32017-07-11 13:34:40 +000011150 if( data.zDbFilename==0 ){
11151#ifndef SQLITE_OMIT_MEMORYDB
11152 data.zDbFilename = ":memory:";
11153 warnInmemoryDb = argc==1;
11154#else
11155 utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
11156 return 1;
11157#endif
11158 }
11159 data.out = stdout;
drh8682e122018-01-07 20:38:10 +000011160 sqlite3_appendvfs_init(0,0,0);
drh2ce15c32017-07-11 13:34:40 +000011161
11162 /* Go ahead and open the database file if it already exists. If the
11163 ** file does not exist, delay opening it. This prevents empty database
11164 ** files from being created if a user mistypes the database name argument
11165 ** to the sqlite command-line tool.
11166 */
11167 if( access(data.zDbFilename, 0)==0 ){
11168 open_db(&data, 0);
11169 }
11170
11171 /* Process the initialization file if there is one. If no -init option
11172 ** is given on the command line, look for a file named ~/.sqliterc and
11173 ** try to process it.
11174 */
11175 process_sqliterc(&data,zInitFile);
11176
11177 /* Make a second pass through the command-line argument and set
11178 ** options. This second pass is delayed until after the initialization
11179 ** file is processed so that the command-line arguments will override
11180 ** settings in the initialization file.
11181 */
11182 for(i=1; i<argc; i++){
11183 char *z = argv[i];
11184 if( z[0]!='-' ) continue;
11185 if( z[1]=='-' ){ z++; }
11186 if( strcmp(z,"-init")==0 ){
11187 i++;
11188 }else if( strcmp(z,"-html")==0 ){
11189 data.mode = MODE_Html;
11190 }else if( strcmp(z,"-list")==0 ){
11191 data.mode = MODE_List;
11192 }else if( strcmp(z,"-quote")==0 ){
11193 data.mode = MODE_Quote;
drh9191c702020-08-17 09:11:21 +000011194 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma);
11195 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +000011196 }else if( strcmp(z,"-line")==0 ){
11197 data.mode = MODE_Line;
11198 }else if( strcmp(z,"-column")==0 ){
11199 data.mode = MODE_Column;
drh30c54a02020-05-28 23:49:50 +000011200 }else if( strcmp(z,"-json")==0 ){
11201 data.mode = MODE_Json;
11202 }else if( strcmp(z,"-markdown")==0 ){
11203 data.mode = MODE_Markdown;
11204 }else if( strcmp(z,"-table")==0 ){
11205 data.mode = MODE_Table;
drh0908e382020-06-04 18:05:39 +000011206 }else if( strcmp(z,"-box")==0 ){
11207 data.mode = MODE_Box;
drh2ce15c32017-07-11 13:34:40 +000011208 }else if( strcmp(z,"-csv")==0 ){
11209 data.mode = MODE_Csv;
11210 memcpy(data.colSeparator,",",2);
drh3baed312018-03-08 18:14:41 +000011211#ifdef SQLITE_HAVE_ZLIB
drh1fa6d9f2018-01-06 21:46:01 +000011212 }else if( strcmp(z,"-zip")==0 ){
11213 data.openMode = SHELL_OPEN_ZIPFILE;
11214#endif
11215 }else if( strcmp(z,"-append")==0 ){
11216 data.openMode = SHELL_OPEN_APPENDVFS;
drh8d889af2021-05-08 17:18:23 +000011217#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +000011218 }else if( strcmp(z,"-deserialize")==0 ){
11219 data.openMode = SHELL_OPEN_DESERIALIZE;
drh6ca64482019-01-22 16:06:20 +000011220 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
11221 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000011222#endif
drh4aafe592018-03-23 16:08:30 +000011223 }else if( strcmp(z,"-readonly")==0 ){
11224 data.openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +000011225 }else if( strcmp(z,"-nofollow")==0 ){
11226 data.openFlags |= SQLITE_OPEN_NOFOLLOW;
drh2ce15c32017-07-11 13:34:40 +000011227 }else if( strcmp(z,"-ascii")==0 ){
11228 data.mode = MODE_Ascii;
drh2fa78182020-10-31 18:58:37 +000011229 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit);
11230 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record);
11231 }else if( strcmp(z,"-tabs")==0 ){
11232 data.mode = MODE_List;
11233 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Tab);
11234 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +000011235 }else if( strcmp(z,"-separator")==0 ){
11236 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
11237 "%s",cmdline_option_value(argc,argv,++i));
11238 }else if( strcmp(z,"-newline")==0 ){
11239 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
11240 "%s",cmdline_option_value(argc,argv,++i));
11241 }else if( strcmp(z,"-nullvalue")==0 ){
11242 sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
11243 "%s",cmdline_option_value(argc,argv,++i));
11244 }else if( strcmp(z,"-header")==0 ){
11245 data.showHeader = 1;
11246 }else if( strcmp(z,"-noheader")==0 ){
11247 data.showHeader = 0;
11248 }else if( strcmp(z,"-echo")==0 ){
11249 ShellSetFlag(&data, SHFLG_Echo);
11250 }else if( strcmp(z,"-eqp")==0 ){
drhada70452017-12-21 21:02:27 +000011251 data.autoEQP = AUTOEQP_on;
drh2ce15c32017-07-11 13:34:40 +000011252 }else if( strcmp(z,"-eqpfull")==0 ){
drhada70452017-12-21 21:02:27 +000011253 data.autoEQP = AUTOEQP_full;
drh2ce15c32017-07-11 13:34:40 +000011254 }else if( strcmp(z,"-stats")==0 ){
11255 data.statsOn = 1;
11256 }else if( strcmp(z,"-scanstats")==0 ){
11257 data.scanstatsOn = 1;
11258 }else if( strcmp(z,"-backslash")==0 ){
11259 /* Undocumented command-line option: -backslash
11260 ** Causes C-style backslash escapes to be evaluated in SQL statements
11261 ** prior to sending the SQL into SQLite. Useful for injecting
11262 ** crazy bytes in the middle of SQL statements for testing and debugging.
11263 */
11264 ShellSetFlag(&data, SHFLG_Backslash);
11265 }else if( strcmp(z,"-bail")==0 ){
drhb7c46aa2020-11-25 13:59:47 +000011266 /* No-op. The bail_on_error flag should already be set. */
drh2ce15c32017-07-11 13:34:40 +000011267 }else if( strcmp(z,"-version")==0 ){
11268 printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
11269 return 0;
11270 }else if( strcmp(z,"-interactive")==0 ){
11271 stdin_is_interactive = 1;
11272 }else if( strcmp(z,"-batch")==0 ){
11273 stdin_is_interactive = 0;
11274 }else if( strcmp(z,"-heap")==0 ){
11275 i++;
drh2ce15c32017-07-11 13:34:40 +000011276 }else if( strcmp(z,"-pagecache")==0 ){
11277 i+=2;
11278 }else if( strcmp(z,"-lookaside")==0 ){
11279 i+=2;
11280 }else if( strcmp(z,"-mmap")==0 ){
11281 i++;
drh50b910a2019-01-21 14:55:03 +000011282 }else if( strcmp(z,"-memtrace")==0 ){
11283 i++;
drha90d84f2018-04-18 15:21:13 +000011284#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11285 }else if( strcmp(z,"-sorterref")==0 ){
11286 i++;
11287#endif
drh2ce15c32017-07-11 13:34:40 +000011288 }else if( strcmp(z,"-vfs")==0 ){
11289 i++;
11290#ifdef SQLITE_ENABLE_VFSTRACE
11291 }else if( strcmp(z,"-vfstrace")==0 ){
11292 i++;
11293#endif
11294#ifdef SQLITE_ENABLE_MULTIPLEX
11295 }else if( strcmp(z,"-multiplex")==0 ){
11296 i++;
11297#endif
11298 }else if( strcmp(z,"-help")==0 ){
11299 usage(1);
11300 }else if( strcmp(z,"-cmd")==0 ){
11301 /* Run commands that follow -cmd first and separately from commands
11302 ** that simply appear on the command-line. This seems goofy. It would
11303 ** be better if all commands ran in the order that they appear. But
11304 ** we retain the goofy behavior for historical compatibility. */
11305 if( i==argc-1 ) break;
11306 z = cmdline_option_value(argc,argv,++i);
11307 if( z[0]=='.' ){
11308 rc = do_meta_command(z, &data);
11309 if( rc && bail_on_error ) return rc==2 ? 0 : rc;
11310 }else{
11311 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000011312 rc = shell_exec(&data, z, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000011313 if( zErrMsg!=0 ){
11314 utf8_printf(stderr,"Error: %s\n", zErrMsg);
11315 if( bail_on_error ) return rc!=0 ? rc : 1;
11316 }else if( rc!=0 ){
11317 utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
11318 if( bail_on_error ) return rc;
11319 }
11320 }
drhda57d962018-03-05 19:34:05 +000011321#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drh93b77312018-03-05 20:20:22 +000011322 }else if( strncmp(z, "-A", 2)==0 ){
drhda57d962018-03-05 19:34:05 +000011323 if( nCmd>0 ){
11324 utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
11325 " with \"%s\"\n", z);
11326 return 1;
11327 }
drhbe4ccb22018-05-17 20:04:24 +000011328 open_db(&data, OPEN_DB_ZIPFILE);
drh93b77312018-03-05 20:20:22 +000011329 if( z[2] ){
11330 argv[i] = &z[2];
drhd0f9cdc2018-05-17 14:09:06 +000011331 arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
drh93b77312018-03-05 20:20:22 +000011332 }else{
drhd0f9cdc2018-05-17 14:09:06 +000011333 arDotCommand(&data, 1, argv+i, argc-i);
drh93b77312018-03-05 20:20:22 +000011334 }
drhda57d962018-03-05 19:34:05 +000011335 readStdin = 0;
11336 break;
11337#endif
drh2ce15c32017-07-11 13:34:40 +000011338 }else{
11339 utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
11340 raw_printf(stderr,"Use -help for a list of options.\n");
11341 return 1;
11342 }
11343 data.cMode = data.mode;
11344 }
11345
11346 if( !readStdin ){
11347 /* Run all arguments that do not begin with '-' as if they were separate
11348 ** command-line inputs, except for the argToSkip argument which contains
11349 ** the database filename.
11350 */
11351 for(i=0; i<nCmd; i++){
11352 if( azCmd[i][0]=='.' ){
11353 rc = do_meta_command(azCmd[i], &data);
danaff1a572020-11-17 21:09:56 +000011354 if( rc ){
11355 free(azCmd);
11356 return rc==2 ? 0 : rc;
11357 }
drh2ce15c32017-07-11 13:34:40 +000011358 }else{
11359 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000011360 rc = shell_exec(&data, azCmd[i], &zErrMsg);
danaff1a572020-11-17 21:09:56 +000011361 if( zErrMsg || rc ){
11362 if( zErrMsg!=0 ){
11363 utf8_printf(stderr,"Error: %s\n", zErrMsg);
11364 }else{
11365 utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
11366 }
11367 sqlite3_free(zErrMsg);
11368 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000011369 return rc!=0 ? rc : 1;
drh2ce15c32017-07-11 13:34:40 +000011370 }
11371 }
11372 }
drh2ce15c32017-07-11 13:34:40 +000011373 }else{
11374 /* Run commands received from standard input
11375 */
11376 if( stdin_is_interactive ){
11377 char *zHome;
drha9e4be32018-10-10 18:56:40 +000011378 char *zHistory;
drh2ce15c32017-07-11 13:34:40 +000011379 int nHistory;
11380 printf(
11381 "SQLite version %s %.19s\n" /*extra-version-info*/
11382 "Enter \".help\" for usage hints.\n",
11383 sqlite3_libversion(), sqlite3_sourceid()
11384 );
11385 if( warnInmemoryDb ){
11386 printf("Connected to a ");
11387 printBold("transient in-memory database");
11388 printf(".\nUse \".open FILENAME\" to reopen on a "
11389 "persistent database.\n");
11390 }
drha9e4be32018-10-10 18:56:40 +000011391 zHistory = getenv("SQLITE_HISTORY");
11392 if( zHistory ){
11393 zHistory = strdup(zHistory);
11394 }else if( (zHome = find_home_dir(0))!=0 ){
drh2ce15c32017-07-11 13:34:40 +000011395 nHistory = strlen30(zHome) + 20;
11396 if( (zHistory = malloc(nHistory))!=0 ){
11397 sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
11398 }
11399 }
11400 if( zHistory ){ shell_read_history(zHistory); }
drh56eb09b2017-07-11 13:59:07 +000011401#if HAVE_READLINE || HAVE_EDITLINE
11402 rl_attempted_completion_function = readline_completion;
11403#elif HAVE_LINENOISE
11404 linenoiseSetCompletionCallback(linenoise_completion);
11405#endif
drh60379d42018-12-13 18:30:01 +000011406 data.in = 0;
11407 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000011408 if( zHistory ){
drh5a75dd82017-07-18 20:59:40 +000011409 shell_stifle_history(2000);
drh2ce15c32017-07-11 13:34:40 +000011410 shell_write_history(zHistory);
11411 free(zHistory);
11412 }
11413 }else{
drh60379d42018-12-13 18:30:01 +000011414 data.in = stdin;
11415 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000011416 }
11417 }
danaff1a572020-11-17 21:09:56 +000011418 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000011419 set_table_name(&data, 0);
11420 if( data.db ){
11421 session_close_all(&data);
drh9e804032018-05-18 17:11:50 +000011422 close_db(data.db);
drh2ce15c32017-07-11 13:34:40 +000011423 }
11424 sqlite3_free(data.zFreeOnClose);
11425 find_home_dir(1);
drh536c3452018-01-11 00:38:39 +000011426 output_reset(&data);
11427 data.doXdgOpen = 0;
drh13c20932018-01-10 21:41:55 +000011428 clearTempFile(&data);
drh2ce15c32017-07-11 13:34:40 +000011429#if !SQLITE_SHELL_IS_UTF8
drh1f22f622018-05-17 13:29:14 +000011430 for(i=0; i<argcToFree; i++) free(argvToFree[i]);
11431 free(argvToFree);
drh2ce15c32017-07-11 13:34:40 +000011432#endif
drh0285d982020-05-29 14:38:43 +000011433 free(data.colWidth);
drh9e804032018-05-18 17:11:50 +000011434 /* Clear the global data structure so that valgrind will detect memory
11435 ** leaks */
11436 memset(&data, 0, sizeof(data));
drh2ce15c32017-07-11 13:34:40 +000011437 return rc;
11438}