blob: bfb9648128aa2f6eacb332dc424c0ba335c5fe8d [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
dan72afc3c2017-12-05 18:32:40 +00001030#ifdef SQLITE_HAVE_ZLIB
dan9ebfaad2017-12-26 20:39:58 +00001031INCLUDE ../ext/misc/zipfile.c
dand1b51d42017-12-16 19:11:26 +00001032INCLUDE ../ext/misc/sqlar.c
dan72afc3c2017-12-05 18:32:40 +00001033#endif
dan43efc182017-12-19 17:42:13 +00001034INCLUDE ../ext/expert/sqlite3expert.h
1035INCLUDE ../ext/expert/sqlite3expert.c
drh2ce15c32017-07-11 13:34:40 +00001036
dan1b162162019-04-27 20:15:15 +00001037#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00001038INCLUDE ../ext/misc/dbdata.c
dan1b162162019-04-27 20:15:15 +00001039#endif
dan68cb86e2019-04-20 20:57:28 +00001040
drh2ce15c32017-07-11 13:34:40 +00001041#if defined(SQLITE_ENABLE_SESSION)
1042/*
1043** State information for a single open session
1044*/
1045typedef struct OpenSession OpenSession;
1046struct OpenSession {
1047 char *zName; /* Symbolic name for this session */
1048 int nFilter; /* Number of xFilter rejection GLOB patterns */
1049 char **azFilter; /* Array of xFilter rejection GLOB patterns */
1050 sqlite3_session *p; /* The open session */
1051};
1052#endif
1053
dan43efc182017-12-19 17:42:13 +00001054typedef struct ExpertInfo ExpertInfo;
1055struct ExpertInfo {
1056 sqlite3expert *pExpert;
1057 int bVerbose;
1058};
1059
drh4b5345c2018-04-24 13:07:40 +00001060/* A single line in the EQP output */
1061typedef struct EQPGraphRow EQPGraphRow;
1062struct EQPGraphRow {
drhe2ca99c2018-05-02 00:33:43 +00001063 int iEqpId; /* ID for this row */
1064 int iParentId; /* ID of the parent row */
drh4b5345c2018-04-24 13:07:40 +00001065 EQPGraphRow *pNext; /* Next row in sequence */
1066 char zText[1]; /* Text to display for this row */
1067};
1068
1069/* All EQP output is collected into an instance of the following */
1070typedef struct EQPGraph EQPGraph;
1071struct EQPGraph {
1072 EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */
1073 EQPGraphRow *pLast; /* Last element of the pRow list */
1074 char zPrefix[100]; /* Graph prefix */
1075};
1076
drh2ce15c32017-07-11 13:34:40 +00001077/*
1078** State information about the database connection is contained in an
1079** instance of the following structure.
1080*/
1081typedef struct ShellState ShellState;
1082struct ShellState {
1083 sqlite3 *db; /* The database */
drh1fa6d9f2018-01-06 21:46:01 +00001084 u8 autoExplain; /* Automatically turn on .explain mode */
1085 u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
drhe2ca99c2018-05-02 00:33:43 +00001086 u8 autoEQPtest; /* autoEQP is in test mode */
drhb4e50392019-01-26 15:40:04 +00001087 u8 autoEQPtrace; /* autoEQP is in trace mode */
drh1fa6d9f2018-01-06 21:46:01 +00001088 u8 scanstatsOn; /* True to display scan stats before each finalize */
1089 u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
drh13c20932018-01-10 21:41:55 +00001090 u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
drh4b5345c2018-04-24 13:07:40 +00001091 u8 nEqpLevel; /* Depth of the EQP output graph */
drh707821f2018-12-05 13:39:06 +00001092 u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
drha6e6cf22021-01-09 19:10:04 +00001093 unsigned statsOn; /* True to display memory stats before each finalize */
drh4b5345c2018-04-24 13:07:40 +00001094 unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */
drh2ce15c32017-07-11 13:34:40 +00001095 int outCount; /* Revert to stdout when reaching zero */
1096 int cnt; /* Number of records displayed so far */
drh2c8ee022018-12-13 18:59:30 +00001097 int lineno; /* Line number of last line read from in */
drh0933aad2019-11-18 17:46:38 +00001098 int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */
drh60379d42018-12-13 18:30:01 +00001099 FILE *in; /* Read commands from this stream */
drh2ce15c32017-07-11 13:34:40 +00001100 FILE *out; /* Write results here */
1101 FILE *traceOut; /* Output for sqlite3_trace() */
1102 int nErr; /* Number of errors seen */
1103 int mode; /* An output mode setting */
drh3c484e82018-01-10 22:27:21 +00001104 int modePrior; /* Saved mode */
drh2ce15c32017-07-11 13:34:40 +00001105 int cMode; /* temporary output mode for the current query */
1106 int normalMode; /* Output mode before ".explain on" */
1107 int writableSchema; /* True if PRAGMA writable_schema=ON */
1108 int showHeader; /* True to show column names in List or Column mode */
1109 int nCheck; /* Number of ".check" commands run */
drh3f83f592019-02-04 14:53:18 +00001110 unsigned nProgress; /* Number of progress callbacks encountered */
1111 unsigned mxProgress; /* Maximum progress callbacks before failing */
1112 unsigned flgProgress; /* Flags for the progress callback */
drh2ce15c32017-07-11 13:34:40 +00001113 unsigned shellFlgs; /* Various flags */
drh7a431002020-04-18 14:12:00 +00001114 unsigned priorShFlgs; /* Saved copy of flags */
drh6ca64482019-01-22 16:06:20 +00001115 sqlite3_int64 szMax; /* --maxsize argument to .open */
drh2ce15c32017-07-11 13:34:40 +00001116 char *zDestTable; /* Name of destination table when MODE_Insert */
drh13c20932018-01-10 21:41:55 +00001117 char *zTempFile; /* Temporary file that might need deleting */
drh2ce15c32017-07-11 13:34:40 +00001118 char zTestcase[30]; /* Name of current test case */
1119 char colSeparator[20]; /* Column separator character for several modes */
1120 char rowSeparator[20]; /* Row separator character for MODE_Ascii */
drh3c484e82018-01-10 22:27:21 +00001121 char colSepPrior[20]; /* Saved column separator */
1122 char rowSepPrior[20]; /* Saved row separator */
drh0285d982020-05-29 14:38:43 +00001123 int *colWidth; /* Requested width of each column in columnar modes */
1124 int *actualWidth; /* Actual width of each column */
1125 int nWidth; /* Number of slots in colWidth[] and actualWidth[] */
drh2ce15c32017-07-11 13:34:40 +00001126 char nullValue[20]; /* The text to print when a NULL comes back from
1127 ** the database */
1128 char outfile[FILENAME_MAX]; /* Filename for *out */
1129 const char *zDbFilename; /* name of the database file */
1130 char *zFreeOnClose; /* Filename to free when closing */
1131 const char *zVfs; /* Name of VFS to use */
1132 sqlite3_stmt *pStmt; /* Current statement if any. */
1133 FILE *pLog; /* Write log output here */
1134 int *aiIndent; /* Array of indents used in MODE_Explain */
1135 int nIndent; /* Size of array aiIndent[] */
1136 int iIndent; /* Index of current op in aiIndent[] */
drh4b5345c2018-04-24 13:07:40 +00001137 EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */
drh2ce15c32017-07-11 13:34:40 +00001138#if defined(SQLITE_ENABLE_SESSION)
1139 int nSession; /* Number of active sessions */
1140 OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */
1141#endif
dan43efc182017-12-19 17:42:13 +00001142 ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
drh2ce15c32017-07-11 13:34:40 +00001143};
1144
drh1fa6d9f2018-01-06 21:46:01 +00001145
drhada70452017-12-21 21:02:27 +00001146/* Allowed values for ShellState.autoEQP
1147*/
drhe2ca99c2018-05-02 00:33:43 +00001148#define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */
1149#define AUTOEQP_on 1 /* Automatic EQP is on */
1150#define AUTOEQP_trigger 2 /* On and also show plans for triggers */
1151#define AUTOEQP_full 3 /* Show full EXPLAIN */
drhada70452017-12-21 21:02:27 +00001152
drh1fa6d9f2018-01-06 21:46:01 +00001153/* Allowed values for ShellState.openMode
1154*/
drh60f34ae2018-10-30 13:19:49 +00001155#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
1156#define SHELL_OPEN_NORMAL 1 /* Normal database file */
1157#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
1158#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
1159#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
1160#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
drh33746482018-12-13 15:06:26 +00001161#define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */
drh1fa6d9f2018-01-06 21:46:01 +00001162
drh707821f2018-12-05 13:39:06 +00001163/* Allowed values for ShellState.eTraceType
1164*/
1165#define SHELL_TRACE_PLAIN 0 /* Show input SQL text */
1166#define SHELL_TRACE_EXPANDED 1 /* Show expanded SQL text */
1167#define SHELL_TRACE_NORMALIZED 2 /* Show normalized SQL text */
1168
drh3f83f592019-02-04 14:53:18 +00001169/* Bits in the ShellState.flgProgress variable */
drhfc4eeef2019-02-05 19:48:46 +00001170#define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */
1171#define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progres
1172 ** callback limit is reached, and for each
1173 ** top-level SQL statement */
1174#define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */
drh3f83f592019-02-04 14:53:18 +00001175
drh2ce15c32017-07-11 13:34:40 +00001176/*
1177** These are the allowed shellFlgs values
1178*/
drhb2a0f752017-08-28 15:51:35 +00001179#define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */
1180#define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */
1181#define SHFLG_Backslash 0x00000004 /* The --backslash option is used */
1182#define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */
1183#define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
1184#define SHFLG_CountChanges 0x00000020 /* .changes setting */
1185#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
drhc0605082020-06-05 00:54:27 +00001186#define SHFLG_HeaderSet 0x00000080 /* .header has been used */
drhc1962192020-10-12 16:54:28 +00001187#define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */
1188#define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */
drh2ce15c32017-07-11 13:34:40 +00001189
1190/*
1191** Macros for testing and setting shellFlgs
1192*/
1193#define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0)
1194#define ShellSetFlag(P,X) ((P)->shellFlgs|=(X))
1195#define ShellClearFlag(P,X) ((P)->shellFlgs&=(~(X)))
1196
1197/*
1198** These are the allowed modes.
1199*/
1200#define MODE_Line 0 /* One column per line. Blank line between records */
1201#define MODE_Column 1 /* One record per line in neat columns */
1202#define MODE_List 2 /* One record per line with a separator */
1203#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
1204#define MODE_Html 4 /* Generate an XHTML table */
1205#define MODE_Insert 5 /* Generate SQL "insert" statements */
1206#define MODE_Quote 6 /* Quote values as for SQL */
1207#define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */
1208#define MODE_Csv 8 /* Quote strings, numbers are plain */
1209#define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */
1210#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
1211#define MODE_Pretty 11 /* Pretty-print schemas */
drh4b5345c2018-04-24 13:07:40 +00001212#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
drh30c54a02020-05-28 23:49:50 +00001213#define MODE_Json 13 /* Output JSON */
1214#define MODE_Markdown 14 /* Markdown formatting */
1215#define MODE_Table 15 /* MySQL-style table formatting */
drh0908e382020-06-04 18:05:39 +00001216#define MODE_Box 16 /* Unicode box-drawing characters */
drh2ce15c32017-07-11 13:34:40 +00001217
1218static const char *modeDescr[] = {
1219 "line",
1220 "column",
1221 "list",
1222 "semi",
1223 "html",
1224 "insert",
1225 "quote",
1226 "tcl",
1227 "csv",
1228 "explain",
1229 "ascii",
1230 "prettyprint",
drh30c54a02020-05-28 23:49:50 +00001231 "eqp",
1232 "json",
1233 "markdown",
drh0908e382020-06-04 18:05:39 +00001234 "table",
1235 "box"
drh2ce15c32017-07-11 13:34:40 +00001236};
1237
1238/*
1239** These are the column/row/line separators used by the various
1240** import/export modes.
1241*/
1242#define SEP_Column "|"
1243#define SEP_Row "\n"
1244#define SEP_Tab "\t"
1245#define SEP_Space " "
1246#define SEP_Comma ","
1247#define SEP_CrLf "\r\n"
1248#define SEP_Unit "\x1F"
1249#define SEP_Record "\x1E"
1250
1251/*
drh2ce15c32017-07-11 13:34:40 +00001252** A callback for the sqlite3_log() interface.
1253*/
1254static void shellLog(void *pArg, int iErrCode, const char *zMsg){
1255 ShellState *p = (ShellState*)pArg;
1256 if( p->pLog==0 ) return;
1257 utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
1258 fflush(p->pLog);
1259}
1260
1261/*
drh634c70f2018-01-10 16:50:18 +00001262** SQL function: shell_putsnl(X)
1263**
1264** Write the text X to the screen (or whatever output is being directed)
1265** adding a newline at the end, and then return X.
1266*/
1267static void shellPutsFunc(
1268 sqlite3_context *pCtx,
1269 int nVal,
1270 sqlite3_value **apVal
1271){
1272 ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
drhb9685182018-01-17 13:15:23 +00001273 (void)nVal;
drh634c70f2018-01-10 16:50:18 +00001274 utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
1275 sqlite3_result_value(pCtx, apVal[0]);
1276}
1277
1278/*
drh97913132018-01-11 00:04:00 +00001279** SQL function: edit(VALUE)
1280** edit(VALUE,EDITOR)
1281**
1282** These steps:
1283**
1284** (1) Write VALUE into a temporary file.
1285** (2) Run program EDITOR on that temporary file.
1286** (3) Read the temporary file back and return its content as the result.
1287** (4) Delete the temporary file
1288**
1289** If the EDITOR argument is omitted, use the value in the VISUAL
1290** environment variable. If still there is no EDITOR, through an error.
1291**
1292** Also throw an error if the EDITOR program returns a non-zero exit code.
1293*/
drh04a28c32018-01-31 01:38:44 +00001294#ifndef SQLITE_NOHAVE_SYSTEM
drh97913132018-01-11 00:04:00 +00001295static void editFunc(
1296 sqlite3_context *context,
1297 int argc,
1298 sqlite3_value **argv
1299){
1300 const char *zEditor;
1301 char *zTempFile = 0;
1302 sqlite3 *db;
1303 char *zCmd = 0;
1304 int bBin;
1305 int rc;
drhf018fd52018-08-06 02:08:53 +00001306 int hasCRNL = 0;
drh97913132018-01-11 00:04:00 +00001307 FILE *f = 0;
1308 sqlite3_int64 sz;
1309 sqlite3_int64 x;
1310 unsigned char *p = 0;
1311
1312 if( argc==2 ){
1313 zEditor = (const char*)sqlite3_value_text(argv[1]);
1314 }else{
1315 zEditor = getenv("VISUAL");
1316 }
1317 if( zEditor==0 ){
1318 sqlite3_result_error(context, "no editor for edit()", -1);
1319 return;
1320 }
1321 if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
1322 sqlite3_result_error(context, "NULL input to edit()", -1);
1323 return;
1324 }
1325 db = sqlite3_context_db_handle(context);
1326 zTempFile = 0;
1327 sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile);
1328 if( zTempFile==0 ){
1329 sqlite3_uint64 r = 0;
1330 sqlite3_randomness(sizeof(r), &r);
1331 zTempFile = sqlite3_mprintf("temp%llx", r);
1332 if( zTempFile==0 ){
1333 sqlite3_result_error_nomem(context);
1334 return;
1335 }
1336 }
1337 bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB;
drhf018fd52018-08-06 02:08:53 +00001338 /* When writing the file to be edited, do \n to \r\n conversions on systems
1339 ** that want \r\n line endings */
drh97913132018-01-11 00:04:00 +00001340 f = fopen(zTempFile, bBin ? "wb" : "w");
1341 if( f==0 ){
1342 sqlite3_result_error(context, "edit() cannot open temp file", -1);
1343 goto edit_func_end;
1344 }
1345 sz = sqlite3_value_bytes(argv[0]);
1346 if( bBin ){
dan4d02b5f2019-07-17 07:23:06 +00001347 x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001348 }else{
drhf018fd52018-08-06 02:08:53 +00001349 const char *z = (const char*)sqlite3_value_text(argv[0]);
1350 /* Remember whether or not the value originally contained \r\n */
1351 if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
dan4d02b5f2019-07-17 07:23:06 +00001352 x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001353 }
1354 fclose(f);
1355 f = 0;
1356 if( x!=sz ){
1357 sqlite3_result_error(context, "edit() could not write the whole file", -1);
1358 goto edit_func_end;
1359 }
1360 zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile);
1361 if( zCmd==0 ){
1362 sqlite3_result_error_nomem(context);
1363 goto edit_func_end;
1364 }
1365 rc = system(zCmd);
1366 sqlite3_free(zCmd);
1367 if( rc ){
1368 sqlite3_result_error(context, "EDITOR returned non-zero", -1);
1369 goto edit_func_end;
1370 }
drhf018fd52018-08-06 02:08:53 +00001371 f = fopen(zTempFile, "rb");
drh97913132018-01-11 00:04:00 +00001372 if( f==0 ){
1373 sqlite3_result_error(context,
1374 "edit() cannot reopen temp file after edit", -1);
1375 goto edit_func_end;
1376 }
1377 fseek(f, 0, SEEK_END);
1378 sz = ftell(f);
1379 rewind(f);
drhee37f8b2019-08-23 23:05:32 +00001380 p = sqlite3_malloc64( sz+1 );
drh97913132018-01-11 00:04:00 +00001381 if( p==0 ){
1382 sqlite3_result_error_nomem(context);
1383 goto edit_func_end;
1384 }
dan4d02b5f2019-07-17 07:23:06 +00001385 x = fread(p, 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001386 fclose(f);
1387 f = 0;
1388 if( x!=sz ){
1389 sqlite3_result_error(context, "could not read back the whole file", -1);
1390 goto edit_func_end;
1391 }
1392 if( bBin ){
mistachkinb71aa092018-01-23 00:05:18 +00001393 sqlite3_result_blob64(context, p, sz, sqlite3_free);
drh97913132018-01-11 00:04:00 +00001394 }else{
dan60bdcf52018-10-03 11:13:30 +00001395 sqlite3_int64 i, j;
drhf018fd52018-08-06 02:08:53 +00001396 if( hasCRNL ){
1397 /* If the original contains \r\n then do no conversions back to \n */
1398 j = sz;
1399 }else{
1400 /* If the file did not originally contain \r\n then convert any new
1401 ** \r\n back into \n */
1402 for(i=j=0; i<sz; i++){
1403 if( p[i]=='\r' && p[i+1]=='\n' ) i++;
1404 p[j++] = p[i];
1405 }
1406 sz = j;
1407 p[sz] = 0;
1408 }
mistachkinb71aa092018-01-23 00:05:18 +00001409 sqlite3_result_text64(context, (const char*)p, sz,
1410 sqlite3_free, SQLITE_UTF8);
drh97913132018-01-11 00:04:00 +00001411 }
1412 p = 0;
1413
1414edit_func_end:
1415 if( f ) fclose(f);
1416 unlink(zTempFile);
1417 sqlite3_free(zTempFile);
1418 sqlite3_free(p);
1419}
drh04a28c32018-01-31 01:38:44 +00001420#endif /* SQLITE_NOHAVE_SYSTEM */
drh97913132018-01-11 00:04:00 +00001421
1422/*
drh3c484e82018-01-10 22:27:21 +00001423** Save or restore the current output mode
1424*/
1425static void outputModePush(ShellState *p){
1426 p->modePrior = p->mode;
drh7a431002020-04-18 14:12:00 +00001427 p->priorShFlgs = p->shellFlgs;
drh3c484e82018-01-10 22:27:21 +00001428 memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));
1429 memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));
1430}
1431static void outputModePop(ShellState *p){
1432 p->mode = p->modePrior;
drh7a431002020-04-18 14:12:00 +00001433 p->shellFlgs = p->priorShFlgs;
drh3c484e82018-01-10 22:27:21 +00001434 memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
1435 memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
1436}
1437
1438/*
drh2ce15c32017-07-11 13:34:40 +00001439** Output the given string as a hex-encoded blob (eg. X'1234' )
1440*/
1441static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
1442 int i;
1443 char *zBlob = (char *)pBlob;
1444 raw_printf(out,"X'");
1445 for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); }
1446 raw_printf(out,"'");
1447}
1448
1449/*
1450** Find a string that is not found anywhere in z[]. Return a pointer
1451** to that string.
1452**
1453** Try to use zA and zB first. If both of those are already found in z[]
1454** then make up some string and store it in the buffer zBuf.
1455*/
1456static const char *unused_string(
1457 const char *z, /* Result must not appear anywhere in z */
1458 const char *zA, const char *zB, /* Try these first */
1459 char *zBuf /* Space to store a generated string */
1460){
1461 unsigned i = 0;
1462 if( strstr(z, zA)==0 ) return zA;
1463 if( strstr(z, zB)==0 ) return zB;
1464 do{
1465 sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
1466 }while( strstr(z,zBuf)!=0 );
1467 return zBuf;
1468}
1469
1470/*
1471** Output the given string as a quoted string using SQL quoting conventions.
1472**
1473** See also: output_quoted_escaped_string()
1474*/
1475static void output_quoted_string(FILE *out, const char *z){
1476 int i;
1477 char c;
1478 setBinaryMode(out, 1);
1479 for(i=0; (c = z[i])!=0 && c!='\''; i++){}
1480 if( c==0 ){
1481 utf8_printf(out,"'%s'",z);
1482 }else{
1483 raw_printf(out, "'");
1484 while( *z ){
1485 for(i=0; (c = z[i])!=0 && c!='\''; i++){}
1486 if( c=='\'' ) i++;
1487 if( i ){
1488 utf8_printf(out, "%.*s", i, z);
1489 z += i;
1490 }
1491 if( c=='\'' ){
1492 raw_printf(out, "'");
1493 continue;
1494 }
1495 if( c==0 ){
1496 break;
1497 }
1498 z++;
1499 }
1500 raw_printf(out, "'");
1501 }
1502 setTextMode(out, 1);
1503}
1504
1505/*
1506** Output the given string as a quoted string using SQL quoting conventions.
1507** Additionallly , escape the "\n" and "\r" characters so that they do not
1508** get corrupted by end-of-line translation facilities in some operating
1509** systems.
1510**
1511** This is like output_quoted_string() but with the addition of the \r\n
1512** escape mechanism.
1513*/
1514static void output_quoted_escaped_string(FILE *out, const char *z){
1515 int i;
1516 char c;
1517 setBinaryMode(out, 1);
1518 for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
1519 if( c==0 ){
1520 utf8_printf(out,"'%s'",z);
1521 }else{
1522 const char *zNL = 0;
1523 const char *zCR = 0;
1524 int nNL = 0;
1525 int nCR = 0;
1526 char zBuf1[20], zBuf2[20];
1527 for(i=0; z[i]; i++){
1528 if( z[i]=='\n' ) nNL++;
1529 if( z[i]=='\r' ) nCR++;
1530 }
1531 if( nNL ){
1532 raw_printf(out, "replace(");
1533 zNL = unused_string(z, "\\n", "\\012", zBuf1);
1534 }
1535 if( nCR ){
1536 raw_printf(out, "replace(");
1537 zCR = unused_string(z, "\\r", "\\015", zBuf2);
1538 }
1539 raw_printf(out, "'");
1540 while( *z ){
1541 for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
1542 if( c=='\'' ) i++;
1543 if( i ){
1544 utf8_printf(out, "%.*s", i, z);
1545 z += i;
1546 }
1547 if( c=='\'' ){
1548 raw_printf(out, "'");
1549 continue;
1550 }
1551 if( c==0 ){
1552 break;
1553 }
1554 z++;
1555 if( c=='\n' ){
1556 raw_printf(out, "%s", zNL);
1557 continue;
1558 }
1559 raw_printf(out, "%s", zCR);
1560 }
1561 raw_printf(out, "'");
1562 if( nCR ){
1563 raw_printf(out, ",'%s',char(13))", zCR);
1564 }
1565 if( nNL ){
1566 raw_printf(out, ",'%s',char(10))", zNL);
1567 }
1568 }
1569 setTextMode(out, 1);
1570}
1571
1572/*
1573** Output the given string as a quoted according to C or TCL quoting rules.
1574*/
1575static void output_c_string(FILE *out, const char *z){
1576 unsigned int c;
1577 fputc('"', out);
1578 while( (c = *(z++))!=0 ){
1579 if( c=='\\' ){
1580 fputc(c, out);
1581 fputc(c, out);
1582 }else if( c=='"' ){
1583 fputc('\\', out);
1584 fputc('"', out);
1585 }else if( c=='\t' ){
1586 fputc('\\', out);
1587 fputc('t', out);
1588 }else if( c=='\n' ){
1589 fputc('\\', out);
1590 fputc('n', out);
1591 }else if( c=='\r' ){
1592 fputc('\\', out);
1593 fputc('r', out);
1594 }else if( !isprint(c&0xff) ){
1595 raw_printf(out, "\\%03o", c&0xff);
1596 }else{
1597 fputc(c, out);
1598 }
1599 }
1600 fputc('"', out);
1601}
1602
1603/*
drh69c093d2020-05-29 00:21:43 +00001604** Output the given string as a quoted according to JSON quoting rules.
1605*/
1606static void output_json_string(FILE *out, const char *z, int n){
1607 unsigned int c;
1608 if( n<0 ) n = (int)strlen(z);
1609 fputc('"', out);
1610 while( n-- ){
1611 c = *(z++);
1612 if( c=='\\' || c=='"' ){
1613 fputc('\\', out);
1614 fputc(c, out);
1615 }else if( c<=0x1f ){
1616 fputc('\\', out);
1617 if( c=='\b' ){
1618 fputc('b', out);
1619 }else if( c=='\f' ){
1620 fputc('f', out);
1621 }else if( c=='\n' ){
1622 fputc('n', out);
1623 }else if( c=='\r' ){
1624 fputc('r', out);
1625 }else if( c=='\t' ){
1626 fputc('t', out);
1627 }else{
1628 raw_printf(out, "u%04x",c);
1629 }
1630 }else{
1631 fputc(c, out);
1632 }
1633 }
1634 fputc('"', out);
1635}
1636
1637/*
drh2ce15c32017-07-11 13:34:40 +00001638** Output the given string with characters that are special to
1639** HTML escaped.
1640*/
1641static void output_html_string(FILE *out, const char *z){
1642 int i;
1643 if( z==0 ) z = "";
1644 while( *z ){
1645 for(i=0; z[i]
1646 && z[i]!='<'
1647 && z[i]!='&'
1648 && z[i]!='>'
1649 && z[i]!='\"'
1650 && z[i]!='\'';
1651 i++){}
1652 if( i>0 ){
1653 utf8_printf(out,"%.*s",i,z);
1654 }
1655 if( z[i]=='<' ){
1656 raw_printf(out,"&lt;");
1657 }else if( z[i]=='&' ){
1658 raw_printf(out,"&amp;");
1659 }else if( z[i]=='>' ){
1660 raw_printf(out,"&gt;");
1661 }else if( z[i]=='\"' ){
1662 raw_printf(out,"&quot;");
1663 }else if( z[i]=='\'' ){
1664 raw_printf(out,"&#39;");
1665 }else{
1666 break;
1667 }
1668 z += i + 1;
1669 }
1670}
1671
1672/*
1673** If a field contains any character identified by a 1 in the following
1674** array, then the string must be quoted for CSV.
1675*/
1676static const char needCsvQuote[] = {
1677 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1678 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1679 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1680 0, 0, 0, 0, 0, 0, 0, 0, 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, 1,
1685 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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};
1694
1695/*
1696** Output a single term of CSV. Actually, p->colSeparator is used for
1697** the separator, which may or may not be a comma. p->nullValue is
1698** the null value. Strings are quoted if necessary. The separator
1699** is only issued if bSep is true.
1700*/
1701static void output_csv(ShellState *p, const char *z, int bSep){
1702 FILE *out = p->out;
1703 if( z==0 ){
1704 utf8_printf(out,"%s",p->nullValue);
1705 }else{
1706 int i;
1707 int nSep = strlen30(p->colSeparator);
1708 for(i=0; z[i]; i++){
1709 if( needCsvQuote[((unsigned char*)z)[i]]
1710 || (z[i]==p->colSeparator[0] &&
1711 (nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){
1712 i = 0;
1713 break;
1714 }
1715 }
1716 if( i==0 ){
drh9b7affc2017-11-26 02:14:18 +00001717 char *zQuoted = sqlite3_mprintf("\"%w\"", z);
1718 utf8_printf(out, "%s", zQuoted);
1719 sqlite3_free(zQuoted);
drh2ce15c32017-07-11 13:34:40 +00001720 }else{
1721 utf8_printf(out, "%s", z);
1722 }
1723 }
1724 if( bSep ){
1725 utf8_printf(p->out, "%s", p->colSeparator);
1726 }
1727}
1728
drh2ce15c32017-07-11 13:34:40 +00001729/*
1730** This routine runs when the user presses Ctrl-C
1731*/
1732static void interrupt_handler(int NotUsed){
1733 UNUSED_PARAMETER(NotUsed);
1734 seenInterrupt++;
1735 if( seenInterrupt>2 ) exit(1);
1736 if( globalDb ) sqlite3_interrupt(globalDb);
1737}
mistachkinb4bab902017-10-27 17:09:44 +00001738
1739#if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
1740/*
1741** This routine runs for console events (e.g. Ctrl-C) on Win32
1742*/
1743static BOOL WINAPI ConsoleCtrlHandler(
1744 DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */
1745){
1746 if( dwCtrlType==CTRL_C_EVENT ){
1747 interrupt_handler(0);
1748 return TRUE;
1749 }
1750 return FALSE;
1751}
drh2ce15c32017-07-11 13:34:40 +00001752#endif
1753
1754#ifndef SQLITE_OMIT_AUTHORIZATION
1755/*
1756** When the ".auth ON" is set, the following authorizer callback is
1757** invoked. It always returns SQLITE_OK.
1758*/
1759static int shellAuth(
1760 void *pClientData,
1761 int op,
1762 const char *zA1,
1763 const char *zA2,
1764 const char *zA3,
1765 const char *zA4
1766){
1767 ShellState *p = (ShellState*)pClientData;
1768 static const char *azAction[] = { 0,
1769 "CREATE_INDEX", "CREATE_TABLE", "CREATE_TEMP_INDEX",
1770 "CREATE_TEMP_TABLE", "CREATE_TEMP_TRIGGER", "CREATE_TEMP_VIEW",
1771 "CREATE_TRIGGER", "CREATE_VIEW", "DELETE",
1772 "DROP_INDEX", "DROP_TABLE", "DROP_TEMP_INDEX",
1773 "DROP_TEMP_TABLE", "DROP_TEMP_TRIGGER", "DROP_TEMP_VIEW",
1774 "DROP_TRIGGER", "DROP_VIEW", "INSERT",
1775 "PRAGMA", "READ", "SELECT",
1776 "TRANSACTION", "UPDATE", "ATTACH",
1777 "DETACH", "ALTER_TABLE", "REINDEX",
1778 "ANALYZE", "CREATE_VTABLE", "DROP_VTABLE",
1779 "FUNCTION", "SAVEPOINT", "RECURSIVE"
1780 };
1781 int i;
1782 const char *az[4];
1783 az[0] = zA1;
1784 az[1] = zA2;
1785 az[2] = zA3;
1786 az[3] = zA4;
1787 utf8_printf(p->out, "authorizer: %s", azAction[op]);
1788 for(i=0; i<4; i++){
1789 raw_printf(p->out, " ");
1790 if( az[i] ){
1791 output_c_string(p->out, az[i]);
1792 }else{
1793 raw_printf(p->out, "NULL");
1794 }
1795 }
1796 raw_printf(p->out, "\n");
1797 return SQLITE_OK;
1798}
1799#endif
1800
1801/*
1802** Print a schema statement. Part of MODE_Semi and MODE_Pretty output.
1803**
1804** This routine converts some CREATE TABLE statements for shadow tables
1805** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
1806*/
1807static void printSchemaLine(FILE *out, const char *z, const char *zTail){
drh0a0536a2019-05-09 18:13:30 +00001808 if( z==0 ) return;
1809 if( zTail==0 ) return;
drh2ce15c32017-07-11 13:34:40 +00001810 if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
1811 utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
1812 }else{
1813 utf8_printf(out, "%s%s", z, zTail);
1814 }
1815}
1816static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
1817 char c = z[n];
1818 z[n] = 0;
1819 printSchemaLine(out, z, zTail);
1820 z[n] = c;
1821}
1822
1823/*
drh11be81d2018-01-06 15:46:20 +00001824** Return true if string z[] has nothing but whitespace and comments to the
1825** end of the first line.
1826*/
1827static int wsToEol(const char *z){
1828 int i;
1829 for(i=0; z[i]; i++){
1830 if( z[i]=='\n' ) return 1;
1831 if( IsSpace(z[i]) ) continue;
1832 if( z[i]=='-' && z[i+1]=='-' ) return 1;
1833 return 0;
1834 }
1835 return 1;
1836}
drh4b5345c2018-04-24 13:07:40 +00001837
1838/*
1839** Add a new entry to the EXPLAIN QUERY PLAN data
1840*/
drhe2ca99c2018-05-02 00:33:43 +00001841static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
drh4b5345c2018-04-24 13:07:40 +00001842 EQPGraphRow *pNew;
1843 int nText = strlen30(zText);
drhe2ca99c2018-05-02 00:33:43 +00001844 if( p->autoEQPtest ){
1845 utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
1846 }
drh4b5345c2018-04-24 13:07:40 +00001847 pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
1848 if( pNew==0 ) shell_out_of_memory();
drhe2ca99c2018-05-02 00:33:43 +00001849 pNew->iEqpId = iEqpId;
1850 pNew->iParentId = p2;
drh4b5345c2018-04-24 13:07:40 +00001851 memcpy(pNew->zText, zText, nText+1);
1852 pNew->pNext = 0;
1853 if( p->sGraph.pLast ){
1854 p->sGraph.pLast->pNext = pNew;
1855 }else{
1856 p->sGraph.pRow = pNew;
1857 }
1858 p->sGraph.pLast = pNew;
1859}
1860
1861/*
1862** Free and reset the EXPLAIN QUERY PLAN data that has been collected
1863** in p->sGraph.
1864*/
1865static void eqp_reset(ShellState *p){
1866 EQPGraphRow *pRow, *pNext;
1867 for(pRow = p->sGraph.pRow; pRow; pRow = pNext){
1868 pNext = pRow->pNext;
1869 sqlite3_free(pRow);
1870 }
1871 memset(&p->sGraph, 0, sizeof(p->sGraph));
1872}
1873
drhe2ca99c2018-05-02 00:33:43 +00001874/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after
drh4b5345c2018-04-24 13:07:40 +00001875** pOld, or return the first such line if pOld is NULL
1876*/
drhe2ca99c2018-05-02 00:33:43 +00001877static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){
drh4b5345c2018-04-24 13:07:40 +00001878 EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow;
drhe2ca99c2018-05-02 00:33:43 +00001879 while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext;
drh4b5345c2018-04-24 13:07:40 +00001880 return pRow;
1881}
1882
drhe2ca99c2018-05-02 00:33:43 +00001883/* Render a single level of the graph that has iEqpId as its parent. Called
drh4b5345c2018-04-24 13:07:40 +00001884** recursively to render sublevels.
1885*/
drhe2ca99c2018-05-02 00:33:43 +00001886static void eqp_render_level(ShellState *p, int iEqpId){
drh4b5345c2018-04-24 13:07:40 +00001887 EQPGraphRow *pRow, *pNext;
drh4b5345c2018-04-24 13:07:40 +00001888 int n = strlen30(p->sGraph.zPrefix);
1889 char *z;
drhe2ca99c2018-05-02 00:33:43 +00001890 for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
1891 pNext = eqp_next_row(p, iEqpId, pRow);
drh4b5345c2018-04-24 13:07:40 +00001892 z = pRow->zText;
drhe2754c12019-08-26 12:50:01 +00001893 utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
1894 pNext ? "|--" : "`--", z);
drhe2188f02018-05-07 11:37:34 +00001895 if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){
drh4b5345c2018-04-24 13:07:40 +00001896 memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4);
drhe2ca99c2018-05-02 00:33:43 +00001897 eqp_render_level(p, pRow->iEqpId);
drh4b5345c2018-04-24 13:07:40 +00001898 p->sGraph.zPrefix[n] = 0;
1899 }
1900 }
1901}
1902
1903/*
1904** Display and reset the EXPLAIN QUERY PLAN data
1905*/
1906static void eqp_render(ShellState *p){
1907 EQPGraphRow *pRow = p->sGraph.pRow;
1908 if( pRow ){
1909 if( pRow->zText[0]=='-' ){
1910 if( pRow->pNext==0 ){
1911 eqp_reset(p);
1912 return;
1913 }
1914 utf8_printf(p->out, "%s\n", pRow->zText+3);
1915 p->sGraph.pRow = pRow->pNext;
1916 sqlite3_free(pRow);
1917 }else{
1918 utf8_printf(p->out, "QUERY PLAN\n");
1919 }
1920 p->sGraph.zPrefix[0] = 0;
1921 eqp_render_level(p, 0);
1922 eqp_reset(p);
1923 }
1924}
drh11be81d2018-01-06 15:46:20 +00001925
drh569b1d92019-02-05 20:51:41 +00001926#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh11be81d2018-01-06 15:46:20 +00001927/*
drh3f83f592019-02-04 14:53:18 +00001928** Progress handler callback.
1929*/
1930static int progress_handler(void *pClientData) {
1931 ShellState *p = (ShellState*)pClientData;
1932 p->nProgress++;
1933 if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
1934 raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
drhfc4eeef2019-02-05 19:48:46 +00001935 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
1936 if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
drh3f83f592019-02-04 14:53:18 +00001937 return 1;
1938 }
drhfc4eeef2019-02-05 19:48:46 +00001939 if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
drh3f83f592019-02-04 14:53:18 +00001940 raw_printf(p->out, "Progress %u\n", p->nProgress);
1941 }
1942 return 0;
1943}
drh569b1d92019-02-05 20:51:41 +00001944#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
drh3f83f592019-02-04 14:53:18 +00001945
1946/*
drh30c54a02020-05-28 23:49:50 +00001947** Print N dashes
1948*/
1949static void print_dashes(FILE *out, int N){
1950 const char zDash[] = "--------------------------------------------------";
1951 const int nDash = sizeof(zDash) - 1;
1952 while( N>nDash ){
1953 fputs(zDash, out);
1954 N -= nDash;
1955 }
1956 raw_printf(out, "%.*s", N, zDash);
1957}
1958
1959/*
drh0908e382020-06-04 18:05:39 +00001960** Print a markdown or table-style row separator using ascii-art
drh30c54a02020-05-28 23:49:50 +00001961*/
1962static void print_row_separator(
1963 ShellState *p,
1964 int nArg,
1965 const char *zSep
1966){
1967 int i;
drh0908e382020-06-04 18:05:39 +00001968 if( nArg>0 ){
drh30c54a02020-05-28 23:49:50 +00001969 fputs(zSep, p->out);
drh0908e382020-06-04 18:05:39 +00001970 print_dashes(p->out, p->actualWidth[0]+2);
1971 for(i=1; i<nArg; i++){
1972 fputs(zSep, p->out);
1973 print_dashes(p->out, p->actualWidth[i]+2);
1974 }
1975 fputs(zSep, p->out);
drh30c54a02020-05-28 23:49:50 +00001976 }
drh30c54a02020-05-28 23:49:50 +00001977 fputs("\n", p->out);
1978}
1979
1980/*
drh2ce15c32017-07-11 13:34:40 +00001981** This is the callback routine that the shell
1982** invokes for each row of a query result.
1983*/
1984static int shell_callback(
1985 void *pArg,
1986 int nArg, /* Number of result columns */
1987 char **azArg, /* Text of each result column */
1988 char **azCol, /* Column names */
drhd6f25242020-05-29 12:31:53 +00001989 int *aiType /* Column types. Might be NULL */
drh2ce15c32017-07-11 13:34:40 +00001990){
1991 int i;
1992 ShellState *p = (ShellState*)pArg;
1993
drhb3c45232017-08-28 14:33:27 +00001994 if( azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00001995 switch( p->cMode ){
1996 case MODE_Line: {
1997 int w = 5;
1998 if( azArg==0 ) break;
1999 for(i=0; i<nArg; i++){
2000 int len = strlen30(azCol[i] ? azCol[i] : "");
2001 if( len>w ) w = len;
2002 }
2003 if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
2004 for(i=0; i<nArg; i++){
2005 utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
2006 azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
2007 }
2008 break;
2009 }
drh8c748632020-05-29 16:15:58 +00002010 case MODE_Explain: {
2011 static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
2012 if( nArg>ArraySize(aExplainWidth) ){
2013 nArg = ArraySize(aExplainWidth);
drh2ce15c32017-07-11 13:34:40 +00002014 }
2015 if( p->cnt++==0 ){
2016 for(i=0; i<nArg; i++){
drh8c748632020-05-29 16:15:58 +00002017 int w = aExplainWidth[i];
2018 utf8_width_print(p->out, w, azCol[i]);
2019 fputs(i==nArg-1 ? "\n" : " ", p->out);
drh2ce15c32017-07-11 13:34:40 +00002020 }
drhe566ceb2020-05-30 15:34:49 +00002021 for(i=0; i<nArg; i++){
2022 int w = aExplainWidth[i];
2023 print_dashes(p->out, w);
2024 fputs(i==nArg-1 ? "\n" : " ", p->out);
2025 }
drh2ce15c32017-07-11 13:34:40 +00002026 }
2027 if( azArg==0 ) break;
2028 for(i=0; i<nArg; i++){
drh8c748632020-05-29 16:15:58 +00002029 int w = aExplainWidth[i];
drhaa556b02021-01-13 12:59:20 +00002030 if( i==nArg-1 ) w = 0;
drh8c748632020-05-29 16:15:58 +00002031 if( azArg[i] && strlenChar(azArg[i])>w ){
2032 w = strlenChar(azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00002033 }
drh8c748632020-05-29 16:15:58 +00002034 if( i==1 && p->aiIndent && p->pStmt ){
2035 if( p->iIndent<p->nIndent ){
2036 utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
drh2ce15c32017-07-11 13:34:40 +00002037 }
drh8c748632020-05-29 16:15:58 +00002038 p->iIndent++;
drh2ce15c32017-07-11 13:34:40 +00002039 }
2040 utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
drh8c748632020-05-29 16:15:58 +00002041 fputs(i==nArg-1 ? "\n" : " ", p->out);
drh2ce15c32017-07-11 13:34:40 +00002042 }
2043 break;
2044 }
2045 case MODE_Semi: { /* .schema and .fullschema output */
2046 printSchemaLine(p->out, azArg[0], ";\n");
2047 break;
2048 }
2049 case MODE_Pretty: { /* .schema and .fullschema with --indent */
2050 char *z;
2051 int j;
2052 int nParen = 0;
2053 char cEnd = 0;
2054 char c;
2055 int nLine = 0;
2056 assert( nArg==1 );
2057 if( azArg[0]==0 ) break;
2058 if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
2059 || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
2060 ){
2061 utf8_printf(p->out, "%s;\n", azArg[0]);
2062 break;
2063 }
2064 z = sqlite3_mprintf("%s", azArg[0]);
2065 j = 0;
2066 for(i=0; IsSpace(z[i]); i++){}
2067 for(; (c = z[i])!=0; i++){
2068 if( IsSpace(c) ){
drhc3cbd672017-10-05 19:12:10 +00002069 if( z[j-1]=='\r' ) z[j-1] = '\n';
drh2ce15c32017-07-11 13:34:40 +00002070 if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
2071 }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
2072 j--;
2073 }
2074 z[j++] = c;
2075 }
2076 while( j>0 && IsSpace(z[j-1]) ){ j--; }
2077 z[j] = 0;
2078 if( strlen30(z)>=79 ){
drhe2754c12019-08-26 12:50:01 +00002079 for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */
drh2ce15c32017-07-11 13:34:40 +00002080 if( c==cEnd ){
2081 cEnd = 0;
2082 }else if( c=='"' || c=='\'' || c=='`' ){
2083 cEnd = c;
2084 }else if( c=='[' ){
2085 cEnd = ']';
drh11be81d2018-01-06 15:46:20 +00002086 }else if( c=='-' && z[i+1]=='-' ){
2087 cEnd = '\n';
drh2ce15c32017-07-11 13:34:40 +00002088 }else if( c=='(' ){
2089 nParen++;
2090 }else if( c==')' ){
2091 nParen--;
2092 if( nLine>0 && nParen==0 && j>0 ){
2093 printSchemaLineN(p->out, z, j, "\n");
2094 j = 0;
2095 }
2096 }
2097 z[j++] = c;
drh11be81d2018-01-06 15:46:20 +00002098 if( nParen==1 && cEnd==0
2099 && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
2100 ){
drh2ce15c32017-07-11 13:34:40 +00002101 if( c=='\n' ) j--;
2102 printSchemaLineN(p->out, z, j, "\n ");
2103 j = 0;
2104 nLine++;
2105 while( IsSpace(z[i+1]) ){ i++; }
2106 }
2107 }
2108 z[j] = 0;
2109 }
2110 printSchemaLine(p->out, z, ";\n");
2111 sqlite3_free(z);
2112 break;
2113 }
2114 case MODE_List: {
2115 if( p->cnt++==0 && p->showHeader ){
2116 for(i=0; i<nArg; i++){
2117 utf8_printf(p->out,"%s%s",azCol[i],
2118 i==nArg-1 ? p->rowSeparator : p->colSeparator);
2119 }
2120 }
2121 if( azArg==0 ) break;
2122 for(i=0; i<nArg; i++){
2123 char *z = azArg[i];
2124 if( z==0 ) z = p->nullValue;
2125 utf8_printf(p->out, "%s", z);
2126 if( i<nArg-1 ){
2127 utf8_printf(p->out, "%s", p->colSeparator);
2128 }else{
2129 utf8_printf(p->out, "%s", p->rowSeparator);
2130 }
2131 }
2132 break;
2133 }
2134 case MODE_Html: {
2135 if( p->cnt++==0 && p->showHeader ){
2136 raw_printf(p->out,"<TR>");
2137 for(i=0; i<nArg; i++){
2138 raw_printf(p->out,"<TH>");
2139 output_html_string(p->out, azCol[i]);
2140 raw_printf(p->out,"</TH>\n");
2141 }
2142 raw_printf(p->out,"</TR>\n");
2143 }
2144 if( azArg==0 ) break;
2145 raw_printf(p->out,"<TR>");
2146 for(i=0; i<nArg; i++){
2147 raw_printf(p->out,"<TD>");
2148 output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
2149 raw_printf(p->out,"</TD>\n");
2150 }
2151 raw_printf(p->out,"</TR>\n");
2152 break;
2153 }
2154 case MODE_Tcl: {
2155 if( p->cnt++==0 && p->showHeader ){
2156 for(i=0; i<nArg; i++){
2157 output_c_string(p->out,azCol[i] ? azCol[i] : "");
2158 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
2159 }
2160 utf8_printf(p->out, "%s", p->rowSeparator);
2161 }
2162 if( azArg==0 ) break;
2163 for(i=0; i<nArg; i++){
2164 output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
2165 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
2166 }
2167 utf8_printf(p->out, "%s", p->rowSeparator);
2168 break;
2169 }
2170 case MODE_Csv: {
2171 setBinaryMode(p->out, 1);
2172 if( p->cnt++==0 && p->showHeader ){
2173 for(i=0; i<nArg; i++){
2174 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
2175 }
2176 utf8_printf(p->out, "%s", p->rowSeparator);
2177 }
2178 if( nArg>0 ){
2179 for(i=0; i<nArg; i++){
2180 output_csv(p, azArg[i], i<nArg-1);
2181 }
2182 utf8_printf(p->out, "%s", p->rowSeparator);
2183 }
2184 setTextMode(p->out, 1);
2185 break;
2186 }
2187 case MODE_Insert: {
2188 if( azArg==0 ) break;
2189 utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
2190 if( p->showHeader ){
2191 raw_printf(p->out,"(");
2192 for(i=0; i<nArg; i++){
2193 if( i>0 ) raw_printf(p->out, ",");
2194 if( quoteChar(azCol[i]) ){
2195 char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
2196 utf8_printf(p->out, "%s", z);
2197 sqlite3_free(z);
2198 }else{
2199 raw_printf(p->out, "%s", azCol[i]);
2200 }
2201 }
2202 raw_printf(p->out,")");
2203 }
2204 p->cnt++;
2205 for(i=0; i<nArg; i++){
2206 raw_printf(p->out, i>0 ? "," : " VALUES(");
2207 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2208 utf8_printf(p->out,"NULL");
2209 }else if( aiType && aiType[i]==SQLITE_TEXT ){
2210 if( ShellHasFlag(p, SHFLG_Newlines) ){
2211 output_quoted_string(p->out, azArg[i]);
2212 }else{
2213 output_quoted_escaped_string(p->out, azArg[i]);
2214 }
2215 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
2216 utf8_printf(p->out,"%s", azArg[i]);
2217 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2218 char z[50];
2219 double r = sqlite3_column_double(p->pStmt, i);
drh2f1f8802018-06-13 17:19:20 +00002220 sqlite3_uint64 ur;
2221 memcpy(&ur,&r,sizeof(r));
2222 if( ur==0x7ff0000000000000LL ){
2223 raw_printf(p->out, "1e999");
2224 }else if( ur==0xfff0000000000000LL ){
2225 raw_printf(p->out, "-1e999");
2226 }else{
2227 sqlite3_snprintf(50,z,"%!.20g", r);
2228 raw_printf(p->out, "%s", z);
2229 }
drh2ce15c32017-07-11 13:34:40 +00002230 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2231 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2232 int nBlob = sqlite3_column_bytes(p->pStmt, i);
2233 output_hex_blob(p->out, pBlob, nBlob);
2234 }else if( isNumber(azArg[i], 0) ){
2235 utf8_printf(p->out,"%s", azArg[i]);
2236 }else if( ShellHasFlag(p, SHFLG_Newlines) ){
2237 output_quoted_string(p->out, azArg[i]);
2238 }else{
2239 output_quoted_escaped_string(p->out, azArg[i]);
2240 }
2241 }
2242 raw_printf(p->out,");\n");
2243 break;
2244 }
drh30c54a02020-05-28 23:49:50 +00002245 case MODE_Json: {
2246 if( azArg==0 ) break;
2247 if( p->cnt==0 ){
2248 fputs("[{", p->out);
2249 }else{
2250 fputs(",\n{", p->out);
2251 }
2252 p->cnt++;
2253 for(i=0; i<nArg; i++){
drh69c093d2020-05-29 00:21:43 +00002254 output_json_string(p->out, azCol[i], -1);
drh30c54a02020-05-28 23:49:50 +00002255 putc(':', p->out);
2256 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2257 fputs("null",p->out);
2258 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2259 char z[50];
2260 double r = sqlite3_column_double(p->pStmt, i);
2261 sqlite3_uint64 ur;
2262 memcpy(&ur,&r,sizeof(r));
2263 if( ur==0x7ff0000000000000LL ){
2264 raw_printf(p->out, "1e999");
2265 }else if( ur==0xfff0000000000000LL ){
2266 raw_printf(p->out, "-1e999");
2267 }else{
2268 sqlite3_snprintf(50,z,"%!.20g", r);
2269 raw_printf(p->out, "%s", z);
2270 }
2271 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2272 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2273 int nBlob = sqlite3_column_bytes(p->pStmt, i);
drh69c093d2020-05-29 00:21:43 +00002274 output_json_string(p->out, pBlob, nBlob);
drh30c54a02020-05-28 23:49:50 +00002275 }else if( aiType && aiType[i]==SQLITE_TEXT ){
drh69c093d2020-05-29 00:21:43 +00002276 output_json_string(p->out, azArg[i], -1);
drh30c54a02020-05-28 23:49:50 +00002277 }else{
2278 utf8_printf(p->out,"%s", azArg[i]);
2279 }
2280 if( i<nArg-1 ){
2281 putc(',', p->out);
2282 }
2283 }
2284 putc('}', p->out);
2285 break;
2286 }
drh2ce15c32017-07-11 13:34:40 +00002287 case MODE_Quote: {
2288 if( azArg==0 ) break;
2289 if( p->cnt==0 && p->showHeader ){
2290 for(i=0; i<nArg; i++){
drhc6835732020-05-28 20:37:17 +00002291 if( i>0 ) fputs(p->colSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002292 output_quoted_string(p->out, azCol[i]);
2293 }
drhc6835732020-05-28 20:37:17 +00002294 fputs(p->rowSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002295 }
2296 p->cnt++;
2297 for(i=0; i<nArg; i++){
drhc6835732020-05-28 20:37:17 +00002298 if( i>0 ) fputs(p->colSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002299 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2300 utf8_printf(p->out,"NULL");
2301 }else if( aiType && aiType[i]==SQLITE_TEXT ){
2302 output_quoted_string(p->out, azArg[i]);
2303 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
2304 utf8_printf(p->out,"%s", azArg[i]);
2305 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2306 char z[50];
2307 double r = sqlite3_column_double(p->pStmt, i);
2308 sqlite3_snprintf(50,z,"%!.20g", r);
2309 raw_printf(p->out, "%s", z);
2310 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2311 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2312 int nBlob = sqlite3_column_bytes(p->pStmt, i);
2313 output_hex_blob(p->out, pBlob, nBlob);
2314 }else if( isNumber(azArg[i], 0) ){
2315 utf8_printf(p->out,"%s", azArg[i]);
2316 }else{
2317 output_quoted_string(p->out, azArg[i]);
2318 }
2319 }
drhc6835732020-05-28 20:37:17 +00002320 fputs(p->rowSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002321 break;
2322 }
2323 case MODE_Ascii: {
2324 if( p->cnt++==0 && p->showHeader ){
2325 for(i=0; i<nArg; i++){
2326 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
2327 utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
2328 }
2329 utf8_printf(p->out, "%s", p->rowSeparator);
2330 }
2331 if( azArg==0 ) break;
2332 for(i=0; i<nArg; i++){
2333 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
2334 utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
2335 }
2336 utf8_printf(p->out, "%s", p->rowSeparator);
2337 break;
2338 }
drh4b5345c2018-04-24 13:07:40 +00002339 case MODE_EQP: {
drhe2ca99c2018-05-02 00:33:43 +00002340 eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]);
drh4b5345c2018-04-24 13:07:40 +00002341 break;
2342 }
drh2ce15c32017-07-11 13:34:40 +00002343 }
2344 return 0;
2345}
2346
2347/*
2348** This is the callback routine that the SQLite library
2349** invokes for each row of a query result.
2350*/
2351static int callback(void *pArg, int nArg, char **azArg, char **azCol){
2352 /* since we don't have type info, call the shell_callback with a NULL value */
2353 return shell_callback(pArg, nArg, azArg, azCol, NULL);
2354}
2355
2356/*
2357** This is the callback routine from sqlite3_exec() that appends all
2358** output onto the end of a ShellText object.
2359*/
2360static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
2361 ShellText *p = (ShellText*)pArg;
2362 int i;
2363 UNUSED_PARAMETER(az);
drhb3c45232017-08-28 14:33:27 +00002364 if( azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00002365 if( p->n ) appendText(p, "|", 0);
2366 for(i=0; i<nArg; i++){
2367 if( i ) appendText(p, ",", 0);
2368 if( azArg[i] ) appendText(p, azArg[i], 0);
2369 }
2370 return 0;
2371}
2372
2373/*
2374** Generate an appropriate SELFTEST table in the main database.
2375*/
2376static void createSelftestTable(ShellState *p){
2377 char *zErrMsg = 0;
2378 sqlite3_exec(p->db,
2379 "SAVEPOINT selftest_init;\n"
2380 "CREATE TABLE IF NOT EXISTS selftest(\n"
2381 " tno INTEGER PRIMARY KEY,\n" /* Test number */
2382 " op TEXT,\n" /* Operator: memo run */
2383 " cmd TEXT,\n" /* Command text */
2384 " ans TEXT\n" /* Desired answer */
2385 ");"
2386 "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n"
2387 "INSERT INTO [_shell$self](rowid,op,cmd)\n"
2388 " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n"
2389 " 'memo','Tests generated by --init');\n"
2390 "INSERT INTO [_shell$self]\n"
2391 " SELECT 'run',\n"
2392 " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql "
drh067b92b2020-06-19 15:24:12 +00002393 "FROM sqlite_schema ORDER BY 2'',224))',\n"
drh2ce15c32017-07-11 13:34:40 +00002394 " hex(sha3_query('SELECT type,name,tbl_name,sql "
drh067b92b2020-06-19 15:24:12 +00002395 "FROM sqlite_schema ORDER BY 2',224));\n"
drh2ce15c32017-07-11 13:34:40 +00002396 "INSERT INTO [_shell$self]\n"
2397 " SELECT 'run',"
2398 " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||"
2399 " printf('%w',name) || '\" NOT INDEXED'',224))',\n"
2400 " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"
2401 " FROM (\n"
drh067b92b2020-06-19 15:24:12 +00002402 " SELECT name FROM sqlite_schema\n"
drh2ce15c32017-07-11 13:34:40 +00002403 " WHERE type='table'\n"
2404 " AND name<>'selftest'\n"
2405 " AND coalesce(rootpage,0)>0\n"
2406 " )\n"
2407 " ORDER BY name;\n"
2408 "INSERT INTO [_shell$self]\n"
2409 " VALUES('run','PRAGMA integrity_check','ok');\n"
2410 "INSERT INTO selftest(tno,op,cmd,ans)"
2411 " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n"
2412 "DROP TABLE [_shell$self];"
2413 ,0,0,&zErrMsg);
2414 if( zErrMsg ){
2415 utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
2416 sqlite3_free(zErrMsg);
2417 }
2418 sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
2419}
2420
2421
2422/*
2423** Set the destination table field of the ShellState structure to
2424** the name of the table given. Escape any quote characters in the
2425** table name.
2426*/
2427static void set_table_name(ShellState *p, const char *zName){
2428 int i, n;
mistachkin2158a0c2017-09-09 00:51:36 +00002429 char cQuote;
drh2ce15c32017-07-11 13:34:40 +00002430 char *z;
2431
2432 if( p->zDestTable ){
2433 free(p->zDestTable);
2434 p->zDestTable = 0;
2435 }
2436 if( zName==0 ) return;
2437 cQuote = quoteChar(zName);
2438 n = strlen30(zName);
2439 if( cQuote ) n += n+2;
2440 z = p->zDestTable = malloc( n+1 );
drh4b5345c2018-04-24 13:07:40 +00002441 if( z==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00002442 n = 0;
2443 if( cQuote ) z[n++] = cQuote;
2444 for(i=0; zName[i]; i++){
2445 z[n++] = zName[i];
2446 if( zName[i]==cQuote ) z[n++] = cQuote;
2447 }
2448 if( cQuote ) z[n++] = cQuote;
2449 z[n] = 0;
2450}
2451
2452
2453/*
2454** Execute a query statement that will generate SQL output. Print
2455** the result columns, comma-separated, on a line and then add a
2456** semicolon terminator to the end of that line.
2457**
2458** If the number of columns is 1 and that column contains text "--"
2459** then write the semicolon on a separate line. That way, if a
2460** "--" comment occurs at the end of the statement, the comment
2461** won't consume the semicolon terminator.
2462*/
2463static int run_table_dump_query(
2464 ShellState *p, /* Query context */
drh8e9297f2020-03-25 12:50:13 +00002465 const char *zSelect /* SELECT statement to extract content */
drh2ce15c32017-07-11 13:34:40 +00002466){
2467 sqlite3_stmt *pSelect;
2468 int rc;
2469 int nResult;
2470 int i;
2471 const char *z;
2472 rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
2473 if( rc!=SQLITE_OK || !pSelect ){
2474 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
2475 sqlite3_errmsg(p->db));
2476 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
2477 return rc;
2478 }
2479 rc = sqlite3_step(pSelect);
2480 nResult = sqlite3_column_count(pSelect);
2481 while( rc==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00002482 z = (const char*)sqlite3_column_text(pSelect, 0);
2483 utf8_printf(p->out, "%s", z);
2484 for(i=1; i<nResult; i++){
2485 utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
2486 }
2487 if( z==0 ) z = "";
2488 while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
2489 if( z[0] ){
2490 raw_printf(p->out, "\n;\n");
2491 }else{
2492 raw_printf(p->out, ";\n");
2493 }
2494 rc = sqlite3_step(pSelect);
2495 }
2496 rc = sqlite3_finalize(pSelect);
2497 if( rc!=SQLITE_OK ){
2498 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
2499 sqlite3_errmsg(p->db));
2500 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
2501 }
2502 return rc;
2503}
2504
2505/*
2506** Allocate space and save off current error string.
2507*/
2508static char *save_err_msg(
2509 sqlite3 *db /* Database to query */
2510){
2511 int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
2512 char *zErrMsg = sqlite3_malloc64(nErrMsg);
2513 if( zErrMsg ){
2514 memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
2515 }
2516 return zErrMsg;
2517}
2518
2519#ifdef __linux__
2520/*
2521** Attempt to display I/O stats on Linux using /proc/PID/io
2522*/
2523static void displayLinuxIoStats(FILE *out){
2524 FILE *in;
2525 char z[200];
2526 sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
2527 in = fopen(z, "rb");
2528 if( in==0 ) return;
2529 while( fgets(z, sizeof(z), in)!=0 ){
2530 static const struct {
2531 const char *zPattern;
2532 const char *zDesc;
2533 } aTrans[] = {
2534 { "rchar: ", "Bytes received by read():" },
2535 { "wchar: ", "Bytes sent to write():" },
2536 { "syscr: ", "Read() system calls:" },
2537 { "syscw: ", "Write() system calls:" },
2538 { "read_bytes: ", "Bytes read from storage:" },
2539 { "write_bytes: ", "Bytes written to storage:" },
2540 { "cancelled_write_bytes: ", "Cancelled write bytes:" },
2541 };
2542 int i;
2543 for(i=0; i<ArraySize(aTrans); i++){
drhaf2770f2018-01-05 14:55:43 +00002544 int n = strlen30(aTrans[i].zPattern);
drh2ce15c32017-07-11 13:34:40 +00002545 if( strncmp(aTrans[i].zPattern, z, n)==0 ){
2546 utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
2547 break;
2548 }
2549 }
2550 }
2551 fclose(in);
2552}
2553#endif
2554
2555/*
2556** Display a single line of status using 64-bit values.
2557*/
2558static void displayStatLine(
2559 ShellState *p, /* The shell context */
2560 char *zLabel, /* Label for this one line */
2561 char *zFormat, /* Format for the result */
2562 int iStatusCtrl, /* Which status to display */
2563 int bReset /* True to reset the stats */
2564){
2565 sqlite3_int64 iCur = -1;
2566 sqlite3_int64 iHiwtr = -1;
2567 int i, nPercent;
2568 char zLine[200];
2569 sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset);
2570 for(i=0, nPercent=0; zFormat[i]; i++){
2571 if( zFormat[i]=='%' ) nPercent++;
2572 }
2573 if( nPercent>1 ){
2574 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr);
2575 }else{
2576 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
2577 }
2578 raw_printf(p->out, "%-36s %s\n", zLabel, zLine);
2579}
2580
2581/*
2582** Display memory stats.
2583*/
2584static int display_stats(
2585 sqlite3 *db, /* Database to query */
2586 ShellState *pArg, /* Pointer to ShellState */
2587 int bReset /* True to reset the stats */
2588){
2589 int iCur;
2590 int iHiwtr;
drh393344f2018-03-09 16:37:05 +00002591 FILE *out;
2592 if( pArg==0 || pArg->out==0 ) return 0;
2593 out = pArg->out;
drh2ce15c32017-07-11 13:34:40 +00002594
drha6e6cf22021-01-09 19:10:04 +00002595 if( pArg->pStmt && pArg->statsOn==2 ){
drh393344f2018-03-09 16:37:05 +00002596 int nCol, i, x;
2597 sqlite3_stmt *pStmt = pArg->pStmt;
2598 char z[100];
2599 nCol = sqlite3_column_count(pStmt);
2600 raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
2601 for(i=0; i<nCol; i++){
2602 sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
2603 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
drh929cce82018-03-17 16:26:36 +00002604#ifndef SQLITE_OMIT_DECLTYPE
drh393344f2018-03-09 16:37:05 +00002605 sqlite3_snprintf(30, z+x, "declared type:");
2606 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
drh929cce82018-03-17 16:26:36 +00002607#endif
2608#ifdef SQLITE_ENABLE_COLUMN_METADATA
drh393344f2018-03-09 16:37:05 +00002609 sqlite3_snprintf(30, z+x, "database name:");
2610 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
2611 sqlite3_snprintf(30, z+x, "table name:");
2612 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
2613 sqlite3_snprintf(30, z+x, "origin name:");
2614 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
drh929cce82018-03-17 16:26:36 +00002615#endif
drh2ce15c32017-07-11 13:34:40 +00002616 }
drh929cce82018-03-17 16:26:36 +00002617 }
drh2ce15c32017-07-11 13:34:40 +00002618
drha6e6cf22021-01-09 19:10:04 +00002619 if( pArg->statsOn==3 ){
2620 if( pArg->pStmt ){
2621 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
2622 raw_printf(pArg->out, "VM-steps: %d\n", iCur);
2623 }
2624 return 0;
2625 }
2626
drh393344f2018-03-09 16:37:05 +00002627 displayStatLine(pArg, "Memory Used:",
2628 "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
2629 displayStatLine(pArg, "Number of Outstanding Allocations:",
2630 "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
2631 if( pArg->shellFlgs & SHFLG_Pagecache ){
2632 displayStatLine(pArg, "Number of Pcache Pages Used:",
2633 "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
2634 }
2635 displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
2636 "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
2637 displayStatLine(pArg, "Largest Allocation:",
2638 "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
2639 displayStatLine(pArg, "Largest Pcache Allocation:",
2640 "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
2641#ifdef YYTRACKMAXSTACKDEPTH
2642 displayStatLine(pArg, "Deepest Parser Stack:",
2643 "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
2644#endif
2645
2646 if( db ){
drh2ce15c32017-07-11 13:34:40 +00002647 if( pArg->shellFlgs & SHFLG_Lookaside ){
2648 iHiwtr = iCur = -1;
2649 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
2650 &iCur, &iHiwtr, bReset);
2651 raw_printf(pArg->out,
2652 "Lookaside Slots Used: %d (max %d)\n",
2653 iCur, iHiwtr);
2654 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
2655 &iCur, &iHiwtr, bReset);
2656 raw_printf(pArg->out, "Successful lookaside attempts: %d\n",
2657 iHiwtr);
2658 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
2659 &iCur, &iHiwtr, bReset);
2660 raw_printf(pArg->out, "Lookaside failures due to size: %d\n",
2661 iHiwtr);
2662 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
2663 &iCur, &iHiwtr, bReset);
2664 raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n",
2665 iHiwtr);
2666 }
2667 iHiwtr = iCur = -1;
2668 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
2669 raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n",
2670 iCur);
2671 iHiwtr = iCur = -1;
2672 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
2673 raw_printf(pArg->out, "Page cache hits: %d\n", iCur);
2674 iHiwtr = iCur = -1;
2675 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
2676 raw_printf(pArg->out, "Page cache misses: %d\n", iCur);
2677 iHiwtr = iCur = -1;
2678 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
2679 raw_printf(pArg->out, "Page cache writes: %d\n", iCur);
2680 iHiwtr = iCur = -1;
drhffc78a42018-03-14 14:53:50 +00002681 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
2682 raw_printf(pArg->out, "Page cache spills: %d\n", iCur);
2683 iHiwtr = iCur = -1;
drh2ce15c32017-07-11 13:34:40 +00002684 sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
2685 raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n",
2686 iCur);
2687 iHiwtr = iCur = -1;
2688 sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
2689 raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
2690 iCur);
2691 }
2692
drh393344f2018-03-09 16:37:05 +00002693 if( pArg->pStmt ){
drh2ce15c32017-07-11 13:34:40 +00002694 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
2695 bReset);
2696 raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
2697 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
2698 raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
2699 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
2700 raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
2701 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
2702 raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
drhe2754c12019-08-26 12:50:01 +00002703 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
drh393344f2018-03-09 16:37:05 +00002704 raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
2705 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
2706 raw_printf(pArg->out, "Number of times run: %d\n", iCur);
2707 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
2708 raw_printf(pArg->out, "Memory used by prepared stmt: %d\n", iCur);
drh2ce15c32017-07-11 13:34:40 +00002709 }
2710
2711#ifdef __linux__
2712 displayLinuxIoStats(pArg->out);
2713#endif
2714
2715 /* Do not remove this machine readable comment: extra-stats-output-here */
2716
2717 return 0;
2718}
2719
2720/*
2721** Display scan stats.
2722*/
2723static void display_scanstats(
2724 sqlite3 *db, /* Database to query */
2725 ShellState *pArg /* Pointer to ShellState */
2726){
2727#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
2728 UNUSED_PARAMETER(db);
2729 UNUSED_PARAMETER(pArg);
2730#else
2731 int i, k, n, mx;
2732 raw_printf(pArg->out, "-------- scanstats --------\n");
2733 mx = 0;
2734 for(k=0; k<=mx; k++){
2735 double rEstLoop = 1.0;
2736 for(i=n=0; 1; i++){
2737 sqlite3_stmt *p = pArg->pStmt;
2738 sqlite3_int64 nLoop, nVisit;
2739 double rEst;
2740 int iSid;
2741 const char *zExplain;
2742 if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){
2743 break;
2744 }
2745 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
2746 if( iSid>mx ) mx = iSid;
2747 if( iSid!=k ) continue;
2748 if( n==0 ){
2749 rEstLoop = (double)nLoop;
2750 if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k);
2751 }
2752 n++;
2753 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
2754 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
2755 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
2756 utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
2757 rEstLoop *= rEst;
2758 raw_printf(pArg->out,
2759 " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
2760 nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
2761 );
2762 }
2763 }
2764 raw_printf(pArg->out, "---------------------------\n");
2765#endif
2766}
2767
2768/*
2769** Parameter azArray points to a zero-terminated array of strings. zStr
2770** points to a single nul-terminated string. Return non-zero if zStr
2771** is equal, according to strcmp(), to any of the strings in the array.
2772** Otherwise, return zero.
2773*/
2774static int str_in_array(const char *zStr, const char **azArray){
2775 int i;
2776 for(i=0; azArray[i]; i++){
2777 if( 0==strcmp(zStr, azArray[i]) ) return 1;
2778 }
2779 return 0;
2780}
2781
2782/*
2783** If compiled statement pSql appears to be an EXPLAIN statement, allocate
2784** and populate the ShellState.aiIndent[] array with the number of
2785** spaces each opcode should be indented before it is output.
2786**
2787** The indenting rules are:
2788**
2789** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
2790** all opcodes that occur between the p2 jump destination and the opcode
2791** itself by 2 spaces.
2792**
2793** * For each "Goto", if the jump destination is earlier in the program
2794** and ends on one of:
2795** Yield SeekGt SeekLt RowSetRead Rewind
2796** or if the P1 parameter is one instead of zero,
2797** then indent all opcodes between the earlier instruction
2798** and "Goto" by 2 spaces.
2799*/
2800static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
2801 const char *zSql; /* The text of the SQL statement */
2802 const char *z; /* Used to check if this is an EXPLAIN */
2803 int *abYield = 0; /* True if op is an OP_Yield */
2804 int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
2805 int iOp; /* Index of operation in p->aiIndent[] */
2806
drhf1949b62018-06-07 17:32:59 +00002807 const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
drh2ce15c32017-07-11 13:34:40 +00002808 const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
2809 "Rewind", 0 };
2810 const char *azGoto[] = { "Goto", 0 };
2811
2812 /* Try to figure out if this is really an EXPLAIN statement. If this
2813 ** cannot be verified, return early. */
2814 if( sqlite3_column_count(pSql)!=8 ){
2815 p->cMode = p->mode;
2816 return;
2817 }
2818 zSql = sqlite3_sql(pSql);
2819 if( zSql==0 ) return;
2820 for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
2821 if( sqlite3_strnicmp(z, "explain", 7) ){
2822 p->cMode = p->mode;
2823 return;
2824 }
2825
2826 for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
2827 int i;
2828 int iAddr = sqlite3_column_int(pSql, 0);
2829 const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
2830
2831 /* Set p2 to the P2 field of the current opcode. Then, assuming that
2832 ** p2 is an instruction address, set variable p2op to the index of that
2833 ** instruction in the aiIndent[] array. p2 and p2op may be different if
2834 ** the current instruction is part of a sub-program generated by an
2835 ** SQL trigger or foreign key. */
2836 int p2 = sqlite3_column_int(pSql, 3);
2837 int p2op = (p2 + (iOp-iAddr));
2838
2839 /* Grow the p->aiIndent array as required */
2840 if( iOp>=nAlloc ){
2841 if( iOp==0 ){
2842 /* Do further verfication that this is explain output. Abort if
2843 ** it is not */
2844 static const char *explainCols[] = {
2845 "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" };
2846 int jj;
2847 for(jj=0; jj<ArraySize(explainCols); jj++){
2848 if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
2849 p->cMode = p->mode;
2850 sqlite3_reset(pSql);
2851 return;
2852 }
2853 }
2854 }
2855 nAlloc += 100;
2856 p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
drh884406b2018-07-29 18:56:35 +00002857 if( p->aiIndent==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00002858 abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
drh884406b2018-07-29 18:56:35 +00002859 if( abYield==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00002860 }
2861 abYield[iOp] = str_in_array(zOp, azYield);
2862 p->aiIndent[iOp] = 0;
2863 p->nIndent = iOp+1;
2864
2865 if( str_in_array(zOp, azNext) ){
2866 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
2867 }
2868 if( str_in_array(zOp, azGoto) && p2op<p->nIndent
2869 && (abYield[p2op] || sqlite3_column_int(pSql, 2))
2870 ){
2871 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
2872 }
2873 }
2874
2875 p->iIndent = 0;
2876 sqlite3_free(abYield);
2877 sqlite3_reset(pSql);
2878}
2879
2880/*
2881** Free the array allocated by explain_data_prepare().
2882*/
2883static void explain_data_delete(ShellState *p){
2884 sqlite3_free(p->aiIndent);
2885 p->aiIndent = 0;
2886 p->nIndent = 0;
2887 p->iIndent = 0;
2888}
2889
2890/*
2891** Disable and restore .wheretrace and .selecttrace settings.
2892*/
drhc0622a42020-12-04 01:17:57 +00002893static unsigned int savedSelectTrace;
2894static unsigned int savedWhereTrace;
drh2ce15c32017-07-11 13:34:40 +00002895static void disable_debug_trace_modes(void){
drh0a2fb792020-12-04 16:58:20 +00002896 unsigned int zero = 0;
drhc0622a42020-12-04 01:17:57 +00002897 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace);
drh0a2fb792020-12-04 16:58:20 +00002898 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero);
drhc0622a42020-12-04 01:17:57 +00002899 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace);
drh0a2fb792020-12-04 16:58:20 +00002900 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero);
drh2ce15c32017-07-11 13:34:40 +00002901}
2902static void restore_debug_trace_modes(void){
drhc0622a42020-12-04 01:17:57 +00002903 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &savedSelectTrace);
2904 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &savedWhereTrace);
drh2ce15c32017-07-11 13:34:40 +00002905}
2906
drh9cb02642019-02-28 20:10:52 +00002907/* Create the TEMP table used to store parameter bindings */
2908static void bind_table_init(ShellState *p){
drh346f4e22019-03-25 21:35:41 +00002909 int wrSchema = 0;
drh4b86e202020-01-19 20:37:26 +00002910 int defensiveMode = 0;
2911 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
2912 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
drh346f4e22019-03-25 21:35:41 +00002913 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
2914 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
drh9cb02642019-02-28 20:10:52 +00002915 sqlite3_exec(p->db,
drh65c29fd2019-03-25 21:56:26 +00002916 "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
drh9cb02642019-02-28 20:10:52 +00002917 " key TEXT PRIMARY KEY,\n"
2918 " value ANY\n"
2919 ") WITHOUT ROWID;",
2920 0, 0, 0);
drh346f4e22019-03-25 21:35:41 +00002921 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
drh4b86e202020-01-19 20:37:26 +00002922 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0);
drh9cb02642019-02-28 20:10:52 +00002923}
2924
drh8b738d02019-02-25 18:43:54 +00002925/*
2926** Bind parameters on a prepared statement.
2927**
2928** Parameter bindings are taken from a TEMP table of the form:
2929**
drh1cb02632019-03-25 22:05:22 +00002930** CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
drh8b738d02019-02-25 18:43:54 +00002931** WITHOUT ROWID;
2932**
drh91654b22020-04-02 13:21:10 +00002933** No bindings occur if this table does not exist. The name of the table
2934** begins with "sqlite_" so that it will not collide with ordinary application
2935** tables. The table must be in the TEMP schema.
drh8b738d02019-02-25 18:43:54 +00002936*/
2937static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
2938 int nVar;
2939 int i;
2940 int rc;
2941 sqlite3_stmt *pQ = 0;
2942
2943 nVar = sqlite3_bind_parameter_count(pStmt);
2944 if( nVar==0 ) return; /* Nothing to do */
drh65c29fd2019-03-25 21:56:26 +00002945 if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters",
drh8b738d02019-02-25 18:43:54 +00002946 "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
2947 return; /* Parameter table does not exist */
2948 }
2949 rc = sqlite3_prepare_v2(pArg->db,
drh65c29fd2019-03-25 21:56:26 +00002950 "SELECT value FROM temp.sqlite_parameters"
drh8b738d02019-02-25 18:43:54 +00002951 " WHERE key=?1", -1, &pQ, 0);
2952 if( rc || pQ==0 ) return;
2953 for(i=1; i<=nVar; i++){
2954 char zNum[30];
2955 const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
2956 if( zVar==0 ){
2957 sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
2958 zVar = zNum;
2959 }
2960 sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
2961 if( sqlite3_step(pQ)==SQLITE_ROW ){
2962 sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
2963 }else{
2964 sqlite3_bind_null(pStmt, i);
2965 }
2966 sqlite3_reset(pQ);
2967 }
2968 sqlite3_finalize(pQ);
2969}
2970
drh30c54a02020-05-28 23:49:50 +00002971/*
drh0908e382020-06-04 18:05:39 +00002972** UTF8 box-drawing characters. Imagine box lines like this:
2973**
2974** 1
2975** |
2976** 4 --+-- 2
2977** |
2978** 3
2979**
2980** Each box characters has between 2 and 4 of the lines leading from
2981** the center. The characters are here identified by the numbers of
2982** their corresponding lines.
2983*/
2984#define BOX_24 "\342\224\200" /* U+2500 --- */
2985#define BOX_13 "\342\224\202" /* U+2502 | */
2986#define BOX_23 "\342\224\214" /* U+250c ,- */
2987#define BOX_34 "\342\224\220" /* U+2510 -, */
2988#define BOX_12 "\342\224\224" /* U+2514 '- */
2989#define BOX_14 "\342\224\230" /* U+2518 -' */
2990#define BOX_123 "\342\224\234" /* U+251c |- */
2991#define BOX_134 "\342\224\244" /* U+2524 -| */
2992#define BOX_234 "\342\224\254" /* U+252c -,- */
2993#define BOX_124 "\342\224\264" /* U+2534 -'- */
2994#define BOX_1234 "\342\224\274" /* U+253c -|- */
2995
2996/* Draw horizontal line N characters long using unicode box
2997** characters
2998*/
2999static void print_box_line(FILE *out, int N){
3000 const char zDash[] =
3001 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
3002 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
3003 const int nDash = sizeof(zDash) - 1;
3004 N *= 3;
3005 while( N>nDash ){
3006 utf8_printf(out, zDash);
3007 N -= nDash;
3008 }
3009 utf8_printf(out, "%.*s", N, zDash);
3010}
3011
3012/*
3013** Draw a horizontal separator for a MODE_Box table.
3014*/
3015static void print_box_row_separator(
3016 ShellState *p,
3017 int nArg,
3018 const char *zSep1,
3019 const char *zSep2,
3020 const char *zSep3
3021){
3022 int i;
3023 if( nArg>0 ){
3024 utf8_printf(p->out, "%s", zSep1);
3025 print_box_line(p->out, p->actualWidth[0]+2);
3026 for(i=1; i<nArg; i++){
3027 utf8_printf(p->out, "%s", zSep2);
3028 print_box_line(p->out, p->actualWidth[i]+2);
3029 }
3030 utf8_printf(p->out, "%s", zSep3);
3031 }
3032 fputs("\n", p->out);
3033}
3034
3035
3036
3037/*
drh30c54a02020-05-28 23:49:50 +00003038** Run a prepared statement and output the result in one of the
drh0908e382020-06-04 18:05:39 +00003039** table-oriented formats: MODE_Column, MODE_Markdown, MODE_Table,
3040** or MODE_Box.
drh30c54a02020-05-28 23:49:50 +00003041**
3042** This is different from ordinary exec_prepared_stmt() in that
3043** it has to run the entire query and gather the results into memory
3044** first, in order to determine column widths, before providing
3045** any output.
3046*/
drh8c748632020-05-29 16:15:58 +00003047static void exec_prepared_stmt_columnar(
3048 ShellState *p, /* Pointer to ShellState */
3049 sqlite3_stmt *pStmt /* Statment to run */
drh30c54a02020-05-28 23:49:50 +00003050){
drhf82ce382020-08-06 16:45:22 +00003051 sqlite3_int64 nRow = 0;
drh8c748632020-05-29 16:15:58 +00003052 int nColumn = 0;
3053 char **azData = 0;
drhf82ce382020-08-06 16:45:22 +00003054 sqlite3_int64 nAlloc = 0;
drh8c748632020-05-29 16:15:58 +00003055 const char *z;
3056 int rc;
drhf82ce382020-08-06 16:45:22 +00003057 sqlite3_int64 i, nData;
3058 int j, nTotal, w, n;
drh0908e382020-06-04 18:05:39 +00003059 const char *colSep = 0;
3060 const char *rowSep = 0;
drh30c54a02020-05-28 23:49:50 +00003061
drhf82ce382020-08-06 16:45:22 +00003062 rc = sqlite3_step(pStmt);
3063 if( rc!=SQLITE_ROW ) return;
3064 nColumn = sqlite3_column_count(pStmt);
3065 nAlloc = nColumn*4;
3066 azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
3067 if( azData==0 ) shell_out_of_memory();
3068 for(i=0; i<nColumn; i++){
3069 azData[i] = strdup(sqlite3_column_name(pStmt,i));
drh8c748632020-05-29 16:15:58 +00003070 }
drhf82ce382020-08-06 16:45:22 +00003071 do{
3072 if( (nRow+2)*nColumn >= nAlloc ){
3073 nAlloc *= 2;
3074 azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*));
3075 if( azData==0 ) shell_out_of_memory();
3076 }
3077 nRow++;
3078 for(i=0; i<nColumn; i++){
3079 z = (const char*)sqlite3_column_text(pStmt,i);
3080 azData[nRow*nColumn + i] = z ? strdup(z) : 0;
3081 }
3082 }while( (rc = sqlite3_step(pStmt))==SQLITE_ROW );
drh8c748632020-05-29 16:15:58 +00003083 if( nColumn>p->nWidth ){
3084 p->colWidth = realloc(p->colWidth, nColumn*2*sizeof(int));
3085 if( p->colWidth==0 ) shell_out_of_memory();
3086 for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0;
3087 p->nWidth = nColumn;
3088 p->actualWidth = &p->colWidth[nColumn];
3089 }
3090 memset(p->actualWidth, 0, nColumn*sizeof(int));
3091 for(i=0; i<nColumn; i++){
3092 w = p->colWidth[i];
3093 if( w<0 ) w = -w;
3094 p->actualWidth[i] = w;
3095 }
3096 nTotal = nColumn*(nRow+1);
3097 for(i=0; i<nTotal; i++){
3098 z = azData[i];
3099 if( z==0 ) z = p->nullValue;
3100 n = strlenChar(z);
3101 j = i%nColumn;
3102 if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
3103 }
drh99942982020-06-15 20:05:37 +00003104 if( seenInterrupt ) goto columnar_end;
drh0908e382020-06-04 18:05:39 +00003105 switch( p->cMode ){
3106 case MODE_Column: {
3107 colSep = " ";
3108 rowSep = "\n";
3109 if( p->showHeader ){
3110 for(i=0; i<nColumn; i++){
3111 w = p->actualWidth[i];
3112 if( p->colWidth[i]<0 ) w = -w;
3113 utf8_width_print(p->out, w, azData[i]);
3114 fputs(i==nColumn-1?"\n":" ", p->out);
3115 }
3116 for(i=0; i<nColumn; i++){
3117 print_dashes(p->out, p->actualWidth[i]);
3118 fputs(i==nColumn-1?"\n":" ", p->out);
3119 }
3120 }
3121 break;
3122 }
3123 case MODE_Table: {
3124 colSep = " | ";
3125 rowSep = " |\n";
3126 print_row_separator(p, nColumn, "+");
3127 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003128 for(i=0; i<nColumn; i++){
3129 w = p->actualWidth[i];
drh0908e382020-06-04 18:05:39 +00003130 n = strlenChar(azData[i]);
3131 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
3132 fputs(i==nColumn-1?" |\n":" | ", p->out);
drh8c748632020-05-29 16:15:58 +00003133 }
drh0908e382020-06-04 18:05:39 +00003134 print_row_separator(p, nColumn, "+");
3135 break;
3136 }
3137 case MODE_Markdown: {
3138 colSep = " | ";
3139 rowSep = " |\n";
3140 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003141 for(i=0; i<nColumn; i++){
drh0908e382020-06-04 18:05:39 +00003142 w = p->actualWidth[i];
3143 n = strlenChar(azData[i]);
3144 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
3145 fputs(i==nColumn-1?" |\n":" | ", p->out);
drh8c748632020-05-29 16:15:58 +00003146 }
drh0908e382020-06-04 18:05:39 +00003147 print_row_separator(p, nColumn, "|");
3148 break;
drh8c748632020-05-29 16:15:58 +00003149 }
drh0908e382020-06-04 18:05:39 +00003150 case MODE_Box: {
3151 colSep = " " BOX_13 " ";
3152 rowSep = " " BOX_13 "\n";
3153 print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34);
3154 utf8_printf(p->out, BOX_13 " ");
3155 for(i=0; i<nColumn; i++){
3156 w = p->actualWidth[i];
3157 n = strlenChar(azData[i]);
3158 utf8_printf(p->out, "%*s%s%*s%s",
3159 (w-n)/2, "", azData[i], (w-n+1)/2, "",
3160 i==nColumn-1?" "BOX_13"\n":" "BOX_13" ");
3161 }
3162 print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
3163 break;
drh8c748632020-05-29 16:15:58 +00003164 }
drh8c748632020-05-29 16:15:58 +00003165 }
3166 for(i=nColumn, j=0; i<nTotal; i++, j++){
drh0908e382020-06-04 18:05:39 +00003167 if( j==0 && p->cMode!=MODE_Column ){
3168 utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| ");
3169 }
drh8c748632020-05-29 16:15:58 +00003170 z = azData[i];
3171 if( z==0 ) z = p->nullValue;
3172 w = p->actualWidth[j];
3173 if( p->colWidth[j]<0 ) w = -w;
3174 utf8_width_print(p->out, w, z);
3175 if( j==nColumn-1 ){
drh0908e382020-06-04 18:05:39 +00003176 utf8_printf(p->out, "%s", rowSep);
drh8c748632020-05-29 16:15:58 +00003177 j = -1;
drhdd853c32020-06-16 17:34:40 +00003178 if( seenInterrupt ) goto columnar_end;
drh8c748632020-05-29 16:15:58 +00003179 }else{
drh0908e382020-06-04 18:05:39 +00003180 utf8_printf(p->out, "%s", colSep);
drh8c748632020-05-29 16:15:58 +00003181 }
3182 }
3183 if( p->cMode==MODE_Table ){
3184 print_row_separator(p, nColumn, "+");
drh0908e382020-06-04 18:05:39 +00003185 }else if( p->cMode==MODE_Box ){
3186 print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14);
drh8c748632020-05-29 16:15:58 +00003187 }
drh99942982020-06-15 20:05:37 +00003188columnar_end:
drhdd853c32020-06-16 17:34:40 +00003189 if( seenInterrupt ){
3190 utf8_printf(p->out, "Interrupt\n");
3191 }
drhf82ce382020-08-06 16:45:22 +00003192 nData = (nRow+1)*nColumn;
3193 for(i=0; i<nData; i++) free(azData[i]);
3194 sqlite3_free(azData);
drh30c54a02020-05-28 23:49:50 +00003195}
drh30c54a02020-05-28 23:49:50 +00003196
drh2ce15c32017-07-11 13:34:40 +00003197/*
3198** Run a prepared statement
3199*/
3200static void exec_prepared_stmt(
3201 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003202 sqlite3_stmt *pStmt /* Statment to run */
drh2ce15c32017-07-11 13:34:40 +00003203){
3204 int rc;
3205
drh8c748632020-05-29 16:15:58 +00003206 if( pArg->cMode==MODE_Column
3207 || pArg->cMode==MODE_Table
drh0908e382020-06-04 18:05:39 +00003208 || pArg->cMode==MODE_Box
drh8c748632020-05-29 16:15:58 +00003209 || pArg->cMode==MODE_Markdown
3210 ){
3211 exec_prepared_stmt_columnar(pArg, pStmt);
3212 return;
3213 }
3214
drh2ce15c32017-07-11 13:34:40 +00003215 /* perform the first step. this will tell us if we
3216 ** have a result set or not and how wide it is.
3217 */
3218 rc = sqlite3_step(pStmt);
3219 /* if we have a result set... */
3220 if( SQLITE_ROW == rc ){
drha10b9992018-03-09 15:24:33 +00003221 /* allocate space for col name ptr, value ptr, and type */
3222 int nCol = sqlite3_column_count(pStmt);
3223 void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
3224 if( !pData ){
3225 rc = SQLITE_NOMEM;
drh2ce15c32017-07-11 13:34:40 +00003226 }else{
drha10b9992018-03-09 15:24:33 +00003227 char **azCols = (char **)pData; /* Names of result columns */
3228 char **azVals = &azCols[nCol]; /* Results */
3229 int *aiTypes = (int *)&azVals[nCol]; /* Result types */
3230 int i, x;
3231 assert(sizeof(int) <= sizeof(char *));
3232 /* save off ptrs to column names */
3233 for(i=0; i<nCol; i++){
3234 azCols[i] = (char *)sqlite3_column_name(pStmt, i);
3235 }
drh2ce15c32017-07-11 13:34:40 +00003236 do{
drha10b9992018-03-09 15:24:33 +00003237 /* extract the data and data types */
3238 for(i=0; i<nCol; i++){
3239 aiTypes[i] = x = sqlite3_column_type(pStmt, i);
3240 if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
3241 azVals[i] = "";
3242 }else{
3243 azVals[i] = (char*)sqlite3_column_text(pStmt, i);
3244 }
3245 if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
3246 rc = SQLITE_NOMEM;
3247 break; /* from for */
3248 }
3249 } /* end for */
3250
3251 /* if data and types extracted successfully... */
3252 if( SQLITE_ROW == rc ){
3253 /* call the supplied callback with the result row data */
3254 if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){
3255 rc = SQLITE_ABORT;
3256 }else{
3257 rc = sqlite3_step(pStmt);
3258 }
3259 }
3260 } while( SQLITE_ROW == rc );
3261 sqlite3_free(pData);
drh0908e382020-06-04 18:05:39 +00003262 if( pArg->cMode==MODE_Json ){
drh30c54a02020-05-28 23:49:50 +00003263 fputs("]\n", pArg->out);
3264 }
drh2ce15c32017-07-11 13:34:40 +00003265 }
3266 }
3267}
3268
dan6b046be2018-01-09 15:25:55 +00003269#ifndef SQLITE_OMIT_VIRTUALTABLE
drh2ce15c32017-07-11 13:34:40 +00003270/*
dan43efc182017-12-19 17:42:13 +00003271** This function is called to process SQL if the previous shell command
3272** was ".expert". It passes the SQL in the second argument directly to
3273** the sqlite3expert object.
3274**
3275** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3276** code. In this case, (*pzErr) may be set to point to a buffer containing
3277** an English language error message. It is the responsibility of the
3278** caller to eventually free this buffer using sqlite3_free().
3279*/
3280static int expertHandleSQL(
3281 ShellState *pState,
3282 const char *zSql,
3283 char **pzErr
3284){
3285 assert( pState->expert.pExpert );
3286 assert( pzErr==0 || *pzErr==0 );
3287 return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr);
3288}
3289
3290/*
3291** This function is called either to silently clean up the object
3292** created by the ".expert" command (if bCancel==1), or to generate a
3293** report from it and then clean it up (if bCancel==0).
3294**
3295** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3296** code. In this case, (*pzErr) may be set to point to a buffer containing
3297** an English language error message. It is the responsibility of the
3298** caller to eventually free this buffer using sqlite3_free().
3299*/
3300static int expertFinish(
3301 ShellState *pState,
3302 int bCancel,
3303 char **pzErr
3304){
3305 int rc = SQLITE_OK;
3306 sqlite3expert *p = pState->expert.pExpert;
3307 assert( p );
3308 assert( bCancel || pzErr==0 || *pzErr==0 );
3309 if( bCancel==0 ){
3310 FILE *out = pState->out;
3311 int bVerbose = pState->expert.bVerbose;
3312
3313 rc = sqlite3_expert_analyze(p, pzErr);
3314 if( rc==SQLITE_OK ){
3315 int nQuery = sqlite3_expert_count(p);
3316 int i;
3317
3318 if( bVerbose ){
3319 const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
3320 raw_printf(out, "-- Candidates -----------------------------\n");
3321 raw_printf(out, "%s\n", zCand);
3322 }
3323 for(i=0; i<nQuery; i++){
3324 const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
3325 const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
3326 const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
3327 if( zIdx==0 ) zIdx = "(no new indexes)\n";
3328 if( bVerbose ){
3329 raw_printf(out, "-- Query %d --------------------------------\n",i+1);
3330 raw_printf(out, "%s\n\n", zSql);
3331 }
3332 raw_printf(out, "%s\n", zIdx);
3333 raw_printf(out, "%s\n", zEQP);
3334 }
3335 }
3336 }
3337 sqlite3_expert_destroy(p);
3338 pState->expert.pExpert = 0;
3339 return rc;
3340}
3341
dan6b046be2018-01-09 15:25:55 +00003342/*
3343** Implementation of ".expert" dot command.
3344*/
3345static int expertDotCommand(
3346 ShellState *pState, /* Current shell tool state */
3347 char **azArg, /* Array of arguments passed to dot command */
3348 int nArg /* Number of entries in azArg[] */
3349){
3350 int rc = SQLITE_OK;
3351 char *zErr = 0;
3352 int i;
3353 int iSample = 0;
3354
3355 assert( pState->expert.pExpert==0 );
3356 memset(&pState->expert, 0, sizeof(ExpertInfo));
3357
3358 for(i=1; rc==SQLITE_OK && i<nArg; i++){
3359 char *z = azArg[i];
3360 int n;
3361 if( z[0]=='-' && z[1]=='-' ) z++;
3362 n = strlen30(z);
3363 if( n>=2 && 0==strncmp(z, "-verbose", n) ){
3364 pState->expert.bVerbose = 1;
3365 }
3366 else if( n>=2 && 0==strncmp(z, "-sample", n) ){
3367 if( i==(nArg-1) ){
3368 raw_printf(stderr, "option requires an argument: %s\n", z);
3369 rc = SQLITE_ERROR;
3370 }else{
3371 iSample = (int)integerValue(azArg[++i]);
3372 if( iSample<0 || iSample>100 ){
3373 raw_printf(stderr, "value out of range: %s\n", azArg[i]);
3374 rc = SQLITE_ERROR;
3375 }
3376 }
3377 }
3378 else{
3379 raw_printf(stderr, "unknown option: %s\n", z);
3380 rc = SQLITE_ERROR;
3381 }
3382 }
3383
3384 if( rc==SQLITE_OK ){
3385 pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
3386 if( pState->expert.pExpert==0 ){
3387 raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr);
3388 rc = SQLITE_ERROR;
3389 }else{
3390 sqlite3_expert_config(
3391 pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
3392 );
3393 }
3394 }
3395
3396 return rc;
3397}
3398#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
dan43efc182017-12-19 17:42:13 +00003399
3400/*
drh2ce15c32017-07-11 13:34:40 +00003401** Execute a statement or set of statements. Print
3402** any result rows/columns depending on the current mode
3403** set via the supplied callback.
3404**
3405** This is very similar to SQLite's built-in sqlite3_exec()
3406** function except it takes a slightly different callback
3407** and callback data argument.
3408*/
3409static int shell_exec(
drh2ce15c32017-07-11 13:34:40 +00003410 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003411 const char *zSql, /* SQL to be evaluated */
drh2ce15c32017-07-11 13:34:40 +00003412 char **pzErrMsg /* Error msg written here */
3413){
3414 sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
3415 int rc = SQLITE_OK; /* Return Code */
3416 int rc2;
3417 const char *zLeftover; /* Tail of unprocessed SQL */
drha10b9992018-03-09 15:24:33 +00003418 sqlite3 *db = pArg->db;
drh2ce15c32017-07-11 13:34:40 +00003419
3420 if( pzErrMsg ){
3421 *pzErrMsg = NULL;
3422 }
3423
dan6b046be2018-01-09 15:25:55 +00003424#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00003425 if( pArg->expert.pExpert ){
3426 rc = expertHandleSQL(pArg, zSql, pzErrMsg);
3427 return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
3428 }
dan6b046be2018-01-09 15:25:55 +00003429#endif
dan43efc182017-12-19 17:42:13 +00003430
drh2ce15c32017-07-11 13:34:40 +00003431 while( zSql[0] && (SQLITE_OK == rc) ){
3432 static const char *zStmtSql;
3433 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
3434 if( SQLITE_OK != rc ){
3435 if( pzErrMsg ){
3436 *pzErrMsg = save_err_msg(db);
3437 }
3438 }else{
3439 if( !pStmt ){
3440 /* this happens for a comment or white-space */
3441 zSql = zLeftover;
3442 while( IsSpace(zSql[0]) ) zSql++;
3443 continue;
3444 }
3445 zStmtSql = sqlite3_sql(pStmt);
3446 if( zStmtSql==0 ) zStmtSql = "";
3447 while( IsSpace(zStmtSql[0]) ) zStmtSql++;
3448
3449 /* save off the prepared statment handle and reset row count */
3450 if( pArg ){
3451 pArg->pStmt = pStmt;
3452 pArg->cnt = 0;
3453 }
3454
3455 /* echo the sql statement if echo on */
3456 if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
3457 utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
3458 }
3459
3460 /* Show the EXPLAIN QUERY PLAN if .eqp is on */
drh39c5c4a2019-03-06 14:53:27 +00003461 if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
drh2ce15c32017-07-11 13:34:40 +00003462 sqlite3_stmt *pExplain;
3463 char *zEQP;
drhada70452017-12-21 21:02:27 +00003464 int triggerEQP = 0;
drh2ce15c32017-07-11 13:34:40 +00003465 disable_debug_trace_modes();
drhada70452017-12-21 21:02:27 +00003466 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
3467 if( pArg->autoEQP>=AUTOEQP_trigger ){
3468 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
3469 }
drh2ce15c32017-07-11 13:34:40 +00003470 zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
3471 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3472 if( rc==SQLITE_OK ){
3473 while( sqlite3_step(pExplain)==SQLITE_ROW ){
drh4b5345c2018-04-24 13:07:40 +00003474 const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
drhe2ca99c2018-05-02 00:33:43 +00003475 int iEqpId = sqlite3_column_int(pExplain, 0);
3476 int iParentId = sqlite3_column_int(pExplain, 1);
drh7e088a62020-05-02 00:01:39 +00003477 if( zEQPLine==0 ) zEQPLine = "";
drh4b5345c2018-04-24 13:07:40 +00003478 if( zEQPLine[0]=='-' ) eqp_render(pArg);
drhe2ca99c2018-05-02 00:33:43 +00003479 eqp_append(pArg, iEqpId, iParentId, zEQPLine);
drh2ce15c32017-07-11 13:34:40 +00003480 }
drh4b5345c2018-04-24 13:07:40 +00003481 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003482 }
3483 sqlite3_finalize(pExplain);
3484 sqlite3_free(zEQP);
drhada70452017-12-21 21:02:27 +00003485 if( pArg->autoEQP>=AUTOEQP_full ){
drh2ce15c32017-07-11 13:34:40 +00003486 /* Also do an EXPLAIN for ".eqp full" mode */
3487 zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
3488 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3489 if( rc==SQLITE_OK ){
3490 pArg->cMode = MODE_Explain;
3491 explain_data_prepare(pArg, pExplain);
drha10b9992018-03-09 15:24:33 +00003492 exec_prepared_stmt(pArg, pExplain);
drh2ce15c32017-07-11 13:34:40 +00003493 explain_data_delete(pArg);
3494 }
3495 sqlite3_finalize(pExplain);
3496 sqlite3_free(zEQP);
3497 }
drh51efe092018-03-20 12:04:38 +00003498 if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
3499 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
3500 /* Reprepare pStmt before reactiving trace modes */
3501 sqlite3_finalize(pStmt);
3502 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
drh3c49eaf2018-06-07 15:23:43 +00003503 if( pArg ) pArg->pStmt = pStmt;
drh51efe092018-03-20 12:04:38 +00003504 }
drh2ce15c32017-07-11 13:34:40 +00003505 restore_debug_trace_modes();
3506 }
3507
3508 if( pArg ){
3509 pArg->cMode = pArg->mode;
drh4b5345c2018-04-24 13:07:40 +00003510 if( pArg->autoExplain ){
drh39c5c4a2019-03-06 14:53:27 +00003511 if( sqlite3_stmt_isexplain(pStmt)==1 ){
drh4b5345c2018-04-24 13:07:40 +00003512 pArg->cMode = MODE_Explain;
3513 }
drh39c5c4a2019-03-06 14:53:27 +00003514 if( sqlite3_stmt_isexplain(pStmt)==2 ){
drh4b5345c2018-04-24 13:07:40 +00003515 pArg->cMode = MODE_EQP;
3516 }
drh2ce15c32017-07-11 13:34:40 +00003517 }
3518
3519 /* If the shell is currently in ".explain" mode, gather the extra
3520 ** data required to add indents to the output.*/
3521 if( pArg->cMode==MODE_Explain ){
3522 explain_data_prepare(pArg, pStmt);
3523 }
3524 }
3525
drh8b738d02019-02-25 18:43:54 +00003526 bind_prepared_stmt(pArg, pStmt);
drha10b9992018-03-09 15:24:33 +00003527 exec_prepared_stmt(pArg, pStmt);
drh2ce15c32017-07-11 13:34:40 +00003528 explain_data_delete(pArg);
drh4b5345c2018-04-24 13:07:40 +00003529 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003530
3531 /* print usage stats if stats on */
3532 if( pArg && pArg->statsOn ){
3533 display_stats(db, pArg, 0);
3534 }
3535
3536 /* print loop-counters if required */
3537 if( pArg && pArg->scanstatsOn ){
3538 display_scanstats(db, pArg);
3539 }
3540
3541 /* Finalize the statement just executed. If this fails, save a
3542 ** copy of the error message. Otherwise, set zSql to point to the
3543 ** next statement to execute. */
3544 rc2 = sqlite3_finalize(pStmt);
3545 if( rc!=SQLITE_NOMEM ) rc = rc2;
3546 if( rc==SQLITE_OK ){
3547 zSql = zLeftover;
3548 while( IsSpace(zSql[0]) ) zSql++;
3549 }else if( pzErrMsg ){
3550 *pzErrMsg = save_err_msg(db);
3551 }
3552
3553 /* clear saved stmt handle */
3554 if( pArg ){
3555 pArg->pStmt = NULL;
3556 }
3557 }
3558 } /* end while */
3559
3560 return rc;
3561}
3562
3563/*
3564** Release memory previously allocated by tableColumnList().
3565*/
3566static void freeColumnList(char **azCol){
3567 int i;
3568 for(i=1; azCol[i]; i++){
3569 sqlite3_free(azCol[i]);
3570 }
3571 /* azCol[0] is a static string */
3572 sqlite3_free(azCol);
3573}
3574
3575/*
3576** Return a list of pointers to strings which are the names of all
3577** columns in table zTab. The memory to hold the names is dynamically
3578** allocated and must be released by the caller using a subsequent call
3579** to freeColumnList().
3580**
3581** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
3582** value that needs to be preserved, then azCol[0] is filled in with the
3583** name of the rowid column.
3584**
3585** The first regular column in the table is azCol[1]. The list is terminated
3586** by an entry with azCol[i]==0.
3587*/
3588static char **tableColumnList(ShellState *p, const char *zTab){
3589 char **azCol = 0;
3590 sqlite3_stmt *pStmt;
3591 char *zSql;
3592 int nCol = 0;
3593 int nAlloc = 0;
3594 int nPK = 0; /* Number of PRIMARY KEY columns seen */
3595 int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
3596 int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
3597 int rc;
3598
3599 zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
3600 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3601 sqlite3_free(zSql);
3602 if( rc ) return 0;
3603 while( sqlite3_step(pStmt)==SQLITE_ROW ){
3604 if( nCol>=nAlloc-2 ){
3605 nAlloc = nAlloc*2 + nCol + 10;
3606 azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
drh4b5345c2018-04-24 13:07:40 +00003607 if( azCol==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00003608 }
3609 azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
3610 if( sqlite3_column_int(pStmt, 5) ){
3611 nPK++;
3612 if( nPK==1
3613 && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
3614 "INTEGER")==0
3615 ){
3616 isIPK = 1;
3617 }else{
3618 isIPK = 0;
3619 }
3620 }
3621 }
3622 sqlite3_finalize(pStmt);
drh4c6cddc2017-10-12 10:28:30 +00003623 if( azCol==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00003624 azCol[0] = 0;
3625 azCol[nCol+1] = 0;
3626
3627 /* The decision of whether or not a rowid really needs to be preserved
3628 ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
3629 ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
3630 ** rowids on tables where the rowid is inaccessible because there are other
3631 ** columns in the table named "rowid", "_rowid_", and "oid".
3632 */
3633 if( preserveRowid && isIPK ){
3634 /* If a single PRIMARY KEY column with type INTEGER was seen, then it
3635 ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID
3636 ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
3637 ** ROWID aliases. To distinguish these cases, check to see if
3638 ** there is a "pk" entry in "PRAGMA index_list". There will be
3639 ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
3640 */
3641 zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
3642 " WHERE origin='pk'", zTab);
3643 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3644 sqlite3_free(zSql);
3645 if( rc ){
3646 freeColumnList(azCol);
3647 return 0;
3648 }
3649 rc = sqlite3_step(pStmt);
3650 sqlite3_finalize(pStmt);
3651 preserveRowid = rc==SQLITE_ROW;
3652 }
3653 if( preserveRowid ){
3654 /* Only preserve the rowid if we can find a name to use for the
3655 ** rowid */
3656 static char *azRowid[] = { "rowid", "_rowid_", "oid" };
3657 int i, j;
3658 for(j=0; j<3; j++){
3659 for(i=1; i<=nCol; i++){
3660 if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
3661 }
3662 if( i>nCol ){
3663 /* At this point, we know that azRowid[j] is not the name of any
3664 ** ordinary column in the table. Verify that azRowid[j] is a valid
3665 ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
3666 ** tables will fail this last check */
3667 rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
3668 if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
3669 break;
3670 }
3671 }
3672 }
3673 return azCol;
3674}
3675
3676/*
3677** Toggle the reverse_unordered_selects setting.
3678*/
3679static void toggleSelectOrder(sqlite3 *db){
3680 sqlite3_stmt *pStmt = 0;
3681 int iSetting = 0;
3682 char zStmt[100];
3683 sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0);
3684 if( sqlite3_step(pStmt)==SQLITE_ROW ){
3685 iSetting = sqlite3_column_int(pStmt, 0);
3686 }
3687 sqlite3_finalize(pStmt);
3688 sqlite3_snprintf(sizeof(zStmt), zStmt,
3689 "PRAGMA reverse_unordered_selects(%d)", !iSetting);
3690 sqlite3_exec(db, zStmt, 0, 0, 0);
3691}
3692
3693/*
3694** This is a different callback routine used for dumping the database.
3695** Each row received by this callback consists of a table name,
3696** the table type ("index" or "table") and SQL to create the table.
3697** This routine should print text sufficient to recreate the table.
3698*/
3699static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
3700 int rc;
3701 const char *zTable;
3702 const char *zType;
3703 const char *zSql;
3704 ShellState *p = (ShellState *)pArg;
mistachkina00a0162020-10-18 18:35:34 +00003705 int dataOnly;
3706 int noSys;
drh2ce15c32017-07-11 13:34:40 +00003707
3708 UNUSED_PARAMETER(azNotUsed);
drhb3c45232017-08-28 14:33:27 +00003709 if( nArg!=3 || azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00003710 zTable = azArg[0];
3711 zType = azArg[1];
3712 zSql = azArg[2];
mistachkina00a0162020-10-18 18:35:34 +00003713 dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
3714 noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
drh2ce15c32017-07-11 13:34:40 +00003715
drhc1962192020-10-12 16:54:28 +00003716 if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
3717 if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
3718 }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
3719 if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00003720 }else if( strncmp(zTable, "sqlite_", 7)==0 ){
3721 return 0;
drhc1962192020-10-12 16:54:28 +00003722 }else if( dataOnly ){
3723 /* no-op */
drh2ce15c32017-07-11 13:34:40 +00003724 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
3725 char *zIns;
3726 if( !p->writableSchema ){
3727 raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
3728 p->writableSchema = 1;
3729 }
3730 zIns = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00003731 "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
drh2ce15c32017-07-11 13:34:40 +00003732 "VALUES('table','%q','%q',0,'%q');",
3733 zTable, zTable, zSql);
3734 utf8_printf(p->out, "%s\n", zIns);
3735 sqlite3_free(zIns);
3736 return 0;
3737 }else{
3738 printSchemaLine(p->out, zSql, ";\n");
3739 }
3740
3741 if( strcmp(zType, "table")==0 ){
3742 ShellText sSelect;
3743 ShellText sTable;
3744 char **azCol;
3745 int i;
3746 char *savedDestTable;
3747 int savedMode;
3748
3749 azCol = tableColumnList(p, zTable);
3750 if( azCol==0 ){
3751 p->nErr++;
3752 return 0;
3753 }
3754
3755 /* Always quote the table name, even if it appears to be pure ascii,
3756 ** in case it is a keyword. Ex: INSERT INTO "table" ... */
3757 initText(&sTable);
3758 appendText(&sTable, zTable, quoteChar(zTable));
3759 /* If preserving the rowid, add a column list after the table name.
3760 ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
3761 ** instead of the usual "INSERT INTO tab VALUES(...)".
3762 */
3763 if( azCol[0] ){
3764 appendText(&sTable, "(", 0);
3765 appendText(&sTable, azCol[0], 0);
3766 for(i=1; azCol[i]; i++){
3767 appendText(&sTable, ",", 0);
3768 appendText(&sTable, azCol[i], quoteChar(azCol[i]));
3769 }
3770 appendText(&sTable, ")", 0);
3771 }
3772
3773 /* Build an appropriate SELECT statement */
3774 initText(&sSelect);
3775 appendText(&sSelect, "SELECT ", 0);
3776 if( azCol[0] ){
3777 appendText(&sSelect, azCol[0], 0);
3778 appendText(&sSelect, ",", 0);
3779 }
3780 for(i=1; azCol[i]; i++){
3781 appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
3782 if( azCol[i+1] ){
3783 appendText(&sSelect, ",", 0);
3784 }
3785 }
3786 freeColumnList(azCol);
3787 appendText(&sSelect, " FROM ", 0);
3788 appendText(&sSelect, zTable, quoteChar(zTable));
3789
3790 savedDestTable = p->zDestTable;
3791 savedMode = p->mode;
3792 p->zDestTable = sTable.z;
3793 p->mode = p->cMode = MODE_Insert;
drha10b9992018-03-09 15:24:33 +00003794 rc = shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00003795 if( (rc&0xff)==SQLITE_CORRUPT ){
3796 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
3797 toggleSelectOrder(p->db);
drha10b9992018-03-09 15:24:33 +00003798 shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00003799 toggleSelectOrder(p->db);
3800 }
3801 p->zDestTable = savedDestTable;
3802 p->mode = savedMode;
3803 freeText(&sTable);
3804 freeText(&sSelect);
3805 if( rc ) p->nErr++;
3806 }
3807 return 0;
3808}
3809
3810/*
3811** Run zQuery. Use dump_callback() as the callback routine so that
3812** the contents of the query are output as SQL statements.
3813**
3814** If we get a SQLITE_CORRUPT error, rerun the query after appending
3815** "ORDER BY rowid DESC" to the end.
3816*/
3817static int run_schema_dump_query(
3818 ShellState *p,
3819 const char *zQuery
3820){
3821 int rc;
3822 char *zErr = 0;
3823 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
3824 if( rc==SQLITE_CORRUPT ){
3825 char *zQ2;
3826 int len = strlen30(zQuery);
3827 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
3828 if( zErr ){
3829 utf8_printf(p->out, "/****** %s ******/\n", zErr);
3830 sqlite3_free(zErr);
3831 zErr = 0;
3832 }
3833 zQ2 = malloc( len+100 );
3834 if( zQ2==0 ) return rc;
3835 sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
3836 rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
3837 if( rc ){
3838 utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
3839 }else{
3840 rc = SQLITE_CORRUPT;
3841 }
3842 sqlite3_free(zErr);
3843 free(zQ2);
3844 }
3845 return rc;
3846}
3847
3848/*
drh98aa2ab2018-09-26 16:53:51 +00003849** Text of help messages.
3850**
3851** The help text for each individual command begins with a line that starts
3852** with ".". Subsequent lines are supplimental information.
3853**
3854** There must be two or more spaces between the end of the command and the
3855** start of the description of what that command does.
drh2ce15c32017-07-11 13:34:40 +00003856*/
drh98aa2ab2018-09-26 16:53:51 +00003857static const char *(azHelp[]) = {
drhe37c0e12018-01-06 19:19:50 +00003858#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drh98aa2ab2018-09-26 16:53:51 +00003859 ".archive ... Manage SQL archives",
3860 " Each command must have exactly one of the following options:",
3861 " -c, --create Create a new archive",
drhe2754c12019-08-26 12:50:01 +00003862 " -u, --update Add or update files with changed mtime",
3863 " -i, --insert Like -u but always add even if unchanged",
drh98aa2ab2018-09-26 16:53:51 +00003864 " -t, --list List contents of archive",
3865 " -x, --extract Extract files from archive",
3866 " Optional arguments:",
3867 " -v, --verbose Print each filename as it is processed",
drhe2754c12019-08-26 12:50:01 +00003868 " -f FILE, --file FILE Use archive FILE (default is current db)",
3869 " -a FILE, --append FILE Open FILE using the apndvfs VFS",
3870 " -C DIR, --directory DIR Read/extract files from directory DIR",
drh98aa2ab2018-09-26 16:53:51 +00003871 " -n, --dryrun Show the SQL that would have occurred",
3872 " Examples:",
drhe2754c12019-08-26 12:50:01 +00003873 " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
3874 " .ar -tf ARCHIVE # List members of ARCHIVE",
3875 " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE",
drh98aa2ab2018-09-26 16:53:51 +00003876 " See also:",
3877 " http://sqlite.org/cli.html#sqlar_archive_support",
drhe37c0e12018-01-06 19:19:50 +00003878#endif
drh2ce15c32017-07-11 13:34:40 +00003879#ifndef SQLITE_OMIT_AUTHORIZATION
drh98aa2ab2018-09-26 16:53:51 +00003880 ".auth ON|OFF Show authorizer callbacks",
drh2ce15c32017-07-11 13:34:40 +00003881#endif
drh98aa2ab2018-09-26 16:53:51 +00003882 ".backup ?DB? FILE Backup DB (default \"main\") to FILE",
3883 " --append Use the appendvfs",
drhe2754c12019-08-26 12:50:01 +00003884 " --async Write to FILE without journal and fsync()",
drh98aa2ab2018-09-26 16:53:51 +00003885 ".bail on|off Stop after hitting an error. Default OFF",
3886 ".binary on|off Turn binary output on or off. Default OFF",
3887 ".cd DIRECTORY Change the working directory to DIRECTORY",
3888 ".changes on|off Show number of rows changed by SQL",
3889 ".check GLOB Fail if output since .testcase does not match",
3890 ".clone NEWDB Clone data into NEWDB from the existing database",
3891 ".databases List names and files of attached databases",
3892 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
3893 ".dbinfo ?DB? Show status information about the database",
drh8e9297f2020-03-25 12:50:13 +00003894 ".dump ?TABLE? Render database content as SQL",
drheb7f2a02018-09-26 18:02:32 +00003895 " Options:",
drhc1962192020-10-12 16:54:28 +00003896 " --data-only Output only INSERT statements",
drheb7f2a02018-09-26 18:02:32 +00003897 " --newlines Allow unescaped newline characters in output",
drhc1962192020-10-12 16:54:28 +00003898 " --nosys Omit system tables (ex: \"sqlite_stat1\")",
3899 " --preserve-rowids Include ROWID values in the output",
drhe551b512019-04-17 13:58:07 +00003900 " TABLE is a LIKE pattern for the tables to dump",
drh8e9297f2020-03-25 12:50:13 +00003901 " Additional LIKE patterns can be given in subsequent arguments",
drh98aa2ab2018-09-26 16:53:51 +00003902 ".echo on|off Turn command echo on or off",
drhb4e50392019-01-26 15:40:04 +00003903 ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
3904 " Other Modes:",
3905#ifdef SQLITE_DEBUG
3906 " test Show raw EXPLAIN QUERY PLAN output",
drhe2754c12019-08-26 12:50:01 +00003907 " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"",
drhb4e50392019-01-26 15:40:04 +00003908#endif
3909 " trigger Like \"full\" but also show trigger bytecode",
drhe2754c12019-08-26 12:50:01 +00003910 ".excel Display the output of next command in spreadsheet",
drh7a431002020-04-18 14:12:00 +00003911 " --bom Put a UTF8 byte-order mark on intermediate file",
drheb7f2a02018-09-26 18:02:32 +00003912 ".exit ?CODE? Exit this program with return-code CODE",
drhe2754c12019-08-26 12:50:01 +00003913 ".expert EXPERIMENTAL. Suggest indexes for queries",
drh978256f2019-11-02 00:00:14 +00003914 ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto",
drhd985f722019-06-05 14:29:53 +00003915 ".filectrl CMD ... Run various sqlite3_file_control() operations",
drh541ef2c2020-04-20 16:21:30 +00003916 " --schema SCHEMA Use SCHEMA instead of \"main\"",
3917 " --help Show CMD details",
drh98aa2ab2018-09-26 16:53:51 +00003918 ".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
3919 ".headers on|off Turn display of headers on or off",
3920 ".help ?-all? ?PATTERN? Show help text for PATTERN",
3921 ".import FILE TABLE Import data from FILE into TABLE",
drhccb37812020-03-09 15:39:39 +00003922 " Options:",
3923 " --ascii Use \\037 and \\036 as column and row separators",
3924 " --csv Use , and \\n as column and row separators",
3925 " --skip N Skip the first N rows of input",
3926 " -v \"Verbose\" - increase auxiliary output",
3927 " Notes:",
3928 " * If TABLE does not exist, it is created. The first row of input",
3929 " determines the column names.",
3930 " * If neither --csv or --ascii are used, the input mode is derived",
3931 " from the \".mode\" output mode",
3932 " * If FILE begins with \"|\" then it is a command that generates the",
3933 " input text.",
drh2ce15c32017-07-11 13:34:40 +00003934#ifndef SQLITE_OMIT_TEST_CONTROL
drh98aa2ab2018-09-26 16:53:51 +00003935 ".imposter INDEX TABLE Create imposter table TABLE on index INDEX",
drh2ce15c32017-07-11 13:34:40 +00003936#endif
drh98aa2ab2018-09-26 16:53:51 +00003937 ".indexes ?TABLE? Show names of indexes",
3938 " If TABLE is specified, only show indexes for",
3939 " tables matching TABLE using the LIKE operator.",
drh2ce15c32017-07-11 13:34:40 +00003940#ifdef SQLITE_ENABLE_IOTRACE
drh98aa2ab2018-09-26 16:53:51 +00003941 ".iotrace FILE Enable I/O diagnostic logging to FILE",
drh2ce15c32017-07-11 13:34:40 +00003942#endif
drh98aa2ab2018-09-26 16:53:51 +00003943 ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
3944 ".lint OPTIONS Report potential schema issues.",
3945 " Options:",
3946 " fkey-indexes Find missing foreign key indexes",
drh2ce15c32017-07-11 13:34:40 +00003947#ifndef SQLITE_OMIT_LOAD_EXTENSION
drh98aa2ab2018-09-26 16:53:51 +00003948 ".load FILE ?ENTRY? Load an extension library",
drh2ce15c32017-07-11 13:34:40 +00003949#endif
drh98aa2ab2018-09-26 16:53:51 +00003950 ".log FILE|off Turn logging on or off. FILE can be stderr/stdout",
3951 ".mode MODE ?TABLE? Set output mode",
3952 " MODE is one of:",
drh7da29a32020-05-29 19:17:20 +00003953 " ascii Columns/rows delimited by 0x1F and 0x1E",
drh0908e382020-06-04 18:05:39 +00003954 " box Tables using unicode box-drawing characters",
drh7da29a32020-05-29 19:17:20 +00003955 " csv Comma-separated values",
3956 " column Output in columns. (See .width)",
3957 " html HTML <table> code",
3958 " insert SQL insert statements for TABLE",
3959 " json Results in a JSON array",
3960 " line One value per line",
3961 " list Values delimited by \"|\"",
3962 " markdown Markdown table format",
3963 " quote Escape answers as for SQL",
3964 " table ASCII-art table",
3965 " tabs Tab-separated values",
3966 " tcl TCL list elements",
drh98aa2ab2018-09-26 16:53:51 +00003967 ".nullvalue STRING Use STRING in place of NULL values",
drh7a431002020-04-18 14:12:00 +00003968 ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE",
drh98aa2ab2018-09-26 16:53:51 +00003969 " If FILE begins with '|' then open as a pipe",
drh7a431002020-04-18 14:12:00 +00003970 " --bom Put a UTF8 byte-order mark at the beginning",
3971 " -e Send output to the system text editor",
3972 " -x Send output as CSV to a spreadsheet (same as \".excel\")",
drh4a3a3eb2020-02-29 15:53:48 +00003973#ifdef SQLITE_DEBUG
drhc0605082020-06-05 00:54:27 +00003974 ".oom ?--repeat M? ?N? Simulate an OOM error on the N-th allocation",
drh4a3a3eb2020-02-29 15:53:48 +00003975#endif
drh98aa2ab2018-09-26 16:53:51 +00003976 ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
3977 " Options:",
drh60f34ae2018-10-30 13:19:49 +00003978 " --append Use appendvfs to append database to the end of FILE",
drha751f392018-10-30 15:31:22 +00003979#ifdef SQLITE_ENABLE_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +00003980 " --deserialize Load into memory useing sqlite3_deserialize()",
drhe2754c12019-08-26 12:50:01 +00003981 " --hexdb Load the output of \"dbtotxt\" as an in-memory db",
drh6ca64482019-01-22 16:06:20 +00003982 " --maxsize N Maximum size for --hexdb or --deserialized database",
drha751f392018-10-30 15:31:22 +00003983#endif
drh60f34ae2018-10-30 13:19:49 +00003984 " --new Initialize FILE to an empty database",
drh0933aad2019-11-18 17:46:38 +00003985 " --nofollow Do not follow symbolic links",
drh60f34ae2018-10-30 13:19:49 +00003986 " --readonly Open FILE readonly",
3987 " --zip FILE is a ZIP archive",
drh98aa2ab2018-09-26 16:53:51 +00003988 ".output ?FILE? Send output to FILE or stdout if FILE is omitted",
drh7a431002020-04-18 14:12:00 +00003989 " If FILE begins with '|' then open it as a pipe.",
3990 " Options:",
3991 " --bom Prefix output with a UTF8 byte-order mark",
3992 " -e Send output to the system text editor",
3993 " -x Send output as CSV to a spreadsheet",
drh9cb02642019-02-28 20:10:52 +00003994 ".parameter CMD ... Manage SQL parameter bindings",
3995 " clear Erase all bindings",
3996 " init Initialize the TEMP table that holds bindings",
3997 " list List the current parameter bindings",
3998 " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE",
drhe2754c12019-08-26 12:50:01 +00003999 " PARAMETER should start with one of: $ : @ ?",
drh9cb02642019-02-28 20:10:52 +00004000 " unset PARAMETER Remove PARAMETER from the binding table",
drh98aa2ab2018-09-26 16:53:51 +00004001 ".print STRING... Print literal STRING",
drh569b1d92019-02-05 20:51:41 +00004002#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh3f83f592019-02-04 14:53:18 +00004003 ".progress N Invoke progress handler after every N opcodes",
4004 " --limit N Interrupt after N progress callbacks",
4005 " --once Do no more than one progress interrupt",
4006 " --quiet|-q No output except at interrupts",
4007 " --reset Reset the count for each input and interrupt",
drh569b1d92019-02-05 20:51:41 +00004008#endif
drh98aa2ab2018-09-26 16:53:51 +00004009 ".prompt MAIN CONTINUE Replace the standard prompts",
4010 ".quit Exit this program",
4011 ".read FILE Read input from FILE",
dan1b162162019-04-27 20:15:15 +00004012#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan42ebb012019-04-27 18:47:03 +00004013 ".recover Recover as much data as possible from corrupt db.",
drhe2754c12019-08-26 12:50:01 +00004014 " --freelist-corrupt Assume the freelist is corrupt",
4015 " --recovery-db NAME Store recovery metadata in database file NAME",
4016 " --lost-and-found TABLE Alternative name for the lost-and-found table",
dan8cce6b82019-09-14 16:44:51 +00004017 " --no-rowids Do not attempt to recover rowid values",
4018 " that are not also INTEGER PRIMARY KEYs",
dan1b162162019-04-27 20:15:15 +00004019#endif
drh98aa2ab2018-09-26 16:53:51 +00004020 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
4021 ".save FILE Write in-memory database into FILE",
4022 ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
4023 ".schema ?PATTERN? Show the CREATE statements matching PATTERN",
drhbbb29ec2020-10-12 14:56:47 +00004024 " Options:",
4025 " --indent Try to pretty-print the schema",
4026 " --nosys Omit objects whose names start with \"sqlite_\"",
drheb7f2a02018-09-26 18:02:32 +00004027 ".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
4028 " Options:",
4029 " --init Create a new SELFTEST table",
4030 " -v Verbose output",
drh98aa2ab2018-09-26 16:53:51 +00004031 ".separator COL ?ROW? Change the column and row separators",
drh2ce15c32017-07-11 13:34:40 +00004032#if defined(SQLITE_ENABLE_SESSION)
drheb7f2a02018-09-26 18:02:32 +00004033 ".session ?NAME? CMD ... Create or control sessions",
4034 " Subcommands:",
4035 " attach TABLE Attach TABLE",
4036 " changeset FILE Write a changeset into FILE",
4037 " close Close one session",
4038 " enable ?BOOLEAN? Set or query the enable bit",
4039 " filter GLOB... Reject tables matching GLOBs",
4040 " indirect ?BOOLEAN? Mark or query the indirect status",
4041 " isempty Query whether the session is empty",
4042 " list List currently open session names",
4043 " open DB NAME Open a new session on DB",
4044 " patchset FILE Write a patchset into FILE",
4045 " If ?NAME? is omitted, the first defined session is used.",
drh2ce15c32017-07-11 13:34:40 +00004046#endif
drheb7f2a02018-09-26 18:02:32 +00004047 ".sha3sum ... Compute a SHA3 hash of database content",
4048 " Options:",
drh067b92b2020-06-19 15:24:12 +00004049 " --schema Also hash the sqlite_schema table",
drheb7f2a02018-09-26 18:02:32 +00004050 " --sha3-224 Use the sha3-224 algorithm",
drhe2754c12019-08-26 12:50:01 +00004051 " --sha3-256 Use the sha3-256 algorithm (default)",
drheb7f2a02018-09-26 18:02:32 +00004052 " --sha3-384 Use the sha3-384 algorithm",
4053 " --sha3-512 Use the sha3-512 algorithm",
4054 " Any other argument is a LIKE pattern for tables to hash",
drh04a28c32018-01-31 01:38:44 +00004055#ifndef SQLITE_NOHAVE_SYSTEM
drh98aa2ab2018-09-26 16:53:51 +00004056 ".shell CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004057#endif
drh98aa2ab2018-09-26 16:53:51 +00004058 ".show Show the current values for various settings",
drha6e6cf22021-01-09 19:10:04 +00004059 ".stats ?ARG? Show stats or turn stats on or off",
4060 " off Turn off automatic stat display",
4061 " on Turn on automatic stat display",
4062 " stmt Show statement stats",
4063 " vmstep Show the virtual machine step count only",
drh04a28c32018-01-31 01:38:44 +00004064#ifndef SQLITE_NOHAVE_SYSTEM
drh98aa2ab2018-09-26 16:53:51 +00004065 ".system CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004066#endif
drh98aa2ab2018-09-26 16:53:51 +00004067 ".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
4068 ".testcase NAME Begin redirecting output to 'testcase-out.txt'",
drhd985f722019-06-05 14:29:53 +00004069 ".testctrl CMD ... Run various sqlite3_test_control() operations",
4070 " Run \".testctrl\" with no arguments for details",
drh98aa2ab2018-09-26 16:53:51 +00004071 ".timeout MS Try opening locked tables for MS milliseconds",
4072 ".timer on|off Turn SQL timer on or off",
drh707821f2018-12-05 13:39:06 +00004073#ifndef SQLITE_OMIT_TRACE
4074 ".trace ?OPTIONS? Output each SQL statement as it is run",
4075 " FILE Send output to FILE",
4076 " stdout Send output to stdout",
4077 " stderr Send output to stderr",
4078 " off Disable tracing",
4079 " --expanded Expand query parameters",
4080#ifdef SQLITE_ENABLE_NORMALIZE
4081 " --normalized Normal the SQL statements",
4082#endif
4083 " --plain Show SQL as it is input",
4084 " --stmt Trace statement execution (SQLITE_TRACE_STMT)",
4085 " --profile Profile statements (SQLITE_TRACE_PROFILE)",
4086 " --row Trace each row (SQLITE_TRACE_ROW)",
4087 " --close Trace connection close (SQLITE_TRACE_CLOSE)",
4088#endif /* SQLITE_OMIT_TRACE */
drhcc5979d2019-08-16 22:58:29 +00004089#ifdef SQLITE_DEBUG
4090 ".unmodule NAME ... Unregister virtual table modules",
drh5df84282019-08-17 19:45:25 +00004091 " --allexcept Unregister everything except those named",
drhcc5979d2019-08-16 22:58:29 +00004092#endif
drh98aa2ab2018-09-26 16:53:51 +00004093 ".vfsinfo ?AUX? Information about the top-level VFS",
4094 ".vfslist List all available VFSes",
4095 ".vfsname ?AUX? Print the name of the VFS stack",
drh7da29a32020-05-29 19:17:20 +00004096 ".width NUM1 NUM2 ... Set minimum column widths for columnar output",
drh98aa2ab2018-09-26 16:53:51 +00004097 " Negative values right-justify",
4098};
4099
4100/*
4101** Output help text.
4102**
4103** zPattern describes the set of commands for which help text is provided.
4104** If zPattern is NULL, then show all commands, but only give a one-line
4105** description of each.
4106**
4107** Return the number of matches.
4108*/
4109static int showHelp(FILE *out, const char *zPattern){
drhe93f8262018-10-11 16:53:37 +00004110 int i = 0;
4111 int j = 0;
drh98aa2ab2018-09-26 16:53:51 +00004112 int n = 0;
4113 char *zPat;
drh488cddf2018-10-06 14:38:17 +00004114 if( zPattern==0
4115 || zPattern[0]=='0'
4116 || strcmp(zPattern,"-a")==0
4117 || strcmp(zPattern,"-all")==0
drh7a431002020-04-18 14:12:00 +00004118 || strcmp(zPattern,"--all")==0
drh488cddf2018-10-06 14:38:17 +00004119 ){
drh98aa2ab2018-09-26 16:53:51 +00004120 /* Show all commands, but only one line per command */
drh488cddf2018-10-06 14:38:17 +00004121 if( zPattern==0 ) zPattern = "";
drh98aa2ab2018-09-26 16:53:51 +00004122 for(i=0; i<ArraySize(azHelp); i++){
drh488cddf2018-10-06 14:38:17 +00004123 if( azHelp[i][0]=='.' || zPattern[0] ){
drh98aa2ab2018-09-26 16:53:51 +00004124 utf8_printf(out, "%s\n", azHelp[i]);
4125 n++;
4126 }
4127 }
4128 }else{
4129 /* Look for commands that for which zPattern is an exact prefix */
4130 zPat = sqlite3_mprintf(".%s*", zPattern);
4131 for(i=0; i<ArraySize(azHelp); i++){
4132 if( sqlite3_strglob(zPat, azHelp[i])==0 ){
4133 utf8_printf(out, "%s\n", azHelp[i]);
drheb7f2a02018-09-26 18:02:32 +00004134 j = i+1;
drh98aa2ab2018-09-26 16:53:51 +00004135 n++;
4136 }
4137 }
4138 sqlite3_free(zPat);
drheb7f2a02018-09-26 18:02:32 +00004139 if( n ){
4140 if( n==1 ){
4141 /* when zPattern is a prefix of exactly one command, then include the
4142 ** details of that command, which should begin at offset j */
4143 while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){
4144 utf8_printf(out, "%s\n", azHelp[j]);
4145 j++;
4146 }
4147 }
4148 return n;
4149 }
4150 /* Look for commands that contain zPattern anywhere. Show the complete
4151 ** text of all commands that match. */
drh98aa2ab2018-09-26 16:53:51 +00004152 zPat = sqlite3_mprintf("%%%s%%", zPattern);
4153 for(i=0; i<ArraySize(azHelp); i++){
4154 if( azHelp[i][0]=='.' ) j = i;
4155 if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
4156 utf8_printf(out, "%s\n", azHelp[j]);
4157 while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
4158 j++;
4159 utf8_printf(out, "%s\n", azHelp[j]);
4160 }
4161 i = j;
4162 n++;
4163 }
4164 }
4165 sqlite3_free(zPat);
4166 }
4167 return n;
4168}
drh2ce15c32017-07-11 13:34:40 +00004169
drh2ce15c32017-07-11 13:34:40 +00004170/* Forward reference */
drh60379d42018-12-13 18:30:01 +00004171static int process_input(ShellState *p);
drh2ce15c32017-07-11 13:34:40 +00004172
4173/*
4174** Read the content of file zName into memory obtained from sqlite3_malloc64()
4175** and return a pointer to the buffer. The caller is responsible for freeing
4176** the memory.
4177**
4178** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
4179** read.
4180**
4181** For convenience, a nul-terminator byte is always appended to the data read
4182** from the file before the buffer is returned. This byte is not included in
4183** the final value of (*pnByte), if applicable.
4184**
4185** NULL is returned if any error is encountered. The final value of *pnByte
4186** is undefined in this case.
4187*/
4188static char *readFile(const char *zName, int *pnByte){
4189 FILE *in = fopen(zName, "rb");
4190 long nIn;
4191 size_t nRead;
4192 char *pBuf;
4193 if( in==0 ) return 0;
4194 fseek(in, 0, SEEK_END);
4195 nIn = ftell(in);
4196 rewind(in);
4197 pBuf = sqlite3_malloc64( nIn+1 );
drh1dbb1472018-10-11 10:37:24 +00004198 if( pBuf==0 ){ fclose(in); return 0; }
drh2ce15c32017-07-11 13:34:40 +00004199 nRead = fread(pBuf, nIn, 1, in);
4200 fclose(in);
4201 if( nRead!=1 ){
4202 sqlite3_free(pBuf);
4203 return 0;
4204 }
4205 pBuf[nIn] = 0;
4206 if( pnByte ) *pnByte = nIn;
4207 return pBuf;
4208}
4209
4210#if defined(SQLITE_ENABLE_SESSION)
4211/*
4212** Close a single OpenSession object and release all of its associated
4213** resources.
4214*/
4215static void session_close(OpenSession *pSession){
4216 int i;
4217 sqlite3session_delete(pSession->p);
4218 sqlite3_free(pSession->zName);
4219 for(i=0; i<pSession->nFilter; i++){
4220 sqlite3_free(pSession->azFilter[i]);
4221 }
4222 sqlite3_free(pSession->azFilter);
4223 memset(pSession, 0, sizeof(OpenSession));
4224}
4225#endif
4226
4227/*
4228** Close all OpenSession objects and release all associated resources.
4229*/
4230#if defined(SQLITE_ENABLE_SESSION)
4231static void session_close_all(ShellState *p){
4232 int i;
4233 for(i=0; i<p->nSession; i++){
4234 session_close(&p->aSession[i]);
4235 }
4236 p->nSession = 0;
4237}
4238#else
4239# define session_close_all(X)
4240#endif
4241
4242/*
4243** Implementation of the xFilter function for an open session. Omit
4244** any tables named by ".session filter" but let all other table through.
4245*/
4246#if defined(SQLITE_ENABLE_SESSION)
4247static int session_filter(void *pCtx, const char *zTab){
4248 OpenSession *pSession = (OpenSession*)pCtx;
4249 int i;
4250 for(i=0; i<pSession->nFilter; i++){
4251 if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
4252 }
4253 return 1;
4254}
4255#endif
4256
4257/*
drh1fa6d9f2018-01-06 21:46:01 +00004258** Try to deduce the type of file for zName based on its content. Return
4259** one of the SHELL_OPEN_* constants.
drh1bf208c2018-03-09 21:54:01 +00004260**
4261** If the file does not exist or is empty but its name looks like a ZIP
4262** archive and the dfltZip flag is true, then assume it is a ZIP archive.
4263** Otherwise, assume an ordinary database regardless of the filename if
4264** the type cannot be determined from content.
drh1fa6d9f2018-01-06 21:46:01 +00004265*/
drhfc97c1c2018-05-14 00:41:12 +00004266int deduceDatabaseType(const char *zName, int dfltZip){
drh1fa6d9f2018-01-06 21:46:01 +00004267 FILE *f = fopen(zName, "rb");
4268 size_t n;
4269 int rc = SHELL_OPEN_UNSPEC;
4270 char zBuf[100];
drh1bf208c2018-03-09 21:54:01 +00004271 if( f==0 ){
drhbe4ccb22018-05-17 20:04:24 +00004272 if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
4273 return SHELL_OPEN_ZIPFILE;
4274 }else{
4275 return SHELL_OPEN_NORMAL;
4276 }
drh1bf208c2018-03-09 21:54:01 +00004277 }
drh2b3c4af2018-10-30 14:36:21 +00004278 n = fread(zBuf, 16, 1, f);
4279 if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
4280 fclose(f);
4281 return SHELL_OPEN_NORMAL;
4282 }
drh1fa6d9f2018-01-06 21:46:01 +00004283 fseek(f, -25, SEEK_END);
4284 n = fread(zBuf, 25, 1, f);
4285 if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
4286 rc = SHELL_OPEN_APPENDVFS;
4287 }else{
4288 fseek(f, -22, SEEK_END);
4289 n = fread(zBuf, 22, 1, f);
4290 if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
4291 && zBuf[3]==0x06 ){
4292 rc = SHELL_OPEN_ZIPFILE;
drh1bf208c2018-03-09 21:54:01 +00004293 }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
mistachkina3926f42018-05-14 12:23:04 +00004294 rc = SHELL_OPEN_ZIPFILE;
drh1fa6d9f2018-01-06 21:46:01 +00004295 }
4296 }
4297 fclose(f);
4298 return rc;
4299}
4300
drh33746482018-12-13 15:06:26 +00004301#ifdef SQLITE_ENABLE_DESERIALIZE
4302/*
4303** Reconstruct an in-memory database using the output from the "dbtotxt"
4304** program. Read content from the file in p->zDbFilename. If p->zDbFilename
4305** is 0, then read from standard input.
4306*/
4307static unsigned char *readHexDb(ShellState *p, int *pnData){
4308 unsigned char *a = 0;
drh2c8ee022018-12-13 18:59:30 +00004309 int nLine;
drh33746482018-12-13 15:06:26 +00004310 int n = 0;
4311 int pgsz = 0;
4312 int iOffset = 0;
4313 int j, k;
4314 int rc;
4315 FILE *in;
drh3ea557e2019-04-23 15:30:58 +00004316 unsigned int x[16];
drh2c8ee022018-12-13 18:59:30 +00004317 char zLine[1000];
drh33746482018-12-13 15:06:26 +00004318 if( p->zDbFilename ){
4319 in = fopen(p->zDbFilename, "r");
4320 if( in==0 ){
4321 utf8_printf(stderr, "cannot open \"%s\" for reading\n", p->zDbFilename);
4322 return 0;
4323 }
drh2c8ee022018-12-13 18:59:30 +00004324 nLine = 0;
drh33746482018-12-13 15:06:26 +00004325 }else{
drh60379d42018-12-13 18:30:01 +00004326 in = p->in;
drh2c8ee022018-12-13 18:59:30 +00004327 nLine = p->lineno;
drh5bf46442019-05-03 02:41:36 +00004328 if( in==0 ) in = stdin;
drh33746482018-12-13 15:06:26 +00004329 }
4330 *pnData = 0;
drh2c8ee022018-12-13 18:59:30 +00004331 nLine++;
drh33746482018-12-13 15:06:26 +00004332 if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
4333 rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
4334 if( rc!=2 ) goto readHexDb_error;
drh68feae52019-05-09 11:18:41 +00004335 if( n<0 ) goto readHexDb_error;
drh09ea1252019-07-17 15:05:16 +00004336 if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
4337 n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */
drh68feae52019-05-09 11:18:41 +00004338 a = sqlite3_malloc( n ? n : 1 );
drh33746482018-12-13 15:06:26 +00004339 if( a==0 ){
4340 utf8_printf(stderr, "Out of memory!\n");
4341 goto readHexDb_error;
4342 }
4343 memset(a, 0, n);
4344 if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
4345 utf8_printf(stderr, "invalid pagesize\n");
4346 goto readHexDb_error;
4347 }
drh2c8ee022018-12-13 18:59:30 +00004348 for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
drh33746482018-12-13 15:06:26 +00004349 rc = sscanf(zLine, "| page %d offset %d", &j, &k);
4350 if( rc==2 ){
4351 iOffset = k;
4352 continue;
4353 }
4354 if( strncmp(zLine, "| end ", 6)==0 ){
4355 break;
4356 }
drh3ea557e2019-04-23 15:30:58 +00004357 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 +00004358 &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
4359 &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
4360 if( rc==17 ){
4361 k = iOffset+j;
drhf354e772018-12-13 22:58:52 +00004362 if( k+16<=n ){
drh3ea557e2019-04-23 15:30:58 +00004363 int ii;
4364 for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
drh33746482018-12-13 15:06:26 +00004365 }
drh33746482018-12-13 15:06:26 +00004366 }
4367 }
4368 *pnData = n;
drh2c8ee022018-12-13 18:59:30 +00004369 if( in!=p->in ){
4370 fclose(in);
4371 }else{
4372 p->lineno = nLine;
4373 }
drh33746482018-12-13 15:06:26 +00004374 return a;
4375
4376readHexDb_error:
drh68feae52019-05-09 11:18:41 +00004377 if( in!=p->in ){
drh33746482018-12-13 15:06:26 +00004378 fclose(in);
4379 }else{
drh60379d42018-12-13 18:30:01 +00004380 while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
drh2c8ee022018-12-13 18:59:30 +00004381 nLine++;
drh33746482018-12-13 15:06:26 +00004382 if(strncmp(zLine, "| end ", 6)==0 ) break;
4383 }
drh2c8ee022018-12-13 18:59:30 +00004384 p->lineno = nLine;
drh33746482018-12-13 15:06:26 +00004385 }
4386 sqlite3_free(a);
4387 utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
4388 return 0;
4389}
4390#endif /* SQLITE_ENABLE_DESERIALIZE */
4391
danb1825882019-04-23 20:48:32 +00004392/*
dan9c014f82019-04-25 19:23:15 +00004393** Scalar function "shell_int32". The first argument to this function
4394** must be a blob. The second a non-negative integer. This function
4395** reads and returns a 32-bit big-endian integer from byte
4396** offset (4*<arg2>) of the blob.
4397*/
4398static void shellInt32(
4399 sqlite3_context *context,
4400 int argc,
4401 sqlite3_value **argv
4402){
4403 const unsigned char *pBlob;
4404 int nBlob;
4405 int iInt;
drh9546c762019-05-10 17:50:33 +00004406
4407 UNUSED_PARAMETER(argc);
dan9c014f82019-04-25 19:23:15 +00004408 nBlob = sqlite3_value_bytes(argv[0]);
4409 pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
4410 iInt = sqlite3_value_int(argv[1]);
4411
4412 if( iInt>=0 && (iInt+1)*4<=nBlob ){
4413 const unsigned char *a = &pBlob[iInt*4];
4414 sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24)
4415 + ((sqlite3_int64)a[1]<<16)
4416 + ((sqlite3_int64)a[2]<< 8)
4417 + ((sqlite3_int64)a[3]<< 0);
4418 sqlite3_result_int64(context, iVal);
4419 }
4420}
4421
4422/*
drha2de66c2019-08-06 20:26:17 +00004423** Scalar function "shell_idquote(X)" returns string X quoted as an identifier,
4424** using "..." with internal double-quote characters doubled.
4425*/
4426static void shellIdQuote(
4427 sqlite3_context *context,
4428 int argc,
4429 sqlite3_value **argv
4430){
4431 const char *zName = (const char*)sqlite3_value_text(argv[0]);
drh51755a72019-08-08 19:40:29 +00004432 UNUSED_PARAMETER(argc);
drha2de66c2019-08-06 20:26:17 +00004433 if( zName ){
4434 char *z = sqlite3_mprintf("\"%w\"", zName);
4435 sqlite3_result_text(context, z, -1, sqlite3_free);
4436 }
4437}
4438
4439/*
drhddcfe922020-09-15 12:29:35 +00004440** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
4441*/
4442static void shellUSleepFunc(
4443 sqlite3_context *context,
drhd36f5882020-11-25 16:28:04 +00004444 int argcUnused,
drhddcfe922020-09-15 12:29:35 +00004445 sqlite3_value **argv
4446){
4447 int sleep = sqlite3_value_int(argv[0]);
drhd36f5882020-11-25 16:28:04 +00004448 (void)argcUnused;
drhddcfe922020-09-15 12:29:35 +00004449 sqlite3_sleep(sleep/1000);
4450 sqlite3_result_int(context, sleep);
4451}
4452
4453/*
danb1825882019-04-23 20:48:32 +00004454** Scalar function "shell_escape_crnl" used by the .recover command.
4455** The argument passed to this function is the output of built-in
4456** function quote(). If the first character of the input is "'",
4457** indicating that the value passed to quote() was a text value,
4458** then this function searches the input for "\n" and "\r" characters
4459** and adds a wrapper similar to the following:
4460**
4461** replace(replace(<input>, '\n', char(10), '\r', char(13));
4462**
4463** Or, if the first character of the input is not "'", then a copy
4464** of the input is returned.
4465*/
4466static void shellEscapeCrnl(
4467 sqlite3_context *context,
4468 int argc,
4469 sqlite3_value **argv
4470){
4471 const char *zText = (const char*)sqlite3_value_text(argv[0]);
drh9546c762019-05-10 17:50:33 +00004472 UNUSED_PARAMETER(argc);
danb1825882019-04-23 20:48:32 +00004473 if( zText[0]=='\'' ){
4474 int nText = sqlite3_value_bytes(argv[0]);
4475 int i;
4476 char zBuf1[20];
4477 char zBuf2[20];
4478 const char *zNL = 0;
4479 const char *zCR = 0;
4480 int nCR = 0;
4481 int nNL = 0;
4482
4483 for(i=0; zText[i]; i++){
4484 if( zNL==0 && zText[i]=='\n' ){
4485 zNL = unused_string(zText, "\\n", "\\012", zBuf1);
4486 nNL = (int)strlen(zNL);
4487 }
4488 if( zCR==0 && zText[i]=='\r' ){
4489 zCR = unused_string(zText, "\\r", "\\015", zBuf2);
4490 nCR = (int)strlen(zCR);
4491 }
4492 }
4493
4494 if( zNL || zCR ){
4495 int iOut = 0;
4496 i64 nMax = (nNL > nCR) ? nNL : nCR;
dan51f5ffa2019-04-29 11:41:46 +00004497 i64 nAlloc = nMax * nText + (nMax+64)*2;
danb1825882019-04-23 20:48:32 +00004498 char *zOut = (char*)sqlite3_malloc64(nAlloc);
4499 if( zOut==0 ){
4500 sqlite3_result_error_nomem(context);
4501 return;
4502 }
4503
4504 if( zNL && zCR ){
4505 memcpy(&zOut[iOut], "replace(replace(", 16);
4506 iOut += 16;
4507 }else{
4508 memcpy(&zOut[iOut], "replace(", 8);
4509 iOut += 8;
4510 }
4511 for(i=0; zText[i]; i++){
4512 if( zText[i]=='\n' ){
4513 memcpy(&zOut[iOut], zNL, nNL);
4514 iOut += nNL;
4515 }else if( zText[i]=='\r' ){
4516 memcpy(&zOut[iOut], zCR, nCR);
4517 iOut += nCR;
4518 }else{
4519 zOut[iOut] = zText[i];
4520 iOut++;
4521 }
4522 }
4523
4524 if( zNL ){
4525 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
4526 memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
4527 memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
4528 }
4529 if( zCR ){
4530 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
4531 memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
4532 memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
4533 }
4534
4535 sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
4536 sqlite3_free(zOut);
4537 return;
4538 }
4539 }
4540
4541 sqlite3_result_value(context, argv[0]);
4542}
4543
drhbe4ccb22018-05-17 20:04:24 +00004544/* Flags for open_db().
4545**
4546** The default behavior of open_db() is to exit(1) if the database fails to
4547** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
4548** but still returns without calling exit.
4549**
4550** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a
4551** ZIP archive if the file does not exist or is empty and its name matches
4552** the *.zip pattern.
4553*/
4554#define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */
4555#define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */
4556
drh1fa6d9f2018-01-06 21:46:01 +00004557/*
drh2ce15c32017-07-11 13:34:40 +00004558** Make sure the database is open. If it is not, then open it. If
4559** the database fails to open, print an error message and exit.
4560*/
drhbe4ccb22018-05-17 20:04:24 +00004561static void open_db(ShellState *p, int openFlags){
drh2ce15c32017-07-11 13:34:40 +00004562 if( p->db==0 ){
drhf2072d12018-05-11 15:10:11 +00004563 if( p->openMode==SHELL_OPEN_UNSPEC ){
4564 if( p->zDbFilename==0 || p->zDbFilename[0]==0 ){
4565 p->openMode = SHELL_OPEN_NORMAL;
drhbe4ccb22018-05-17 20:04:24 +00004566 }else{
4567 p->openMode = (u8)deduceDatabaseType(p->zDbFilename,
4568 (openFlags & OPEN_DB_ZIPFILE)!=0);
drhf2072d12018-05-11 15:10:11 +00004569 }
drh1fa6d9f2018-01-06 21:46:01 +00004570 }
4571 switch( p->openMode ){
4572 case SHELL_OPEN_APPENDVFS: {
4573 sqlite3_open_v2(p->zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004574 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
drh1fa6d9f2018-01-06 21:46:01 +00004575 break;
4576 }
drh33746482018-12-13 15:06:26 +00004577 case SHELL_OPEN_HEXDB:
drh60f34ae2018-10-30 13:19:49 +00004578 case SHELL_OPEN_DESERIALIZE: {
4579 sqlite3_open(0, &p->db);
4580 break;
4581 }
drh1fa6d9f2018-01-06 21:46:01 +00004582 case SHELL_OPEN_ZIPFILE: {
4583 sqlite3_open(":memory:", &p->db);
4584 break;
4585 }
drhee269a62018-02-14 23:27:43 +00004586 case SHELL_OPEN_READONLY: {
drh0933aad2019-11-18 17:46:38 +00004587 sqlite3_open_v2(p->zDbFilename, &p->db,
4588 SQLITE_OPEN_READONLY|p->openFlags, 0);
drhee269a62018-02-14 23:27:43 +00004589 break;
4590 }
drh1fa6d9f2018-01-06 21:46:01 +00004591 case SHELL_OPEN_UNSPEC:
4592 case SHELL_OPEN_NORMAL: {
drh0933aad2019-11-18 17:46:38 +00004593 sqlite3_open_v2(p->zDbFilename, &p->db,
4594 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
drh1fa6d9f2018-01-06 21:46:01 +00004595 break;
4596 }
4597 }
drh2ce15c32017-07-11 13:34:40 +00004598 globalDb = p->db;
4599 if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
4600 utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
4601 p->zDbFilename, sqlite3_errmsg(p->db));
drhf25cc4f2019-01-04 14:29:21 +00004602 if( openFlags & OPEN_DB_KEEPALIVE ){
4603 sqlite3_open(":memory:", &p->db);
4604 return;
4605 }
drh2ce15c32017-07-11 13:34:40 +00004606 exit(1);
4607 }
4608#ifndef SQLITE_OMIT_LOAD_EXTENSION
4609 sqlite3_enable_load_extension(p->db, 1);
4610#endif
4611 sqlite3_fileio_init(p->db, 0, 0);
4612 sqlite3_shathree_init(p->db, 0, 0);
drh56eb09b2017-07-11 13:59:07 +00004613 sqlite3_completion_init(p->db, 0, 0);
drhf05dd032020-04-14 15:53:58 +00004614 sqlite3_uint_init(p->db, 0, 0);
drhbeb9def2020-06-22 19:12:23 +00004615 sqlite3_decimal_init(p->db, 0, 0);
drh8cda77d2020-06-24 15:06:29 +00004616 sqlite3_ieee_init(p->db, 0, 0);
mistachkin72c38d82020-08-28 18:47:39 +00004617 sqlite3_series_init(p->db, 0, 0);
dan1b162162019-04-27 20:15:15 +00004618#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00004619 sqlite3_dbdata_init(p->db, 0, 0);
dan1b162162019-04-27 20:15:15 +00004620#endif
dan72afc3c2017-12-05 18:32:40 +00004621#ifdef SQLITE_HAVE_ZLIB
dan9ebfaad2017-12-26 20:39:58 +00004622 sqlite3_zipfile_init(p->db, 0, 0);
dand1b51d42017-12-16 19:11:26 +00004623 sqlite3_sqlar_init(p->db, 0, 0);
dan72afc3c2017-12-05 18:32:40 +00004624#endif
drhceba7922018-01-01 21:28:25 +00004625 sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
drh2ce15c32017-07-11 13:34:40 +00004626 shellAddSchemaName, 0, 0);
drh667a2a22018-01-02 00:04:37 +00004627 sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
4628 shellModuleSchema, 0, 0);
drh634c70f2018-01-10 16:50:18 +00004629 sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
4630 shellPutsFunc, 0, 0);
danb1825882019-04-23 20:48:32 +00004631 sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0,
4632 shellEscapeCrnl, 0, 0);
dan9c014f82019-04-25 19:23:15 +00004633 sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
4634 shellInt32, 0, 0);
drha2de66c2019-08-06 20:26:17 +00004635 sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
4636 shellIdQuote, 0, 0);
drhddcfe922020-09-15 12:29:35 +00004637 sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
4638 shellUSleepFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00004639#ifndef SQLITE_NOHAVE_SYSTEM
drh97913132018-01-11 00:04:00 +00004640 sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
4641 editFunc, 0, 0);
4642 sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
4643 editFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00004644#endif
drh1fa6d9f2018-01-06 21:46:01 +00004645 if( p->openMode==SHELL_OPEN_ZIPFILE ){
4646 char *zSql = sqlite3_mprintf(
4647 "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename);
4648 sqlite3_exec(p->db, zSql, 0, 0, 0);
4649 sqlite3_free(zSql);
drha751f392018-10-30 15:31:22 +00004650 }
4651#ifdef SQLITE_ENABLE_DESERIALIZE
drh33746482018-12-13 15:06:26 +00004652 else
4653 if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
mistachkin99490932018-12-17 22:19:57 +00004654 int rc;
drh60f34ae2018-10-30 13:19:49 +00004655 int nData = 0;
drh33746482018-12-13 15:06:26 +00004656 unsigned char *aData;
4657 if( p->openMode==SHELL_OPEN_DESERIALIZE ){
4658 aData = (unsigned char*)readFile(p->zDbFilename, &nData);
4659 }else{
4660 aData = readHexDb(p, &nData);
4661 if( aData==0 ){
drh33746482018-12-13 15:06:26 +00004662 return;
4663 }
4664 }
mistachkin99490932018-12-17 22:19:57 +00004665 rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
drh60f34ae2018-10-30 13:19:49 +00004666 SQLITE_DESERIALIZE_RESIZEABLE |
4667 SQLITE_DESERIALIZE_FREEONCLOSE);
4668 if( rc ){
4669 utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
4670 }
drh6ca64482019-01-22 16:06:20 +00004671 if( p->szMax>0 ){
4672 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
4673 }
drh1fa6d9f2018-01-06 21:46:01 +00004674 }
drha751f392018-10-30 15:31:22 +00004675#endif
drh2ce15c32017-07-11 13:34:40 +00004676 }
4677}
4678
drh9e804032018-05-18 17:11:50 +00004679/*
4680** Attempt to close the databaes connection. Report errors.
4681*/
4682void close_db(sqlite3 *db){
4683 int rc = sqlite3_close(db);
4684 if( rc ){
4685 utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
4686 rc, sqlite3_errmsg(db));
4687 }
4688}
4689
drh56eb09b2017-07-11 13:59:07 +00004690#if HAVE_READLINE || HAVE_EDITLINE
4691/*
4692** Readline completion callbacks
4693*/
4694static char *readline_completion_generator(const char *text, int state){
4695 static sqlite3_stmt *pStmt = 0;
4696 char *zRet;
4697 if( state==0 ){
4698 char *zSql;
drh56eb09b2017-07-11 13:59:07 +00004699 sqlite3_finalize(pStmt);
4700 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
4701 " FROM completion(%Q) ORDER BY 1", text);
4702 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
4703 sqlite3_free(zSql);
4704 }
4705 if( sqlite3_step(pStmt)==SQLITE_ROW ){
drh968d8712017-07-14 00:28:28 +00004706 zRet = strdup((const char*)sqlite3_column_text(pStmt, 0));
drh56eb09b2017-07-11 13:59:07 +00004707 }else{
4708 sqlite3_finalize(pStmt);
4709 pStmt = 0;
4710 zRet = 0;
4711 }
4712 return zRet;
4713}
4714static char **readline_completion(const char *zText, int iStart, int iEnd){
4715 rl_attempted_completion_over = 1;
4716 return rl_completion_matches(zText, readline_completion_generator);
4717}
4718
4719#elif HAVE_LINENOISE
4720/*
4721** Linenoise completion callback
4722*/
4723static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
drhaf2770f2018-01-05 14:55:43 +00004724 int nLine = strlen30(zLine);
drh56eb09b2017-07-11 13:59:07 +00004725 int i, iStart;
4726 sqlite3_stmt *pStmt = 0;
4727 char *zSql;
4728 char zBuf[1000];
4729
4730 if( nLine>sizeof(zBuf)-30 ) return;
drh1615c372018-05-12 23:56:22 +00004731 if( zLine[0]=='.' || zLine[0]=='#') return;
drh56eb09b2017-07-11 13:59:07 +00004732 for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
4733 if( i==nLine-1 ) return;
4734 iStart = i+1;
4735 memcpy(zBuf, zLine, iStart);
4736 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
4737 " FROM completion(%Q,%Q) ORDER BY 1",
4738 &zLine[iStart], zLine);
4739 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
4740 sqlite3_free(zSql);
4741 sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
4742 while( sqlite3_step(pStmt)==SQLITE_ROW ){
4743 const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
4744 int nCompletion = sqlite3_column_bytes(pStmt, 0);
4745 if( iStart+nCompletion < sizeof(zBuf)-1 ){
4746 memcpy(zBuf+iStart, zCompletion, nCompletion+1);
4747 linenoiseAddCompletion(lc, zBuf);
4748 }
4749 }
4750 sqlite3_finalize(pStmt);
4751}
4752#endif
4753
drh2ce15c32017-07-11 13:34:40 +00004754/*
4755** Do C-language style dequoting.
4756**
4757** \a -> alarm
4758** \b -> backspace
4759** \t -> tab
4760** \n -> newline
4761** \v -> vertical tab
4762** \f -> form feed
4763** \r -> carriage return
4764** \s -> space
4765** \" -> "
4766** \' -> '
4767** \\ -> backslash
4768** \NNN -> ascii character NNN in octal
4769*/
4770static void resolve_backslashes(char *z){
4771 int i, j;
4772 char c;
4773 while( *z && *z!='\\' ) z++;
4774 for(i=j=0; (c = z[i])!=0; i++, j++){
4775 if( c=='\\' && z[i+1]!=0 ){
4776 c = z[++i];
4777 if( c=='a' ){
4778 c = '\a';
4779 }else if( c=='b' ){
4780 c = '\b';
4781 }else if( c=='t' ){
4782 c = '\t';
4783 }else if( c=='n' ){
4784 c = '\n';
4785 }else if( c=='v' ){
4786 c = '\v';
4787 }else if( c=='f' ){
4788 c = '\f';
4789 }else if( c=='r' ){
4790 c = '\r';
4791 }else if( c=='"' ){
4792 c = '"';
4793 }else if( c=='\'' ){
4794 c = '\'';
4795 }else if( c=='\\' ){
4796 c = '\\';
4797 }else if( c>='0' && c<='7' ){
4798 c -= '0';
4799 if( z[i+1]>='0' && z[i+1]<='7' ){
4800 i++;
4801 c = (c<<3) + z[i] - '0';
4802 if( z[i+1]>='0' && z[i+1]<='7' ){
4803 i++;
4804 c = (c<<3) + z[i] - '0';
4805 }
4806 }
4807 }
4808 }
4809 z[j] = c;
4810 }
4811 if( j<i ) z[j] = 0;
4812}
4813
4814/*
drh2ce15c32017-07-11 13:34:40 +00004815** Interpret zArg as either an integer or a boolean value. Return 1 or 0
4816** for TRUE and FALSE. Return the integer value if appropriate.
4817*/
4818static int booleanValue(const char *zArg){
4819 int i;
4820 if( zArg[0]=='0' && zArg[1]=='x' ){
4821 for(i=2; hexDigitValue(zArg[i])>=0; i++){}
4822 }else{
4823 for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
4824 }
4825 if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
4826 if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
4827 return 1;
4828 }
4829 if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
4830 return 0;
4831 }
4832 utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
4833 zArg);
4834 return 0;
4835}
4836
4837/*
4838** Set or clear a shell flag according to a boolean value.
4839*/
4840static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){
4841 if( booleanValue(zArg) ){
4842 ShellSetFlag(p, mFlag);
4843 }else{
4844 ShellClearFlag(p, mFlag);
4845 }
4846}
4847
4848/*
4849** Close an output file, assuming it is not stderr or stdout
4850*/
4851static void output_file_close(FILE *f){
4852 if( f && f!=stdout && f!=stderr ) fclose(f);
4853}
4854
4855/*
4856** Try to open an output file. The names "stdout" and "stderr" are
4857** recognized and do the right thing. NULL is returned if the output
4858** filename is "off".
4859*/
drha92a01a2018-01-10 22:15:37 +00004860static FILE *output_file_open(const char *zFile, int bTextMode){
drh2ce15c32017-07-11 13:34:40 +00004861 FILE *f;
4862 if( strcmp(zFile,"stdout")==0 ){
4863 f = stdout;
4864 }else if( strcmp(zFile, "stderr")==0 ){
4865 f = stderr;
4866 }else if( strcmp(zFile, "off")==0 ){
4867 f = 0;
4868 }else{
drha92a01a2018-01-10 22:15:37 +00004869 f = fopen(zFile, bTextMode ? "w" : "wb");
drh2ce15c32017-07-11 13:34:40 +00004870 if( f==0 ){
4871 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
4872 }
4873 }
4874 return f;
4875}
4876
drh707821f2018-12-05 13:39:06 +00004877#ifndef SQLITE_OMIT_TRACE
drh2ce15c32017-07-11 13:34:40 +00004878/*
4879** A routine for handling output from sqlite3_trace().
4880*/
4881static int sql_trace_callback(
drh707821f2018-12-05 13:39:06 +00004882 unsigned mType, /* The trace type */
4883 void *pArg, /* The ShellState pointer */
4884 void *pP, /* Usually a pointer to sqlite_stmt */
4885 void *pX /* Auxiliary output */
drh2ce15c32017-07-11 13:34:40 +00004886){
drh707821f2018-12-05 13:39:06 +00004887 ShellState *p = (ShellState*)pArg;
4888 sqlite3_stmt *pStmt;
4889 const char *zSql;
4890 int nSql;
4891 if( p->traceOut==0 ) return 0;
4892 if( mType==SQLITE_TRACE_CLOSE ){
4893 utf8_printf(p->traceOut, "-- closing database connection\n");
4894 return 0;
4895 }
4896 if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){
4897 zSql = (const char*)pX;
4898 }else{
4899 pStmt = (sqlite3_stmt*)pP;
4900 switch( p->eTraceType ){
4901 case SHELL_TRACE_EXPANDED: {
4902 zSql = sqlite3_expanded_sql(pStmt);
4903 break;
4904 }
4905#ifdef SQLITE_ENABLE_NORMALIZE
4906 case SHELL_TRACE_NORMALIZED: {
4907 zSql = sqlite3_normalized_sql(pStmt);
4908 break;
4909 }
4910#endif
4911 default: {
4912 zSql = sqlite3_sql(pStmt);
4913 break;
4914 }
4915 }
4916 }
4917 if( zSql==0 ) return 0;
4918 nSql = strlen30(zSql);
4919 while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
4920 switch( mType ){
4921 case SQLITE_TRACE_ROW:
4922 case SQLITE_TRACE_STMT: {
4923 utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql);
4924 break;
4925 }
4926 case SQLITE_TRACE_PROFILE: {
4927 sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
4928 utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec);
4929 break;
4930 }
drh2ce15c32017-07-11 13:34:40 +00004931 }
4932 return 0;
4933}
4934#endif
drh2ce15c32017-07-11 13:34:40 +00004935
4936/*
4937** A no-op routine that runs with the ".breakpoint" doc-command. This is
4938** a useful spot to set a debugger breakpoint.
4939*/
4940static void test_breakpoint(void){
4941 static int nCall = 0;
4942 nCall++;
4943}
4944
4945/*
4946** An object used to read a CSV and other files for import.
4947*/
4948typedef struct ImportCtx ImportCtx;
4949struct ImportCtx {
4950 const char *zFile; /* Name of the input file */
4951 FILE *in; /* Read the CSV text from this input stream */
drh97767842020-05-29 19:39:35 +00004952 int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */
drh2ce15c32017-07-11 13:34:40 +00004953 char *z; /* Accumulated text for a field */
4954 int n; /* Number of bytes in z */
4955 int nAlloc; /* Space allocated for z[] */
4956 int nLine; /* Current line number */
drhccb37812020-03-09 15:39:39 +00004957 int nRow; /* Number of rows imported */
4958 int nErr; /* Number of errors encountered */
drh2ce15c32017-07-11 13:34:40 +00004959 int bNotFirst; /* True if one or more bytes already read */
4960 int cTerm; /* Character that terminated the most recent field */
4961 int cColSep; /* The column separator character. (Usually ",") */
4962 int cRowSep; /* The row separator character. (Usually "\n") */
4963};
4964
drh97767842020-05-29 19:39:35 +00004965/* Clean up resourced used by an ImportCtx */
4966static void import_cleanup(ImportCtx *p){
drh42c2a042020-05-29 20:16:19 +00004967 if( p->in!=0 && p->xCloser!=0 ){
drh97767842020-05-29 19:39:35 +00004968 p->xCloser(p->in);
4969 p->in = 0;
4970 }
4971 sqlite3_free(p->z);
4972 p->z = 0;
4973}
4974
drh2ce15c32017-07-11 13:34:40 +00004975/* Append a single byte to z[] */
4976static void import_append_char(ImportCtx *p, int c){
4977 if( p->n+1>=p->nAlloc ){
4978 p->nAlloc += p->nAlloc + 100;
4979 p->z = sqlite3_realloc64(p->z, p->nAlloc);
drh4b5345c2018-04-24 13:07:40 +00004980 if( p->z==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00004981 }
4982 p->z[p->n++] = (char)c;
4983}
4984
4985/* Read a single field of CSV text. Compatible with rfc4180 and extended
4986** with the option of having a separator other than ",".
4987**
4988** + Input comes from p->in.
4989** + Store results in p->z of length p->n. Space to hold p->z comes
4990** from sqlite3_malloc64().
4991** + Use p->cSep as the column separator. The default is ",".
4992** + Use p->rSep as the row separator. The default is "\n".
4993** + Keep track of the line number in p->nLine.
4994** + Store the character that terminates the field in p->cTerm. Store
4995** EOF on end-of-file.
4996** + Report syntax errors on stderr
4997*/
4998static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
4999 int c;
5000 int cSep = p->cColSep;
5001 int rSep = p->cRowSep;
5002 p->n = 0;
5003 c = fgetc(p->in);
5004 if( c==EOF || seenInterrupt ){
5005 p->cTerm = EOF;
5006 return 0;
5007 }
5008 if( c=='"' ){
5009 int pc, ppc;
5010 int startLine = p->nLine;
5011 int cQuote = c;
5012 pc = ppc = 0;
5013 while( 1 ){
5014 c = fgetc(p->in);
5015 if( c==rSep ) p->nLine++;
5016 if( c==cQuote ){
5017 if( pc==cQuote ){
5018 pc = 0;
5019 continue;
5020 }
5021 }
5022 if( (c==cSep && pc==cQuote)
5023 || (c==rSep && pc==cQuote)
5024 || (c==rSep && pc=='\r' && ppc==cQuote)
5025 || (c==EOF && pc==cQuote)
5026 ){
5027 do{ p->n--; }while( p->z[p->n]!=cQuote );
5028 p->cTerm = c;
5029 break;
5030 }
5031 if( pc==cQuote && c!='\r' ){
5032 utf8_printf(stderr, "%s:%d: unescaped %c character\n",
5033 p->zFile, p->nLine, cQuote);
5034 }
5035 if( c==EOF ){
5036 utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
5037 p->zFile, startLine, cQuote);
5038 p->cTerm = c;
5039 break;
5040 }
5041 import_append_char(p, c);
5042 ppc = pc;
5043 pc = c;
5044 }
5045 }else{
5046 /* If this is the first field being parsed and it begins with the
5047 ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
5048 if( (c&0xff)==0xef && p->bNotFirst==0 ){
5049 import_append_char(p, c);
5050 c = fgetc(p->in);
5051 if( (c&0xff)==0xbb ){
5052 import_append_char(p, c);
5053 c = fgetc(p->in);
5054 if( (c&0xff)==0xbf ){
5055 p->bNotFirst = 1;
5056 p->n = 0;
5057 return csv_read_one_field(p);
5058 }
5059 }
5060 }
5061 while( c!=EOF && c!=cSep && c!=rSep ){
5062 import_append_char(p, c);
5063 c = fgetc(p->in);
5064 }
5065 if( c==rSep ){
5066 p->nLine++;
5067 if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
5068 }
5069 p->cTerm = c;
5070 }
5071 if( p->z ) p->z[p->n] = 0;
5072 p->bNotFirst = 1;
5073 return p->z;
5074}
5075
5076/* Read a single field of ASCII delimited text.
5077**
5078** + Input comes from p->in.
5079** + Store results in p->z of length p->n. Space to hold p->z comes
5080** from sqlite3_malloc64().
5081** + Use p->cSep as the column separator. The default is "\x1F".
5082** + Use p->rSep as the row separator. The default is "\x1E".
5083** + Keep track of the row number in p->nLine.
5084** + Store the character that terminates the field in p->cTerm. Store
5085** EOF on end-of-file.
5086** + Report syntax errors on stderr
5087*/
5088static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
5089 int c;
5090 int cSep = p->cColSep;
5091 int rSep = p->cRowSep;
5092 p->n = 0;
5093 c = fgetc(p->in);
5094 if( c==EOF || seenInterrupt ){
5095 p->cTerm = EOF;
5096 return 0;
5097 }
5098 while( c!=EOF && c!=cSep && c!=rSep ){
5099 import_append_char(p, c);
5100 c = fgetc(p->in);
5101 }
5102 if( c==rSep ){
5103 p->nLine++;
5104 }
5105 p->cTerm = c;
5106 if( p->z ) p->z[p->n] = 0;
5107 return p->z;
5108}
5109
5110/*
5111** Try to transfer data for table zTable. If an error is seen while
5112** moving forward, try to go backwards. The backwards movement won't
5113** work for WITHOUT ROWID tables.
5114*/
5115static void tryToCloneData(
5116 ShellState *p,
5117 sqlite3 *newDb,
5118 const char *zTable
5119){
5120 sqlite3_stmt *pQuery = 0;
5121 sqlite3_stmt *pInsert = 0;
5122 char *zQuery = 0;
5123 char *zInsert = 0;
5124 int rc;
5125 int i, j, n;
drhaf2770f2018-01-05 14:55:43 +00005126 int nTable = strlen30(zTable);
drh2ce15c32017-07-11 13:34:40 +00005127 int k = 0;
5128 int cnt = 0;
5129 const int spinRate = 10000;
5130
5131 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
5132 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5133 if( rc ){
5134 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5135 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5136 zQuery);
5137 goto end_data_xfer;
5138 }
5139 n = sqlite3_column_count(pQuery);
5140 zInsert = sqlite3_malloc64(200 + nTable + n*3);
drh4b5345c2018-04-24 13:07:40 +00005141 if( zInsert==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00005142 sqlite3_snprintf(200+nTable,zInsert,
5143 "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
drhaf2770f2018-01-05 14:55:43 +00005144 i = strlen30(zInsert);
drh2ce15c32017-07-11 13:34:40 +00005145 for(j=1; j<n; j++){
5146 memcpy(zInsert+i, ",?", 2);
5147 i += 2;
5148 }
5149 memcpy(zInsert+i, ");", 3);
5150 rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
5151 if( rc ){
5152 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5153 sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
5154 zQuery);
5155 goto end_data_xfer;
5156 }
5157 for(k=0; k<2; k++){
5158 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5159 for(i=0; i<n; i++){
5160 switch( sqlite3_column_type(pQuery, i) ){
5161 case SQLITE_NULL: {
5162 sqlite3_bind_null(pInsert, i+1);
5163 break;
5164 }
5165 case SQLITE_INTEGER: {
5166 sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
5167 break;
5168 }
5169 case SQLITE_FLOAT: {
5170 sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
5171 break;
5172 }
5173 case SQLITE_TEXT: {
5174 sqlite3_bind_text(pInsert, i+1,
5175 (const char*)sqlite3_column_text(pQuery,i),
5176 -1, SQLITE_STATIC);
5177 break;
5178 }
5179 case SQLITE_BLOB: {
5180 sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
5181 sqlite3_column_bytes(pQuery,i),
5182 SQLITE_STATIC);
5183 break;
5184 }
5185 }
5186 } /* End for */
5187 rc = sqlite3_step(pInsert);
5188 if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
5189 utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
5190 sqlite3_errmsg(newDb));
5191 }
5192 sqlite3_reset(pInsert);
5193 cnt++;
5194 if( (cnt%spinRate)==0 ){
5195 printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
5196 fflush(stdout);
5197 }
5198 } /* End while */
5199 if( rc==SQLITE_DONE ) break;
5200 sqlite3_finalize(pQuery);
5201 sqlite3_free(zQuery);
5202 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
5203 zTable);
5204 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5205 if( rc ){
5206 utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
5207 break;
5208 }
5209 } /* End for(k=0...) */
5210
5211end_data_xfer:
5212 sqlite3_finalize(pQuery);
5213 sqlite3_finalize(pInsert);
5214 sqlite3_free(zQuery);
5215 sqlite3_free(zInsert);
5216}
5217
5218
5219/*
5220** Try to transfer all rows of the schema that match zWhere. For
5221** each row, invoke xForEach() on the object defined by that row.
5222** If an error is encountered while moving forward through the
drh067b92b2020-06-19 15:24:12 +00005223** sqlite_schema table, try again moving backwards.
drh2ce15c32017-07-11 13:34:40 +00005224*/
5225static void tryToCloneSchema(
5226 ShellState *p,
5227 sqlite3 *newDb,
5228 const char *zWhere,
5229 void (*xForEach)(ShellState*,sqlite3*,const char*)
5230){
5231 sqlite3_stmt *pQuery = 0;
5232 char *zQuery = 0;
5233 int rc;
5234 const unsigned char *zName;
5235 const unsigned char *zSql;
5236 char *zErrMsg = 0;
5237
drh067b92b2020-06-19 15:24:12 +00005238 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005239 " WHERE %s", zWhere);
5240 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5241 if( rc ){
5242 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5243 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5244 zQuery);
5245 goto end_schema_xfer;
5246 }
5247 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5248 zName = sqlite3_column_text(pQuery, 0);
5249 zSql = sqlite3_column_text(pQuery, 1);
5250 printf("%s... ", zName); fflush(stdout);
5251 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5252 if( zErrMsg ){
5253 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5254 sqlite3_free(zErrMsg);
5255 zErrMsg = 0;
5256 }
5257 if( xForEach ){
5258 xForEach(p, newDb, (const char*)zName);
5259 }
5260 printf("done\n");
5261 }
5262 if( rc!=SQLITE_DONE ){
5263 sqlite3_finalize(pQuery);
5264 sqlite3_free(zQuery);
drh067b92b2020-06-19 15:24:12 +00005265 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005266 " WHERE %s ORDER BY rowid DESC", zWhere);
5267 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5268 if( rc ){
5269 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5270 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5271 zQuery);
5272 goto end_schema_xfer;
5273 }
5274 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5275 zName = sqlite3_column_text(pQuery, 0);
5276 zSql = sqlite3_column_text(pQuery, 1);
5277 printf("%s... ", zName); fflush(stdout);
5278 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5279 if( zErrMsg ){
5280 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5281 sqlite3_free(zErrMsg);
5282 zErrMsg = 0;
5283 }
5284 if( xForEach ){
5285 xForEach(p, newDb, (const char*)zName);
5286 }
5287 printf("done\n");
5288 }
5289 }
5290end_schema_xfer:
5291 sqlite3_finalize(pQuery);
5292 sqlite3_free(zQuery);
5293}
5294
5295/*
5296** Open a new database file named "zNewDb". Try to recover as much information
5297** as possible out of the main database (which might be corrupt) and write it
5298** into zNewDb.
5299*/
5300static void tryToClone(ShellState *p, const char *zNewDb){
5301 int rc;
5302 sqlite3 *newDb = 0;
5303 if( access(zNewDb,0)==0 ){
5304 utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
5305 return;
5306 }
5307 rc = sqlite3_open(zNewDb, &newDb);
5308 if( rc ){
5309 utf8_printf(stderr, "Cannot create output database: %s\n",
5310 sqlite3_errmsg(newDb));
5311 }else{
5312 sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
5313 sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
5314 tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
5315 tryToCloneSchema(p, newDb, "type!='table'", 0);
5316 sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
5317 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
5318 }
drh9e804032018-05-18 17:11:50 +00005319 close_db(newDb);
drh2ce15c32017-07-11 13:34:40 +00005320}
5321
5322/*
drh13c20932018-01-10 21:41:55 +00005323** Change the output file back to stdout.
5324**
5325** If the p->doXdgOpen flag is set, that means the output was being
5326** redirected to a temporary file named by p->zTempFile. In that case,
5327** launch start/open/xdg-open on that temporary file.
drh2ce15c32017-07-11 13:34:40 +00005328*/
5329static void output_reset(ShellState *p){
5330 if( p->outfile[0]=='|' ){
5331#ifndef SQLITE_OMIT_POPEN
5332 pclose(p->out);
5333#endif
5334 }else{
5335 output_file_close(p->out);
drh04a28c32018-01-31 01:38:44 +00005336#ifndef SQLITE_NOHAVE_SYSTEM
drh13c20932018-01-10 21:41:55 +00005337 if( p->doXdgOpen ){
5338 const char *zXdgOpenCmd =
5339#if defined(_WIN32)
5340 "start";
5341#elif defined(__APPLE__)
5342 "open";
5343#else
5344 "xdg-open";
5345#endif
5346 char *zCmd;
5347 zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
drha92a01a2018-01-10 22:15:37 +00005348 if( system(zCmd) ){
5349 utf8_printf(stderr, "Failed: [%s]\n", zCmd);
drh1d9ea272020-04-17 23:46:54 +00005350 }else{
5351 /* Give the start/open/xdg-open command some time to get
5352 ** going before we continue, and potential delete the
5353 ** p->zTempFile data file out from under it */
5354 sqlite3_sleep(2000);
drha92a01a2018-01-10 22:15:37 +00005355 }
drh13c20932018-01-10 21:41:55 +00005356 sqlite3_free(zCmd);
drh3c484e82018-01-10 22:27:21 +00005357 outputModePop(p);
drh13c20932018-01-10 21:41:55 +00005358 p->doXdgOpen = 0;
5359 }
drh04a28c32018-01-31 01:38:44 +00005360#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
drh2ce15c32017-07-11 13:34:40 +00005361 }
5362 p->outfile[0] = 0;
5363 p->out = stdout;
5364}
5365
5366/*
5367** Run an SQL command and return the single integer result.
5368*/
5369static int db_int(ShellState *p, const char *zSql){
5370 sqlite3_stmt *pStmt;
5371 int res = 0;
5372 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
5373 if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
5374 res = sqlite3_column_int(pStmt,0);
5375 }
5376 sqlite3_finalize(pStmt);
5377 return res;
5378}
5379
5380/*
5381** Convert a 2-byte or 4-byte big-endian integer into a native integer
5382*/
5383static unsigned int get2byteInt(unsigned char *a){
5384 return (a[0]<<8) + a[1];
5385}
5386static unsigned int get4byteInt(unsigned char *a){
5387 return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
5388}
5389
5390/*
drh76c12062020-01-14 13:13:19 +00005391** Implementation of the ".dbinfo" command.
drh2ce15c32017-07-11 13:34:40 +00005392**
5393** Return 1 on error, 2 to exit, and 0 otherwise.
5394*/
5395static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
5396 static const struct { const char *zName; int ofst; } aField[] = {
5397 { "file change counter:", 24 },
5398 { "database page count:", 28 },
5399 { "freelist page count:", 36 },
5400 { "schema cookie:", 40 },
5401 { "schema format:", 44 },
5402 { "default cache size:", 48 },
5403 { "autovacuum top root:", 52 },
5404 { "incremental vacuum:", 64 },
5405 { "text encoding:", 56 },
5406 { "user version:", 60 },
5407 { "application id:", 68 },
5408 { "software version:", 96 },
5409 };
5410 static const struct { const char *zName; const char *zSql; } aQuery[] = {
5411 { "number of tables:",
5412 "SELECT count(*) FROM %s WHERE type='table'" },
5413 { "number of indexes:",
5414 "SELECT count(*) FROM %s WHERE type='index'" },
5415 { "number of triggers:",
5416 "SELECT count(*) FROM %s WHERE type='trigger'" },
5417 { "number of views:",
5418 "SELECT count(*) FROM %s WHERE type='view'" },
5419 { "schema size:",
5420 "SELECT total(length(sql)) FROM %s" },
5421 };
drh87c889c2019-03-20 18:22:51 +00005422 int i, rc;
drhea99a312018-07-18 19:09:07 +00005423 unsigned iDataVersion;
drh2ce15c32017-07-11 13:34:40 +00005424 char *zSchemaTab;
5425 char *zDb = nArg>=2 ? azArg[1] : "main";
drh512e6c32017-10-11 17:51:08 +00005426 sqlite3_stmt *pStmt = 0;
drh2ce15c32017-07-11 13:34:40 +00005427 unsigned char aHdr[100];
5428 open_db(p, 0);
5429 if( p->db==0 ) return 1;
drh87c889c2019-03-20 18:22:51 +00005430 rc = sqlite3_prepare_v2(p->db,
5431 "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
5432 -1, &pStmt, 0);
5433 if( rc ){
drh451f89a2020-04-28 23:09:56 +00005434 utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
drh87c889c2019-03-20 18:22:51 +00005435 sqlite3_finalize(pStmt);
5436 return 1;
5437 }
drh512e6c32017-10-11 17:51:08 +00005438 sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
5439 if( sqlite3_step(pStmt)==SQLITE_ROW
5440 && sqlite3_column_bytes(pStmt,0)>100
5441 ){
5442 memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
5443 sqlite3_finalize(pStmt);
5444 }else{
drh2ce15c32017-07-11 13:34:40 +00005445 raw_printf(stderr, "unable to read database header\n");
drh512e6c32017-10-11 17:51:08 +00005446 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00005447 return 1;
5448 }
5449 i = get2byteInt(aHdr+16);
5450 if( i==1 ) i = 65536;
5451 utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
5452 utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
5453 utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
5454 utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
5455 for(i=0; i<ArraySize(aField); i++){
5456 int ofst = aField[i].ofst;
5457 unsigned int val = get4byteInt(aHdr + ofst);
5458 utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
5459 switch( ofst ){
5460 case 56: {
5461 if( val==1 ) raw_printf(p->out, " (utf8)");
5462 if( val==2 ) raw_printf(p->out, " (utf16le)");
5463 if( val==3 ) raw_printf(p->out, " (utf16be)");
5464 }
5465 }
5466 raw_printf(p->out, "\n");
5467 }
5468 if( zDb==0 ){
drh067b92b2020-06-19 15:24:12 +00005469 zSchemaTab = sqlite3_mprintf("main.sqlite_schema");
drh2ce15c32017-07-11 13:34:40 +00005470 }else if( strcmp(zDb,"temp")==0 ){
drh067b92b2020-06-19 15:24:12 +00005471 zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
drh2ce15c32017-07-11 13:34:40 +00005472 }else{
drh067b92b2020-06-19 15:24:12 +00005473 zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
drh2ce15c32017-07-11 13:34:40 +00005474 }
5475 for(i=0; i<ArraySize(aQuery); i++){
5476 char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
5477 int val = db_int(p, zSql);
5478 sqlite3_free(zSql);
5479 utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
5480 }
5481 sqlite3_free(zSchemaTab);
drhea99a312018-07-18 19:09:07 +00005482 sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
5483 utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
drh2ce15c32017-07-11 13:34:40 +00005484 return 0;
5485}
5486
5487/*
5488** Print the current sqlite3_errmsg() value to stderr and return 1.
5489*/
5490static int shellDatabaseError(sqlite3 *db){
5491 const char *zErr = sqlite3_errmsg(db);
5492 utf8_printf(stderr, "Error: %s\n", zErr);
5493 return 1;
5494}
5495
5496/*
drh2ce15c32017-07-11 13:34:40 +00005497** Compare the pattern in zGlob[] against the text in z[]. Return TRUE
5498** if they match and FALSE (0) if they do not match.
5499**
5500** Globbing rules:
5501**
5502** '*' Matches any sequence of zero or more characters.
5503**
5504** '?' Matches exactly one character.
5505**
5506** [...] Matches one character from the enclosed list of
5507** characters.
5508**
5509** [^...] Matches one character not in the enclosed list.
5510**
5511** '#' Matches any sequence of one or more digits with an
5512** optional + or - sign in front
5513**
5514** ' ' Any span of whitespace matches any other span of
5515** whitespace.
5516**
5517** Extra whitespace at the end of z[] is ignored.
5518*/
5519static int testcase_glob(const char *zGlob, const char *z){
5520 int c, c2;
5521 int invert;
5522 int seen;
5523
5524 while( (c = (*(zGlob++)))!=0 ){
5525 if( IsSpace(c) ){
5526 if( !IsSpace(*z) ) return 0;
5527 while( IsSpace(*zGlob) ) zGlob++;
5528 while( IsSpace(*z) ) z++;
5529 }else if( c=='*' ){
5530 while( (c=(*(zGlob++))) == '*' || c=='?' ){
5531 if( c=='?' && (*(z++))==0 ) return 0;
5532 }
5533 if( c==0 ){
5534 return 1;
5535 }else if( c=='[' ){
5536 while( *z && testcase_glob(zGlob-1,z)==0 ){
5537 z++;
5538 }
5539 return (*z)!=0;
5540 }
5541 while( (c2 = (*(z++)))!=0 ){
5542 while( c2!=c ){
5543 c2 = *(z++);
5544 if( c2==0 ) return 0;
5545 }
5546 if( testcase_glob(zGlob,z) ) return 1;
5547 }
5548 return 0;
5549 }else if( c=='?' ){
5550 if( (*(z++))==0 ) return 0;
5551 }else if( c=='[' ){
5552 int prior_c = 0;
5553 seen = 0;
5554 invert = 0;
5555 c = *(z++);
5556 if( c==0 ) return 0;
5557 c2 = *(zGlob++);
5558 if( c2=='^' ){
5559 invert = 1;
5560 c2 = *(zGlob++);
5561 }
5562 if( c2==']' ){
5563 if( c==']' ) seen = 1;
5564 c2 = *(zGlob++);
5565 }
5566 while( c2 && c2!=']' ){
5567 if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
5568 c2 = *(zGlob++);
5569 if( c>=prior_c && c<=c2 ) seen = 1;
5570 prior_c = 0;
5571 }else{
5572 if( c==c2 ){
5573 seen = 1;
5574 }
5575 prior_c = c2;
5576 }
5577 c2 = *(zGlob++);
5578 }
5579 if( c2==0 || (seen ^ invert)==0 ) return 0;
5580 }else if( c=='#' ){
5581 if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++;
5582 if( !IsDigit(z[0]) ) return 0;
5583 z++;
5584 while( IsDigit(z[0]) ){ z++; }
5585 }else{
5586 if( c!=(*(z++)) ) return 0;
5587 }
5588 }
5589 while( IsSpace(*z) ){ z++; }
5590 return *z==0;
5591}
5592
5593
5594/*
5595** Compare the string as a command-line option with either one or two
5596** initial "-" characters.
5597*/
5598static int optionMatch(const char *zStr, const char *zOpt){
5599 if( zStr[0]!='-' ) return 0;
5600 zStr++;
5601 if( zStr[0]=='-' ) zStr++;
5602 return strcmp(zStr, zOpt)==0;
5603}
5604
5605/*
5606** Delete a file.
5607*/
5608int shellDeleteFile(const char *zFilename){
5609 int rc;
5610#ifdef _WIN32
5611 wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
5612 rc = _wunlink(z);
5613 sqlite3_free(z);
5614#else
5615 rc = unlink(zFilename);
5616#endif
5617 return rc;
5618}
5619
drh13c20932018-01-10 21:41:55 +00005620/*
5621** Try to delete the temporary file (if there is one) and free the
5622** memory used to hold the name of the temp file.
5623*/
5624static void clearTempFile(ShellState *p){
5625 if( p->zTempFile==0 ) return;
drh536c3452018-01-11 00:38:39 +00005626 if( p->doXdgOpen ) return;
drh13c20932018-01-10 21:41:55 +00005627 if( shellDeleteFile(p->zTempFile) ) return;
5628 sqlite3_free(p->zTempFile);
5629 p->zTempFile = 0;
5630}
5631
5632/*
5633** Create a new temp file name with the given suffix.
5634*/
5635static void newTempFile(ShellState *p, const char *zSuffix){
5636 clearTempFile(p);
5637 sqlite3_free(p->zTempFile);
5638 p->zTempFile = 0;
drh7f3bf8a2018-01-10 21:50:08 +00005639 if( p->db ){
5640 sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
5641 }
drh13c20932018-01-10 21:41:55 +00005642 if( p->zTempFile==0 ){
drh1d9ea272020-04-17 23:46:54 +00005643 /* If p->db is an in-memory database then the TEMPFILENAME file-control
5644 ** will not work and we will need to fallback to guessing */
5645 char *zTemp;
drh13c20932018-01-10 21:41:55 +00005646 sqlite3_uint64 r;
5647 sqlite3_randomness(sizeof(r), &r);
drh1d9ea272020-04-17 23:46:54 +00005648 zTemp = getenv("TEMP");
5649 if( zTemp==0 ) zTemp = getenv("TMP");
5650 if( zTemp==0 ){
5651#ifdef _WIN32
5652 zTemp = "\\tmp";
5653#else
5654 zTemp = "/tmp";
5655#endif
5656 }
5657 p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix);
drh13c20932018-01-10 21:41:55 +00005658 }else{
5659 p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
5660 }
5661 if( p->zTempFile==0 ){
5662 raw_printf(stderr, "out of memory\n");
5663 exit(1);
5664 }
5665}
5666
drh2ce15c32017-07-11 13:34:40 +00005667
5668/*
5669** The implementation of SQL scalar function fkey_collate_clause(), used
5670** by the ".lint fkey-indexes" command. This scalar function is always
5671** called with four arguments - the parent table name, the parent column name,
5672** the child table name and the child column name.
5673**
5674** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
5675**
5676** If either of the named tables or columns do not exist, this function
5677** returns an empty string. An empty string is also returned if both tables
5678** and columns exist but have the same default collation sequence. Or,
5679** if both exist but the default collation sequences are different, this
5680** function returns the string " COLLATE <parent-collation>", where
5681** <parent-collation> is the default collation sequence of the parent column.
5682*/
5683static void shellFkeyCollateClause(
5684 sqlite3_context *pCtx,
5685 int nVal,
5686 sqlite3_value **apVal
5687){
5688 sqlite3 *db = sqlite3_context_db_handle(pCtx);
5689 const char *zParent;
5690 const char *zParentCol;
5691 const char *zParentSeq;
5692 const char *zChild;
5693 const char *zChildCol;
5694 const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */
5695 int rc;
5696
5697 assert( nVal==4 );
5698 zParent = (const char*)sqlite3_value_text(apVal[0]);
5699 zParentCol = (const char*)sqlite3_value_text(apVal[1]);
5700 zChild = (const char*)sqlite3_value_text(apVal[2]);
5701 zChildCol = (const char*)sqlite3_value_text(apVal[3]);
5702
5703 sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
5704 rc = sqlite3_table_column_metadata(
5705 db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0
5706 );
5707 if( rc==SQLITE_OK ){
5708 rc = sqlite3_table_column_metadata(
5709 db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0
5710 );
5711 }
5712
5713 if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){
5714 char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq);
5715 sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
5716 sqlite3_free(z);
5717 }
5718}
5719
5720
5721/*
5722** The implementation of dot-command ".lint fkey-indexes".
5723*/
5724static int lintFkeyIndexes(
5725 ShellState *pState, /* Current shell tool state */
5726 char **azArg, /* Array of arguments passed to dot command */
5727 int nArg /* Number of entries in azArg[] */
5728){
5729 sqlite3 *db = pState->db; /* Database handle to query "main" db of */
5730 FILE *out = pState->out; /* Stream to write non-error output to */
5731 int bVerbose = 0; /* If -verbose is present */
5732 int bGroupByParent = 0; /* If -groupbyparent is present */
5733 int i; /* To iterate through azArg[] */
5734 const char *zIndent = ""; /* How much to indent CREATE INDEX by */
5735 int rc; /* Return code */
5736 sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */
5737
5738 /*
5739 ** This SELECT statement returns one row for each foreign key constraint
5740 ** in the schema of the main database. The column values are:
5741 **
5742 ** 0. The text of an SQL statement similar to:
5743 **
danf9679312017-12-01 18:40:18 +00005744 ** "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?"
drh2ce15c32017-07-11 13:34:40 +00005745 **
danf9679312017-12-01 18:40:18 +00005746 ** This SELECT is similar to the one that the foreign keys implementation
5747 ** needs to run internally on child tables. If there is an index that can
drh2ce15c32017-07-11 13:34:40 +00005748 ** be used to optimize this query, then it can also be used by the FK
5749 ** implementation to optimize DELETE or UPDATE statements on the parent
5750 ** table.
5751 **
5752 ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by
5753 ** the EXPLAIN QUERY PLAN command matches this pattern, then the schema
5754 ** contains an index that can be used to optimize the query.
5755 **
5756 ** 2. Human readable text that describes the child table and columns. e.g.
5757 **
5758 ** "child_table(child_key1, child_key2)"
5759 **
5760 ** 3. Human readable text that describes the parent table and columns. e.g.
5761 **
5762 ** "parent_table(parent_key1, parent_key2)"
5763 **
5764 ** 4. A full CREATE INDEX statement for an index that could be used to
5765 ** optimize DELETE or UPDATE statements on the parent table. e.g.
5766 **
5767 ** "CREATE INDEX child_table_child_key ON child_table(child_key)"
5768 **
5769 ** 5. The name of the parent table.
5770 **
5771 ** These six values are used by the C logic below to generate the report.
5772 */
5773 const char *zSql =
5774 "SELECT "
danf9679312017-12-01 18:40:18 +00005775 " 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
drh2ce15c32017-07-11 13:34:40 +00005776 " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
5777 " || fkey_collate_clause("
5778 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
5779 ", "
5780 " 'SEARCH TABLE ' || s.name || ' USING COVERING INDEX*('"
5781 " || group_concat('*=?', ' AND ') || ')'"
5782 ", "
5783 " s.name || '(' || group_concat(f.[from], ', ') || ')'"
5784 ", "
5785 " f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
5786 ", "
5787 " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
5788 " || ' ON ' || quote(s.name) || '('"
5789 " || group_concat(quote(f.[from]) ||"
5790 " fkey_collate_clause("
5791 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
5792 " || ');'"
5793 ", "
5794 " f.[table] "
drh067b92b2020-06-19 15:24:12 +00005795 "FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f "
drh2ce15c32017-07-11 13:34:40 +00005796 "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
5797 "GROUP BY s.name, f.id "
5798 "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
5799 ;
5800 const char *zGlobIPK = "SEARCH TABLE * USING INTEGER PRIMARY KEY (rowid=?)";
5801
5802 for(i=2; i<nArg; i++){
drhaf2770f2018-01-05 14:55:43 +00005803 int n = strlen30(azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00005804 if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
5805 bVerbose = 1;
5806 }
5807 else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
5808 bGroupByParent = 1;
5809 zIndent = " ";
5810 }
5811 else{
5812 raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
5813 azArg[0], azArg[1]
5814 );
5815 return SQLITE_ERROR;
5816 }
5817 }
5818
5819 /* Register the fkey_collate_clause() SQL function */
5820 rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
5821 0, shellFkeyCollateClause, 0, 0
5822 );
5823
5824
5825 if( rc==SQLITE_OK ){
5826 rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
5827 }
5828 if( rc==SQLITE_OK ){
5829 sqlite3_bind_int(pSql, 1, bGroupByParent);
5830 }
5831
5832 if( rc==SQLITE_OK ){
5833 int rc2;
5834 char *zPrev = 0;
5835 while( SQLITE_ROW==sqlite3_step(pSql) ){
5836 int res = -1;
5837 sqlite3_stmt *pExplain = 0;
5838 const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
5839 const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
5840 const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
5841 const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
5842 const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
5843 const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
5844
5845 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
5846 if( rc!=SQLITE_OK ) break;
5847 if( SQLITE_ROW==sqlite3_step(pExplain) ){
5848 const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
5849 res = (
5850 0==sqlite3_strglob(zGlob, zPlan)
5851 || 0==sqlite3_strglob(zGlobIPK, zPlan)
5852 );
5853 }
5854 rc = sqlite3_finalize(pExplain);
5855 if( rc!=SQLITE_OK ) break;
5856
5857 if( res<0 ){
5858 raw_printf(stderr, "Error: internal error");
5859 break;
5860 }else{
5861 if( bGroupByParent
5862 && (bVerbose || res==0)
5863 && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
5864 ){
5865 raw_printf(out, "-- Parent table %s\n", zParent);
5866 sqlite3_free(zPrev);
5867 zPrev = sqlite3_mprintf("%s", zParent);
5868 }
5869
5870 if( res==0 ){
5871 raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
5872 }else if( bVerbose ){
5873 raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
5874 zIndent, zFrom, zTarget
5875 );
5876 }
5877 }
5878 }
5879 sqlite3_free(zPrev);
5880
5881 if( rc!=SQLITE_OK ){
5882 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
5883 }
5884
5885 rc2 = sqlite3_finalize(pSql);
5886 if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
5887 rc = rc2;
5888 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
5889 }
5890 }else{
5891 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
5892 }
5893
5894 return rc;
5895}
5896
5897/*
5898** Implementation of ".lint" dot command.
5899*/
5900static int lintDotCommand(
5901 ShellState *pState, /* Current shell tool state */
5902 char **azArg, /* Array of arguments passed to dot command */
5903 int nArg /* Number of entries in azArg[] */
5904){
5905 int n;
drhaf2770f2018-01-05 14:55:43 +00005906 n = (nArg>=2 ? strlen30(azArg[1]) : 0);
drh2ce15c32017-07-11 13:34:40 +00005907 if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
5908 return lintFkeyIndexes(pState, azArg, nArg);
5909
5910 usage:
5911 raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
5912 raw_printf(stderr, "Where sub-commands are:\n");
5913 raw_printf(stderr, " fkey-indexes\n");
5914 return SQLITE_ERROR;
5915}
5916
dan1b162162019-04-27 20:15:15 +00005917#if !defined SQLITE_OMIT_VIRTUALTABLE
danfd0245d2017-12-07 15:44:29 +00005918static void shellPrepare(
dand4b56e52017-12-12 20:04:59 +00005919 sqlite3 *db,
danfd0245d2017-12-07 15:44:29 +00005920 int *pRc,
5921 const char *zSql,
5922 sqlite3_stmt **ppStmt
5923){
5924 *ppStmt = 0;
5925 if( *pRc==SQLITE_OK ){
dand4b56e52017-12-12 20:04:59 +00005926 int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
danfd0245d2017-12-07 15:44:29 +00005927 if( rc!=SQLITE_OK ){
5928 raw_printf(stderr, "sql error: %s (%d)\n",
dand4b56e52017-12-12 20:04:59 +00005929 sqlite3_errmsg(db), sqlite3_errcode(db)
danfd0245d2017-12-07 15:44:29 +00005930 );
5931 *pRc = rc;
5932 }
5933 }
5934}
5935
drh9546c762019-05-10 17:50:33 +00005936/*
5937** Create a prepared statement using printf-style arguments for the SQL.
5938**
5939** This routine is could be marked "static". But it is not always used,
5940** depending on compile-time options. By omitting the "static", we avoid
5941** nuisance compiler warnings about "defined but not used".
5942*/
5943void shellPreparePrintf(
dan3f67ddf2017-12-13 20:04:53 +00005944 sqlite3 *db,
5945 int *pRc,
danac15e2d2017-12-14 19:15:07 +00005946 sqlite3_stmt **ppStmt,
5947 const char *zFmt,
5948 ...
dan3f67ddf2017-12-13 20:04:53 +00005949){
danac15e2d2017-12-14 19:15:07 +00005950 *ppStmt = 0;
5951 if( *pRc==SQLITE_OK ){
5952 va_list ap;
5953 char *z;
5954 va_start(ap, zFmt);
5955 z = sqlite3_vmprintf(zFmt, ap);
drh1dbb1472018-10-11 10:37:24 +00005956 va_end(ap);
dan3f67ddf2017-12-13 20:04:53 +00005957 if( z==0 ){
5958 *pRc = SQLITE_NOMEM;
5959 }else{
5960 shellPrepare(db, pRc, z, ppStmt);
5961 sqlite3_free(z);
5962 }
dan3f67ddf2017-12-13 20:04:53 +00005963 }
5964}
5965
drh9546c762019-05-10 17:50:33 +00005966/* Finalize the prepared statement created using shellPreparePrintf().
5967**
5968** This routine is could be marked "static". But it is not always used,
5969** depending on compile-time options. By omitting the "static", we avoid
5970** nuisance compiler warnings about "defined but not used".
5971*/
5972void shellFinalize(
danfd0245d2017-12-07 15:44:29 +00005973 int *pRc,
5974 sqlite3_stmt *pStmt
5975){
dan25c12182017-12-07 21:03:33 +00005976 if( pStmt ){
5977 sqlite3 *db = sqlite3_db_handle(pStmt);
5978 int rc = sqlite3_finalize(pStmt);
5979 if( *pRc==SQLITE_OK ){
5980 if( rc!=SQLITE_OK ){
5981 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
5982 }
5983 *pRc = rc;
5984 }
5985 }
danfd0245d2017-12-07 15:44:29 +00005986}
5987
drh9546c762019-05-10 17:50:33 +00005988/* Reset the prepared statement created using shellPreparePrintf().
5989**
5990** This routine is could be marked "static". But it is not always used,
5991** depending on compile-time options. By omitting the "static", we avoid
5992** nuisance compiler warnings about "defined but not used".
5993*/
5994void shellReset(
danfd0245d2017-12-07 15:44:29 +00005995 int *pRc,
5996 sqlite3_stmt *pStmt
5997){
5998 int rc = sqlite3_reset(pStmt);
dan5a78b812017-12-27 18:54:11 +00005999 if( *pRc==SQLITE_OK ){
6000 if( rc!=SQLITE_OK ){
6001 sqlite3 *db = sqlite3_db_handle(pStmt);
6002 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
6003 }
6004 *pRc = rc;
6005 }
danfd0245d2017-12-07 15:44:29 +00006006}
dan1b162162019-04-27 20:15:15 +00006007#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
6008
6009#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drhe2754c12019-08-26 12:50:01 +00006010/******************************************************************************
dan1b162162019-04-27 20:15:15 +00006011** The ".archive" or ".ar" command.
6012*/
drhe37c0e12018-01-06 19:19:50 +00006013/*
dan88be0202017-12-09 17:58:02 +00006014** Structure representing a single ".ar" command.
6015*/
6016typedef struct ArCommand ArCommand;
6017struct ArCommand {
drhb376b3d2018-01-10 13:11:51 +00006018 u8 eCmd; /* An AR_CMD_* value */
6019 u8 bVerbose; /* True if --verbose */
drha5676c42018-01-10 15:17:34 +00006020 u8 bZip; /* True if the archive is a ZIP */
drhb376b3d2018-01-10 13:11:51 +00006021 u8 bDryRun; /* True if --dry-run */
drha5676c42018-01-10 15:17:34 +00006022 u8 bAppend; /* True if --append */
drhd0f9cdc2018-05-17 14:09:06 +00006023 u8 fromCmdLine; /* Run from -A instead of .archive */
drhb376b3d2018-01-10 13:11:51 +00006024 int nArg; /* Number of command arguments */
drha5676c42018-01-10 15:17:34 +00006025 char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
dan88be0202017-12-09 17:58:02 +00006026 const char *zFile; /* --file argument, or NULL */
6027 const char *zDir; /* --directory argument, or NULL */
dan88be0202017-12-09 17:58:02 +00006028 char **azArg; /* Array of command arguments */
drhb376b3d2018-01-10 13:11:51 +00006029 ShellState *p; /* Shell state */
6030 sqlite3 *db; /* Database containing the archive */
dan88be0202017-12-09 17:58:02 +00006031};
6032
6033/*
6034** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
6035*/
dan0d0547f2017-12-14 15:40:42 +00006036static int arUsage(FILE *f){
drh98aa2ab2018-09-26 16:53:51 +00006037 showHelp(f,"archive");
dan0d0547f2017-12-14 15:40:42 +00006038 return SQLITE_ERROR;
6039}
6040
6041/*
6042** Print an error message for the .ar command to stderr and return
6043** SQLITE_ERROR.
6044*/
drhd0f9cdc2018-05-17 14:09:06 +00006045static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
dan0d0547f2017-12-14 15:40:42 +00006046 va_list ap;
6047 char *z;
6048 va_start(ap, zFmt);
6049 z = sqlite3_vmprintf(zFmt, ap);
6050 va_end(ap);
drhd0f9cdc2018-05-17 14:09:06 +00006051 utf8_printf(stderr, "Error: %s\n", z);
6052 if( pAr->fromCmdLine ){
6053 utf8_printf(stderr, "Use \"-A\" for more help\n");
6054 }else{
6055 utf8_printf(stderr, "Use \".archive --help\" for more help\n");
6056 }
dan0d0547f2017-12-14 15:40:42 +00006057 sqlite3_free(z);
dan88be0202017-12-09 17:58:02 +00006058 return SQLITE_ERROR;
6059}
6060
6061/*
6062** Values for ArCommand.eCmd.
6063*/
dand4b56e52017-12-12 20:04:59 +00006064#define AR_CMD_CREATE 1
drhb17ea912019-03-25 14:24:19 +00006065#define AR_CMD_UPDATE 2
6066#define AR_CMD_INSERT 3
6067#define AR_CMD_EXTRACT 4
6068#define AR_CMD_LIST 5
6069#define AR_CMD_HELP 6
dand4b56e52017-12-12 20:04:59 +00006070
6071/*
6072** Other (non-command) switches.
6073*/
drhb17ea912019-03-25 14:24:19 +00006074#define AR_SWITCH_VERBOSE 7
6075#define AR_SWITCH_FILE 8
6076#define AR_SWITCH_DIRECTORY 9
6077#define AR_SWITCH_APPEND 10
6078#define AR_SWITCH_DRYRUN 11
dand4b56e52017-12-12 20:04:59 +00006079
6080static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
6081 switch( eSwitch ){
6082 case AR_CMD_CREATE:
6083 case AR_CMD_EXTRACT:
6084 case AR_CMD_LIST:
6085 case AR_CMD_UPDATE:
drhb17ea912019-03-25 14:24:19 +00006086 case AR_CMD_INSERT:
dan0d0547f2017-12-14 15:40:42 +00006087 case AR_CMD_HELP:
6088 if( pAr->eCmd ){
drhd0f9cdc2018-05-17 14:09:06 +00006089 return arErrorMsg(pAr, "multiple command options");
dan0d0547f2017-12-14 15:40:42 +00006090 }
dand4b56e52017-12-12 20:04:59 +00006091 pAr->eCmd = eSwitch;
6092 break;
6093
drhb376b3d2018-01-10 13:11:51 +00006094 case AR_SWITCH_DRYRUN:
6095 pAr->bDryRun = 1;
6096 break;
dand4b56e52017-12-12 20:04:59 +00006097 case AR_SWITCH_VERBOSE:
6098 pAr->bVerbose = 1;
6099 break;
drha5676c42018-01-10 15:17:34 +00006100 case AR_SWITCH_APPEND:
6101 pAr->bAppend = 1;
drhca7733b2018-01-10 18:09:20 +00006102 /* Fall thru into --file */
dand4b56e52017-12-12 20:04:59 +00006103 case AR_SWITCH_FILE:
6104 pAr->zFile = zArg;
6105 break;
6106 case AR_SWITCH_DIRECTORY:
6107 pAr->zDir = zArg;
6108 break;
6109 }
6110
6111 return SQLITE_OK;
6112}
dan88be0202017-12-09 17:58:02 +00006113
6114/*
6115** Parse the command line for an ".ar" command. The results are written into
6116** structure (*pAr). SQLITE_OK is returned if the command line is parsed
6117** successfully, otherwise an error message is written to stderr and
6118** SQLITE_ERROR returned.
6119*/
6120static int arParseCommand(
6121 char **azArg, /* Array of arguments passed to dot command */
6122 int nArg, /* Number of entries in azArg[] */
6123 ArCommand *pAr /* Populate this object */
6124){
dand4b56e52017-12-12 20:04:59 +00006125 struct ArSwitch {
dand4b56e52017-12-12 20:04:59 +00006126 const char *zLong;
drhb376b3d2018-01-10 13:11:51 +00006127 char cShort;
6128 u8 eSwitch;
6129 u8 bArg;
dand4b56e52017-12-12 20:04:59 +00006130 } aSwitch[] = {
drhb376b3d2018-01-10 13:11:51 +00006131 { "create", 'c', AR_CMD_CREATE, 0 },
6132 { "extract", 'x', AR_CMD_EXTRACT, 0 },
drhb17ea912019-03-25 14:24:19 +00006133 { "insert", 'i', AR_CMD_INSERT, 0 },
drhb376b3d2018-01-10 13:11:51 +00006134 { "list", 't', AR_CMD_LIST, 0 },
6135 { "update", 'u', AR_CMD_UPDATE, 0 },
6136 { "help", 'h', AR_CMD_HELP, 0 },
6137 { "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
6138 { "file", 'f', AR_SWITCH_FILE, 1 },
drhca7733b2018-01-10 18:09:20 +00006139 { "append", 'a', AR_SWITCH_APPEND, 1 },
drhb376b3d2018-01-10 13:11:51 +00006140 { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
drhb376b3d2018-01-10 13:11:51 +00006141 { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
dand4b56e52017-12-12 20:04:59 +00006142 };
6143 int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
6144 struct ArSwitch *pEnd = &aSwitch[nSwitch];
6145
dan88be0202017-12-09 17:58:02 +00006146 if( nArg<=1 ){
drh98aa2ab2018-09-26 16:53:51 +00006147 utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
dan0d0547f2017-12-14 15:40:42 +00006148 return arUsage(stderr);
dan88be0202017-12-09 17:58:02 +00006149 }else{
6150 char *z = azArg[1];
dan88be0202017-12-09 17:58:02 +00006151 if( z[0]!='-' ){
6152 /* Traditional style [tar] invocation */
6153 int i;
6154 int iArg = 2;
6155 for(i=0; z[i]; i++){
dand4b56e52017-12-12 20:04:59 +00006156 const char *zArg = 0;
6157 struct ArSwitch *pOpt;
6158 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6159 if( z[i]==pOpt->cShort ) break;
dan88be0202017-12-09 17:58:02 +00006160 }
dan0d0547f2017-12-14 15:40:42 +00006161 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006162 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006163 }
dand4b56e52017-12-12 20:04:59 +00006164 if( pOpt->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006165 if( iArg>=nArg ){
drhd0f9cdc2018-05-17 14:09:06 +00006166 return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
dan0d0547f2017-12-14 15:40:42 +00006167 }
dand4b56e52017-12-12 20:04:59 +00006168 zArg = azArg[iArg++];
6169 }
6170 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
dan88be0202017-12-09 17:58:02 +00006171 }
dan88be0202017-12-09 17:58:02 +00006172 pAr->nArg = nArg-iArg;
6173 if( pAr->nArg>0 ){
6174 pAr->azArg = &azArg[iArg];
6175 }
dand4b56e52017-12-12 20:04:59 +00006176 }else{
6177 /* Non-traditional invocation */
6178 int iArg;
6179 for(iArg=1; iArg<nArg; iArg++){
6180 int n;
6181 z = azArg[iArg];
6182 if( z[0]!='-' ){
6183 /* All remaining command line words are command arguments. */
6184 pAr->azArg = &azArg[iArg];
6185 pAr->nArg = nArg-iArg;
6186 break;
6187 }
drhaf2770f2018-01-05 14:55:43 +00006188 n = strlen30(z);
dand4b56e52017-12-12 20:04:59 +00006189
6190 if( z[1]!='-' ){
6191 int i;
6192 /* One or more short options */
6193 for(i=1; i<n; i++){
6194 const char *zArg = 0;
6195 struct ArSwitch *pOpt;
6196 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6197 if( z[i]==pOpt->cShort ) break;
6198 }
dan0d0547f2017-12-14 15:40:42 +00006199 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006200 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006201 }
dand4b56e52017-12-12 20:04:59 +00006202 if( pOpt->bArg ){
6203 if( i<(n-1) ){
6204 zArg = &z[i+1];
6205 i = n;
6206 }else{
dan0d0547f2017-12-14 15:40:42 +00006207 if( iArg>=(nArg-1) ){
drhe2754c12019-08-26 12:50:01 +00006208 return arErrorMsg(pAr, "option requires an argument: %c",
6209 z[i]);
dan0d0547f2017-12-14 15:40:42 +00006210 }
dand4b56e52017-12-12 20:04:59 +00006211 zArg = azArg[++iArg];
6212 }
6213 }
6214 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
6215 }
6216 }else if( z[2]=='\0' ){
6217 /* A -- option, indicating that all remaining command line words
6218 ** are command arguments. */
6219 pAr->azArg = &azArg[iArg+1];
6220 pAr->nArg = nArg-iArg-1;
6221 break;
6222 }else{
6223 /* A long option */
6224 const char *zArg = 0; /* Argument for option, if any */
6225 struct ArSwitch *pMatch = 0; /* Matching option */
6226 struct ArSwitch *pOpt; /* Iterator */
6227 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6228 const char *zLong = pOpt->zLong;
drhaf2770f2018-01-05 14:55:43 +00006229 if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
dand4b56e52017-12-12 20:04:59 +00006230 if( pMatch ){
drhd0f9cdc2018-05-17 14:09:06 +00006231 return arErrorMsg(pAr, "ambiguous option: %s",z);
dand4b56e52017-12-12 20:04:59 +00006232 }else{
6233 pMatch = pOpt;
6234 }
6235 }
6236 }
6237
6238 if( pMatch==0 ){
drhd0f9cdc2018-05-17 14:09:06 +00006239 return arErrorMsg(pAr, "unrecognized option: %s", z);
dand4b56e52017-12-12 20:04:59 +00006240 }
6241 if( pMatch->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006242 if( iArg>=(nArg-1) ){
drhd0f9cdc2018-05-17 14:09:06 +00006243 return arErrorMsg(pAr, "option requires an argument: %s", z);
dan0d0547f2017-12-14 15:40:42 +00006244 }
dand4b56e52017-12-12 20:04:59 +00006245 zArg = azArg[++iArg];
6246 }
6247 if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
6248 }
6249 }
dan88be0202017-12-09 17:58:02 +00006250 }
6251 }
6252
6253 return SQLITE_OK;
6254}
6255
6256/*
dan3f67ddf2017-12-13 20:04:53 +00006257** This function assumes that all arguments within the ArCommand.azArg[]
6258** array refer to archive members, as for the --extract or --list commands.
6259** It checks that each of them are present. If any specified file is not
6260** present in the archive, an error is printed to stderr and an error
6261** code returned. Otherwise, if all specified arguments are present in
6262** the archive, SQLITE_OK is returned.
6263**
6264** This function strips any trailing '/' characters from each argument.
6265** This is consistent with the way the [tar] command seems to work on
6266** Linux.
6267*/
drhb376b3d2018-01-10 13:11:51 +00006268static int arCheckEntries(ArCommand *pAr){
dan3f67ddf2017-12-13 20:04:53 +00006269 int rc = SQLITE_OK;
6270 if( pAr->nArg ){
drhb376b3d2018-01-10 13:11:51 +00006271 int i, j;
dan3f67ddf2017-12-13 20:04:53 +00006272 sqlite3_stmt *pTest = 0;
6273
drhb376b3d2018-01-10 13:11:51 +00006274 shellPreparePrintf(pAr->db, &rc, &pTest,
6275 "SELECT name FROM %s WHERE name=$name",
6276 pAr->zSrcTable
dan5a78b812017-12-27 18:54:11 +00006277 );
drhb376b3d2018-01-10 13:11:51 +00006278 j = sqlite3_bind_parameter_index(pTest, "$name");
dan3f67ddf2017-12-13 20:04:53 +00006279 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
6280 char *z = pAr->azArg[i];
drhaf2770f2018-01-05 14:55:43 +00006281 int n = strlen30(z);
dan3f67ddf2017-12-13 20:04:53 +00006282 int bOk = 0;
6283 while( n>0 && z[n-1]=='/' ) n--;
6284 z[n] = '\0';
drhb376b3d2018-01-10 13:11:51 +00006285 sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
dan3f67ddf2017-12-13 20:04:53 +00006286 if( SQLITE_ROW==sqlite3_step(pTest) ){
6287 bOk = 1;
6288 }
6289 shellReset(&rc, pTest);
6290 if( rc==SQLITE_OK && bOk==0 ){
drhb376b3d2018-01-10 13:11:51 +00006291 utf8_printf(stderr, "not found in archive: %s\n", z);
dan3f67ddf2017-12-13 20:04:53 +00006292 rc = SQLITE_ERROR;
6293 }
6294 }
6295 shellFinalize(&rc, pTest);
6296 }
dan3f67ddf2017-12-13 20:04:53 +00006297 return rc;
6298}
6299
6300/*
6301** Format a WHERE clause that can be used against the "sqlar" table to
6302** identify all archive members that match the command arguments held
6303** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
6304** The caller is responsible for eventually calling sqlite3_free() on
6305** any non-NULL (*pzWhere) value.
6306*/
6307static void arWhereClause(
6308 int *pRc,
6309 ArCommand *pAr,
danac15e2d2017-12-14 19:15:07 +00006310 char **pzWhere /* OUT: New WHERE clause */
dan3f67ddf2017-12-13 20:04:53 +00006311){
6312 char *zWhere = 0;
6313 if( *pRc==SQLITE_OK ){
danac15e2d2017-12-14 19:15:07 +00006314 if( pAr->nArg==0 ){
6315 zWhere = sqlite3_mprintf("1");
6316 }else{
6317 int i;
6318 const char *zSep = "";
6319 for(i=0; i<pAr->nArg; i++){
6320 const char *z = pAr->azArg[i];
6321 zWhere = sqlite3_mprintf(
drhb376b3d2018-01-10 13:11:51 +00006322 "%z%s name = '%q' OR substr(name,1,%d) = '%q/'",
6323 zWhere, zSep, z, strlen30(z)+1, z
6324 );
danac15e2d2017-12-14 19:15:07 +00006325 if( zWhere==0 ){
6326 *pRc = SQLITE_NOMEM;
6327 break;
6328 }
6329 zSep = " OR ";
dan3f67ddf2017-12-13 20:04:53 +00006330 }
dan3f67ddf2017-12-13 20:04:53 +00006331 }
6332 }
6333 *pzWhere = zWhere;
6334}
6335
6336/*
dan88be0202017-12-09 17:58:02 +00006337** Implementation of .ar "lisT" command.
6338*/
drhb376b3d2018-01-10 13:11:51 +00006339static int arListCommand(ArCommand *pAr){
danb5090e42017-12-27 21:13:21 +00006340 const char *zSql = "SELECT %s FROM %s WHERE %s";
danb5090e42017-12-27 21:13:21 +00006341 const char *azCols[] = {
6342 "name",
drh410cad92018-01-10 17:19:16 +00006343 "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
danb5090e42017-12-27 21:13:21 +00006344 };
dan5a78b812017-12-27 18:54:11 +00006345
dan3f67ddf2017-12-13 20:04:53 +00006346 char *zWhere = 0;
6347 sqlite3_stmt *pSql = 0;
6348 int rc;
6349
drhb376b3d2018-01-10 13:11:51 +00006350 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006351 arWhereClause(&rc, pAr, &zWhere);
6352
drhb376b3d2018-01-10 13:11:51 +00006353 shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
6354 pAr->zSrcTable, zWhere);
drhb376b3d2018-01-10 13:11:51 +00006355 if( pAr->bDryRun ){
6356 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
6357 }else{
6358 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
6359 if( pAr->bVerbose ){
drh410cad92018-01-10 17:19:16 +00006360 utf8_printf(pAr->p->out, "%s % 10d %s %s\n",
6361 sqlite3_column_text(pSql, 0),
drhb376b3d2018-01-10 13:11:51 +00006362 sqlite3_column_int(pSql, 1),
6363 sqlite3_column_text(pSql, 2),
6364 sqlite3_column_text(pSql, 3)
6365 );
6366 }else{
6367 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
6368 }
danb5090e42017-12-27 21:13:21 +00006369 }
dan3f67ddf2017-12-13 20:04:53 +00006370 }
dan5a78b812017-12-27 18:54:11 +00006371 shellFinalize(&rc, pSql);
drhd0f9cdc2018-05-17 14:09:06 +00006372 sqlite3_free(zWhere);
dan3f67ddf2017-12-13 20:04:53 +00006373 return rc;
dan88be0202017-12-09 17:58:02 +00006374}
6375
6376
danfd0245d2017-12-07 15:44:29 +00006377/*
6378** Implementation of .ar "eXtract" command.
6379*/
drhb376b3d2018-01-10 13:11:51 +00006380static int arExtractCommand(ArCommand *pAr){
dan25c12182017-12-07 21:03:33 +00006381 const char *zSql1 =
dand1b51d42017-12-16 19:11:26 +00006382 "SELECT "
drhb376b3d2018-01-10 13:11:51 +00006383 " ($dir || name),"
6384 " writefile(($dir || name), %s, mode, mtime) "
drh0cfd46a2018-06-06 01:18:01 +00006385 "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
6386 " AND name NOT GLOB '*..[/\\]*'";
dan5a78b812017-12-27 18:54:11 +00006387
6388 const char *azExtraArg[] = {
6389 "sqlar_uncompress(data, sz)",
dan7c15ac12018-01-08 19:59:59 +00006390 "data"
dan5a78b812017-12-27 18:54:11 +00006391 };
dan5a78b812017-12-27 18:54:11 +00006392
danfd0245d2017-12-07 15:44:29 +00006393 sqlite3_stmt *pSql = 0;
6394 int rc = SQLITE_OK;
dan2ad09492017-12-09 18:28:22 +00006395 char *zDir = 0;
dan3f67ddf2017-12-13 20:04:53 +00006396 char *zWhere = 0;
drhb376b3d2018-01-10 13:11:51 +00006397 int i, j;
dan2ad09492017-12-09 18:28:22 +00006398
dan3f67ddf2017-12-13 20:04:53 +00006399 /* If arguments are specified, check that they actually exist within
6400 ** the archive before proceeding. And formulate a WHERE clause to
6401 ** match them. */
drhb376b3d2018-01-10 13:11:51 +00006402 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006403 arWhereClause(&rc, pAr, &zWhere);
6404
6405 if( rc==SQLITE_OK ){
6406 if( pAr->zDir ){
6407 zDir = sqlite3_mprintf("%s/", pAr->zDir);
6408 }else{
6409 zDir = sqlite3_mprintf("");
6410 }
6411 if( zDir==0 ) rc = SQLITE_NOMEM;
dan2ad09492017-12-09 18:28:22 +00006412 }
danfd0245d2017-12-07 15:44:29 +00006413
drhb376b3d2018-01-10 13:11:51 +00006414 shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
6415 azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
dan5a78b812017-12-27 18:54:11 +00006416 );
6417
dan2ad09492017-12-09 18:28:22 +00006418 if( rc==SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00006419 j = sqlite3_bind_parameter_index(pSql, "$dir");
6420 sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
dan25c12182017-12-07 21:03:33 +00006421
danac15e2d2017-12-14 19:15:07 +00006422 /* Run the SELECT statement twice. The first time, writefile() is called
6423 ** for all archive members that should be extracted. The second time,
6424 ** only for the directories. This is because the timestamps for
6425 ** extracted directories must be reset after they are populated (as
6426 ** populating them changes the timestamp). */
6427 for(i=0; i<2; i++){
drhb376b3d2018-01-10 13:11:51 +00006428 j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
6429 sqlite3_bind_int(pSql, j, i);
6430 if( pAr->bDryRun ){
6431 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
6432 }else{
6433 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
6434 if( i==0 && pAr->bVerbose ){
6435 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
6436 }
danac15e2d2017-12-14 19:15:07 +00006437 }
6438 }
6439 shellReset(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00006440 }
danac15e2d2017-12-14 19:15:07 +00006441 shellFinalize(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00006442 }
dan25c12182017-12-07 21:03:33 +00006443
dan2ad09492017-12-09 18:28:22 +00006444 sqlite3_free(zDir);
dan3f67ddf2017-12-13 20:04:53 +00006445 sqlite3_free(zWhere);
danfd0245d2017-12-07 15:44:29 +00006446 return rc;
6447}
6448
drhb376b3d2018-01-10 13:11:51 +00006449/*
6450** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out.
6451*/
6452static int arExecSql(ArCommand *pAr, const char *zSql){
6453 int rc;
6454 if( pAr->bDryRun ){
6455 utf8_printf(pAr->p->out, "%s\n", zSql);
6456 rc = SQLITE_OK;
6457 }else{
drh410cad92018-01-10 17:19:16 +00006458 char *zErr = 0;
6459 rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
6460 if( zErr ){
6461 utf8_printf(stdout, "ERROR: %s\n", zErr);
6462 sqlite3_free(zErr);
6463 }
drhb376b3d2018-01-10 13:11:51 +00006464 }
6465 return rc;
6466}
6467
dan1ad3f612017-12-11 20:22:02 +00006468
danfd0245d2017-12-07 15:44:29 +00006469/*
drhb17ea912019-03-25 14:24:19 +00006470** Implementation of .ar "create", "insert", and "update" commands.
6471**
6472** create -> Create a new SQL archive
6473** insert -> Insert or reinsert all files listed
6474** update -> Insert files that have changed or that were not
6475** previously in the archive
danfd0245d2017-12-07 15:44:29 +00006476**
6477** Create the "sqlar" table in the database if it does not already exist.
6478** Then add each file in the azFile[] array to the archive. Directories
6479** are added recursively. If argument bVerbose is non-zero, a message is
6480** printed on stdout for each file archived.
dan06741a32017-12-13 20:17:18 +00006481**
6482** The create command is the same as update, except that it drops
drhb17ea912019-03-25 14:24:19 +00006483** any existing "sqlar" table before beginning. The "insert" command
6484** always overwrites every file named on the command-line, where as
6485** "update" only overwrites if the size or mtime or mode has changed.
danfd0245d2017-12-07 15:44:29 +00006486*/
drhb376b3d2018-01-10 13:11:51 +00006487static int arCreateOrUpdateCommand(
dan06741a32017-12-13 20:17:18 +00006488 ArCommand *pAr, /* Command arguments and options */
drhb17ea912019-03-25 14:24:19 +00006489 int bUpdate, /* true for a --create. */
6490 int bOnlyIfChanged /* Only update if file has changed */
danfd0245d2017-12-07 15:44:29 +00006491){
dand4b56e52017-12-12 20:04:59 +00006492 const char *zCreate =
drhafba1802018-01-06 15:49:57 +00006493 "CREATE TABLE IF NOT EXISTS sqlar(\n"
6494 " name TEXT PRIMARY KEY, -- name of the file\n"
6495 " mode INT, -- access permissions\n"
6496 " mtime INT, -- last modification time\n"
6497 " sz INT, -- original file size\n"
6498 " data BLOB -- compressed content\n"
6499 ")";
dand4b56e52017-12-12 20:04:59 +00006500 const char *zDrop = "DROP TABLE IF EXISTS sqlar";
drh1bf208c2018-03-09 21:54:01 +00006501 const char *zInsertFmt[2] = {
6502 "REPLACE INTO %s(name,mode,mtime,sz,data)\n"
drh634c70f2018-01-10 16:50:18 +00006503 " SELECT\n"
6504 " %s,\n"
6505 " mode,\n"
6506 " mtime,\n"
drh410cad92018-01-10 17:19:16 +00006507 " CASE substr(lsmode(mode),1,1)\n"
6508 " WHEN '-' THEN length(data)\n"
6509 " WHEN 'd' THEN 0\n"
drh634c70f2018-01-10 16:50:18 +00006510 " ELSE -1 END,\n"
drh69d2d352018-03-09 22:18:53 +00006511 " sqlar_compress(data)\n"
drhb17ea912019-03-25 14:24:19 +00006512 " FROM fsdir(%Q,%Q) AS disk\n"
6513 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
6514 ,
drh1bf208c2018-03-09 21:54:01 +00006515 "REPLACE INTO %s(name,mode,mtime,data)\n"
6516 " SELECT\n"
6517 " %s,\n"
6518 " mode,\n"
6519 " mtime,\n"
6520 " data\n"
drhb17ea912019-03-25 14:24:19 +00006521 " FROM fsdir(%Q,%Q) AS disk\n"
6522 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
drh1bf208c2018-03-09 21:54:01 +00006523 };
danfd0245d2017-12-07 15:44:29 +00006524 int i; /* For iterating through azFile[] */
6525 int rc; /* Return code */
drh1bf208c2018-03-09 21:54:01 +00006526 const char *zTab = 0; /* SQL table into which to insert */
6527 char *zSql;
6528 char zTemp[50];
drhb17ea912019-03-25 14:24:19 +00006529 char *zExists = 0;
danfd0245d2017-12-07 15:44:29 +00006530
drh1bf208c2018-03-09 21:54:01 +00006531 arExecSql(pAr, "PRAGMA page_size=512");
drhb376b3d2018-01-10 13:11:51 +00006532 rc = arExecSql(pAr, "SAVEPOINT ar;");
danfd0245d2017-12-07 15:44:29 +00006533 if( rc!=SQLITE_OK ) return rc;
drh1bf208c2018-03-09 21:54:01 +00006534 zTemp[0] = 0;
6535 if( pAr->bZip ){
6536 /* Initialize the zipfile virtual table, if necessary */
6537 if( pAr->zFile ){
6538 sqlite3_uint64 r;
6539 sqlite3_randomness(sizeof(r),&r);
6540 sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
6541 zTab = zTemp;
6542 zSql = sqlite3_mprintf(
6543 "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)",
6544 zTab, pAr->zFile
6545 );
6546 rc = arExecSql(pAr, zSql);
6547 sqlite3_free(zSql);
6548 }else{
6549 zTab = "zip";
6550 }
6551 }else{
6552 /* Initialize the table for an SQLAR */
6553 zTab = "sqlar";
6554 if( bUpdate==0 ){
6555 rc = arExecSql(pAr, zDrop);
6556 if( rc!=SQLITE_OK ) goto end_ar_transaction;
6557 }
6558 rc = arExecSql(pAr, zCreate);
dan06741a32017-12-13 20:17:18 +00006559 }
drhb17ea912019-03-25 14:24:19 +00006560 if( bOnlyIfChanged ){
6561 zExists = sqlite3_mprintf(
6562 " AND NOT EXISTS("
6563 "SELECT 1 FROM %s AS mem"
6564 " WHERE mem.name=disk.name"
6565 " AND mem.mtime=disk.mtime"
6566 " AND mem.mode=disk.mode)", zTab);
6567 }else{
6568 zExists = sqlite3_mprintf("");
6569 }
6570 if( zExists==0 ) rc = SQLITE_NOMEM;
dan88be0202017-12-09 17:58:02 +00006571 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
mistachkince2052b2018-03-23 00:31:53 +00006572 char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
drh634c70f2018-01-10 16:50:18 +00006573 pAr->bVerbose ? "shell_putsnl(name)" : "name",
drhb17ea912019-03-25 14:24:19 +00006574 pAr->azArg[i], pAr->zDir, zExists);
mistachkince2052b2018-03-23 00:31:53 +00006575 rc = arExecSql(pAr, zSql2);
6576 sqlite3_free(zSql2);
danfd0245d2017-12-07 15:44:29 +00006577 }
drh1bf208c2018-03-09 21:54:01 +00006578end_ar_transaction:
danfd0245d2017-12-07 15:44:29 +00006579 if( rc!=SQLITE_OK ){
drh2bd207f2019-01-11 17:19:59 +00006580 sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
danfd0245d2017-12-07 15:44:29 +00006581 }else{
drhb376b3d2018-01-10 13:11:51 +00006582 rc = arExecSql(pAr, "RELEASE ar;");
drh1bf208c2018-03-09 21:54:01 +00006583 if( pAr->bZip && pAr->zFile ){
6584 zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
6585 arExecSql(pAr, zSql);
6586 sqlite3_free(zSql);
6587 }
danfd0245d2017-12-07 15:44:29 +00006588 }
drhb17ea912019-03-25 14:24:19 +00006589 sqlite3_free(zExists);
danfd0245d2017-12-07 15:44:29 +00006590 return rc;
6591}
6592
6593/*
6594** Implementation of ".ar" dot command.
6595*/
6596static int arDotCommand(
drhe2754c12019-08-26 12:50:01 +00006597 ShellState *pState, /* Current shell tool state */
6598 int fromCmdLine, /* True if -A command-line option, not .ar cmd */
6599 char **azArg, /* Array of arguments passed to dot command */
6600 int nArg /* Number of entries in azArg[] */
danfd0245d2017-12-07 15:44:29 +00006601){
dan88be0202017-12-09 17:58:02 +00006602 ArCommand cmd;
6603 int rc;
drh34660642018-01-10 17:39:54 +00006604 memset(&cmd, 0, sizeof(cmd));
drhd0f9cdc2018-05-17 14:09:06 +00006605 cmd.fromCmdLine = fromCmdLine;
dan88be0202017-12-09 17:58:02 +00006606 rc = arParseCommand(azArg, nArg, &cmd);
6607 if( rc==SQLITE_OK ){
drha5676c42018-01-10 15:17:34 +00006608 int eDbType = SHELL_OPEN_UNSPEC;
drhb376b3d2018-01-10 13:11:51 +00006609 cmd.p = pState;
6610 cmd.db = pState->db;
drha5676c42018-01-10 15:17:34 +00006611 if( cmd.zFile ){
drh1bf208c2018-03-09 21:54:01 +00006612 eDbType = deduceDatabaseType(cmd.zFile, 1);
drha5676c42018-01-10 15:17:34 +00006613 }else{
6614 eDbType = pState->openMode;
6615 }
6616 if( eDbType==SHELL_OPEN_ZIPFILE ){
drh1bf208c2018-03-09 21:54:01 +00006617 if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){
6618 if( cmd.zFile==0 ){
6619 cmd.zSrcTable = sqlite3_mprintf("zip");
6620 }else{
6621 cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
6622 }
dan5a78b812017-12-27 18:54:11 +00006623 }
drha5676c42018-01-10 15:17:34 +00006624 cmd.bZip = 1;
dan5a78b812017-12-27 18:54:11 +00006625 }else if( cmd.zFile ){
dand4b56e52017-12-12 20:04:59 +00006626 int flags;
drha5676c42018-01-10 15:17:34 +00006627 if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
drhb17ea912019-03-25 14:24:19 +00006628 if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
6629 || cmd.eCmd==AR_CMD_UPDATE ){
dand4b56e52017-12-12 20:04:59 +00006630 flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
6631 }else{
6632 flags = SQLITE_OPEN_READONLY;
6633 }
drha82c95b2018-01-10 14:00:00 +00006634 cmd.db = 0;
drha5676c42018-01-10 15:17:34 +00006635 if( cmd.bDryRun ){
6636 utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
6637 eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
6638 }
6639 rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
6640 eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
dand4b56e52017-12-12 20:04:59 +00006641 if( rc!=SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00006642 utf8_printf(stderr, "cannot open file: %s (%s)\n",
6643 cmd.zFile, sqlite3_errmsg(cmd.db)
dand4b56e52017-12-12 20:04:59 +00006644 );
drha5676c42018-01-10 15:17:34 +00006645 goto end_ar_command;
dand4b56e52017-12-12 20:04:59 +00006646 }
drhb376b3d2018-01-10 13:11:51 +00006647 sqlite3_fileio_init(cmd.db, 0, 0);
drhb376b3d2018-01-10 13:11:51 +00006648 sqlite3_sqlar_init(cmd.db, 0, 0);
drh34660642018-01-10 17:39:54 +00006649 sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
6650 shellPutsFunc, 0, 0);
6651
dand4b56e52017-12-12 20:04:59 +00006652 }
drhd0f9cdc2018-05-17 14:09:06 +00006653 if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
drh634c70f2018-01-10 16:50:18 +00006654 if( cmd.eCmd!=AR_CMD_CREATE
6655 && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
6656 ){
drha5676c42018-01-10 15:17:34 +00006657 utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
6658 rc = SQLITE_ERROR;
6659 goto end_ar_command;
6660 }
6661 cmd.zSrcTable = sqlite3_mprintf("sqlar");
6662 }
dand4b56e52017-12-12 20:04:59 +00006663
dan88be0202017-12-09 17:58:02 +00006664 switch( cmd.eCmd ){
6665 case AR_CMD_CREATE:
drhb17ea912019-03-25 14:24:19 +00006666 rc = arCreateOrUpdateCommand(&cmd, 0, 0);
dan88be0202017-12-09 17:58:02 +00006667 break;
danfd0245d2017-12-07 15:44:29 +00006668
dan88be0202017-12-09 17:58:02 +00006669 case AR_CMD_EXTRACT:
drhb376b3d2018-01-10 13:11:51 +00006670 rc = arExtractCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00006671 break;
6672
6673 case AR_CMD_LIST:
drhb376b3d2018-01-10 13:11:51 +00006674 rc = arListCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00006675 break;
6676
dan0d0547f2017-12-14 15:40:42 +00006677 case AR_CMD_HELP:
6678 arUsage(pState->out);
6679 break;
6680
drhb17ea912019-03-25 14:24:19 +00006681 case AR_CMD_INSERT:
6682 rc = arCreateOrUpdateCommand(&cmd, 1, 0);
6683 break;
6684
dan88be0202017-12-09 17:58:02 +00006685 default:
6686 assert( cmd.eCmd==AR_CMD_UPDATE );
drhb17ea912019-03-25 14:24:19 +00006687 rc = arCreateOrUpdateCommand(&cmd, 1, 1);
dan88be0202017-12-09 17:58:02 +00006688 break;
danfd0245d2017-12-07 15:44:29 +00006689 }
6690 }
drha5676c42018-01-10 15:17:34 +00006691end_ar_command:
6692 if( cmd.db!=pState->db ){
drh9e804032018-05-18 17:11:50 +00006693 close_db(cmd.db);
drha5676c42018-01-10 15:17:34 +00006694 }
6695 sqlite3_free(cmd.zSrcTable);
danfd0245d2017-12-07 15:44:29 +00006696
dan88be0202017-12-09 17:58:02 +00006697 return rc;
danfd0245d2017-12-07 15:44:29 +00006698}
drhe37c0e12018-01-06 19:19:50 +00006699/* End of the ".archive" or ".ar" command logic
drhe2754c12019-08-26 12:50:01 +00006700*******************************************************************************/
drhe37c0e12018-01-06 19:19:50 +00006701#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
danfd0245d2017-12-07 15:44:29 +00006702
dan1b162162019-04-27 20:15:15 +00006703#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan42ebb012019-04-27 18:47:03 +00006704/*
6705** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
6706** Otherwise, the SQL statement or statements in zSql are executed using
6707** database connection db and the error code written to *pRc before
6708** this function returns.
6709*/
dan68cb86e2019-04-20 20:57:28 +00006710static void shellExec(sqlite3 *db, int *pRc, const char *zSql){
6711 int rc = *pRc;
6712 if( rc==SQLITE_OK ){
6713 char *zErr = 0;
6714 rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
6715 if( rc!=SQLITE_OK ){
6716 raw_printf(stderr, "SQL error: %s\n", zErr);
6717 }
6718 *pRc = rc;
6719 }
6720}
6721
dan42ebb012019-04-27 18:47:03 +00006722/*
6723** Like shellExec(), except that zFmt is a printf() style format string.
6724*/
danc0b42432019-04-26 15:14:53 +00006725static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){
6726 char *z = 0;
6727 if( *pRc==SQLITE_OK ){
6728 va_list ap;
6729 va_start(ap, zFmt);
6730 z = sqlite3_vmprintf(zFmt, ap);
6731 va_end(ap);
6732 if( z==0 ){
6733 *pRc = SQLITE_NOMEM;
6734 }else{
6735 shellExec(db, pRc, z);
6736 }
6737 sqlite3_free(z);
6738 }
6739}
6740
dan42ebb012019-04-27 18:47:03 +00006741/*
6742** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
6743** Otherwise, an attempt is made to allocate, zero and return a pointer
6744** to a buffer nByte bytes in size. If an OOM error occurs, *pRc is set
6745** to SQLITE_NOMEM and NULL returned.
6746*/
dan68cb86e2019-04-20 20:57:28 +00006747static void *shellMalloc(int *pRc, sqlite3_int64 nByte){
6748 void *pRet = 0;
6749 if( *pRc==SQLITE_OK ){
6750 pRet = sqlite3_malloc64(nByte);
6751 if( pRet==0 ){
6752 *pRc = SQLITE_NOMEM;
6753 }else{
6754 memset(pRet, 0, nByte);
6755 }
6756 }
6757 return pRet;
6758}
6759
dan42ebb012019-04-27 18:47:03 +00006760/*
6761** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
6762** Otherwise, zFmt is treated as a printf() style string. The result of
6763** formatting it along with any trailing arguments is written into a
6764** buffer obtained from sqlite3_malloc(), and pointer to which is returned.
6765** It is the responsibility of the caller to eventually free this buffer
6766** using a call to sqlite3_free().
6767**
6768** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL
6769** pointer returned.
6770*/
dan68cb86e2019-04-20 20:57:28 +00006771static char *shellMPrintf(int *pRc, const char *zFmt, ...){
6772 char *z = 0;
6773 if( *pRc==SQLITE_OK ){
6774 va_list ap;
6775 va_start(ap, zFmt);
6776 z = sqlite3_vmprintf(zFmt, ap);
6777 va_end(ap);
6778 if( z==0 ){
6779 *pRc = SQLITE_NOMEM;
6780 }
6781 }
6782 return z;
6783}
6784
dan42ebb012019-04-27 18:47:03 +00006785/*
6786** When running the ".recover" command, each output table, and the special
6787** orphaned row table if it is required, is represented by an instance
6788** of the following struct.
6789*/
dan68cb86e2019-04-20 20:57:28 +00006790typedef struct RecoverTable RecoverTable;
6791struct RecoverTable {
dan42ebb012019-04-27 18:47:03 +00006792 char *zQuoted; /* Quoted version of table name */
dan68cb86e2019-04-20 20:57:28 +00006793 int nCol; /* Number of columns in table */
6794 char **azlCol; /* Array of column lists */
dan42ebb012019-04-27 18:47:03 +00006795 int iPk; /* Index of IPK column */
dan68cb86e2019-04-20 20:57:28 +00006796};
6797
6798/*
dan42ebb012019-04-27 18:47:03 +00006799** Free a RecoverTable object allocated by recoverFindTable() or
6800** recoverOrphanTable().
dan68cb86e2019-04-20 20:57:28 +00006801*/
6802static void recoverFreeTable(RecoverTable *pTab){
6803 if( pTab ){
dan68cb86e2019-04-20 20:57:28 +00006804 sqlite3_free(pTab->zQuoted);
dan68cb86e2019-04-20 20:57:28 +00006805 if( pTab->azlCol ){
6806 int i;
dan98c5ad32019-04-26 21:11:37 +00006807 for(i=0; i<=pTab->nCol; i++){
dan68cb86e2019-04-20 20:57:28 +00006808 sqlite3_free(pTab->azlCol[i]);
6809 }
6810 sqlite3_free(pTab->azlCol);
6811 }
6812 sqlite3_free(pTab);
6813 }
6814}
6815
dan42ebb012019-04-27 18:47:03 +00006816/*
6817** This function is a no-op if (*pRc) is not SQLITE_OK when it is called.
6818** Otherwise, it allocates and returns a RecoverTable object based on the
6819** final four arguments passed to this function. It is the responsibility
6820** of the caller to eventually free the returned object using
6821** recoverFreeTable().
6822*/
6823static RecoverTable *recoverNewTable(
danb40af492019-04-22 20:52:12 +00006824 int *pRc, /* IN/OUT: Error code */
danb40af492019-04-22 20:52:12 +00006825 const char *zName, /* Name of table */
6826 const char *zSql, /* CREATE TABLE statement */
6827 int bIntkey,
6828 int nCol
6829){
6830 sqlite3 *dbtmp = 0; /* sqlite3 handle for testing CREATE TABLE */
6831 int rc = *pRc;
dan98c5ad32019-04-26 21:11:37 +00006832 RecoverTable *pTab = 0;
danb40af492019-04-22 20:52:12 +00006833
dan98c5ad32019-04-26 21:11:37 +00006834 pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable));
danb40af492019-04-22 20:52:12 +00006835 if( rc==SQLITE_OK ){
6836 int nSqlCol = 0;
6837 int bSqlIntkey = 0;
6838 sqlite3_stmt *pStmt = 0;
dan98c5ad32019-04-26 21:11:37 +00006839
danb40af492019-04-22 20:52:12 +00006840 rc = sqlite3_open("", &dbtmp);
6841 if( rc==SQLITE_OK ){
drha2de66c2019-08-06 20:26:17 +00006842 sqlite3_create_function(dbtmp, "shell_idquote", 1, SQLITE_UTF8, 0,
6843 shellIdQuote, 0, 0);
6844 }
6845 if( rc==SQLITE_OK ){
dan38f9c712019-04-23 18:03:02 +00006846 rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
6847 }
6848 if( rc==SQLITE_OK ){
danb40af492019-04-22 20:52:12 +00006849 rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0);
6850 if( rc==SQLITE_ERROR ){
6851 rc = SQLITE_OK;
6852 goto finished;
6853 }
6854 }
6855 shellPreparePrintf(dbtmp, &rc, &pStmt,
6856 "SELECT count(*) FROM pragma_table_info(%Q)", zName
6857 );
6858 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
6859 nSqlCol = sqlite3_column_int(pStmt, 0);
6860 }
6861 shellFinalize(&rc, pStmt);
6862
6863 if( rc!=SQLITE_OK || nSqlCol<nCol ){
6864 goto finished;
6865 }
6866
6867 shellPreparePrintf(dbtmp, &rc, &pStmt,
6868 "SELECT ("
6869 " SELECT substr(data,1,1)==X'0D' FROM sqlite_dbpage WHERE pgno=rootpage"
drh067b92b2020-06-19 15:24:12 +00006870 ") FROM sqlite_schema WHERE name = %Q", zName
danb40af492019-04-22 20:52:12 +00006871 );
6872 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
6873 bSqlIntkey = sqlite3_column_int(pStmt, 0);
6874 }
6875 shellFinalize(&rc, pStmt);
6876
6877 if( bIntkey==bSqlIntkey ){
dan98c5ad32019-04-26 21:11:37 +00006878 int i;
danb40af492019-04-22 20:52:12 +00006879 const char *zPk = "_rowid_";
6880 sqlite3_stmt *pPkFinder = 0;
6881
danf57bea32019-04-27 15:35:45 +00006882 /* If this is an intkey table and there is an INTEGER PRIMARY KEY,
6883 ** set zPk to the name of the PK column, and pTab->iPk to the index
6884 ** of the column, where columns are 0-numbered from left to right.
6885 ** Or, if this is a WITHOUT ROWID table or if there is no IPK column,
6886 ** leave zPk as "_rowid_" and pTab->iPk at -2. */
dan98c5ad32019-04-26 21:11:37 +00006887 pTab->iPk = -2;
6888 if( bIntkey ){
6889 shellPreparePrintf(dbtmp, &rc, &pPkFinder,
danb40af492019-04-22 20:52:12 +00006890 "SELECT cid, name FROM pragma_table_info(%Q) "
6891 " WHERE pk=1 AND type='integer' COLLATE nocase"
dan98c5ad32019-04-26 21:11:37 +00006892 " AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
6893 , zName, zName
6894 );
6895 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){
6896 pTab->iPk = sqlite3_column_int(pPkFinder, 0);
6897 zPk = (const char*)sqlite3_column_text(pPkFinder, 1);
6898 }
danb40af492019-04-22 20:52:12 +00006899 }
6900
drha2de66c2019-08-06 20:26:17 +00006901 pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName);
dan98c5ad32019-04-26 21:11:37 +00006902 pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
danb40af492019-04-22 20:52:12 +00006903 pTab->nCol = nSqlCol;
6904
dan98c5ad32019-04-26 21:11:37 +00006905 if( bIntkey ){
drha2de66c2019-08-06 20:26:17 +00006906 pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk);
danb40af492019-04-22 20:52:12 +00006907 }else{
dan98c5ad32019-04-26 21:11:37 +00006908 pTab->azlCol[0] = shellMPrintf(&rc, "");
danb40af492019-04-22 20:52:12 +00006909 }
dan98c5ad32019-04-26 21:11:37 +00006910 i = 1;
6911 shellPreparePrintf(dbtmp, &rc, &pStmt,
drha2de66c2019-08-06 20:26:17 +00006912 "SELECT %Q || group_concat(shell_idquote(name), ', ') "
danf57bea32019-04-27 15:35:45 +00006913 " FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
dan98c5ad32019-04-26 21:11:37 +00006914 "FROM pragma_table_info(%Q)",
danf57bea32019-04-27 15:35:45 +00006915 bIntkey ? ", " : "", pTab->iPk,
6916 bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ",
6917 zName
dan98c5ad32019-04-26 21:11:37 +00006918 );
6919 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
6920 const char *zText = (const char*)sqlite3_column_text(pStmt, 0);
6921 pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText);
6922 i++;
6923 }
6924 shellFinalize(&rc, pStmt);
6925
danb40af492019-04-22 20:52:12 +00006926 shellFinalize(&rc, pPkFinder);
6927 }
6928 }
6929
6930 finished:
6931 sqlite3_close(dbtmp);
6932 *pRc = rc;
dan98779652019-05-09 14:15:19 +00006933 if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){
dan98c5ad32019-04-26 21:11:37 +00006934 recoverFreeTable(pTab);
6935 pTab = 0;
6936 }
6937 return pTab;
danb40af492019-04-22 20:52:12 +00006938}
6939
dan0aa01ee2019-04-27 19:36:49 +00006940/*
6941** This function is called to search the schema recovered from the
drh067b92b2020-06-19 15:24:12 +00006942** sqlite_schema table of the (possibly) corrupt database as part
dan0aa01ee2019-04-27 19:36:49 +00006943** of a ".recover" command. Specifically, for a table with root page
6944** iRoot and at least nCol columns. Additionally, if bIntkey is 0, the
6945** table must be a WITHOUT ROWID table, or if non-zero, not one of
6946** those.
6947**
6948** If a table is found, a (RecoverTable*) object is returned. Or, if
6949** no such table is found, but bIntkey is false and iRoot is the
6950** root page of an index in the recovered schema, then (*pbNoop) is
6951** set to true and NULL returned. Or, if there is no such table or
6952** index, NULL is returned and (*pbNoop) set to 0, indicating that
6953** the caller should write data to the orphans table.
6954*/
dan42ebb012019-04-27 18:47:03 +00006955static RecoverTable *recoverFindTable(
dan0aa01ee2019-04-27 19:36:49 +00006956 ShellState *pState, /* Shell state object */
6957 int *pRc, /* IN/OUT: Error code */
6958 int iRoot, /* Root page of table */
6959 int bIntkey, /* True for an intkey table */
6960 int nCol, /* Number of columns in table */
6961 int *pbNoop /* OUT: True if iRoot is root of index */
dan68cb86e2019-04-20 20:57:28 +00006962){
danb40af492019-04-22 20:52:12 +00006963 sqlite3_stmt *pStmt = 0;
dan68cb86e2019-04-20 20:57:28 +00006964 RecoverTable *pRet = 0;
danb40af492019-04-22 20:52:12 +00006965 int bNoop = 0;
6966 const char *zSql = 0;
6967 const char *zName = 0;
dan68cb86e2019-04-20 20:57:28 +00006968
danb40af492019-04-22 20:52:12 +00006969 /* Search the recovered schema for an object with root page iRoot. */
6970 shellPreparePrintf(pState->db, pRc, &pStmt,
6971 "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot
6972 );
6973 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
6974 const char *zType = (const char*)sqlite3_column_text(pStmt, 0);
6975 if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){
6976 bNoop = 1;
6977 break;
6978 }
6979 if( sqlite3_stricmp(zType, "table")==0 ){
6980 zName = (const char*)sqlite3_column_text(pStmt, 1);
6981 zSql = (const char*)sqlite3_column_text(pStmt, 2);
dan42ebb012019-04-27 18:47:03 +00006982 pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol);
danb40af492019-04-22 20:52:12 +00006983 break;
6984 }
6985 }
dan98c5ad32019-04-26 21:11:37 +00006986
danb40af492019-04-22 20:52:12 +00006987 shellFinalize(pRc, pStmt);
dan98c5ad32019-04-26 21:11:37 +00006988 *pbNoop = bNoop;
6989 return pRet;
6990}
danb40af492019-04-22 20:52:12 +00006991
dan0aa01ee2019-04-27 19:36:49 +00006992/*
6993** Return a RecoverTable object representing the orphans table.
6994*/
dan98c5ad32019-04-26 21:11:37 +00006995static RecoverTable *recoverOrphanTable(
dan0aa01ee2019-04-27 19:36:49 +00006996 ShellState *pState, /* Shell state object */
6997 int *pRc, /* IN/OUT: Error code */
6998 const char *zLostAndFound, /* Base name for orphans table */
6999 int nCol /* Number of user data columns */
dan98c5ad32019-04-26 21:11:37 +00007000){
7001 RecoverTable *pTab = 0;
7002 if( nCol>=0 && *pRc==SQLITE_OK ){
7003 int i;
dan42ebb012019-04-27 18:47:03 +00007004
7005 /* This block determines the name of the orphan table. The prefered
7006 ** name is zLostAndFound. But if that clashes with another name
7007 ** in the recovered schema, try zLostAndFound_0, zLostAndFound_1
7008 ** and so on until a non-clashing name is found. */
7009 int iTab = 0;
7010 char *zTab = shellMPrintf(pRc, "%s", zLostAndFound);
7011 sqlite3_stmt *pTest = 0;
7012 shellPrepare(pState->db, pRc,
7013 "SELECT 1 FROM recovery.schema WHERE name=?", &pTest
dan68cb86e2019-04-20 20:57:28 +00007014 );
dan42ebb012019-04-27 18:47:03 +00007015 if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
7016 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){
7017 shellReset(pRc, pTest);
7018 sqlite3_free(zTab);
7019 zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++);
7020 sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
dan68cb86e2019-04-20 20:57:28 +00007021 }
dan42ebb012019-04-27 18:47:03 +00007022 shellFinalize(pRc, pTest);
dan68cb86e2019-04-20 20:57:28 +00007023
dan98c5ad32019-04-26 21:11:37 +00007024 pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
7025 if( pTab ){
drha2de66c2019-08-06 20:26:17 +00007026 pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab);
dan98c5ad32019-04-26 21:11:37 +00007027 pTab->nCol = nCol;
7028 pTab->iPk = -2;
7029 if( nCol>0 ){
7030 pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1));
7031 if( pTab->azlCol ){
7032 pTab->azlCol[nCol] = shellMPrintf(pRc, "");
7033 for(i=nCol-1; i>=0; i--){
7034 pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]);
7035 }
7036 }
danb40af492019-04-22 20:52:12 +00007037 }
dan68cb86e2019-04-20 20:57:28 +00007038
dan42ebb012019-04-27 18:47:03 +00007039 if( *pRc!=SQLITE_OK ){
7040 recoverFreeTable(pTab);
7041 pTab = 0;
7042 }else{
7043 raw_printf(pState->out,
7044 "CREATE TABLE %s(rootpgno INTEGER, "
7045 "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted
7046 );
7047 for(i=0; i<nCol; i++){
7048 raw_printf(pState->out, ", c%d", i);
7049 }
7050 raw_printf(pState->out, ");\n");
7051 }
dan98c5ad32019-04-26 21:11:37 +00007052 }
dan42ebb012019-04-27 18:47:03 +00007053 sqlite3_free(zTab);
dan68cb86e2019-04-20 20:57:28 +00007054 }
dan98c5ad32019-04-26 21:11:37 +00007055 return pTab;
dan68cb86e2019-04-20 20:57:28 +00007056}
7057
7058/*
7059** This function is called to recover data from the database. A script
7060** to construct a new database containing all recovered data is output
7061** on stream pState->out.
7062*/
danb9b71db2019-04-25 16:20:40 +00007063static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
dan68cb86e2019-04-20 20:57:28 +00007064 int rc = SQLITE_OK;
7065 sqlite3_stmt *pLoop = 0; /* Loop through all root pages */
danefa363b2019-04-24 20:48:55 +00007066 sqlite3_stmt *pPages = 0; /* Loop through all pages in a group */
7067 sqlite3_stmt *pCells = 0; /* Loop through all cells in a page */
danc0b42432019-04-26 15:14:53 +00007068 const char *zRecoveryDb = ""; /* Name of "recovery" database */
dan42ebb012019-04-27 18:47:03 +00007069 const char *zLostAndFound = "lost_and_found";
dan9c014f82019-04-25 19:23:15 +00007070 int i;
dan98c5ad32019-04-26 21:11:37 +00007071 int nOrphan = -1;
7072 RecoverTable *pOrphan = 0;
dan9c014f82019-04-25 19:23:15 +00007073
7074 int bFreelist = 1; /* 0 if --freelist-corrupt is specified */
dan8cce6b82019-09-14 16:44:51 +00007075 int bRowids = 1; /* 0 if --no-rowids */
dan9c014f82019-04-25 19:23:15 +00007076 for(i=1; i<nArg; i++){
7077 char *z = azArg[i];
7078 int n;
7079 if( z[0]=='-' && z[1]=='-' ) z++;
drh4245e042019-06-13 13:52:46 +00007080 n = strlen30(z);
dan9c014f82019-04-25 19:23:15 +00007081 if( n<=17 && memcmp("-freelist-corrupt", z, n)==0 ){
7082 bFreelist = 0;
dan42ebb012019-04-27 18:47:03 +00007083 }else
danc0b42432019-04-26 15:14:53 +00007084 if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
7085 i++;
7086 zRecoveryDb = azArg[i];
dan42ebb012019-04-27 18:47:03 +00007087 }else
7088 if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
7089 i++;
7090 zLostAndFound = azArg[i];
dan8cce6b82019-09-14 16:44:51 +00007091 }else
7092 if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
7093 bRowids = 0;
danc0b42432019-04-26 15:14:53 +00007094 }
dan9c014f82019-04-25 19:23:15 +00007095 else{
drhe2754c12019-08-26 12:50:01 +00007096 utf8_printf(stderr, "unexpected option: %s\n", azArg[i]);
7097 showHelp(pState->out, azArg[0]);
dan9c014f82019-04-25 19:23:15 +00007098 return 1;
7099 }
7100 }
dan68cb86e2019-04-20 20:57:28 +00007101
danc0b42432019-04-26 15:14:53 +00007102 shellExecPrintf(pState->db, &rc,
dan68cb86e2019-04-20 20:57:28 +00007103 /* Attach an in-memory database named 'recovery'. Create an indexed
7104 ** cache of the sqlite_dbptr virtual table. */
dan01c08bc2019-07-24 19:20:30 +00007105 "PRAGMA writable_schema = on;"
danc0b42432019-04-26 15:14:53 +00007106 "ATTACH %Q AS recovery;"
7107 "DROP TABLE IF EXISTS recovery.dbptr;"
7108 "DROP TABLE IF EXISTS recovery.freelist;"
7109 "DROP TABLE IF EXISTS recovery.map;"
7110 "DROP TABLE IF EXISTS recovery.schema;"
danc0b42432019-04-26 15:14:53 +00007111 "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb
dan9c014f82019-04-25 19:23:15 +00007112 );
7113
7114 if( bFreelist ){
7115 shellExec(pState->db, &rc,
7116 "WITH trunk(pgno) AS ("
7117 " SELECT shell_int32("
7118 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x "
7119 " WHERE x>0"
7120 " UNION"
7121 " SELECT shell_int32("
7122 " (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x "
7123 " FROM trunk WHERE x>0"
7124 "),"
7125 "freelist(data, n, freepgno) AS ("
danf6099e92019-05-09 16:57:39 +00007126 " SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno "
dan9c014f82019-04-25 19:23:15 +00007127 " FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno"
7128 " UNION ALL"
7129 " SELECT data, n-1, shell_int32(data, 2+n) "
7130 " FROM freelist WHERE n>=0"
7131 ")"
7132 "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;"
7133 );
7134 }
7135
dan95063c22019-07-24 08:15:09 +00007136 /* If this is an auto-vacuum database, add all pointer-map pages to
7137 ** the freelist table. Do this regardless of whether or not
7138 ** --freelist-corrupt was specified. */
7139 shellExec(pState->db, &rc,
7140 "WITH ptrmap(pgno) AS ("
7141 " SELECT 2 WHERE shell_int32("
7142 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 13"
7143 " )"
7144 " UNION ALL "
7145 " SELECT pgno+1+(SELECT page_size FROM pragma_page_size)/5 AS pp "
7146 " FROM ptrmap WHERE pp<=(SELECT page_count FROM pragma_page_count)"
7147 ")"
7148 "REPLACE INTO recovery.freelist SELECT pgno FROM ptrmap"
7149 );
7150
dan9c014f82019-04-25 19:23:15 +00007151 shellExec(pState->db, &rc,
danca424382019-04-26 15:40:27 +00007152 "CREATE TABLE recovery.dbptr("
7153 " pgno, child, PRIMARY KEY(child, pgno)"
7154 ") WITHOUT ROWID;"
7155 "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) "
7156 " SELECT * FROM sqlite_dbptr"
7157 " WHERE pgno NOT IN freelist AND child NOT IN freelist;"
7158
7159 /* Delete any pointer to page 1. This ensures that page 1 is considered
7160 ** a root page, regardless of how corrupt the db is. */
7161 "DELETE FROM recovery.dbptr WHERE child = 1;"
7162
7163 /* Delete all pointers to any pages that have more than one pointer
7164 ** to them. Such pages will be treated as root pages when recovering
7165 ** data. */
7166 "DELETE FROM recovery.dbptr WHERE child IN ("
7167 " SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1"
7168 ");"
7169
dan68cb86e2019-04-20 20:57:28 +00007170 /* Create the "map" table that will (eventually) contain instructions
7171 ** for dealing with each page in the db that contains one or more
7172 ** records. */
danb40af492019-04-22 20:52:12 +00007173 "CREATE TABLE recovery.map("
7174 "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT"
7175 ");"
dan68cb86e2019-04-20 20:57:28 +00007176
7177 /* Populate table [map]. If there are circular loops of pages in the
7178 ** database, the following adds all pages in such a loop to the map
7179 ** as individual root pages. This could be handled better. */
7180 "WITH pages(i, maxlen) AS ("
danb9b71db2019-04-25 16:20:40 +00007181 " SELECT page_count, ("
7182 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count"
dan13b87672019-05-09 11:45:21 +00007183 " ) FROM pragma_page_count WHERE page_count>0"
dan68cb86e2019-04-20 20:57:28 +00007184 " UNION ALL"
danb40af492019-04-22 20:52:12 +00007185 " SELECT i-1, ("
7186 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1"
7187 " ) FROM pages WHERE i>=2"
dan68cb86e2019-04-20 20:57:28 +00007188 ")"
danb40af492019-04-22 20:52:12 +00007189 "INSERT INTO recovery.map(pgno, maxlen, intkey, root) "
7190 " SELECT i, maxlen, NULL, ("
dan68cb86e2019-04-20 20:57:28 +00007191 " WITH p(orig, pgno, parent) AS ("
7192 " SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)"
dan39e04f82019-05-09 18:33:32 +00007193 " UNION "
dan68cb86e2019-04-20 20:57:28 +00007194 " SELECT i, p.parent, "
7195 " (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p"
7196 " )"
7197 " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
7198 ") "
dand790c9a2019-08-26 14:57:58 +00007199 "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;"
danb40af492019-04-22 20:52:12 +00007200 "UPDATE recovery.map AS o SET intkey = ("
7201 " SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
7202 ");"
dan68cb86e2019-04-20 20:57:28 +00007203
7204 /* Extract data from page 1 and any linked pages into table
drh067b92b2020-06-19 15:24:12 +00007205 ** recovery.schema. With the same schema as an sqlite_schema table. */
dan68cb86e2019-04-20 20:57:28 +00007206 "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
7207 "INSERT INTO recovery.schema SELECT "
7208 " max(CASE WHEN field=0 THEN value ELSE NULL END),"
7209 " max(CASE WHEN field=1 THEN value ELSE NULL END),"
7210 " max(CASE WHEN field=2 THEN value ELSE NULL END),"
7211 " max(CASE WHEN field=3 THEN value ELSE NULL END),"
7212 " max(CASE WHEN field=4 THEN value ELSE NULL END)"
7213 "FROM sqlite_dbdata WHERE pgno IN ("
7214 " SELECT pgno FROM recovery.map WHERE root=1"
7215 ")"
7216 "GROUP BY pgno, cell;"
dan98c5ad32019-04-26 21:11:37 +00007217 "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);"
dan68cb86e2019-04-20 20:57:28 +00007218 );
7219
danb40af492019-04-22 20:52:12 +00007220 /* Open a transaction, then print out all non-virtual, non-"sqlite_%"
7221 ** CREATE TABLE statements that extracted from the existing schema. */
7222 if( rc==SQLITE_OK ){
7223 sqlite3_stmt *pStmt = 0;
danf3210572019-08-06 18:40:36 +00007224 /* ".recover" might output content in an order which causes immediate
7225 ** foreign key constraints to be violated. So disable foreign-key
7226 ** constraint enforcement to prevent problems when running the output
7227 ** script. */
7228 raw_printf(pState->out, "PRAGMA foreign_keys=OFF;\n");
danb40af492019-04-22 20:52:12 +00007229 raw_printf(pState->out, "BEGIN;\n");
dan38f9c712019-04-23 18:03:02 +00007230 raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
7231 shellPrepare(pState->db, &rc,
danb40af492019-04-22 20:52:12 +00007232 "SELECT sql FROM recovery.schema "
dan38f9c712019-04-23 18:03:02 +00007233 "WHERE type='table' AND sql LIKE 'create table%'", &pStmt
danb40af492019-04-22 20:52:12 +00007234 );
7235 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7236 const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0);
dan38f9c712019-04-23 18:03:02 +00007237 raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n",
7238 &zCreateTable[12]
7239 );
danb40af492019-04-22 20:52:12 +00007240 }
7241 shellFinalize(&rc, pStmt);
7242 }
7243
dan98c5ad32019-04-26 21:11:37 +00007244 /* Figure out if an orphan table will be required. And if so, how many
7245 ** user columns it should contain */
7246 shellPrepare(pState->db, &rc,
dan98779652019-05-09 14:15:19 +00007247 "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1"
dan98c5ad32019-04-26 21:11:37 +00007248 , &pLoop
7249 );
7250 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
7251 nOrphan = sqlite3_column_int(pLoop, 0);
7252 }
7253 shellFinalize(&rc, pLoop);
7254 pLoop = 0;
dan98c5ad32019-04-26 21:11:37 +00007255
danefa363b2019-04-24 20:48:55 +00007256 shellPrepare(pState->db, &rc,
7257 "SELECT pgno FROM recovery.map WHERE root=?", &pPages
7258 );
dan8cce6b82019-09-14 16:44:51 +00007259
danefa363b2019-04-24 20:48:55 +00007260 shellPrepare(pState->db, &rc,
dan8cce6b82019-09-14 16:44:51 +00007261 "SELECT max(field), group_concat(shell_escape_crnl(quote"
7262 "(case when (? AND field<0) then NULL else value end)"
7263 "), ', ')"
dan9443dbc2019-07-24 20:10:27 +00007264 ", min(field) "
danefa363b2019-04-24 20:48:55 +00007265 "FROM sqlite_dbdata WHERE pgno = ? AND field != ?"
7266 "GROUP BY cell", &pCells
7267 );
7268
dan68cb86e2019-04-20 20:57:28 +00007269 /* Loop through each root page. */
danb40af492019-04-22 20:52:12 +00007270 shellPrepare(pState->db, &rc,
7271 "SELECT root, intkey, max(maxlen) FROM recovery.map"
dan38f9c712019-04-23 18:03:02 +00007272 " WHERE root>1 GROUP BY root, intkey ORDER BY root=("
7273 " SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'"
7274 ")", &pLoop
danb40af492019-04-22 20:52:12 +00007275 );
dan68cb86e2019-04-20 20:57:28 +00007276 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
7277 int iRoot = sqlite3_column_int(pLoop, 0);
danb40af492019-04-22 20:52:12 +00007278 int bIntkey = sqlite3_column_int(pLoop, 1);
7279 int nCol = sqlite3_column_int(pLoop, 2);
dan98c5ad32019-04-26 21:11:37 +00007280 int bNoop = 0;
dan68cb86e2019-04-20 20:57:28 +00007281 RecoverTable *pTab;
7282
dan9443dbc2019-07-24 20:10:27 +00007283 assert( bIntkey==0 || bIntkey==1 );
dan42ebb012019-04-27 18:47:03 +00007284 pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);
dan98c5ad32019-04-26 21:11:37 +00007285 if( bNoop || rc ) continue;
dan98779652019-05-09 14:15:19 +00007286 if( pTab==0 ){
7287 if( pOrphan==0 ){
7288 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
7289 }
7290 pTab = pOrphan;
7291 if( pTab==0 ) break;
7292 }
dan98c5ad32019-04-26 21:11:37 +00007293
drha2de66c2019-08-06 20:26:17 +00007294 if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){
dan98c5ad32019-04-26 21:11:37 +00007295 raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
7296 }
7297 sqlite3_bind_int(pPages, 1, iRoot);
dan8cce6b82019-09-14 16:44:51 +00007298 if( bRowids==0 && pTab->iPk<0 ){
7299 sqlite3_bind_int(pCells, 1, 1);
7300 }else{
7301 sqlite3_bind_int(pCells, 1, 0);
7302 }
7303 sqlite3_bind_int(pCells, 3, pTab->iPk);
dan98c5ad32019-04-26 21:11:37 +00007304
7305 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){
7306 int iPgno = sqlite3_column_int(pPages, 0);
dan8cce6b82019-09-14 16:44:51 +00007307 sqlite3_bind_int(pCells, 2, iPgno);
dan98c5ad32019-04-26 21:11:37 +00007308 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){
7309 int nField = sqlite3_column_int(pCells, 0);
dan9443dbc2019-07-24 20:10:27 +00007310 int iMin = sqlite3_column_int(pCells, 2);
dan98c5ad32019-04-26 21:11:37 +00007311 const char *zVal = (const char*)sqlite3_column_text(pCells, 1);
7312
dan9443dbc2019-07-24 20:10:27 +00007313 RecoverTable *pTab2 = pTab;
7314 if( pTab!=pOrphan && (iMin<0)!=bIntkey ){
7315 if( pOrphan==0 ){
7316 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
7317 }
7318 pTab2 = pOrphan;
7319 if( pTab2==0 ) break;
7320 }
7321
dan98c5ad32019-04-26 21:11:37 +00007322 nField = nField+1;
dan9443dbc2019-07-24 20:10:27 +00007323 if( pTab2==pOrphan ){
dan98c5ad32019-04-26 21:11:37 +00007324 raw_printf(pState->out,
7325 "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",
dan9443dbc2019-07-24 20:10:27 +00007326 pTab2->zQuoted, iRoot, iPgno, nField,
7327 iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField]
dan98c5ad32019-04-26 21:11:37 +00007328 );
7329 }else{
danefa363b2019-04-24 20:48:55 +00007330 raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n",
dan9443dbc2019-07-24 20:10:27 +00007331 pTab2->zQuoted, pTab2->azlCol[nField], zVal
danefa363b2019-04-24 20:48:55 +00007332 );
7333 }
dan68cb86e2019-04-20 20:57:28 +00007334 }
dan98c5ad32019-04-26 21:11:37 +00007335 shellReset(&rc, pCells);
dan68cb86e2019-04-20 20:57:28 +00007336 }
dan98c5ad32019-04-26 21:11:37 +00007337 shellReset(&rc, pPages);
7338 if( pTab!=pOrphan ) recoverFreeTable(pTab);
dan68cb86e2019-04-20 20:57:28 +00007339 }
7340 shellFinalize(&rc, pLoop);
danefa363b2019-04-24 20:48:55 +00007341 shellFinalize(&rc, pPages);
7342 shellFinalize(&rc, pCells);
dan98c5ad32019-04-26 21:11:37 +00007343 recoverFreeTable(pOrphan);
dan68cb86e2019-04-20 20:57:28 +00007344
dan38f9c712019-04-23 18:03:02 +00007345 /* The rest of the schema */
danb40af492019-04-22 20:52:12 +00007346 if( rc==SQLITE_OK ){
dan38f9c712019-04-23 18:03:02 +00007347 sqlite3_stmt *pStmt = 0;
7348 shellPrepare(pState->db, &rc,
7349 "SELECT sql, name FROM recovery.schema "
danb1825882019-04-23 20:48:32 +00007350 "WHERE sql NOT LIKE 'create table%'", &pStmt
dan38f9c712019-04-23 18:03:02 +00007351 );
7352 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7353 const char *zSql = (const char*)sqlite3_column_text(pStmt, 0);
7354 if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){
7355 const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
7356 char *zPrint = shellMPrintf(&rc,
drh067b92b2020-06-19 15:24:12 +00007357 "INSERT INTO sqlite_schema VALUES('table', %Q, %Q, 0, %Q)",
dan38f9c712019-04-23 18:03:02 +00007358 zName, zName, zSql
7359 );
7360 raw_printf(pState->out, "%s;\n", zPrint);
7361 sqlite3_free(zPrint);
7362 }else{
7363 raw_printf(pState->out, "%s;\n", zSql);
7364 }
7365 }
7366 shellFinalize(&rc, pStmt);
7367 }
7368
7369 if( rc==SQLITE_OK ){
7370 raw_printf(pState->out, "PRAGMA writable_schema = off;\n");
danb40af492019-04-22 20:52:12 +00007371 raw_printf(pState->out, "COMMIT;\n");
7372 }
dan68cb86e2019-04-20 20:57:28 +00007373 sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
7374 return rc;
7375}
dan1b162162019-04-27 20:15:15 +00007376#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
dan68cb86e2019-04-20 20:57:28 +00007377
drh2ce15c32017-07-11 13:34:40 +00007378
7379/*
7380** If an input line begins with "." then invoke this routine to
7381** process that line.
7382**
7383** Return 1 on error, 2 to exit, and 0 otherwise.
7384*/
7385static int do_meta_command(char *zLine, ShellState *p){
7386 int h = 1;
7387 int nArg = 0;
7388 int n, c;
7389 int rc = 0;
drh5df84282019-08-17 19:45:25 +00007390 char *azArg[52];
drh2ce15c32017-07-11 13:34:40 +00007391
dan6b046be2018-01-09 15:25:55 +00007392#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00007393 if( p->expert.pExpert ){
7394 expertFinish(p, 1, 0);
7395 }
dan6b046be2018-01-09 15:25:55 +00007396#endif
dan43efc182017-12-19 17:42:13 +00007397
drh2ce15c32017-07-11 13:34:40 +00007398 /* Parse the input line into tokens.
7399 */
drh5df84282019-08-17 19:45:25 +00007400 while( zLine[h] && nArg<ArraySize(azArg)-1 ){
drh2ce15c32017-07-11 13:34:40 +00007401 while( IsSpace(zLine[h]) ){ h++; }
7402 if( zLine[h]==0 ) break;
7403 if( zLine[h]=='\'' || zLine[h]=='"' ){
7404 int delim = zLine[h++];
7405 azArg[nArg++] = &zLine[h];
7406 while( zLine[h] && zLine[h]!=delim ){
7407 if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
7408 h++;
7409 }
7410 if( zLine[h]==delim ){
7411 zLine[h++] = 0;
7412 }
7413 if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
7414 }else{
7415 azArg[nArg++] = &zLine[h];
7416 while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
7417 if( zLine[h] ) zLine[h++] = 0;
7418 resolve_backslashes(azArg[nArg-1]);
7419 }
7420 }
drh5df84282019-08-17 19:45:25 +00007421 azArg[nArg] = 0;
drh2ce15c32017-07-11 13:34:40 +00007422
7423 /* Process the input line.
7424 */
7425 if( nArg==0 ) return 0; /* no tokens, no error */
7426 n = strlen30(azArg[0]);
7427 c = azArg[0][0];
drh13c20932018-01-10 21:41:55 +00007428 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +00007429
7430#ifndef SQLITE_OMIT_AUTHORIZATION
7431 if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
7432 if( nArg!=2 ){
7433 raw_printf(stderr, "Usage: .auth ON|OFF\n");
7434 rc = 1;
7435 goto meta_command_exit;
7436 }
7437 open_db(p, 0);
7438 if( booleanValue(azArg[1]) ){
7439 sqlite3_set_authorizer(p->db, shellAuth, p);
7440 }else{
7441 sqlite3_set_authorizer(p->db, 0, 0);
7442 }
7443 }else
7444#endif
7445
drhe37c0e12018-01-06 19:19:50 +00007446#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
7447 if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
danfd0245d2017-12-07 15:44:29 +00007448 open_db(p, 0);
drhd0f9cdc2018-05-17 14:09:06 +00007449 rc = arDotCommand(p, 0, azArg, nArg);
danfd0245d2017-12-07 15:44:29 +00007450 }else
7451#endif
7452
drh2ce15c32017-07-11 13:34:40 +00007453 if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
7454 || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
7455 ){
7456 const char *zDestFile = 0;
7457 const char *zDb = 0;
7458 sqlite3 *pDest;
7459 sqlite3_backup *pBackup;
7460 int j;
drha50bffb2018-12-08 01:09:14 +00007461 int bAsync = 0;
drh69ed38a2018-05-14 00:23:08 +00007462 const char *zVfs = 0;
drh2ce15c32017-07-11 13:34:40 +00007463 for(j=1; j<nArg; j++){
7464 const char *z = azArg[j];
7465 if( z[0]=='-' ){
drh69ed38a2018-05-14 00:23:08 +00007466 if( z[1]=='-' ) z++;
7467 if( strcmp(z, "-append")==0 ){
7468 zVfs = "apndvfs";
7469 }else
drha50bffb2018-12-08 01:09:14 +00007470 if( strcmp(z, "-async")==0 ){
7471 bAsync = 1;
7472 }else
drh2ce15c32017-07-11 13:34:40 +00007473 {
7474 utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
7475 return 1;
7476 }
7477 }else if( zDestFile==0 ){
7478 zDestFile = azArg[j];
7479 }else if( zDb==0 ){
7480 zDb = zDestFile;
7481 zDestFile = azArg[j];
7482 }else{
drha50bffb2018-12-08 01:09:14 +00007483 raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
drh2ce15c32017-07-11 13:34:40 +00007484 return 1;
7485 }
7486 }
7487 if( zDestFile==0 ){
7488 raw_printf(stderr, "missing FILENAME argument on .backup\n");
7489 return 1;
7490 }
7491 if( zDb==0 ) zDb = "main";
drh69ed38a2018-05-14 00:23:08 +00007492 rc = sqlite3_open_v2(zDestFile, &pDest,
7493 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
drh2ce15c32017-07-11 13:34:40 +00007494 if( rc!=SQLITE_OK ){
7495 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
drh9e804032018-05-18 17:11:50 +00007496 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007497 return 1;
7498 }
drha50bffb2018-12-08 01:09:14 +00007499 if( bAsync ){
7500 sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
7501 0, 0, 0);
7502 }
drh2ce15c32017-07-11 13:34:40 +00007503 open_db(p, 0);
7504 pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
7505 if( pBackup==0 ){
7506 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
drh9e804032018-05-18 17:11:50 +00007507 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007508 return 1;
7509 }
7510 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
7511 sqlite3_backup_finish(pBackup);
7512 if( rc==SQLITE_DONE ){
7513 rc = 0;
7514 }else{
7515 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
7516 rc = 1;
7517 }
drh9e804032018-05-18 17:11:50 +00007518 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007519 }else
7520
7521 if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
7522 if( nArg==2 ){
7523 bail_on_error = booleanValue(azArg[1]);
7524 }else{
7525 raw_printf(stderr, "Usage: .bail on|off\n");
7526 rc = 1;
7527 }
7528 }else
7529
7530 if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
7531 if( nArg==2 ){
7532 if( booleanValue(azArg[1]) ){
7533 setBinaryMode(p->out, 1);
7534 }else{
7535 setTextMode(p->out, 1);
7536 }
7537 }else{
7538 raw_printf(stderr, "Usage: .binary on|off\n");
7539 rc = 1;
7540 }
7541 }else
7542
7543 if( c=='c' && strcmp(azArg[0],"cd")==0 ){
7544 if( nArg==2 ){
7545#if defined(_WIN32) || defined(WIN32)
7546 wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
7547 rc = !SetCurrentDirectoryW(z);
7548 sqlite3_free(z);
7549#else
7550 rc = chdir(azArg[1]);
7551#endif
7552 if( rc ){
7553 utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
7554 rc = 1;
7555 }
7556 }else{
7557 raw_printf(stderr, "Usage: .cd DIRECTORY\n");
7558 rc = 1;
7559 }
7560 }else
7561
7562 /* The undocumented ".breakpoint" command causes a call to the no-op
7563 ** routine named test_breakpoint().
7564 */
7565 if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
7566 test_breakpoint();
7567 }else
7568
7569 if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
7570 if( nArg==2 ){
7571 setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
7572 }else{
7573 raw_printf(stderr, "Usage: .changes on|off\n");
7574 rc = 1;
7575 }
7576 }else
7577
7578 /* Cancel output redirection, if it is currently set (by .testcase)
7579 ** Then read the content of the testcase-out.txt file and compare against
7580 ** azArg[1]. If there are differences, report an error and exit.
7581 */
7582 if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
7583 char *zRes = 0;
7584 output_reset(p);
7585 if( nArg!=2 ){
7586 raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
7587 rc = 2;
7588 }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
7589 raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
7590 rc = 2;
7591 }else if( testcase_glob(azArg[1],zRes)==0 ){
7592 utf8_printf(stderr,
7593 "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
7594 p->zTestcase, azArg[1], zRes);
drhf30d3452017-10-17 13:44:46 +00007595 rc = 1;
drh2ce15c32017-07-11 13:34:40 +00007596 }else{
7597 utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
7598 p->nCheck++;
7599 }
7600 sqlite3_free(zRes);
7601 }else
7602
7603 if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
7604 if( nArg==2 ){
7605 tryToClone(p, azArg[1]);
7606 }else{
7607 raw_printf(stderr, "Usage: .clone FILENAME\n");
7608 rc = 1;
7609 }
7610 }else
7611
7612 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
drh60081a02020-08-26 19:07:18 +00007613 char **azName = 0;
7614 int nName = 0;
7615 sqlite3_stmt *pStmt;
drh60081a02020-08-26 19:07:18 +00007616 int i;
drh2ce15c32017-07-11 13:34:40 +00007617 open_db(p, 0);
drh60081a02020-08-26 19:07:18 +00007618 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
7619 if( rc ){
7620 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh2ce15c32017-07-11 13:34:40 +00007621 rc = 1;
drh60081a02020-08-26 19:07:18 +00007622 }else{
7623 while( sqlite3_step(pStmt)==SQLITE_ROW ){
7624 const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
7625 const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
7626 azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
7627 if( azName==0 ){ shell_out_of_memory(); /* Does not return */ }
7628 azName[nName*2] = strdup(zSchema);
7629 azName[nName*2+1] = strdup(zFile);
7630 nName++;
7631 }
drh2ce15c32017-07-11 13:34:40 +00007632 }
drh60081a02020-08-26 19:07:18 +00007633 sqlite3_finalize(pStmt);
7634 for(i=0; i<nName; i++){
7635 int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
7636 int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
7637 const char *z = azName[i*2+1];
7638 utf8_printf(p->out, "%s: %s %s%s\n",
7639 azName[i*2],
7640 z && z[0] ? z : "\"\"",
7641 bRdonly ? "r/o" : "r/w",
7642 eTxn==SQLITE_TXN_NONE ? "" :
7643 eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
7644 free(azName[i*2]);
7645 free(azName[i*2+1]);
7646 }
7647 sqlite3_free(azName);
drh2ce15c32017-07-11 13:34:40 +00007648 }else
7649
drh7df01192018-04-28 12:43:16 +00007650 if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
drheb7f2a02018-09-26 18:02:32 +00007651 static const struct DbConfigChoices {
7652 const char *zName;
7653 int op;
7654 } aDbConfig[] = {
drhb945bcd2019-12-31 22:52:10 +00007655 { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
7656 { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL },
7657 { "dqs_dml", SQLITE_DBCONFIG_DQS_DML },
drh0a6873b2019-06-14 21:25:25 +00007658 { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
drhb945bcd2019-12-31 22:52:10 +00007659 { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
drh0a6873b2019-06-14 21:25:25 +00007660 { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
drh11d88e62019-08-15 21:27:20 +00007661 { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
drh0a6873b2019-06-14 21:25:25 +00007662 { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
drhb945bcd2019-12-31 22:52:10 +00007663 { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
7664 { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
drh0a6873b2019-06-14 21:25:25 +00007665 { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
7666 { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
drh0a6873b2019-06-14 21:25:25 +00007667 { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
drhb945bcd2019-12-31 22:52:10 +00007668 { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
drhb77da372020-01-07 16:09:11 +00007669 { "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA },
dan07312a62019-06-21 14:05:27 +00007670 { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA },
drh7df01192018-04-28 12:43:16 +00007671 };
7672 int ii, v;
7673 open_db(p, 0);
7674 for(ii=0; ii<ArraySize(aDbConfig); ii++){
7675 if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
7676 if( nArg>=3 ){
7677 sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
7678 }
7679 sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
drhb945bcd2019-12-31 22:52:10 +00007680 utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
drh7df01192018-04-28 12:43:16 +00007681 if( nArg>1 ) break;
7682 }
7683 if( nArg>1 && ii==ArraySize(aDbConfig) ){
7684 utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
7685 utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
7686 }
7687 }else
7688
7689 if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00007690 rc = shell_dbinfo_command(p, nArg, azArg);
7691 }else
7692
dan1b162162019-04-27 20:15:15 +00007693#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00007694 if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){
7695 open_db(p, 0);
danb9b71db2019-04-25 16:20:40 +00007696 rc = recoverDatabaseCmd(p, nArg, azArg);
dan68cb86e2019-04-20 20:57:28 +00007697 }else
dan1b162162019-04-27 20:15:15 +00007698#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
dan68cb86e2019-04-20 20:57:28 +00007699
drh2ce15c32017-07-11 13:34:40 +00007700 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
drh8e9297f2020-03-25 12:50:13 +00007701 char *zLike = 0;
7702 char *zSql;
drh2ce15c32017-07-11 13:34:40 +00007703 int i;
7704 int savedShowHeader = p->showHeader;
drhf213b332018-07-05 17:35:46 +00007705 int savedShellFlags = p->shellFlgs;
drhc1962192020-10-12 16:54:28 +00007706 ShellClearFlag(p,
7707 SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
7708 |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
drh2ce15c32017-07-11 13:34:40 +00007709 for(i=1; i<nArg; i++){
7710 if( azArg[i][0]=='-' ){
7711 const char *z = azArg[i]+1;
7712 if( z[0]=='-' ) z++;
7713 if( strcmp(z,"preserve-rowids")==0 ){
7714#ifdef SQLITE_OMIT_VIRTUALTABLE
7715 raw_printf(stderr, "The --preserve-rowids option is not compatible"
7716 " with SQLITE_OMIT_VIRTUALTABLE\n");
7717 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00007718 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00007719 goto meta_command_exit;
7720#else
7721 ShellSetFlag(p, SHFLG_PreserveRowid);
7722#endif
7723 }else
7724 if( strcmp(z,"newlines")==0 ){
7725 ShellSetFlag(p, SHFLG_Newlines);
7726 }else
drhc1962192020-10-12 16:54:28 +00007727 if( strcmp(z,"data-only")==0 ){
7728 ShellSetFlag(p, SHFLG_DumpDataOnly);
7729 }else
7730 if( strcmp(z,"nosys")==0 ){
7731 ShellSetFlag(p, SHFLG_DumpNoSys);
7732 }else
drh2ce15c32017-07-11 13:34:40 +00007733 {
7734 raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
7735 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00007736 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00007737 goto meta_command_exit;
7738 }
7739 }else if( zLike ){
drhcdbb2812020-03-25 20:31:45 +00007740 zLike = sqlite3_mprintf("%z OR name LIKE %Q ESCAPE '\\'",
7741 zLike, azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00007742 }else{
drhcdbb2812020-03-25 20:31:45 +00007743 zLike = sqlite3_mprintf("name LIKE %Q ESCAPE '\\'", azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00007744 }
7745 }
dan68cb86e2019-04-20 20:57:28 +00007746
drh2ce15c32017-07-11 13:34:40 +00007747 open_db(p, 0);
dan68cb86e2019-04-20 20:57:28 +00007748
drhc1962192020-10-12 16:54:28 +00007749 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
7750 /* When playing back a "dump", the content might appear in an order
7751 ** which causes immediate foreign key constraints to be violated.
7752 ** So disable foreign-key constraint enforcement to prevent problems. */
7753 raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
7754 raw_printf(p->out, "BEGIN TRANSACTION;\n");
7755 }
drh2ce15c32017-07-11 13:34:40 +00007756 p->writableSchema = 0;
7757 p->showHeader = 0;
7758 /* Set writable_schema=ON since doing so forces SQLite to initialize
drh067b92b2020-06-19 15:24:12 +00007759 ** as much of the schema as it can even if the sqlite_schema table is
drh2ce15c32017-07-11 13:34:40 +00007760 ** corrupt. */
7761 sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
7762 p->nErr = 0;
drh8e9297f2020-03-25 12:50:13 +00007763 if( zLike==0 ) zLike = sqlite3_mprintf("true");
7764 zSql = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00007765 "SELECT name, type, sql FROM sqlite_schema "
drh8e9297f2020-03-25 12:50:13 +00007766 "WHERE (%s) AND type=='table'"
7767 " AND sql NOT NULL"
7768 " ORDER BY tbl_name='sqlite_sequence', rowid",
7769 zLike
7770 );
7771 run_schema_dump_query(p,zSql);
7772 sqlite3_free(zSql);
drhc1962192020-10-12 16:54:28 +00007773 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
7774 zSql = sqlite3_mprintf(
7775 "SELECT sql FROM sqlite_schema "
7776 "WHERE (%s) AND sql NOT NULL"
7777 " AND type IN ('index','trigger','view')",
7778 zLike
7779 );
7780 run_table_dump_query(p, zSql);
7781 sqlite3_free(zSql);
7782 }
drh8e9297f2020-03-25 12:50:13 +00007783 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00007784 if( p->writableSchema ){
7785 raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
7786 p->writableSchema = 0;
7787 }
7788 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
7789 sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
drhc1962192020-10-12 16:54:28 +00007790 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
7791 raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
7792 }
drh2ce15c32017-07-11 13:34:40 +00007793 p->showHeader = savedShowHeader;
drhf213b332018-07-05 17:35:46 +00007794 p->shellFlgs = savedShellFlags;
drh2ce15c32017-07-11 13:34:40 +00007795 }else
7796
7797 if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
7798 if( nArg==2 ){
7799 setOrClearFlag(p, SHFLG_Echo, azArg[1]);
7800 }else{
7801 raw_printf(stderr, "Usage: .echo on|off\n");
7802 rc = 1;
7803 }
7804 }else
7805
7806 if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
7807 if( nArg==2 ){
drhe2ca99c2018-05-02 00:33:43 +00007808 p->autoEQPtest = 0;
drhb4e50392019-01-26 15:40:04 +00007809 if( p->autoEQPtrace ){
7810 if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
7811 p->autoEQPtrace = 0;
7812 }
drh2ce15c32017-07-11 13:34:40 +00007813 if( strcmp(azArg[1],"full")==0 ){
drhada70452017-12-21 21:02:27 +00007814 p->autoEQP = AUTOEQP_full;
7815 }else if( strcmp(azArg[1],"trigger")==0 ){
7816 p->autoEQP = AUTOEQP_trigger;
drhb4e50392019-01-26 15:40:04 +00007817#ifdef SQLITE_DEBUG
drhe2ca99c2018-05-02 00:33:43 +00007818 }else if( strcmp(azArg[1],"test")==0 ){
7819 p->autoEQP = AUTOEQP_on;
7820 p->autoEQPtest = 1;
drhb4e50392019-01-26 15:40:04 +00007821 }else if( strcmp(azArg[1],"trace")==0 ){
7822 p->autoEQP = AUTOEQP_full;
7823 p->autoEQPtrace = 1;
7824 open_db(p, 0);
drh067b92b2020-06-19 15:24:12 +00007825 sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0);
drhb4e50392019-01-26 15:40:04 +00007826 sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
7827#endif
drh2ce15c32017-07-11 13:34:40 +00007828 }else{
mistachkinb71aa092018-01-23 00:05:18 +00007829 p->autoEQP = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00007830 }
7831 }else{
drhb4e50392019-01-26 15:40:04 +00007832 raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
drh2ce15c32017-07-11 13:34:40 +00007833 rc = 1;
7834 }
7835 }else
7836
7837 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
7838 if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
7839 rc = 2;
7840 }else
7841
7842 /* The ".explain" command is automatic now. It is largely pointless. It
7843 ** retained purely for backwards compatibility */
7844 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
7845 int val = 1;
7846 if( nArg>=2 ){
7847 if( strcmp(azArg[1],"auto")==0 ){
7848 val = 99;
7849 }else{
7850 val = booleanValue(azArg[1]);
7851 }
7852 }
7853 if( val==1 && p->mode!=MODE_Explain ){
7854 p->normalMode = p->mode;
7855 p->mode = MODE_Explain;
7856 p->autoExplain = 0;
7857 }else if( val==0 ){
7858 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
7859 p->autoExplain = 0;
7860 }else if( val==99 ){
7861 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
7862 p->autoExplain = 1;
7863 }
7864 }else
7865
dan6b046be2018-01-09 15:25:55 +00007866#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00007867 if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
7868 open_db(p, 0);
7869 expertDotCommand(p, azArg, nArg);
7870 }else
dan6b046be2018-01-09 15:25:55 +00007871#endif
dan43efc182017-12-19 17:42:13 +00007872
drhd985f722019-06-05 14:29:53 +00007873 if( c=='f' && strncmp(azArg[0], "filectrl", n)==0 ){
7874 static const struct {
7875 const char *zCtrlName; /* Name of a test-control option */
7876 int ctrlCode; /* Integer code for that option */
7877 const char *zUsage; /* Usage notes */
7878 } aCtrl[] = {
drhd985f722019-06-05 14:29:53 +00007879 { "chunk_size", SQLITE_FCNTL_CHUNK_SIZE, "SIZE" },
drh18a4bbd2020-12-17 15:17:42 +00007880 { "data_version", SQLITE_FCNTL_DATA_VERSION, "" },
drhd985f722019-06-05 14:29:53 +00007881 { "has_moved", SQLITE_FCNTL_HAS_MOVED, "" },
7882 { "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" },
drh18a4bbd2020-12-17 15:17:42 +00007883 { "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" },
7884 /* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/
7885 { "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" },
drh541ef2c2020-04-20 16:21:30 +00007886 { "reserve_bytes", SQLITE_FCNTL_RESERVE_BYTES, "[N]" },
drh18a4bbd2020-12-17 15:17:42 +00007887 { "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" },
7888 { "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" },
7889 /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/
drhd985f722019-06-05 14:29:53 +00007890 };
7891 int filectrl = -1;
7892 int iCtrl = -1;
drh4245e042019-06-13 13:52:46 +00007893 sqlite3_int64 iRes = 0; /* Integer result to display if rc2==1 */
7894 int isOk = 0; /* 0: usage 1: %lld 2: no-result */
drhd985f722019-06-05 14:29:53 +00007895 int n2, i;
7896 const char *zCmd = 0;
drh541ef2c2020-04-20 16:21:30 +00007897 const char *zSchema = 0;
drhd985f722019-06-05 14:29:53 +00007898
7899 open_db(p, 0);
7900 zCmd = nArg>=2 ? azArg[1] : "help";
7901
drh541ef2c2020-04-20 16:21:30 +00007902 if( zCmd[0]=='-'
7903 && (strcmp(zCmd,"--schema")==0 || strcmp(zCmd,"-schema")==0)
7904 && nArg>=4
7905 ){
7906 zSchema = azArg[2];
7907 for(i=3; i<nArg; i++) azArg[i-2] = azArg[i];
7908 nArg -= 2;
7909 zCmd = azArg[1];
7910 }
7911
drhd985f722019-06-05 14:29:53 +00007912 /* The argument can optionally begin with "-" or "--" */
7913 if( zCmd[0]=='-' && zCmd[1] ){
7914 zCmd++;
7915 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
7916 }
7917
7918 /* --help lists all file-controls */
7919 if( strcmp(zCmd,"help")==0 ){
7920 utf8_printf(p->out, "Available file-controls:\n");
7921 for(i=0; i<ArraySize(aCtrl); i++){
7922 utf8_printf(p->out, " .filectrl %s %s\n",
7923 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
7924 }
7925 rc = 1;
7926 goto meta_command_exit;
7927 }
7928
7929 /* convert filectrl text option to value. allow any unique prefix
7930 ** of the option name, or a numerical value. */
7931 n2 = strlen30(zCmd);
7932 for(i=0; i<ArraySize(aCtrl); i++){
7933 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
7934 if( filectrl<0 ){
7935 filectrl = aCtrl[i].ctrlCode;
7936 iCtrl = i;
7937 }else{
7938 utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n"
7939 "Use \".filectrl --help\" for help\n", zCmd);
7940 rc = 1;
7941 goto meta_command_exit;
7942 }
7943 }
7944 }
7945 if( filectrl<0 ){
7946 utf8_printf(stderr,"Error: unknown file-control: %s\n"
7947 "Use \".filectrl --help\" for help\n", zCmd);
7948 }else{
7949 switch(filectrl){
7950 case SQLITE_FCNTL_SIZE_LIMIT: {
7951 if( nArg!=2 && nArg!=3 ) break;
7952 iRes = nArg==3 ? integerValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00007953 sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
drhd985f722019-06-05 14:29:53 +00007954 isOk = 1;
7955 break;
7956 }
7957 case SQLITE_FCNTL_LOCK_TIMEOUT:
7958 case SQLITE_FCNTL_CHUNK_SIZE: {
7959 int x;
7960 if( nArg!=3 ) break;
7961 x = (int)integerValue(azArg[2]);
drh541ef2c2020-04-20 16:21:30 +00007962 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00007963 isOk = 2;
7964 break;
7965 }
7966 case SQLITE_FCNTL_PERSIST_WAL:
7967 case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
7968 int x;
7969 if( nArg!=2 && nArg!=3 ) break;
7970 x = nArg==3 ? booleanValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00007971 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00007972 iRes = x;
7973 isOk = 1;
7974 break;
7975 }
drh18a4bbd2020-12-17 15:17:42 +00007976 case SQLITE_FCNTL_DATA_VERSION:
drhd985f722019-06-05 14:29:53 +00007977 case SQLITE_FCNTL_HAS_MOVED: {
7978 int x;
7979 if( nArg!=2 ) break;
drh541ef2c2020-04-20 16:21:30 +00007980 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00007981 iRes = x;
7982 isOk = 1;
7983 break;
7984 }
7985 case SQLITE_FCNTL_TEMPFILENAME: {
7986 char *z = 0;
7987 if( nArg!=2 ) break;
drh541ef2c2020-04-20 16:21:30 +00007988 sqlite3_file_control(p->db, zSchema, filectrl, &z);
drhd985f722019-06-05 14:29:53 +00007989 if( z ){
7990 utf8_printf(p->out, "%s\n", z);
7991 sqlite3_free(z);
7992 }
7993 isOk = 2;
7994 break;
7995 }
drh541ef2c2020-04-20 16:21:30 +00007996 case SQLITE_FCNTL_RESERVE_BYTES: {
7997 int x;
7998 if( nArg>=3 ){
7999 x = atoi(azArg[2]);
8000 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8001 }
8002 x = -1;
8003 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8004 utf8_printf(p->out,"%d\n", x);
8005 isOk = 2;
8006 break;
8007 }
drhd985f722019-06-05 14:29:53 +00008008 }
8009 }
8010 if( isOk==0 && iCtrl>=0 ){
8011 utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
8012 rc = 1;
8013 }else if( isOk==1 ){
drhe2500762019-06-13 14:07:41 +00008014 char zBuf[100];
8015 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
8016 raw_printf(p->out, "%s\n", zBuf);
drhd985f722019-06-05 14:29:53 +00008017 }
8018 }else
8019
drh2ce15c32017-07-11 13:34:40 +00008020 if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
8021 ShellState data;
8022 char *zErrMsg = 0;
8023 int doStats = 0;
8024 memcpy(&data, p, sizeof(data));
8025 data.showHeader = 0;
8026 data.cMode = data.mode = MODE_Semi;
8027 if( nArg==2 && optionMatch(azArg[1], "indent") ){
8028 data.cMode = data.mode = MODE_Pretty;
8029 nArg = 1;
8030 }
8031 if( nArg!=1 ){
8032 raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
8033 rc = 1;
8034 goto meta_command_exit;
8035 }
8036 open_db(p, 0);
8037 rc = sqlite3_exec(p->db,
8038 "SELECT sql FROM"
8039 " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
drh067b92b2020-06-19 15:24:12 +00008040 " FROM sqlite_schema UNION ALL"
8041 " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
drh2ce15c32017-07-11 13:34:40 +00008042 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
8043 "ORDER BY rowid",
8044 callback, &data, &zErrMsg
8045 );
8046 if( rc==SQLITE_OK ){
8047 sqlite3_stmt *pStmt;
8048 rc = sqlite3_prepare_v2(p->db,
drh067b92b2020-06-19 15:24:12 +00008049 "SELECT rowid FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00008050 " WHERE name GLOB 'sqlite_stat[134]'",
8051 -1, &pStmt, 0);
8052 doStats = sqlite3_step(pStmt)==SQLITE_ROW;
8053 sqlite3_finalize(pStmt);
8054 }
8055 if( doStats==0 ){
8056 raw_printf(p->out, "/* No STAT tables available */\n");
8057 }else{
drh067b92b2020-06-19 15:24:12 +00008058 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
8059 sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_schema'",
drh2ce15c32017-07-11 13:34:40 +00008060 callback, &data, &zErrMsg);
8061 data.cMode = data.mode = MODE_Insert;
8062 data.zDestTable = "sqlite_stat1";
drh4c540452018-05-08 23:17:36 +00008063 shell_exec(&data, "SELECT * FROM sqlite_stat1", &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +00008064 data.zDestTable = "sqlite_stat4";
drh4c540452018-05-08 23:17:36 +00008065 shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg);
drh067b92b2020-06-19 15:24:12 +00008066 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00008067 }
8068 }else
8069
8070 if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
8071 if( nArg==2 ){
8072 p->showHeader = booleanValue(azArg[1]);
drhc0605082020-06-05 00:54:27 +00008073 p->shellFlgs |= SHFLG_HeaderSet;
drh2ce15c32017-07-11 13:34:40 +00008074 }else{
8075 raw_printf(stderr, "Usage: .headers on|off\n");
8076 rc = 1;
8077 }
8078 }else
8079
8080 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
drh98aa2ab2018-09-26 16:53:51 +00008081 if( nArg>=2 ){
drhe93f8262018-10-11 16:53:37 +00008082 n = showHelp(p->out, azArg[1]);
drh98aa2ab2018-09-26 16:53:51 +00008083 if( n==0 ){
8084 utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
8085 }
8086 }else{
8087 showHelp(p->out, 0);
8088 }
drh2ce15c32017-07-11 13:34:40 +00008089 }else
8090
8091 if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
drhccb37812020-03-09 15:39:39 +00008092 char *zTable = 0; /* Insert data into this table */
8093 char *zFile = 0; /* Name of file to extra content from */
drh2ce15c32017-07-11 13:34:40 +00008094 sqlite3_stmt *pStmt = NULL; /* A statement */
8095 int nCol; /* Number of columns in the table */
8096 int nByte; /* Number of bytes in an SQL string */
8097 int i, j; /* Loop counters */
8098 int needCommit; /* True to COMMIT or ROLLBACK at end */
8099 int nSep; /* Number of bytes in p->colSeparator[] */
8100 char *zSql; /* An SQL statement */
8101 ImportCtx sCtx; /* Reader context */
8102 char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
drhccb37812020-03-09 15:39:39 +00008103 int eVerbose = 0; /* Larger for more console output */
8104 int nSkip = 0; /* Initial lines to skip */
8105 int useOutputMode = 1; /* Use output mode to determine separators */
drh2ce15c32017-07-11 13:34:40 +00008106
drhccb37812020-03-09 15:39:39 +00008107 memset(&sCtx, 0, sizeof(sCtx));
8108 if( p->mode==MODE_Ascii ){
8109 xRead = ascii_read_one_field;
8110 }else{
8111 xRead = csv_read_one_field;
8112 }
8113 for(i=1; i<nArg; i++){
8114 char *z = azArg[i];
8115 if( z[0]=='-' && z[1]=='-' ) z++;
8116 if( z[0]!='-' ){
8117 if( zFile==0 ){
8118 zFile = z;
8119 }else if( zTable==0 ){
8120 zTable = z;
8121 }else{
8122 utf8_printf(p->out, "ERROR: extra argument: \"%s\". Usage:\n", z);
8123 showHelp(p->out, "import");
8124 rc = 1;
8125 goto meta_command_exit;
8126 }
8127 }else if( strcmp(z,"-v")==0 ){
8128 eVerbose++;
8129 }else if( strcmp(z,"-skip")==0 && i<nArg-1 ){
8130 nSkip = integerValue(azArg[++i]);
8131 }else if( strcmp(z,"-ascii")==0 ){
8132 sCtx.cColSep = SEP_Unit[0];
8133 sCtx.cRowSep = SEP_Record[0];
8134 xRead = ascii_read_one_field;
8135 useOutputMode = 0;
8136 }else if( strcmp(z,"-csv")==0 ){
8137 sCtx.cColSep = ',';
8138 sCtx.cRowSep = '\n';
8139 xRead = csv_read_one_field;
8140 useOutputMode = 0;
8141 }else{
8142 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", z);
8143 showHelp(p->out, "import");
8144 rc = 1;
8145 goto meta_command_exit;
8146 }
8147 }
8148 if( zTable==0 ){
8149 utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
8150 zFile==0 ? "FILE" : "TABLE");
8151 showHelp(p->out, "import");
8152 rc = 1;
drh2ce15c32017-07-11 13:34:40 +00008153 goto meta_command_exit;
8154 }
drh2ce15c32017-07-11 13:34:40 +00008155 seenInterrupt = 0;
drh2ce15c32017-07-11 13:34:40 +00008156 open_db(p, 0);
drhccb37812020-03-09 15:39:39 +00008157 if( useOutputMode ){
8158 /* If neither the --csv or --ascii options are specified, then set
8159 ** the column and row separator characters from the output mode. */
8160 nSep = strlen30(p->colSeparator);
8161 if( nSep==0 ){
8162 raw_printf(stderr,
8163 "Error: non-null column separator required for import\n");
8164 rc = 1;
8165 goto meta_command_exit;
8166 }
8167 if( nSep>1 ){
8168 raw_printf(stderr,
8169 "Error: multi-character column separators not allowed"
8170 " for import\n");
8171 rc = 1;
8172 goto meta_command_exit;
8173 }
drh2ce15c32017-07-11 13:34:40 +00008174 nSep = strlen30(p->rowSeparator);
drhccb37812020-03-09 15:39:39 +00008175 if( nSep==0 ){
8176 raw_printf(stderr,
8177 "Error: non-null row separator required for import\n");
8178 rc = 1;
8179 goto meta_command_exit;
8180 }
8181 if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator,SEP_CrLf)==0 ){
8182 /* When importing CSV (only), if the row separator is set to the
8183 ** default output row separator, change it to the default input
8184 ** row separator. This avoids having to maintain different input
8185 ** and output row separators. */
8186 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8187 nSep = strlen30(p->rowSeparator);
8188 }
8189 if( nSep>1 ){
8190 raw_printf(stderr, "Error: multi-character row separators not allowed"
8191 " for import\n");
8192 rc = 1;
8193 goto meta_command_exit;
8194 }
8195 sCtx.cColSep = p->colSeparator[0];
8196 sCtx.cRowSep = p->rowSeparator[0];
drh2ce15c32017-07-11 13:34:40 +00008197 }
8198 sCtx.zFile = zFile;
8199 sCtx.nLine = 1;
8200 if( sCtx.zFile[0]=='|' ){
8201#ifdef SQLITE_OMIT_POPEN
8202 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
drhccb37812020-03-09 15:39:39 +00008203 rc = 1;
8204 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008205#else
8206 sCtx.in = popen(sCtx.zFile+1, "r");
8207 sCtx.zFile = "<pipe>";
drh97767842020-05-29 19:39:35 +00008208 sCtx.xCloser = pclose;
drh2ce15c32017-07-11 13:34:40 +00008209#endif
8210 }else{
8211 sCtx.in = fopen(sCtx.zFile, "rb");
drh97767842020-05-29 19:39:35 +00008212 sCtx.xCloser = fclose;
drh2ce15c32017-07-11 13:34:40 +00008213 }
drh2ce15c32017-07-11 13:34:40 +00008214 if( sCtx.in==0 ){
8215 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
drhccb37812020-03-09 15:39:39 +00008216 rc = 1;
8217 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008218 }
drhccb37812020-03-09 15:39:39 +00008219 if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
8220 char zSep[2];
8221 zSep[1] = 0;
8222 zSep[0] = sCtx.cColSep;
8223 utf8_printf(p->out, "Column separator ");
8224 output_c_string(p->out, zSep);
8225 utf8_printf(p->out, ", row separator ");
8226 zSep[0] = sCtx.cRowSep;
8227 output_c_string(p->out, zSep);
8228 utf8_printf(p->out, "\n");
8229 }
8230 while( (nSkip--)>0 ){
8231 while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
drhccb37812020-03-09 15:39:39 +00008232 }
drhc6712642020-10-12 17:57:29 +00008233 zSql = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
drh2ce15c32017-07-11 13:34:40 +00008234 if( zSql==0 ){
drh97767842020-05-29 19:39:35 +00008235 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00008236 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00008237 }
8238 nByte = strlen30(zSql);
8239 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8240 import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
8241 if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
drhc6712642020-10-12 17:57:29 +00008242 char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"", zTable);
drh2ce15c32017-07-11 13:34:40 +00008243 char cSep = '(';
8244 while( xRead(&sCtx) ){
8245 zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z);
8246 cSep = ',';
8247 if( sCtx.cTerm!=sCtx.cColSep ) break;
8248 }
8249 if( cSep=='(' ){
8250 sqlite3_free(zCreate);
drh97767842020-05-29 19:39:35 +00008251 import_cleanup(&sCtx);
drh2ce15c32017-07-11 13:34:40 +00008252 utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
drhccb37812020-03-09 15:39:39 +00008253 rc = 1;
8254 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008255 }
8256 zCreate = sqlite3_mprintf("%z\n)", zCreate);
drhccb37812020-03-09 15:39:39 +00008257 if( eVerbose>=1 ){
8258 utf8_printf(p->out, "%s\n", zCreate);
8259 }
drh2ce15c32017-07-11 13:34:40 +00008260 rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
8261 sqlite3_free(zCreate);
8262 if( rc ){
drhc6712642020-10-12 17:57:29 +00008263 utf8_printf(stderr, "CREATE TABLE \"%s\"(...) failed: %s\n", zTable,
drh2ce15c32017-07-11 13:34:40 +00008264 sqlite3_errmsg(p->db));
drh97767842020-05-29 19:39:35 +00008265 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008266 rc = 1;
8267 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008268 }
8269 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8270 }
8271 sqlite3_free(zSql);
8272 if( rc ){
8273 if (pStmt) sqlite3_finalize(pStmt);
8274 utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
drh97767842020-05-29 19:39:35 +00008275 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008276 rc = 1;
8277 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008278 }
8279 nCol = sqlite3_column_count(pStmt);
8280 sqlite3_finalize(pStmt);
8281 pStmt = 0;
8282 if( nCol==0 ) return 0; /* no columns, no error */
8283 zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
8284 if( zSql==0 ){
drh97767842020-05-29 19:39:35 +00008285 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00008286 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00008287 }
8288 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
8289 j = strlen30(zSql);
8290 for(i=1; i<nCol; i++){
8291 zSql[j++] = ',';
8292 zSql[j++] = '?';
8293 }
8294 zSql[j++] = ')';
8295 zSql[j] = 0;
drhccb37812020-03-09 15:39:39 +00008296 if( eVerbose>=2 ){
8297 utf8_printf(p->out, "Insert using: %s\n", zSql);
8298 }
drh2ce15c32017-07-11 13:34:40 +00008299 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8300 sqlite3_free(zSql);
8301 if( rc ){
8302 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
8303 if (pStmt) sqlite3_finalize(pStmt);
drh97767842020-05-29 19:39:35 +00008304 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008305 rc = 1;
8306 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008307 }
8308 needCommit = sqlite3_get_autocommit(p->db);
8309 if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
8310 do{
8311 int startLine = sCtx.nLine;
8312 for(i=0; i<nCol; i++){
8313 char *z = xRead(&sCtx);
8314 /*
8315 ** Did we reach end-of-file before finding any columns?
8316 ** If so, stop instead of NULL filling the remaining columns.
8317 */
8318 if( z==0 && i==0 ) break;
8319 /*
8320 ** Did we reach end-of-file OR end-of-line before finding any
8321 ** columns in ASCII mode? If so, stop instead of NULL filling
8322 ** the remaining columns.
8323 */
8324 if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
8325 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
8326 if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
8327 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
8328 "filling the rest with NULL\n",
8329 sCtx.zFile, startLine, nCol, i+1);
8330 i += 2;
8331 while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
8332 }
8333 }
8334 if( sCtx.cTerm==sCtx.cColSep ){
8335 do{
8336 xRead(&sCtx);
8337 i++;
8338 }while( sCtx.cTerm==sCtx.cColSep );
8339 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
8340 "extras ignored\n",
8341 sCtx.zFile, startLine, nCol, i);
8342 }
8343 if( i>=nCol ){
8344 sqlite3_step(pStmt);
8345 rc = sqlite3_reset(pStmt);
8346 if( rc!=SQLITE_OK ){
8347 utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
8348 startLine, sqlite3_errmsg(p->db));
drhccb37812020-03-09 15:39:39 +00008349 sCtx.nErr++;
8350 }else{
8351 sCtx.nRow++;
drh2ce15c32017-07-11 13:34:40 +00008352 }
8353 }
8354 }while( sCtx.cTerm!=EOF );
8355
drh97767842020-05-29 19:39:35 +00008356 import_cleanup(&sCtx);
drh2ce15c32017-07-11 13:34:40 +00008357 sqlite3_finalize(pStmt);
8358 if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
drhccb37812020-03-09 15:39:39 +00008359 if( eVerbose>0 ){
8360 utf8_printf(p->out,
8361 "Added %d rows with %d errors using %d lines of input\n",
8362 sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
8363 }
drh2ce15c32017-07-11 13:34:40 +00008364 }else
8365
8366#ifndef SQLITE_UNTESTABLE
8367 if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
8368 char *zSql;
8369 char *zCollist = 0;
8370 sqlite3_stmt *pStmt;
8371 int tnum = 0;
drh491c5be2019-10-18 15:58:50 +00008372 int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */
8373 int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
drh2ce15c32017-07-11 13:34:40 +00008374 int i;
drh48d219a2018-04-23 18:38:48 +00008375 if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
8376 utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
8377 " .imposter off\n");
drh491c5be2019-10-18 15:58:50 +00008378 /* Also allowed, but not documented:
8379 **
8380 ** .imposter TABLE IMPOSTER
8381 **
8382 ** where TABLE is a WITHOUT ROWID table. In that case, the
8383 ** imposter is another WITHOUT ROWID table with the columns in
8384 ** storage order. */
drh2ce15c32017-07-11 13:34:40 +00008385 rc = 1;
8386 goto meta_command_exit;
8387 }
8388 open_db(p, 0);
drh48d219a2018-04-23 18:38:48 +00008389 if( nArg==2 ){
8390 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
8391 goto meta_command_exit;
8392 }
drh491c5be2019-10-18 15:58:50 +00008393 zSql = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00008394 "SELECT rootpage, 0 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00008395 " WHERE name='%q' AND type='index'"
8396 "UNION ALL "
drh067b92b2020-06-19 15:24:12 +00008397 "SELECT rootpage, 1 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00008398 " WHERE name='%q' AND type='table'"
8399 " AND sql LIKE '%%without%%rowid%%'",
8400 azArg[1], azArg[1]
8401 );
drh2ce15c32017-07-11 13:34:40 +00008402 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8403 sqlite3_free(zSql);
8404 if( sqlite3_step(pStmt)==SQLITE_ROW ){
8405 tnum = sqlite3_column_int(pStmt, 0);
drh491c5be2019-10-18 15:58:50 +00008406 isWO = sqlite3_column_int(pStmt, 1);
drh2ce15c32017-07-11 13:34:40 +00008407 }
8408 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00008409 zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
8410 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8411 sqlite3_free(zSql);
8412 i = 0;
8413 while( sqlite3_step(pStmt)==SQLITE_ROW ){
8414 char zLabel[20];
8415 const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
8416 i++;
8417 if( zCol==0 ){
8418 if( sqlite3_column_int(pStmt,1)==-1 ){
8419 zCol = "_ROWID_";
8420 }else{
8421 sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
8422 zCol = zLabel;
8423 }
8424 }
drh491c5be2019-10-18 15:58:50 +00008425 if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){
8426 lenPK = (int)strlen(zCollist);
8427 }
drh2ce15c32017-07-11 13:34:40 +00008428 if( zCollist==0 ){
8429 zCollist = sqlite3_mprintf("\"%w\"", zCol);
8430 }else{
8431 zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
8432 }
8433 }
8434 sqlite3_finalize(pStmt);
drh491c5be2019-10-18 15:58:50 +00008435 if( i==0 || tnum==0 ){
8436 utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
8437 rc = 1;
8438 sqlite3_free(zCollist);
8439 goto meta_command_exit;
8440 }
8441 if( lenPK==0 ) lenPK = 100000;
drh2ce15c32017-07-11 13:34:40 +00008442 zSql = sqlite3_mprintf(
drh491c5be2019-10-18 15:58:50 +00008443 "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
8444 azArg[2], zCollist, lenPK, zCollist);
drh2ce15c32017-07-11 13:34:40 +00008445 sqlite3_free(zCollist);
8446 rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
8447 if( rc==SQLITE_OK ){
8448 rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
8449 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
8450 if( rc ){
8451 utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
8452 }else{
8453 utf8_printf(stdout, "%s;\n", zSql);
8454 raw_printf(stdout,
drh491c5be2019-10-18 15:58:50 +00008455 "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
8456 azArg[1], isWO ? "table" : "index"
drh2ce15c32017-07-11 13:34:40 +00008457 );
8458 }
8459 }else{
8460 raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
8461 rc = 1;
8462 }
8463 sqlite3_free(zSql);
8464 }else
8465#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
8466
8467#ifdef SQLITE_ENABLE_IOTRACE
8468 if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
8469 SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
8470 if( iotrace && iotrace!=stdout ) fclose(iotrace);
8471 iotrace = 0;
8472 if( nArg<2 ){
8473 sqlite3IoTrace = 0;
8474 }else if( strcmp(azArg[1], "-")==0 ){
8475 sqlite3IoTrace = iotracePrintf;
8476 iotrace = stdout;
8477 }else{
8478 iotrace = fopen(azArg[1], "w");
8479 if( iotrace==0 ){
8480 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
8481 sqlite3IoTrace = 0;
8482 rc = 1;
8483 }else{
8484 sqlite3IoTrace = iotracePrintf;
8485 }
8486 }
8487 }else
8488#endif
8489
8490 if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
8491 static const struct {
8492 const char *zLimitName; /* Name of a limit */
8493 int limitCode; /* Integer code for that limit */
8494 } aLimit[] = {
8495 { "length", SQLITE_LIMIT_LENGTH },
8496 { "sql_length", SQLITE_LIMIT_SQL_LENGTH },
8497 { "column", SQLITE_LIMIT_COLUMN },
8498 { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
8499 { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
8500 { "vdbe_op", SQLITE_LIMIT_VDBE_OP },
8501 { "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
8502 { "attached", SQLITE_LIMIT_ATTACHED },
8503 { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
8504 { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER },
8505 { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
8506 { "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
8507 };
8508 int i, n2;
8509 open_db(p, 0);
8510 if( nArg==1 ){
8511 for(i=0; i<ArraySize(aLimit); i++){
8512 printf("%20s %d\n", aLimit[i].zLimitName,
8513 sqlite3_limit(p->db, aLimit[i].limitCode, -1));
8514 }
8515 }else if( nArg>3 ){
8516 raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
8517 rc = 1;
8518 goto meta_command_exit;
8519 }else{
8520 int iLimit = -1;
8521 n2 = strlen30(azArg[1]);
8522 for(i=0; i<ArraySize(aLimit); i++){
8523 if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
8524 if( iLimit<0 ){
8525 iLimit = i;
8526 }else{
8527 utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
8528 rc = 1;
8529 goto meta_command_exit;
8530 }
8531 }
8532 }
8533 if( iLimit<0 ){
8534 utf8_printf(stderr, "unknown limit: \"%s\"\n"
8535 "enter \".limits\" with no arguments for a list.\n",
8536 azArg[1]);
8537 rc = 1;
8538 goto meta_command_exit;
8539 }
8540 if( nArg==3 ){
8541 sqlite3_limit(p->db, aLimit[iLimit].limitCode,
8542 (int)integerValue(azArg[2]));
8543 }
8544 printf("%20s %d\n", aLimit[iLimit].zLimitName,
8545 sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
8546 }
8547 }else
8548
8549 if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
8550 open_db(p, 0);
8551 lintDotCommand(p, azArg, nArg);
8552 }else
8553
8554#ifndef SQLITE_OMIT_LOAD_EXTENSION
8555 if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
8556 const char *zFile, *zProc;
8557 char *zErrMsg = 0;
8558 if( nArg<2 ){
8559 raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
8560 rc = 1;
8561 goto meta_command_exit;
8562 }
8563 zFile = azArg[1];
8564 zProc = nArg>=3 ? azArg[2] : 0;
8565 open_db(p, 0);
8566 rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
8567 if( rc!=SQLITE_OK ){
8568 utf8_printf(stderr, "Error: %s\n", zErrMsg);
8569 sqlite3_free(zErrMsg);
8570 rc = 1;
8571 }
8572 }else
8573#endif
8574
8575 if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
8576 if( nArg!=2 ){
8577 raw_printf(stderr, "Usage: .log FILENAME\n");
8578 rc = 1;
8579 }else{
8580 const char *zFile = azArg[1];
8581 output_file_close(p->pLog);
drha92a01a2018-01-10 22:15:37 +00008582 p->pLog = output_file_open(zFile, 0);
drh2ce15c32017-07-11 13:34:40 +00008583 }
8584 }else
8585
8586 if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
8587 const char *zMode = nArg>=2 ? azArg[1] : "";
drhaf2770f2018-01-05 14:55:43 +00008588 int n2 = strlen30(zMode);
drh2ce15c32017-07-11 13:34:40 +00008589 int c2 = zMode[0];
8590 if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){
8591 p->mode = MODE_Line;
8592 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8593 }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
8594 p->mode = MODE_Column;
drhc0605082020-06-05 00:54:27 +00008595 if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){
8596 p->showHeader = 1;
8597 }
drh2ce15c32017-07-11 13:34:40 +00008598 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8599 }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
8600 p->mode = MODE_List;
8601 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
8602 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8603 }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){
8604 p->mode = MODE_Html;
8605 }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
8606 p->mode = MODE_Tcl;
8607 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
8608 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8609 }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
8610 p->mode = MODE_Csv;
8611 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
8612 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
8613 }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
8614 p->mode = MODE_List;
8615 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
8616 }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
8617 p->mode = MODE_Insert;
8618 set_table_name(p, nArg>=3 ? azArg[2] : "table");
8619 }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
8620 p->mode = MODE_Quote;
drhc6835732020-05-28 20:37:17 +00008621 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
8622 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +00008623 }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
8624 p->mode = MODE_Ascii;
8625 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
8626 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
drh30c54a02020-05-28 23:49:50 +00008627 }else if( c2=='m' && strncmp(azArg[1],"markdown",n2)==0 ){
8628 p->mode = MODE_Markdown;
8629 }else if( c2=='t' && strncmp(azArg[1],"table",n2)==0 ){
8630 p->mode = MODE_Table;
drh0908e382020-06-04 18:05:39 +00008631 }else if( c2=='b' && strncmp(azArg[1],"box",n2)==0 ){
8632 p->mode = MODE_Box;
drh30c54a02020-05-28 23:49:50 +00008633 }else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){
8634 p->mode = MODE_Json;
drh2ce15c32017-07-11 13:34:40 +00008635 }else if( nArg==1 ){
8636 raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
8637 }else{
8638 raw_printf(stderr, "Error: mode should be one of: "
drh0908e382020-06-04 18:05:39 +00008639 "ascii box column csv html insert json line list markdown "
drh30c54a02020-05-28 23:49:50 +00008640 "quote table tabs tcl\n");
drh2ce15c32017-07-11 13:34:40 +00008641 rc = 1;
8642 }
8643 p->cMode = p->mode;
8644 }else
8645
8646 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
8647 if( nArg==2 ){
8648 sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
8649 "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
8650 }else{
8651 raw_printf(stderr, "Usage: .nullvalue STRING\n");
8652 rc = 1;
8653 }
8654 }else
8655
drh4a3a3eb2020-02-29 15:53:48 +00008656#ifdef SQLITE_DEBUG
8657 if( c=='o' && strcmp(azArg[0],"oom")==0 ){
8658 int i;
8659 for(i=1; i<nArg; i++){
8660 const char *z = azArg[i];
8661 if( z[0]=='-' && z[1]=='-' ) z++;
8662 if( strcmp(z,"-repeat")==0 ){
8663 if( i==nArg-1 ){
8664 raw_printf(p->out, "missing argument on \"%s\"\n", azArg[i]);
8665 rc = 1;
8666 }else{
8667 oomRepeat = (int)integerValue(azArg[++i]);
8668 }
8669 }else if( IsDigit(z[0]) ){
8670 oomCounter = (int)integerValue(azArg[i]);
8671 }else{
8672 raw_printf(p->out, "unknown argument: \"%s\"\n", azArg[i]);
8673 raw_printf(p->out, "Usage: .oom [--repeat N] [M]\n");
8674 rc = 1;
8675 }
8676 }
8677 if( rc==0 ){
8678 raw_printf(p->out, "oomCounter = %d\n", oomCounter);
8679 raw_printf(p->out, "oomRepeat = %d\n", oomRepeat);
8680 }
8681 }else
8682#endif /* SQLITE_DEBUG */
8683
drh2ce15c32017-07-11 13:34:40 +00008684 if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
drhf30bbce2020-12-02 18:27:48 +00008685 char *zNewFilename = 0; /* Name of the database file to open */
8686 int iName = 1; /* Index in azArg[] of the filename */
8687 int newFlag = 0; /* True to delete file before opening */
drh2ce15c32017-07-11 13:34:40 +00008688 /* Close the existing database */
8689 session_close_all(p);
drh9e804032018-05-18 17:11:50 +00008690 close_db(p->db);
drh2ce15c32017-07-11 13:34:40 +00008691 p->db = 0;
8692 p->zDbFilename = 0;
8693 sqlite3_free(p->zFreeOnClose);
8694 p->zFreeOnClose = 0;
drh1fa6d9f2018-01-06 21:46:01 +00008695 p->openMode = SHELL_OPEN_UNSPEC;
drh0933aad2019-11-18 17:46:38 +00008696 p->openFlags = 0;
drh6ca64482019-01-22 16:06:20 +00008697 p->szMax = 0;
drh2ce15c32017-07-11 13:34:40 +00008698 /* Check for command-line arguments */
drhf30bbce2020-12-02 18:27:48 +00008699 for(iName=1; iName<nArg; iName++){
drh2ce15c32017-07-11 13:34:40 +00008700 const char *z = azArg[iName];
8701 if( optionMatch(z,"new") ){
8702 newFlag = 1;
drh3baed312018-03-08 18:14:41 +00008703#ifdef SQLITE_HAVE_ZLIB
drh1fa6d9f2018-01-06 21:46:01 +00008704 }else if( optionMatch(z, "zip") ){
8705 p->openMode = SHELL_OPEN_ZIPFILE;
8706#endif
8707 }else if( optionMatch(z, "append") ){
8708 p->openMode = SHELL_OPEN_APPENDVFS;
drhee269a62018-02-14 23:27:43 +00008709 }else if( optionMatch(z, "readonly") ){
8710 p->openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +00008711 }else if( optionMatch(z, "nofollow") ){
8712 p->openFlags |= SQLITE_OPEN_NOFOLLOW;
drha751f392018-10-30 15:31:22 +00008713#ifdef SQLITE_ENABLE_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +00008714 }else if( optionMatch(z, "deserialize") ){
8715 p->openMode = SHELL_OPEN_DESERIALIZE;
drh33746482018-12-13 15:06:26 +00008716 }else if( optionMatch(z, "hexdb") ){
8717 p->openMode = SHELL_OPEN_HEXDB;
drh6ca64482019-01-22 16:06:20 +00008718 }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
8719 p->szMax = integerValue(azArg[++iName]);
drh33746482018-12-13 15:06:26 +00008720#endif /* SQLITE_ENABLE_DESERIALIZE */
drh2ce15c32017-07-11 13:34:40 +00008721 }else if( z[0]=='-' ){
8722 utf8_printf(stderr, "unknown option: %s\n", z);
8723 rc = 1;
8724 goto meta_command_exit;
drhf30bbce2020-12-02 18:27:48 +00008725 }else if( zNewFilename ){
8726 utf8_printf(stderr, "extra argument: \"%s\"\n", z);
8727 rc = 1;
8728 goto meta_command_exit;
8729 }else{
8730 zNewFilename = sqlite3_mprintf("%s", z);
drh2ce15c32017-07-11 13:34:40 +00008731 }
8732 }
8733 /* If a filename is specified, try to open it first */
drh33746482018-12-13 15:06:26 +00008734 if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
drh2ce15c32017-07-11 13:34:40 +00008735 if( newFlag ) shellDeleteFile(zNewFilename);
8736 p->zDbFilename = zNewFilename;
drhbe4ccb22018-05-17 20:04:24 +00008737 open_db(p, OPEN_DB_KEEPALIVE);
drh2ce15c32017-07-11 13:34:40 +00008738 if( p->db==0 ){
8739 utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
8740 sqlite3_free(zNewFilename);
8741 }else{
8742 p->zFreeOnClose = zNewFilename;
8743 }
8744 }
8745 if( p->db==0 ){
8746 /* As a fall-back open a TEMP database */
8747 p->zDbFilename = 0;
8748 open_db(p, 0);
8749 }
8750 }else
8751
drh13c20932018-01-10 21:41:55 +00008752 if( (c=='o'
8753 && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
8754 || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
drh2ce15c32017-07-11 13:34:40 +00008755 ){
drh7a431002020-04-18 14:12:00 +00008756 const char *zFile = 0;
drha92a01a2018-01-10 22:15:37 +00008757 int bTxtMode = 0;
drh7a431002020-04-18 14:12:00 +00008758 int i;
8759 int eMode = 0;
8760 int bBOM = 0;
drh5415ab42020-04-23 20:45:46 +00008761 int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */
drh7a431002020-04-18 14:12:00 +00008762
8763 if( c=='e' ){
8764 eMode = 'x';
8765 bOnce = 2;
8766 }else if( strncmp(azArg[0],"once",n)==0 ){
8767 bOnce = 1;
drh13c20932018-01-10 21:41:55 +00008768 }
drh7a431002020-04-18 14:12:00 +00008769 for(i=1; i<nArg; i++){
8770 char *z = azArg[i];
8771 if( z[0]=='-' ){
8772 if( z[1]=='-' ) z++;
8773 if( strcmp(z,"-bom")==0 ){
8774 bBOM = 1;
8775 }else if( c!='e' && strcmp(z,"-x")==0 ){
8776 eMode = 'x'; /* spreadsheet */
8777 }else if( c!='e' && strcmp(z,"-e")==0 ){
8778 eMode = 'e'; /* text editor */
8779 }else{
8780 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n",
8781 azArg[i]);
8782 showHelp(p->out, azArg[0]);
8783 rc = 1;
8784 goto meta_command_exit;
8785 }
8786 }else if( zFile==0 ){
8787 zFile = z;
8788 }else{
8789 utf8_printf(p->out,"ERROR: extra parameter: \"%s\". Usage:\n",
8790 azArg[i]);
8791 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00008792 rc = 1;
8793 goto meta_command_exit;
8794 }
drh7a431002020-04-18 14:12:00 +00008795 }
8796 if( zFile==0 ) zFile = "stdout";
8797 if( bOnce ){
drh2ce15c32017-07-11 13:34:40 +00008798 p->outCount = 2;
8799 }else{
8800 p->outCount = 0;
8801 }
8802 output_reset(p);
drh04a28c32018-01-31 01:38:44 +00008803#ifndef SQLITE_NOHAVE_SYSTEM
drh7a431002020-04-18 14:12:00 +00008804 if( eMode=='e' || eMode=='x' ){
drh3c484e82018-01-10 22:27:21 +00008805 p->doXdgOpen = 1;
8806 outputModePush(p);
drh7a431002020-04-18 14:12:00 +00008807 if( eMode=='x' ){
8808 /* spreadsheet mode. Output as CSV. */
drh13c20932018-01-10 21:41:55 +00008809 newTempFile(p, "csv");
drh7a431002020-04-18 14:12:00 +00008810 ShellClearFlag(p, SHFLG_Echo);
drh13c20932018-01-10 21:41:55 +00008811 p->mode = MODE_Csv;
8812 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
8813 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
8814 }else{
drh7a431002020-04-18 14:12:00 +00008815 /* text editor mode */
drh13c20932018-01-10 21:41:55 +00008816 newTempFile(p, "txt");
drha92a01a2018-01-10 22:15:37 +00008817 bTxtMode = 1;
drh13c20932018-01-10 21:41:55 +00008818 }
8819 zFile = p->zTempFile;
8820 }
drh04a28c32018-01-31 01:38:44 +00008821#endif /* SQLITE_NOHAVE_SYSTEM */
drh2ce15c32017-07-11 13:34:40 +00008822 if( zFile[0]=='|' ){
8823#ifdef SQLITE_OMIT_POPEN
8824 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
8825 rc = 1;
8826 p->out = stdout;
8827#else
8828 p->out = popen(zFile + 1, "w");
8829 if( p->out==0 ){
8830 utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
8831 p->out = stdout;
8832 rc = 1;
8833 }else{
drh7a431002020-04-18 14:12:00 +00008834 if( bBOM ) fprintf(p->out,"\357\273\277");
drh2ce15c32017-07-11 13:34:40 +00008835 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
8836 }
8837#endif
8838 }else{
drha92a01a2018-01-10 22:15:37 +00008839 p->out = output_file_open(zFile, bTxtMode);
drh2ce15c32017-07-11 13:34:40 +00008840 if( p->out==0 ){
8841 if( strcmp(zFile,"off")!=0 ){
8842 utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
8843 }
8844 p->out = stdout;
8845 rc = 1;
8846 } else {
drh7a431002020-04-18 14:12:00 +00008847 if( bBOM ) fprintf(p->out,"\357\273\277");
drh2ce15c32017-07-11 13:34:40 +00008848 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
8849 }
8850 }
8851 }else
8852
drh9cb02642019-02-28 20:10:52 +00008853 if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
8854 open_db(p,0);
8855 if( nArg<=1 ) goto parameter_syntax_error;
8856
8857 /* .parameter clear
8858 ** Clear all bind parameters by dropping the TEMP table that holds them.
8859 */
8860 if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
drh65c29fd2019-03-25 21:56:26 +00008861 sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
drh9cb02642019-02-28 20:10:52 +00008862 0, 0, 0);
8863 }else
8864
8865 /* .parameter list
8866 ** List all bind parameters.
8867 */
8868 if( nArg==2 && strcmp(azArg[1],"list")==0 ){
8869 sqlite3_stmt *pStmt = 0;
8870 int rx;
8871 int len = 0;
8872 rx = sqlite3_prepare_v2(p->db,
8873 "SELECT max(length(key)) "
drh65c29fd2019-03-25 21:56:26 +00008874 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drh9cb02642019-02-28 20:10:52 +00008875 if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
8876 len = sqlite3_column_int(pStmt, 0);
8877 if( len>40 ) len = 40;
8878 }
8879 sqlite3_finalize(pStmt);
8880 pStmt = 0;
8881 if( len ){
8882 rx = sqlite3_prepare_v2(p->db,
8883 "SELECT key, quote(value) "
drh65c29fd2019-03-25 21:56:26 +00008884 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drh9cb02642019-02-28 20:10:52 +00008885 while( sqlite3_step(pStmt)==SQLITE_ROW ){
8886 utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
8887 sqlite3_column_text(pStmt,1));
8888 }
8889 sqlite3_finalize(pStmt);
8890 }
8891 }else
8892
8893 /* .parameter init
8894 ** Make sure the TEMP table used to hold bind parameters exists.
8895 ** Create it if necessary.
8896 */
8897 if( nArg==2 && strcmp(azArg[1],"init")==0 ){
8898 bind_table_init(p);
8899 }else
8900
8901 /* .parameter set NAME VALUE
8902 ** Set or reset a bind parameter. NAME should be the full parameter
8903 ** name exactly as it appears in the query. (ex: $abc, @def). The
8904 ** VALUE can be in either SQL literal notation, or if not it will be
8905 ** understood to be a text string.
8906 */
8907 if( nArg==4 && strcmp(azArg[1],"set")==0 ){
8908 int rx;
8909 char *zSql;
8910 sqlite3_stmt *pStmt;
8911 const char *zKey = azArg[2];
8912 const char *zValue = azArg[3];
8913 bind_table_init(p);
8914 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00008915 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00008916 "VALUES(%Q,%s);", zKey, zValue);
8917 if( zSql==0 ) shell_out_of_memory();
8918 pStmt = 0;
8919 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8920 sqlite3_free(zSql);
8921 if( rx!=SQLITE_OK ){
8922 sqlite3_finalize(pStmt);
8923 pStmt = 0;
8924 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00008925 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00008926 "VALUES(%Q,%Q);", zKey, zValue);
8927 if( zSql==0 ) shell_out_of_memory();
8928 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8929 sqlite3_free(zSql);
8930 if( rx!=SQLITE_OK ){
8931 utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
8932 sqlite3_finalize(pStmt);
8933 pStmt = 0;
8934 rc = 1;
8935 }
8936 }
8937 sqlite3_step(pStmt);
8938 sqlite3_finalize(pStmt);
8939 }else
8940
8941 /* .parameter unset NAME
8942 ** Remove the NAME binding from the parameter binding table, if it
8943 ** exists.
8944 */
8945 if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
8946 char *zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00008947 "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
drh9cb02642019-02-28 20:10:52 +00008948 if( zSql==0 ) shell_out_of_memory();
8949 sqlite3_exec(p->db, zSql, 0, 0, 0);
8950 sqlite3_free(zSql);
8951 }else
8952 /* If no command name matches, show a syntax error */
8953 parameter_syntax_error:
8954 showHelp(p->out, "parameter");
8955 }else
8956
drh2ce15c32017-07-11 13:34:40 +00008957 if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
8958 int i;
8959 for(i=1; i<nArg; i++){
8960 if( i>1 ) raw_printf(p->out, " ");
8961 utf8_printf(p->out, "%s", azArg[i]);
8962 }
8963 raw_printf(p->out, "\n");
8964 }else
8965
drh569b1d92019-02-05 20:51:41 +00008966#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh3f83f592019-02-04 14:53:18 +00008967 if( c=='p' && n>=3 && strncmp(azArg[0], "progress", n)==0 ){
8968 int i;
drhfc4eeef2019-02-05 19:48:46 +00008969 int nn = 0;
drh3f83f592019-02-04 14:53:18 +00008970 p->flgProgress = 0;
8971 p->mxProgress = 0;
8972 p->nProgress = 0;
8973 for(i=1; i<nArg; i++){
8974 const char *z = azArg[i];
8975 if( z[0]=='-' ){
8976 z++;
8977 if( z[0]=='-' ) z++;
8978 if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00008979 p->flgProgress |= SHELL_PROGRESS_QUIET;
drh3f83f592019-02-04 14:53:18 +00008980 continue;
8981 }
8982 if( strcmp(z,"reset")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00008983 p->flgProgress |= SHELL_PROGRESS_RESET;
drh3f83f592019-02-04 14:53:18 +00008984 continue;
8985 }
8986 if( strcmp(z,"once")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00008987 p->flgProgress |= SHELL_PROGRESS_ONCE;
drh3f83f592019-02-04 14:53:18 +00008988 continue;
8989 }
8990 if( strcmp(z,"limit")==0 ){
8991 if( i+1>=nArg ){
8992 utf8_printf(stderr, "Error: missing argument on --limit\n");
8993 rc = 1;
8994 goto meta_command_exit;
8995 }else{
8996 p->mxProgress = (int)integerValue(azArg[++i]);
8997 }
8998 continue;
8999 }
9000 utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
9001 rc = 1;
9002 goto meta_command_exit;
9003 }else{
drhfc4eeef2019-02-05 19:48:46 +00009004 nn = (int)integerValue(z);
drh3f83f592019-02-04 14:53:18 +00009005 }
9006 }
9007 open_db(p, 0);
drhfc4eeef2019-02-05 19:48:46 +00009008 sqlite3_progress_handler(p->db, nn, progress_handler, p);
drh3f83f592019-02-04 14:53:18 +00009009 }else
drh569b1d92019-02-05 20:51:41 +00009010#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
drh3f83f592019-02-04 14:53:18 +00009011
drh2ce15c32017-07-11 13:34:40 +00009012 if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
9013 if( nArg >= 2) {
9014 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
9015 }
9016 if( nArg >= 3) {
9017 strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
9018 }
9019 }else
9020
9021 if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
9022 rc = 2;
9023 }else
9024
9025 if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
drh60379d42018-12-13 18:30:01 +00009026 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +00009027 int savedLineno = p->lineno;
drh2ce15c32017-07-11 13:34:40 +00009028 if( nArg!=2 ){
9029 raw_printf(stderr, "Usage: .read FILE\n");
9030 rc = 1;
9031 goto meta_command_exit;
9032 }
drh30497f42020-08-26 10:50:48 +00009033 if( azArg[1][0]=='|' ){
9034 p->in = popen(azArg[1]+1, "r");
9035 if( p->in==0 ){
9036 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
9037 rc = 1;
9038 }else{
9039 rc = process_input(p);
9040 pclose(p->in);
9041 }
9042 }else if( notNormalFile(azArg[1]) || (p->in = fopen(azArg[1], "rb"))==0 ){
drh2ce15c32017-07-11 13:34:40 +00009043 utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
9044 rc = 1;
9045 }else{
drh60379d42018-12-13 18:30:01 +00009046 rc = process_input(p);
9047 fclose(p->in);
drh2ce15c32017-07-11 13:34:40 +00009048 }
drh60379d42018-12-13 18:30:01 +00009049 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +00009050 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +00009051 }else
9052
9053 if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
9054 const char *zSrcFile;
9055 const char *zDb;
9056 sqlite3 *pSrc;
9057 sqlite3_backup *pBackup;
9058 int nTimeout = 0;
9059
9060 if( nArg==2 ){
9061 zSrcFile = azArg[1];
9062 zDb = "main";
9063 }else if( nArg==3 ){
9064 zSrcFile = azArg[2];
9065 zDb = azArg[1];
9066 }else{
9067 raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
9068 rc = 1;
9069 goto meta_command_exit;
9070 }
9071 rc = sqlite3_open(zSrcFile, &pSrc);
9072 if( rc!=SQLITE_OK ){
9073 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
drh9e804032018-05-18 17:11:50 +00009074 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009075 return 1;
9076 }
9077 open_db(p, 0);
9078 pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
9079 if( pBackup==0 ){
9080 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh9e804032018-05-18 17:11:50 +00009081 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009082 return 1;
9083 }
9084 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
9085 || rc==SQLITE_BUSY ){
9086 if( rc==SQLITE_BUSY ){
9087 if( nTimeout++ >= 3 ) break;
9088 sqlite3_sleep(100);
9089 }
9090 }
9091 sqlite3_backup_finish(pBackup);
9092 if( rc==SQLITE_DONE ){
9093 rc = 0;
9094 }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
9095 raw_printf(stderr, "Error: source database is busy\n");
9096 rc = 1;
9097 }else{
9098 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9099 rc = 1;
9100 }
drh9e804032018-05-18 17:11:50 +00009101 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009102 }else
9103
drh2ce15c32017-07-11 13:34:40 +00009104 if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
9105 if( nArg==2 ){
mistachkinb71aa092018-01-23 00:05:18 +00009106 p->scanstatsOn = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00009107#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
9108 raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
9109#endif
9110 }else{
9111 raw_printf(stderr, "Usage: .scanstats on|off\n");
9112 rc = 1;
9113 }
9114 }else
9115
9116 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
9117 ShellText sSelect;
9118 ShellState data;
9119 char *zErrMsg = 0;
drh667a2a22018-01-02 00:04:37 +00009120 const char *zDiv = "(";
drhceba7922018-01-01 21:28:25 +00009121 const char *zName = 0;
drh2ce15c32017-07-11 13:34:40 +00009122 int iSchema = 0;
drhceba7922018-01-01 21:28:25 +00009123 int bDebug = 0;
drhbbb29ec2020-10-12 14:56:47 +00009124 int bNoSystemTabs = 0;
drhceba7922018-01-01 21:28:25 +00009125 int ii;
drh2ce15c32017-07-11 13:34:40 +00009126
9127 open_db(p, 0);
9128 memcpy(&data, p, sizeof(data));
9129 data.showHeader = 0;
9130 data.cMode = data.mode = MODE_Semi;
9131 initText(&sSelect);
drhceba7922018-01-01 21:28:25 +00009132 for(ii=1; ii<nArg; ii++){
9133 if( optionMatch(azArg[ii],"indent") ){
9134 data.cMode = data.mode = MODE_Pretty;
9135 }else if( optionMatch(azArg[ii],"debug") ){
9136 bDebug = 1;
drhbbb29ec2020-10-12 14:56:47 +00009137 }else if( optionMatch(azArg[ii],"nosys") ){
9138 bNoSystemTabs = 1;
9139 }else if( azArg[ii][0]=='-' ){
9140 utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
9141 rc = 1;
9142 goto meta_command_exit;
drhceba7922018-01-01 21:28:25 +00009143 }else if( zName==0 ){
9144 zName = azArg[ii];
drh2ce15c32017-07-11 13:34:40 +00009145 }else{
drhbbb29ec2020-10-12 14:56:47 +00009146 raw_printf(stderr, "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
drhceba7922018-01-01 21:28:25 +00009147 rc = 1;
9148 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00009149 }
drh2ce15c32017-07-11 13:34:40 +00009150 }
drhceba7922018-01-01 21:28:25 +00009151 if( zName!=0 ){
drh067b92b2020-06-19 15:24:12 +00009152 int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0
drh346a70c2020-06-15 20:27:35 +00009153 || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
9154 || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
9155 || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
drh067b92b2020-06-19 15:24:12 +00009156 if( isSchema ){
drh2ce15c32017-07-11 13:34:40 +00009157 char *new_argv[2], *new_colv[2];
drhc22b7162018-01-01 20:11:23 +00009158 new_argv[0] = sqlite3_mprintf(
9159 "CREATE TABLE %s (\n"
drh2ce15c32017-07-11 13:34:40 +00009160 " type text,\n"
9161 " name text,\n"
9162 " tbl_name text,\n"
9163 " rootpage integer,\n"
9164 " sql text\n"
drh346a70c2020-06-15 20:27:35 +00009165 ")", zName);
drh2ce15c32017-07-11 13:34:40 +00009166 new_argv[1] = 0;
9167 new_colv[0] = "sql";
9168 new_colv[1] = 0;
9169 callback(&data, 1, new_argv, new_colv);
drhc22b7162018-01-01 20:11:23 +00009170 sqlite3_free(new_argv[0]);
drh2ce15c32017-07-11 13:34:40 +00009171 }
drh2ce15c32017-07-11 13:34:40 +00009172 }
9173 if( zDiv ){
9174 sqlite3_stmt *pStmt = 0;
9175 rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
9176 -1, &pStmt, 0);
9177 if( rc ){
9178 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9179 sqlite3_finalize(pStmt);
9180 rc = 1;
9181 goto meta_command_exit;
9182 }
9183 appendText(&sSelect, "SELECT sql FROM", 0);
9184 iSchema = 0;
9185 while( sqlite3_step(pStmt)==SQLITE_ROW ){
9186 const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
9187 char zScNum[30];
9188 sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
9189 appendText(&sSelect, zDiv, 0);
9190 zDiv = " UNION ALL ";
drhceba7922018-01-01 21:28:25 +00009191 appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
9192 if( sqlite3_stricmp(zDb, "main")!=0 ){
drhea38f4f2019-07-13 17:21:47 +00009193 appendText(&sSelect, zDb, '\'');
drh2ce15c32017-07-11 13:34:40 +00009194 }else{
drhceba7922018-01-01 21:28:25 +00009195 appendText(&sSelect, "NULL", 0);
drh2ce15c32017-07-11 13:34:40 +00009196 }
drhceba7922018-01-01 21:28:25 +00009197 appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0);
9198 appendText(&sSelect, zScNum, 0);
9199 appendText(&sSelect, " AS snum, ", 0);
9200 appendText(&sSelect, zDb, '\'');
9201 appendText(&sSelect, " AS sname FROM ", 0);
drhea38f4f2019-07-13 17:21:47 +00009202 appendText(&sSelect, zDb, quoteChar(zDb));
drh067b92b2020-06-19 15:24:12 +00009203 appendText(&sSelect, ".sqlite_schema", 0);
drh2ce15c32017-07-11 13:34:40 +00009204 }
9205 sqlite3_finalize(pStmt);
drhcc3f3d12019-08-17 15:27:58 +00009206#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
drh667a2a22018-01-02 00:04:37 +00009207 if( zName ){
9208 appendText(&sSelect,
9209 " UNION ALL SELECT shell_module_schema(name),"
drhe2754c12019-08-26 12:50:01 +00009210 " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
9211 0);
drh667a2a22018-01-02 00:04:37 +00009212 }
drhcde7b772018-01-02 12:50:40 +00009213#endif
drh2ce15c32017-07-11 13:34:40 +00009214 appendText(&sSelect, ") WHERE ", 0);
drhceba7922018-01-01 21:28:25 +00009215 if( zName ){
9216 char *zQarg = sqlite3_mprintf("%Q", zName);
mistachkin9d107262018-03-23 14:24:34 +00009217 int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
9218 strchr(zName, '[') != 0;
drhceba7922018-01-01 21:28:25 +00009219 if( strchr(zName, '.') ){
drh2ce15c32017-07-11 13:34:40 +00009220 appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
9221 }else{
9222 appendText(&sSelect, "lower(tbl_name)", 0);
9223 }
mistachkin9d107262018-03-23 14:24:34 +00009224 appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0);
drh2ce15c32017-07-11 13:34:40 +00009225 appendText(&sSelect, zQarg, 0);
mistachkin9d107262018-03-23 14:24:34 +00009226 if( !bGlob ){
9227 appendText(&sSelect, " ESCAPE '\\' ", 0);
9228 }
drh2ce15c32017-07-11 13:34:40 +00009229 appendText(&sSelect, " AND ", 0);
9230 sqlite3_free(zQarg);
9231 }
drhbbb29ec2020-10-12 14:56:47 +00009232 if( bNoSystemTabs ){
9233 appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
9234 }
9235 appendText(&sSelect, "sql IS NOT NULL"
drh2ce15c32017-07-11 13:34:40 +00009236 " ORDER BY snum, rowid", 0);
drhceba7922018-01-01 21:28:25 +00009237 if( bDebug ){
9238 utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
9239 }else{
9240 rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
9241 }
drh2ce15c32017-07-11 13:34:40 +00009242 freeText(&sSelect);
9243 }
9244 if( zErrMsg ){
9245 utf8_printf(stderr,"Error: %s\n", zErrMsg);
9246 sqlite3_free(zErrMsg);
9247 rc = 1;
9248 }else if( rc != SQLITE_OK ){
9249 raw_printf(stderr,"Error: querying schema information\n");
9250 rc = 1;
9251 }else{
9252 rc = 0;
9253 }
9254 }else
9255
drh2ce15c32017-07-11 13:34:40 +00009256 if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
drhfda8e492020-12-04 16:04:45 +00009257 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
drhc0622a42020-12-04 01:17:57 +00009258 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
drh2ce15c32017-07-11 13:34:40 +00009259 }else
drh2ce15c32017-07-11 13:34:40 +00009260
9261#if defined(SQLITE_ENABLE_SESSION)
9262 if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
9263 OpenSession *pSession = &p->aSession[0];
9264 char **azCmd = &azArg[1];
9265 int iSes = 0;
9266 int nCmd = nArg - 1;
9267 int i;
9268 if( nArg<=1 ) goto session_syntax_error;
9269 open_db(p, 0);
9270 if( nArg>=3 ){
9271 for(iSes=0; iSes<p->nSession; iSes++){
9272 if( strcmp(p->aSession[iSes].zName, azArg[1])==0 ) break;
9273 }
9274 if( iSes<p->nSession ){
9275 pSession = &p->aSession[iSes];
9276 azCmd++;
9277 nCmd--;
9278 }else{
9279 pSession = &p->aSession[0];
9280 iSes = 0;
9281 }
9282 }
9283
9284 /* .session attach TABLE
9285 ** Invoke the sqlite3session_attach() interface to attach a particular
9286 ** table so that it is never filtered.
9287 */
9288 if( strcmp(azCmd[0],"attach")==0 ){
9289 if( nCmd!=2 ) goto session_syntax_error;
9290 if( pSession->p==0 ){
9291 session_not_open:
9292 raw_printf(stderr, "ERROR: No sessions are open\n");
9293 }else{
9294 rc = sqlite3session_attach(pSession->p, azCmd[1]);
9295 if( rc ){
9296 raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
9297 rc = 0;
9298 }
9299 }
9300 }else
9301
9302 /* .session changeset FILE
9303 ** .session patchset FILE
9304 ** Write a changeset or patchset into a file. The file is overwritten.
9305 */
9306 if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
9307 FILE *out = 0;
9308 if( nCmd!=2 ) goto session_syntax_error;
9309 if( pSession->p==0 ) goto session_not_open;
9310 out = fopen(azCmd[1], "wb");
9311 if( out==0 ){
drhe2754c12019-08-26 12:50:01 +00009312 utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
9313 azCmd[1]);
drh2ce15c32017-07-11 13:34:40 +00009314 }else{
9315 int szChng;
9316 void *pChng;
9317 if( azCmd[0][0]=='c' ){
9318 rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
9319 }else{
9320 rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
9321 }
9322 if( rc ){
9323 printf("Error: error code %d\n", rc);
9324 rc = 0;
9325 }
9326 if( pChng
9327 && fwrite(pChng, szChng, 1, out)!=1 ){
9328 raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
9329 szChng);
9330 }
9331 sqlite3_free(pChng);
9332 fclose(out);
9333 }
9334 }else
9335
9336 /* .session close
9337 ** Close the identified session
9338 */
9339 if( strcmp(azCmd[0], "close")==0 ){
9340 if( nCmd!=1 ) goto session_syntax_error;
9341 if( p->nSession ){
9342 session_close(pSession);
9343 p->aSession[iSes] = p->aSession[--p->nSession];
9344 }
9345 }else
9346
9347 /* .session enable ?BOOLEAN?
9348 ** Query or set the enable flag
9349 */
9350 if( strcmp(azCmd[0], "enable")==0 ){
9351 int ii;
9352 if( nCmd>2 ) goto session_syntax_error;
9353 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
9354 if( p->nSession ){
9355 ii = sqlite3session_enable(pSession->p, ii);
9356 utf8_printf(p->out, "session %s enable flag = %d\n",
9357 pSession->zName, ii);
9358 }
9359 }else
9360
9361 /* .session filter GLOB ....
9362 ** Set a list of GLOB patterns of table names to be excluded.
9363 */
9364 if( strcmp(azCmd[0], "filter")==0 ){
9365 int ii, nByte;
9366 if( nCmd<2 ) goto session_syntax_error;
9367 if( p->nSession ){
9368 for(ii=0; ii<pSession->nFilter; ii++){
9369 sqlite3_free(pSession->azFilter[ii]);
9370 }
9371 sqlite3_free(pSession->azFilter);
9372 nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
9373 pSession->azFilter = sqlite3_malloc( nByte );
9374 if( pSession->azFilter==0 ){
9375 raw_printf(stderr, "Error: out or memory\n");
9376 exit(1);
9377 }
9378 for(ii=1; ii<nCmd; ii++){
9379 pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
9380 }
9381 pSession->nFilter = ii-1;
9382 }
9383 }else
9384
9385 /* .session indirect ?BOOLEAN?
9386 ** Query or set the indirect flag
9387 */
9388 if( strcmp(azCmd[0], "indirect")==0 ){
9389 int ii;
9390 if( nCmd>2 ) goto session_syntax_error;
9391 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
9392 if( p->nSession ){
9393 ii = sqlite3session_indirect(pSession->p, ii);
9394 utf8_printf(p->out, "session %s indirect flag = %d\n",
9395 pSession->zName, ii);
9396 }
9397 }else
9398
9399 /* .session isempty
9400 ** Determine if the session is empty
9401 */
9402 if( strcmp(azCmd[0], "isempty")==0 ){
9403 int ii;
9404 if( nCmd!=1 ) goto session_syntax_error;
9405 if( p->nSession ){
9406 ii = sqlite3session_isempty(pSession->p);
9407 utf8_printf(p->out, "session %s isempty flag = %d\n",
9408 pSession->zName, ii);
9409 }
9410 }else
9411
9412 /* .session list
9413 ** List all currently open sessions
9414 */
9415 if( strcmp(azCmd[0],"list")==0 ){
9416 for(i=0; i<p->nSession; i++){
9417 utf8_printf(p->out, "%d %s\n", i, p->aSession[i].zName);
9418 }
9419 }else
9420
9421 /* .session open DB NAME
9422 ** Open a new session called NAME on the attached database DB.
9423 ** DB is normally "main".
9424 */
9425 if( strcmp(azCmd[0],"open")==0 ){
9426 char *zName;
9427 if( nCmd!=3 ) goto session_syntax_error;
9428 zName = azCmd[2];
9429 if( zName[0]==0 ) goto session_syntax_error;
9430 for(i=0; i<p->nSession; i++){
9431 if( strcmp(p->aSession[i].zName,zName)==0 ){
9432 utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
9433 goto meta_command_exit;
9434 }
9435 }
9436 if( p->nSession>=ArraySize(p->aSession) ){
9437 raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(p->aSession));
9438 goto meta_command_exit;
9439 }
9440 pSession = &p->aSession[p->nSession];
9441 rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
9442 if( rc ){
9443 raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
9444 rc = 0;
9445 goto meta_command_exit;
9446 }
9447 pSession->nFilter = 0;
9448 sqlite3session_table_filter(pSession->p, session_filter, pSession);
9449 p->nSession++;
9450 pSession->zName = sqlite3_mprintf("%s", zName);
9451 }else
9452 /* If no command name matches, show a syntax error */
9453 session_syntax_error:
drheb7f2a02018-09-26 18:02:32 +00009454 showHelp(p->out, "session");
drh2ce15c32017-07-11 13:34:40 +00009455 }else
9456#endif
9457
9458#ifdef SQLITE_DEBUG
9459 /* Undocumented commands for internal testing. Subject to change
9460 ** without notice. */
9461 if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
9462 if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
9463 int i, v;
9464 for(i=1; i<nArg; i++){
9465 v = booleanValue(azArg[i]);
9466 utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
9467 }
9468 }
9469 if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
9470 int i; sqlite3_int64 v;
9471 for(i=1; i<nArg; i++){
9472 char zBuf[200];
9473 v = integerValue(azArg[i]);
9474 sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
9475 utf8_printf(p->out, "%s", zBuf);
9476 }
9477 }
9478 }else
9479#endif
9480
9481 if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){
9482 int bIsInit = 0; /* True to initialize the SELFTEST table */
9483 int bVerbose = 0; /* Verbose output */
9484 int bSelftestExists; /* True if SELFTEST already exists */
9485 int i, k; /* Loop counters */
9486 int nTest = 0; /* Number of tests runs */
9487 int nErr = 0; /* Number of errors seen */
9488 ShellText str; /* Answer for a query */
9489 sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
9490
9491 open_db(p,0);
9492 for(i=1; i<nArg; i++){
9493 const char *z = azArg[i];
9494 if( z[0]=='-' && z[1]=='-' ) z++;
9495 if( strcmp(z,"-init")==0 ){
9496 bIsInit = 1;
9497 }else
9498 if( strcmp(z,"-v")==0 ){
9499 bVerbose++;
9500 }else
9501 {
9502 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
9503 azArg[i], azArg[0]);
9504 raw_printf(stderr, "Should be one of: --init -v\n");
9505 rc = 1;
9506 goto meta_command_exit;
9507 }
9508 }
9509 if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
9510 != SQLITE_OK ){
9511 bSelftestExists = 0;
9512 }else{
9513 bSelftestExists = 1;
9514 }
9515 if( bIsInit ){
9516 createSelftestTable(p);
9517 bSelftestExists = 1;
9518 }
9519 initText(&str);
9520 appendText(&str, "x", 0);
9521 for(k=bSelftestExists; k>=0; k--){
9522 if( k==1 ){
9523 rc = sqlite3_prepare_v2(p->db,
9524 "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
9525 -1, &pStmt, 0);
9526 }else{
9527 rc = sqlite3_prepare_v2(p->db,
9528 "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
9529 " (1,'run','PRAGMA integrity_check','ok')",
9530 -1, &pStmt, 0);
9531 }
9532 if( rc ){
9533 raw_printf(stderr, "Error querying the selftest table\n");
9534 rc = 1;
9535 sqlite3_finalize(pStmt);
9536 goto meta_command_exit;
9537 }
9538 for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
9539 int tno = sqlite3_column_int(pStmt, 0);
9540 const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
9541 const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
9542 const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
9543
9544 k = 0;
9545 if( bVerbose>0 ){
9546 char *zQuote = sqlite3_mprintf("%q", zSql);
9547 printf("%d: %s %s\n", tno, zOp, zSql);
9548 sqlite3_free(zQuote);
9549 }
9550 if( strcmp(zOp,"memo")==0 ){
9551 utf8_printf(p->out, "%s\n", zSql);
9552 }else
9553 if( strcmp(zOp,"run")==0 ){
9554 char *zErrMsg = 0;
9555 str.n = 0;
9556 str.z[0] = 0;
9557 rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
9558 nTest++;
9559 if( bVerbose ){
9560 utf8_printf(p->out, "Result: %s\n", str.z);
9561 }
9562 if( rc || zErrMsg ){
9563 nErr++;
9564 rc = 1;
9565 utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
9566 sqlite3_free(zErrMsg);
9567 }else if( strcmp(zAns,str.z)!=0 ){
9568 nErr++;
9569 rc = 1;
9570 utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
9571 utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z);
9572 }
9573 }else
9574 {
9575 utf8_printf(stderr,
9576 "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
9577 rc = 1;
9578 break;
9579 }
9580 } /* End loop over rows of content from SELFTEST */
9581 sqlite3_finalize(pStmt);
9582 } /* End loop over k */
9583 freeText(&str);
9584 utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
9585 }else
9586
9587 if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
9588 if( nArg<2 || nArg>3 ){
9589 raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
9590 rc = 1;
9591 }
9592 if( nArg>=2 ){
9593 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
9594 "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
9595 }
9596 if( nArg>=3 ){
9597 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator,
9598 "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]);
9599 }
9600 }else
9601
9602 if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){
9603 const char *zLike = 0; /* Which table to checksum. 0 means everything */
9604 int i; /* Loop counter */
9605 int bSchema = 0; /* Also hash the schema */
9606 int bSeparate = 0; /* Hash each table separately */
9607 int iSize = 224; /* Hash algorithm to use */
9608 int bDebug = 0; /* Only show the query that would have run */
9609 sqlite3_stmt *pStmt; /* For querying tables names */
9610 char *zSql; /* SQL to be run */
9611 char *zSep; /* Separator */
9612 ShellText sSql; /* Complete SQL for the query to run the hash */
9613 ShellText sQuery; /* Set of queries used to read all content */
9614 open_db(p, 0);
9615 for(i=1; i<nArg; i++){
9616 const char *z = azArg[i];
9617 if( z[0]=='-' ){
9618 z++;
9619 if( z[0]=='-' ) z++;
9620 if( strcmp(z,"schema")==0 ){
9621 bSchema = 1;
9622 }else
9623 if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
9624 || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
9625 ){
9626 iSize = atoi(&z[5]);
9627 }else
9628 if( strcmp(z,"debug")==0 ){
9629 bDebug = 1;
9630 }else
9631 {
9632 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
9633 azArg[i], azArg[0]);
drhe2754c12019-08-26 12:50:01 +00009634 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00009635 rc = 1;
9636 goto meta_command_exit;
9637 }
9638 }else if( zLike ){
9639 raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
9640 rc = 1;
9641 goto meta_command_exit;
9642 }else{
9643 zLike = z;
9644 bSeparate = 1;
drhcedfecf2018-03-23 12:59:10 +00009645 if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1;
drh2ce15c32017-07-11 13:34:40 +00009646 }
9647 }
9648 if( bSchema ){
drh067b92b2020-06-19 15:24:12 +00009649 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00009650 " WHERE type='table' AND coalesce(rootpage,0)>1"
drh067b92b2020-06-19 15:24:12 +00009651 " UNION ALL SELECT 'sqlite_schema'"
drh2ce15c32017-07-11 13:34:40 +00009652 " ORDER BY 1 collate nocase";
9653 }else{
drh067b92b2020-06-19 15:24:12 +00009654 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00009655 " WHERE type='table' AND coalesce(rootpage,0)>1"
9656 " AND name NOT LIKE 'sqlite_%'"
9657 " ORDER BY 1 collate nocase";
9658 }
9659 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9660 initText(&sQuery);
9661 initText(&sSql);
9662 appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
9663 zSep = "VALUES(";
9664 while( SQLITE_ROW==sqlite3_step(pStmt) ){
9665 const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
9666 if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
9667 if( strncmp(zTab, "sqlite_",7)!=0 ){
9668 appendText(&sQuery,"SELECT * FROM ", 0);
9669 appendText(&sQuery,zTab,'"');
9670 appendText(&sQuery," NOT INDEXED;", 0);
drh067b92b2020-06-19 15:24:12 +00009671 }else if( strcmp(zTab, "sqlite_schema")==0 ){
9672 appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00009673 " ORDER BY name;", 0);
9674 }else if( strcmp(zTab, "sqlite_sequence")==0 ){
9675 appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
9676 " ORDER BY name;", 0);
9677 }else if( strcmp(zTab, "sqlite_stat1")==0 ){
9678 appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
9679 " ORDER BY tbl,idx;", 0);
drh175b8f02019-08-08 15:24:17 +00009680 }else if( strcmp(zTab, "sqlite_stat4")==0 ){
drh2ce15c32017-07-11 13:34:40 +00009681 appendText(&sQuery, "SELECT * FROM ", 0);
9682 appendText(&sQuery, zTab, 0);
9683 appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
9684 }
9685 appendText(&sSql, zSep, 0);
9686 appendText(&sSql, sQuery.z, '\'');
9687 sQuery.n = 0;
9688 appendText(&sSql, ",", 0);
9689 appendText(&sSql, zTab, '\'');
9690 zSep = "),(";
9691 }
9692 sqlite3_finalize(pStmt);
9693 if( bSeparate ){
9694 zSql = sqlite3_mprintf(
9695 "%s))"
9696 " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
9697 " FROM [sha3sum$query]",
9698 sSql.z, iSize);
9699 }else{
9700 zSql = sqlite3_mprintf(
9701 "%s))"
9702 " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
9703 " FROM [sha3sum$query]",
9704 sSql.z, iSize);
9705 }
9706 freeText(&sQuery);
9707 freeText(&sSql);
9708 if( bDebug ){
9709 utf8_printf(p->out, "%s\n", zSql);
9710 }else{
drha10b9992018-03-09 15:24:33 +00009711 shell_exec(p, zSql, 0);
drh2ce15c32017-07-11 13:34:40 +00009712 }
9713 sqlite3_free(zSql);
9714 }else
9715
drh04a28c32018-01-31 01:38:44 +00009716#ifndef SQLITE_NOHAVE_SYSTEM
drh2ce15c32017-07-11 13:34:40 +00009717 if( c=='s'
9718 && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
9719 ){
9720 char *zCmd;
9721 int i, x;
9722 if( nArg<2 ){
9723 raw_printf(stderr, "Usage: .system COMMAND\n");
9724 rc = 1;
9725 goto meta_command_exit;
9726 }
9727 zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
9728 for(i=2; i<nArg; i++){
9729 zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
9730 zCmd, azArg[i]);
9731 }
9732 x = system(zCmd);
9733 sqlite3_free(zCmd);
9734 if( x ) raw_printf(stderr, "System command returns %d\n", x);
9735 }else
drh04a28c32018-01-31 01:38:44 +00009736#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
drh2ce15c32017-07-11 13:34:40 +00009737
9738 if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
drhada70452017-12-21 21:02:27 +00009739 static const char *azBool[] = { "off", "on", "trigger", "full"};
drha6e6cf22021-01-09 19:10:04 +00009740 const char *zOut;
drh2ce15c32017-07-11 13:34:40 +00009741 int i;
9742 if( nArg!=1 ){
9743 raw_printf(stderr, "Usage: .show\n");
9744 rc = 1;
9745 goto meta_command_exit;
9746 }
9747 utf8_printf(p->out, "%12.12s: %s\n","echo",
9748 azBool[ShellHasFlag(p, SHFLG_Echo)]);
9749 utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
9750 utf8_printf(p->out, "%12.12s: %s\n","explain",
9751 p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
9752 utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
9753 utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
9754 utf8_printf(p->out, "%12.12s: ", "nullvalue");
9755 output_c_string(p->out, p->nullValue);
9756 raw_printf(p->out, "\n");
9757 utf8_printf(p->out,"%12.12s: %s\n","output",
9758 strlen30(p->outfile) ? p->outfile : "stdout");
9759 utf8_printf(p->out,"%12.12s: ", "colseparator");
9760 output_c_string(p->out, p->colSeparator);
9761 raw_printf(p->out, "\n");
9762 utf8_printf(p->out,"%12.12s: ", "rowseparator");
9763 output_c_string(p->out, p->rowSeparator);
9764 raw_printf(p->out, "\n");
drha6e6cf22021-01-09 19:10:04 +00009765 switch( p->statsOn ){
9766 case 0: zOut = "off"; break;
9767 default: zOut = "on"; break;
9768 case 2: zOut = "stmt"; break;
9769 case 3: zOut = "vmstep"; break;
9770 }
9771 utf8_printf(p->out, "%12.12s: %s\n","stats", zOut);
drh2ce15c32017-07-11 13:34:40 +00009772 utf8_printf(p->out, "%12.12s: ", "width");
drh0285d982020-05-29 14:38:43 +00009773 for (i=0;i<p->nWidth;i++) {
drh2ce15c32017-07-11 13:34:40 +00009774 raw_printf(p->out, "%d ", p->colWidth[i]);
9775 }
9776 raw_printf(p->out, "\n");
9777 utf8_printf(p->out, "%12.12s: %s\n", "filename",
9778 p->zDbFilename ? p->zDbFilename : "");
9779 }else
9780
9781 if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
9782 if( nArg==2 ){
drha6e6cf22021-01-09 19:10:04 +00009783 if( strcmp(azArg[1],"stmt")==0 ){
9784 p->statsOn = 2;
9785 }else if( strcmp(azArg[1],"vmstep")==0 ){
9786 p->statsOn = 3;
9787 }else{
9788 p->statsOn = (u8)booleanValue(azArg[1]);
9789 }
drh2ce15c32017-07-11 13:34:40 +00009790 }else if( nArg==1 ){
9791 display_stats(p->db, p, 0);
9792 }else{
drha6e6cf22021-01-09 19:10:04 +00009793 raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n");
drh2ce15c32017-07-11 13:34:40 +00009794 rc = 1;
9795 }
9796 }else
9797
9798 if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0)
9799 || (c=='i' && (strncmp(azArg[0], "indices", n)==0
9800 || strncmp(azArg[0], "indexes", n)==0) )
9801 ){
9802 sqlite3_stmt *pStmt;
9803 char **azResult;
9804 int nRow, nAlloc;
9805 int ii;
9806 ShellText s;
9807 initText(&s);
9808 open_db(p, 0);
9809 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
drh9e804032018-05-18 17:11:50 +00009810 if( rc ){
9811 sqlite3_finalize(pStmt);
9812 return shellDatabaseError(p->db);
9813 }
drh2ce15c32017-07-11 13:34:40 +00009814
9815 if( nArg>2 && c=='i' ){
9816 /* It is an historical accident that the .indexes command shows an error
9817 ** when called with the wrong number of arguments whereas the .tables
9818 ** command does not. */
9819 raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
9820 rc = 1;
drh9e804032018-05-18 17:11:50 +00009821 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00009822 goto meta_command_exit;
9823 }
9824 for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
9825 const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
9826 if( zDbName==0 ) continue;
9827 if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0);
9828 if( sqlite3_stricmp(zDbName, "main")==0 ){
9829 appendText(&s, "SELECT name FROM ", 0);
9830 }else{
9831 appendText(&s, "SELECT ", 0);
9832 appendText(&s, zDbName, '\'');
9833 appendText(&s, "||'.'||name FROM ", 0);
9834 }
9835 appendText(&s, zDbName, '"');
drh067b92b2020-06-19 15:24:12 +00009836 appendText(&s, ".sqlite_schema ", 0);
drh2ce15c32017-07-11 13:34:40 +00009837 if( c=='t' ){
9838 appendText(&s," WHERE type IN ('table','view')"
9839 " AND name NOT LIKE 'sqlite_%'"
9840 " AND name LIKE ?1", 0);
9841 }else{
9842 appendText(&s," WHERE type='index'"
9843 " AND tbl_name LIKE ?1", 0);
9844 }
9845 }
9846 rc = sqlite3_finalize(pStmt);
9847 appendText(&s, " ORDER BY 1", 0);
9848 rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
9849 freeText(&s);
9850 if( rc ) return shellDatabaseError(p->db);
9851
9852 /* Run the SQL statement prepared by the above block. Store the results
9853 ** as an array of nul-terminated strings in azResult[]. */
9854 nRow = nAlloc = 0;
9855 azResult = 0;
9856 if( nArg>1 ){
9857 sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
9858 }else{
9859 sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
9860 }
9861 while( sqlite3_step(pStmt)==SQLITE_ROW ){
9862 if( nRow>=nAlloc ){
9863 char **azNew;
9864 int n2 = nAlloc*2 + 10;
9865 azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
drh4b5345c2018-04-24 13:07:40 +00009866 if( azNew==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00009867 nAlloc = n2;
9868 azResult = azNew;
9869 }
9870 azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
drh4b5345c2018-04-24 13:07:40 +00009871 if( 0==azResult[nRow] ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00009872 nRow++;
9873 }
9874 if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
9875 rc = shellDatabaseError(p->db);
9876 }
9877
9878 /* Pretty-print the contents of array azResult[] to the output */
9879 if( rc==0 && nRow>0 ){
9880 int len, maxlen = 0;
9881 int i, j;
9882 int nPrintCol, nPrintRow;
9883 for(i=0; i<nRow; i++){
9884 len = strlen30(azResult[i]);
9885 if( len>maxlen ) maxlen = len;
9886 }
9887 nPrintCol = 80/(maxlen+2);
9888 if( nPrintCol<1 ) nPrintCol = 1;
9889 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
9890 for(i=0; i<nPrintRow; i++){
9891 for(j=i; j<nRow; j+=nPrintRow){
9892 char *zSp = j<nPrintRow ? "" : " ";
9893 utf8_printf(p->out, "%s%-*s", zSp, maxlen,
9894 azResult[j] ? azResult[j]:"");
9895 }
9896 raw_printf(p->out, "\n");
9897 }
9898 }
9899
9900 for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
9901 sqlite3_free(azResult);
9902 }else
9903
9904 /* Begin redirecting output to the file "testcase-out.txt" */
9905 if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
9906 output_reset(p);
drha92a01a2018-01-10 22:15:37 +00009907 p->out = output_file_open("testcase-out.txt", 0);
drh2ce15c32017-07-11 13:34:40 +00009908 if( p->out==0 ){
9909 raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
9910 }
9911 if( nArg>=2 ){
9912 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
9913 }else{
9914 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
9915 }
9916 }else
9917
9918#ifndef SQLITE_UNTESTABLE
drh35f51a42017-11-15 17:07:22 +00009919 if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009920 static const struct {
9921 const char *zCtrlName; /* Name of a test-control option */
9922 int ctrlCode; /* Integer code for that option */
drhef302e82017-11-15 19:14:08 +00009923 const char *zUsage; /* Usage notes */
drh2ce15c32017-07-11 13:34:40 +00009924 } aCtrl[] = {
drhe2754c12019-08-26 12:50:01 +00009925 { "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" },
9926 { "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" },
9927 /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/
9928 /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/
9929 { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" },
9930 { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN" },
9931 /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" },*/
9932 { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
drh171c50e2020-01-01 15:43:30 +00009933 { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "" },
drhe2754c12019-08-26 12:50:01 +00009934 { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" },
9935 { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" },
9936 { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" },
drh0d9de992017-12-26 18:04:23 +00009937#ifdef YYCOVERAGE
drhe2754c12019-08-26 12:50:01 +00009938 { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" },
drh0d9de992017-12-26 18:04:23 +00009939#endif
drhe2754c12019-08-26 12:50:01 +00009940 { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " },
9941 { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
9942 { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
9943 { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
drh37ccfcf2020-08-31 18:49:04 +00009944 { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, "" },
drh2ce15c32017-07-11 13:34:40 +00009945 };
9946 int testctrl = -1;
drhef302e82017-11-15 19:14:08 +00009947 int iCtrl = -1;
9948 int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */
9949 int isOk = 0;
drh2ce15c32017-07-11 13:34:40 +00009950 int i, n2;
mistachkinc6bc15a2017-11-21 21:14:32 +00009951 const char *zCmd = 0;
9952
drh2ce15c32017-07-11 13:34:40 +00009953 open_db(p, 0);
mistachkinc6bc15a2017-11-21 21:14:32 +00009954 zCmd = nArg>=2 ? azArg[1] : "help";
drh35f51a42017-11-15 17:07:22 +00009955
9956 /* The argument can optionally begin with "-" or "--" */
9957 if( zCmd[0]=='-' && zCmd[1] ){
9958 zCmd++;
9959 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
9960 }
9961
9962 /* --help lists all test-controls */
9963 if( strcmp(zCmd,"help")==0 ){
9964 utf8_printf(p->out, "Available test-controls:\n");
9965 for(i=0; i<ArraySize(aCtrl); i++){
drhef302e82017-11-15 19:14:08 +00009966 utf8_printf(p->out, " .testctrl %s %s\n",
9967 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
drh35f51a42017-11-15 17:07:22 +00009968 }
9969 rc = 1;
9970 goto meta_command_exit;
9971 }
drh2ce15c32017-07-11 13:34:40 +00009972
9973 /* convert testctrl text option to value. allow any unique prefix
9974 ** of the option name, or a numerical value. */
drh35f51a42017-11-15 17:07:22 +00009975 n2 = strlen30(zCmd);
drh2ce15c32017-07-11 13:34:40 +00009976 for(i=0; i<ArraySize(aCtrl); i++){
drh35f51a42017-11-15 17:07:22 +00009977 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009978 if( testctrl<0 ){
9979 testctrl = aCtrl[i].ctrlCode;
drhef302e82017-11-15 19:14:08 +00009980 iCtrl = i;
drh2ce15c32017-07-11 13:34:40 +00009981 }else{
drh35f51a42017-11-15 17:07:22 +00009982 utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
9983 "Use \".testctrl --help\" for help\n", zCmd);
9984 rc = 1;
9985 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00009986 }
9987 }
9988 }
drhef302e82017-11-15 19:14:08 +00009989 if( testctrl<0 ){
drh35f51a42017-11-15 17:07:22 +00009990 utf8_printf(stderr,"Error: unknown test-control: %s\n"
9991 "Use \".testctrl --help\" for help\n", zCmd);
drh2ce15c32017-07-11 13:34:40 +00009992 }else{
9993 switch(testctrl){
9994
9995 /* sqlite3_test_control(int, db, int) */
9996 case SQLITE_TESTCTRL_OPTIMIZATIONS:
drh2ce15c32017-07-11 13:34:40 +00009997 if( nArg==3 ){
drhaf7b7652021-01-13 19:28:17 +00009998 unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
drh2ce15c32017-07-11 13:34:40 +00009999 rc2 = sqlite3_test_control(testctrl, p->db, opt);
drhef302e82017-11-15 19:14:08 +000010000 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010001 }
10002 break;
10003
10004 /* sqlite3_test_control(int) */
10005 case SQLITE_TESTCTRL_PRNG_SAVE:
10006 case SQLITE_TESTCTRL_PRNG_RESTORE:
drh2ce15c32017-07-11 13:34:40 +000010007 case SQLITE_TESTCTRL_BYTEORDER:
10008 if( nArg==2 ){
10009 rc2 = sqlite3_test_control(testctrl);
drhef302e82017-11-15 19:14:08 +000010010 isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
drh2ce15c32017-07-11 13:34:40 +000010011 }
10012 break;
10013
10014 /* sqlite3_test_control(int, uint) */
10015 case SQLITE_TESTCTRL_PENDING_BYTE:
10016 if( nArg==3 ){
10017 unsigned int opt = (unsigned int)integerValue(azArg[2]);
10018 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010019 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010020 }
10021 break;
10022
drh2e6d83b2019-08-03 01:39:20 +000010023 /* sqlite3_test_control(int, int, sqlite3*) */
10024 case SQLITE_TESTCTRL_PRNG_SEED:
10025 if( nArg==3 || nArg==4 ){
drh51755a72019-08-08 19:40:29 +000010026 int ii = (int)integerValue(azArg[2]);
drh2e6d83b2019-08-03 01:39:20 +000010027 sqlite3 *db;
drh41428a92019-08-12 16:25:11 +000010028 if( ii==0 && strcmp(azArg[2],"random")==0 ){
10029 sqlite3_randomness(sizeof(ii),&ii);
10030 printf("-- random seed: %d\n", ii);
10031 }
drh2e6d83b2019-08-03 01:39:20 +000010032 if( nArg==3 ){
10033 db = 0;
10034 }else{
10035 db = p->db;
10036 /* Make sure the schema has been loaded */
10037 sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);
10038 }
drh51755a72019-08-08 19:40:29 +000010039 rc2 = sqlite3_test_control(testctrl, ii, db);
drh2e6d83b2019-08-03 01:39:20 +000010040 isOk = 3;
10041 }
10042 break;
10043
drh2ce15c32017-07-11 13:34:40 +000010044 /* sqlite3_test_control(int, int) */
10045 case SQLITE_TESTCTRL_ASSERT:
10046 case SQLITE_TESTCTRL_ALWAYS:
drhef302e82017-11-15 19:14:08 +000010047 if( nArg==3 ){
10048 int opt = booleanValue(azArg[2]);
10049 rc2 = sqlite3_test_control(testctrl, opt);
10050 isOk = 1;
10051 }
10052 break;
10053
10054 /* sqlite3_test_control(int, int) */
10055 case SQLITE_TESTCTRL_LOCALTIME_FAULT:
drh2ce15c32017-07-11 13:34:40 +000010056 case SQLITE_TESTCTRL_NEVER_CORRUPT:
10057 if( nArg==3 ){
10058 int opt = booleanValue(azArg[2]);
10059 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010060 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010061 }
10062 break;
10063
drh171c50e2020-01-01 15:43:30 +000010064 /* sqlite3_test_control(sqlite3*) */
10065 case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
10066 rc2 = sqlite3_test_control(testctrl, p->db);
drh2a83c102020-01-01 23:02:35 +000010067 isOk = 3;
drh171c50e2020-01-01 15:43:30 +000010068 break;
10069
drh2ce15c32017-07-11 13:34:40 +000010070 case SQLITE_TESTCTRL_IMPOSTER:
10071 if( nArg==5 ){
10072 rc2 = sqlite3_test_control(testctrl, p->db,
10073 azArg[2],
10074 integerValue(azArg[3]),
10075 integerValue(azArg[4]));
drhef302e82017-11-15 19:14:08 +000010076 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010077 }
10078 break;
drh0d9de992017-12-26 18:04:23 +000010079
drh37ccfcf2020-08-31 18:49:04 +000010080 case SQLITE_TESTCTRL_SEEK_COUNT: {
10081 u64 x = 0;
10082 rc2 = sqlite3_test_control(testctrl, p->db, &x);
10083 utf8_printf(p->out, "%llu\n", x);
10084 isOk = 3;
10085 break;
10086 }
10087
drh0d9de992017-12-26 18:04:23 +000010088#ifdef YYCOVERAGE
10089 case SQLITE_TESTCTRL_PARSER_COVERAGE:
10090 if( nArg==2 ){
10091 sqlite3_test_control(testctrl, p->out);
10092 isOk = 3;
10093 }
10094#endif
drh2ce15c32017-07-11 13:34:40 +000010095 }
10096 }
drhef302e82017-11-15 19:14:08 +000010097 if( isOk==0 && iCtrl>=0 ){
drhe2754c12019-08-26 12:50:01 +000010098 utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
drhef302e82017-11-15 19:14:08 +000010099 rc = 1;
10100 }else if( isOk==1 ){
10101 raw_printf(p->out, "%d\n", rc2);
10102 }else if( isOk==2 ){
10103 raw_printf(p->out, "0x%08x\n", rc2);
10104 }
drh2ce15c32017-07-11 13:34:40 +000010105 }else
10106#endif /* !defined(SQLITE_UNTESTABLE) */
10107
10108 if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
10109 open_db(p, 0);
10110 sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
10111 }else
10112
10113 if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
10114 if( nArg==2 ){
10115 enableTimer = booleanValue(azArg[1]);
10116 if( enableTimer && !HAS_TIMER ){
10117 raw_printf(stderr, "Error: timer not available on this system.\n");
10118 enableTimer = 0;
10119 }
10120 }else{
10121 raw_printf(stderr, "Usage: .timer on|off\n");
10122 rc = 1;
10123 }
10124 }else
10125
drh707821f2018-12-05 13:39:06 +000010126#ifndef SQLITE_OMIT_TRACE
drh2ce15c32017-07-11 13:34:40 +000010127 if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
drh707821f2018-12-05 13:39:06 +000010128 int mType = 0;
10129 int jj;
drh2ce15c32017-07-11 13:34:40 +000010130 open_db(p, 0);
drh707821f2018-12-05 13:39:06 +000010131 for(jj=1; jj<nArg; jj++){
10132 const char *z = azArg[jj];
10133 if( z[0]=='-' ){
10134 if( optionMatch(z, "expanded") ){
10135 p->eTraceType = SHELL_TRACE_EXPANDED;
10136 }
10137#ifdef SQLITE_ENABLE_NORMALIZE
10138 else if( optionMatch(z, "normalized") ){
10139 p->eTraceType = SHELL_TRACE_NORMALIZED;
10140 }
10141#endif
10142 else if( optionMatch(z, "plain") ){
10143 p->eTraceType = SHELL_TRACE_PLAIN;
10144 }
10145 else if( optionMatch(z, "profile") ){
10146 mType |= SQLITE_TRACE_PROFILE;
10147 }
10148 else if( optionMatch(z, "row") ){
10149 mType |= SQLITE_TRACE_ROW;
10150 }
10151 else if( optionMatch(z, "stmt") ){
10152 mType |= SQLITE_TRACE_STMT;
10153 }
10154 else if( optionMatch(z, "close") ){
10155 mType |= SQLITE_TRACE_CLOSE;
10156 }
10157 else {
10158 raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
10159 rc = 1;
10160 goto meta_command_exit;
10161 }
10162 }else{
10163 output_file_close(p->traceOut);
10164 p->traceOut = output_file_open(azArg[1], 0);
10165 }
drh2ce15c32017-07-11 13:34:40 +000010166 }
drh2ce15c32017-07-11 13:34:40 +000010167 if( p->traceOut==0 ){
10168 sqlite3_trace_v2(p->db, 0, 0, 0);
10169 }else{
drh707821f2018-12-05 13:39:06 +000010170 if( mType==0 ) mType = SQLITE_TRACE_STMT;
10171 sqlite3_trace_v2(p->db, mType, sql_trace_callback, p);
drh2ce15c32017-07-11 13:34:40 +000010172 }
drh2ce15c32017-07-11 13:34:40 +000010173 }else
drh707821f2018-12-05 13:39:06 +000010174#endif /* !defined(SQLITE_OMIT_TRACE) */
drh2ce15c32017-07-11 13:34:40 +000010175
drhe2b7a762019-10-02 00:25:08 +000010176#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhcc5979d2019-08-16 22:58:29 +000010177 if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){
10178 int ii;
drh8c754a32019-08-19 20:35:30 +000010179 int lenOpt;
drh5df84282019-08-17 19:45:25 +000010180 char *zOpt;
drhcc5979d2019-08-16 22:58:29 +000010181 if( nArg<2 ){
drh5df84282019-08-17 19:45:25 +000010182 raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
drhcc5979d2019-08-16 22:58:29 +000010183 rc = 1;
10184 goto meta_command_exit;
10185 }
10186 open_db(p, 0);
drh5df84282019-08-17 19:45:25 +000010187 zOpt = azArg[1];
10188 if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
drh8c754a32019-08-19 20:35:30 +000010189 lenOpt = (int)strlen(zOpt);
10190 if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){
drh5df84282019-08-17 19:45:25 +000010191 assert( azArg[nArg]==0 );
drh8c754a32019-08-19 20:35:30 +000010192 sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0);
drh5df84282019-08-17 19:45:25 +000010193 }else{
10194 for(ii=1; ii<nArg; ii++){
10195 sqlite3_create_module(p->db, azArg[ii], 0, 0);
10196 }
drhcc5979d2019-08-16 22:58:29 +000010197 }
10198 }else
10199#endif
10200
drh2ce15c32017-07-11 13:34:40 +000010201#if SQLITE_USER_AUTHENTICATION
10202 if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
10203 if( nArg<2 ){
10204 raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
10205 rc = 1;
10206 goto meta_command_exit;
10207 }
10208 open_db(p, 0);
10209 if( strcmp(azArg[1],"login")==0 ){
10210 if( nArg!=4 ){
10211 raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
10212 rc = 1;
10213 goto meta_command_exit;
10214 }
drhe2754c12019-08-26 12:50:01 +000010215 rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
10216 strlen30(azArg[3]));
drh2ce15c32017-07-11 13:34:40 +000010217 if( rc ){
10218 utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
10219 rc = 1;
10220 }
10221 }else if( strcmp(azArg[1],"add")==0 ){
10222 if( nArg!=5 ){
10223 raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
10224 rc = 1;
10225 goto meta_command_exit;
10226 }
drhaf2770f2018-01-05 14:55:43 +000010227 rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000010228 booleanValue(azArg[4]));
10229 if( rc ){
10230 raw_printf(stderr, "User-Add failed: %d\n", rc);
10231 rc = 1;
10232 }
10233 }else if( strcmp(azArg[1],"edit")==0 ){
10234 if( nArg!=5 ){
10235 raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
10236 rc = 1;
10237 goto meta_command_exit;
10238 }
drhaf2770f2018-01-05 14:55:43 +000010239 rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000010240 booleanValue(azArg[4]));
10241 if( rc ){
10242 raw_printf(stderr, "User-Edit failed: %d\n", rc);
10243 rc = 1;
10244 }
10245 }else if( strcmp(azArg[1],"delete")==0 ){
10246 if( nArg!=3 ){
10247 raw_printf(stderr, "Usage: .user delete USER\n");
10248 rc = 1;
10249 goto meta_command_exit;
10250 }
10251 rc = sqlite3_user_delete(p->db, azArg[2]);
10252 if( rc ){
10253 raw_printf(stderr, "User-Delete failed: %d\n", rc);
10254 rc = 1;
10255 }
10256 }else{
10257 raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
10258 rc = 1;
10259 goto meta_command_exit;
10260 }
10261 }else
10262#endif /* SQLITE_USER_AUTHENTICATION */
10263
10264 if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
10265 utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
10266 sqlite3_libversion(), sqlite3_sourceid());
drh0ed2fd82018-01-16 20:05:27 +000010267#if SQLITE_HAVE_ZLIB
10268 utf8_printf(p->out, "zlib version %s\n", zlibVersion());
10269#endif
10270#define CTIMEOPT_VAL_(opt) #opt
10271#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
10272#if defined(__clang__) && defined(__clang_major__)
10273 utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
10274 CTIMEOPT_VAL(__clang_minor__) "."
10275 CTIMEOPT_VAL(__clang_patchlevel__) "\n");
10276#elif defined(_MSC_VER)
10277 utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n");
10278#elif defined(__GNUC__) && defined(__VERSION__)
10279 utf8_printf(p->out, "gcc-" __VERSION__ "\n");
10280#endif
drh2ce15c32017-07-11 13:34:40 +000010281 }else
10282
10283 if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
10284 const char *zDbName = nArg==2 ? azArg[1] : "main";
10285 sqlite3_vfs *pVfs = 0;
10286 if( p->db ){
10287 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
10288 if( pVfs ){
10289 utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
10290 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
10291 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
10292 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
10293 }
10294 }
10295 }else
10296
10297 if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){
10298 sqlite3_vfs *pVfs;
10299 sqlite3_vfs *pCurrent = 0;
10300 if( p->db ){
10301 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
10302 }
10303 for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
10304 utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName,
10305 pVfs==pCurrent ? " <--- CURRENT" : "");
10306 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
10307 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
10308 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
10309 if( pVfs->pNext ){
10310 raw_printf(p->out, "-----------------------------------\n");
10311 }
10312 }
10313 }else
10314
10315 if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
10316 const char *zDbName = nArg==2 ? azArg[1] : "main";
10317 char *zVfsName = 0;
10318 if( p->db ){
10319 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
10320 if( zVfsName ){
10321 utf8_printf(p->out, "%s\n", zVfsName);
10322 sqlite3_free(zVfsName);
10323 }
10324 }
10325 }else
10326
drh2ce15c32017-07-11 13:34:40 +000010327 if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
drhc0622a42020-12-04 01:17:57 +000010328 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
10329 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x);
drh2ce15c32017-07-11 13:34:40 +000010330 }else
drh2ce15c32017-07-11 13:34:40 +000010331
10332 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
10333 int j;
10334 assert( nArg<=ArraySize(azArg) );
drh0285d982020-05-29 14:38:43 +000010335 p->nWidth = nArg-1;
10336 p->colWidth = realloc(p->colWidth, p->nWidth*sizeof(int)*2);
10337 if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory();
10338 if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
10339 for(j=1; j<nArg; j++){
drh2ce15c32017-07-11 13:34:40 +000010340 p->colWidth[j-1] = (int)integerValue(azArg[j]);
10341 }
10342 }else
10343
10344 {
10345 utf8_printf(stderr, "Error: unknown command or invalid arguments: "
10346 " \"%s\". Enter \".help\" for help\n", azArg[0]);
10347 rc = 1;
10348 }
10349
10350meta_command_exit:
10351 if( p->outCount ){
10352 p->outCount--;
10353 if( p->outCount==0 ) output_reset(p);
10354 }
10355 return rc;
10356}
10357
10358/*
10359** Return TRUE if a semicolon occurs anywhere in the first N characters
10360** of string z[].
10361*/
10362static int line_contains_semicolon(const char *z, int N){
10363 int i;
10364 for(i=0; i<N; i++){ if( z[i]==';' ) return 1; }
10365 return 0;
10366}
10367
10368/*
10369** Test to see if a line consists entirely of whitespace.
10370*/
10371static int _all_whitespace(const char *z){
10372 for(; *z; z++){
10373 if( IsSpace(z[0]) ) continue;
10374 if( *z=='/' && z[1]=='*' ){
10375 z += 2;
10376 while( *z && (*z!='*' || z[1]!='/') ){ z++; }
10377 if( *z==0 ) return 0;
10378 z++;
10379 continue;
10380 }
10381 if( *z=='-' && z[1]=='-' ){
10382 z += 2;
10383 while( *z && *z!='\n' ){ z++; }
10384 if( *z==0 ) return 1;
10385 continue;
10386 }
10387 return 0;
10388 }
10389 return 1;
10390}
10391
10392/*
10393** Return TRUE if the line typed in is an SQL command terminator other
10394** than a semi-colon. The SQL Server style "go" command is understood
10395** as is the Oracle "/".
10396*/
10397static int line_is_command_terminator(const char *zLine){
10398 while( IsSpace(zLine[0]) ){ zLine++; };
10399 if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ){
10400 return 1; /* Oracle */
10401 }
10402 if( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o'
10403 && _all_whitespace(&zLine[2]) ){
10404 return 1; /* SQL Server */
10405 }
10406 return 0;
10407}
10408
10409/*
drh56f17742018-01-24 01:58:49 +000010410** We need a default sqlite3_complete() implementation to use in case
10411** the shell is compiled with SQLITE_OMIT_COMPLETE. The default assumes
10412** any arbitrary text is a complete SQL statement. This is not very
10413** user-friendly, but it does seem to work.
10414*/
10415#ifdef SQLITE_OMIT_COMPLETE
danc86b23b2018-11-16 14:36:42 +000010416#define sqlite3_complete(x) 1
drh56f17742018-01-24 01:58:49 +000010417#endif
10418
10419/*
drh2ce15c32017-07-11 13:34:40 +000010420** Return true if zSql is a complete SQL statement. Return false if it
10421** ends in the middle of a string literal or C-style comment.
10422*/
10423static int line_is_complete(char *zSql, int nSql){
10424 int rc;
10425 if( zSql==0 ) return 1;
10426 zSql[nSql] = ';';
10427 zSql[nSql+1] = 0;
10428 rc = sqlite3_complete(zSql);
10429 zSql[nSql] = 0;
10430 return rc;
10431}
10432
10433/*
drhfc29a862018-05-11 19:11:18 +000010434** Run a single line of SQL. Return the number of errors.
drh2ce15c32017-07-11 13:34:40 +000010435*/
10436static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
10437 int rc;
10438 char *zErrMsg = 0;
10439
10440 open_db(p, 0);
10441 if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
drhfc4eeef2019-02-05 19:48:46 +000010442 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
drh2ce15c32017-07-11 13:34:40 +000010443 BEGIN_TIMER;
drha10b9992018-03-09 15:24:33 +000010444 rc = shell_exec(p, zSql, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000010445 END_TIMER;
10446 if( rc || zErrMsg ){
10447 char zPrefix[100];
10448 if( in!=0 || !stdin_is_interactive ){
10449 sqlite3_snprintf(sizeof(zPrefix), zPrefix,
10450 "Error: near line %d:", startline);
10451 }else{
10452 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
10453 }
10454 if( zErrMsg!=0 ){
10455 utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
10456 sqlite3_free(zErrMsg);
10457 zErrMsg = 0;
10458 }else{
10459 utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
10460 }
10461 return 1;
10462 }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
10463 raw_printf(p->out, "changes: %3d total_changes: %d\n",
10464 sqlite3_changes(p->db), sqlite3_total_changes(p->db));
10465 }
10466 return 0;
10467}
10468
10469
10470/*
10471** Read input from *in and process it. If *in==0 then input
10472** is interactive - the user is typing it it. Otherwise, input
10473** is coming from a file or device. A prompt is issued and history
10474** is saved only if input is interactive. An interrupt signal will
10475** cause this routine to exit immediately, unless input is interactive.
10476**
10477** Return the number of errors.
10478*/
drh60379d42018-12-13 18:30:01 +000010479static int process_input(ShellState *p){
drh2ce15c32017-07-11 13:34:40 +000010480 char *zLine = 0; /* A single input line */
10481 char *zSql = 0; /* Accumulated SQL text */
10482 int nLine; /* Length of current line */
10483 int nSql = 0; /* Bytes of zSql[] used */
10484 int nAlloc = 0; /* Allocated zSql[] space */
10485 int nSqlPrior = 0; /* Bytes of zSql[] used by prior line */
10486 int rc; /* Error code */
10487 int errCnt = 0; /* Number of errors seen */
drh2ce15c32017-07-11 13:34:40 +000010488 int startline = 0; /* Line number for start of current input */
10489
drh2c8ee022018-12-13 18:59:30 +000010490 p->lineno = 0;
drh60379d42018-12-13 18:30:01 +000010491 while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
drh2ce15c32017-07-11 13:34:40 +000010492 fflush(p->out);
drh60379d42018-12-13 18:30:01 +000010493 zLine = one_input_line(p->in, zLine, nSql>0);
drh2ce15c32017-07-11 13:34:40 +000010494 if( zLine==0 ){
10495 /* End of input */
drh60379d42018-12-13 18:30:01 +000010496 if( p->in==0 && stdin_is_interactive ) printf("\n");
drh2ce15c32017-07-11 13:34:40 +000010497 break;
10498 }
10499 if( seenInterrupt ){
drh60379d42018-12-13 18:30:01 +000010500 if( p->in!=0 ) break;
drh2ce15c32017-07-11 13:34:40 +000010501 seenInterrupt = 0;
10502 }
drh2c8ee022018-12-13 18:59:30 +000010503 p->lineno++;
drh2ce15c32017-07-11 13:34:40 +000010504 if( nSql==0 && _all_whitespace(zLine) ){
10505 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
10506 continue;
10507 }
drh1615c372018-05-12 23:56:22 +000010508 if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
drh2ce15c32017-07-11 13:34:40 +000010509 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
drh1615c372018-05-12 23:56:22 +000010510 if( zLine[0]=='.' ){
10511 rc = do_meta_command(zLine, p);
10512 if( rc==2 ){ /* exit requested */
10513 break;
10514 }else if( rc ){
10515 errCnt++;
10516 }
drh2ce15c32017-07-11 13:34:40 +000010517 }
10518 continue;
10519 }
10520 if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){
10521 memcpy(zLine,";",2);
10522 }
10523 nLine = strlen30(zLine);
10524 if( nSql+nLine+2>=nAlloc ){
10525 nAlloc = nSql+nLine+100;
10526 zSql = realloc(zSql, nAlloc);
drh4b5345c2018-04-24 13:07:40 +000010527 if( zSql==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +000010528 }
10529 nSqlPrior = nSql;
10530 if( nSql==0 ){
10531 int i;
10532 for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
10533 assert( nAlloc>0 && zSql!=0 );
10534 memcpy(zSql, zLine+i, nLine+1-i);
drh2c8ee022018-12-13 18:59:30 +000010535 startline = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000010536 nSql = nLine-i;
10537 }else{
10538 zSql[nSql++] = '\n';
10539 memcpy(zSql+nSql, zLine, nLine+1);
10540 nSql += nLine;
10541 }
10542 if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
10543 && sqlite3_complete(zSql) ){
drh60379d42018-12-13 18:30:01 +000010544 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000010545 nSql = 0;
10546 if( p->outCount ){
10547 output_reset(p);
10548 p->outCount = 0;
drh13c20932018-01-10 21:41:55 +000010549 }else{
10550 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +000010551 }
10552 }else if( nSql && _all_whitespace(zSql) ){
10553 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
10554 nSql = 0;
10555 }
10556 }
10557 if( nSql && !_all_whitespace(zSql) ){
drh60379d42018-12-13 18:30:01 +000010558 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000010559 }
10560 free(zSql);
10561 free(zLine);
10562 return errCnt>0;
10563}
10564
10565/*
10566** Return a pathname which is the user's home directory. A
10567** 0 return indicates an error of some kind.
10568*/
10569static char *find_home_dir(int clearFlag){
10570 static char *home_dir = NULL;
10571 if( clearFlag ){
10572 free(home_dir);
10573 home_dir = 0;
10574 return 0;
10575 }
10576 if( home_dir ) return home_dir;
10577
10578#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
10579 && !defined(__RTP__) && !defined(_WRS_KERNEL)
10580 {
10581 struct passwd *pwent;
10582 uid_t uid = getuid();
10583 if( (pwent=getpwuid(uid)) != NULL) {
10584 home_dir = pwent->pw_dir;
10585 }
10586 }
10587#endif
10588
10589#if defined(_WIN32_WCE)
10590 /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
10591 */
10592 home_dir = "/";
10593#else
10594
10595#if defined(_WIN32) || defined(WIN32)
10596 if (!home_dir) {
10597 home_dir = getenv("USERPROFILE");
10598 }
10599#endif
10600
10601 if (!home_dir) {
10602 home_dir = getenv("HOME");
10603 }
10604
10605#if defined(_WIN32) || defined(WIN32)
10606 if (!home_dir) {
10607 char *zDrive, *zPath;
10608 int n;
10609 zDrive = getenv("HOMEDRIVE");
10610 zPath = getenv("HOMEPATH");
10611 if( zDrive && zPath ){
10612 n = strlen30(zDrive) + strlen30(zPath) + 1;
10613 home_dir = malloc( n );
10614 if( home_dir==0 ) return 0;
10615 sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
10616 return home_dir;
10617 }
10618 home_dir = "c:\\";
10619 }
10620#endif
10621
10622#endif /* !_WIN32_WCE */
10623
10624 if( home_dir ){
10625 int n = strlen30(home_dir) + 1;
10626 char *z = malloc( n );
10627 if( z ) memcpy(z, home_dir, n);
10628 home_dir = z;
10629 }
10630
10631 return home_dir;
10632}
10633
10634/*
10635** Read input from the file given by sqliterc_override. Or if that
10636** parameter is NULL, take input from ~/.sqliterc
10637**
10638** Returns the number of errors.
10639*/
10640static void process_sqliterc(
10641 ShellState *p, /* Configuration data */
10642 const char *sqliterc_override /* Name of config file. NULL to use default */
10643){
10644 char *home_dir = NULL;
10645 const char *sqliterc = sqliterc_override;
10646 char *zBuf = 0;
drh60379d42018-12-13 18:30:01 +000010647 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +000010648 int savedLineno = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000010649
10650 if (sqliterc == NULL) {
10651 home_dir = find_home_dir(0);
10652 if( home_dir==0 ){
10653 raw_printf(stderr, "-- warning: cannot find home directory;"
10654 " cannot read ~/.sqliterc\n");
10655 return;
10656 }
drh2ce15c32017-07-11 13:34:40 +000010657 zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
10658 sqliterc = zBuf;
10659 }
drh60379d42018-12-13 18:30:01 +000010660 p->in = fopen(sqliterc,"rb");
10661 if( p->in ){
drh2ce15c32017-07-11 13:34:40 +000010662 if( stdin_is_interactive ){
10663 utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
10664 }
drhb7c46aa2020-11-25 13:59:47 +000010665 if( process_input(p) && bail_on_error ) exit(1);
drh60379d42018-12-13 18:30:01 +000010666 fclose(p->in);
drhb7c46aa2020-11-25 13:59:47 +000010667 }else if( sqliterc_override!=0 ){
10668 utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
10669 if( bail_on_error ) exit(1);
drh2ce15c32017-07-11 13:34:40 +000010670 }
drh60379d42018-12-13 18:30:01 +000010671 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +000010672 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +000010673 sqlite3_free(zBuf);
10674}
10675
10676/*
10677** Show available command line options
10678*/
10679static const char zOptions[] =
drhda57d962018-03-05 19:34:05 +000010680#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhad7fd5d2018-03-05 20:21:50 +000010681 " -A ARGS... run \".archive ARGS\" and exit\n"
drhda57d962018-03-05 19:34:05 +000010682#endif
drh3baed312018-03-08 18:14:41 +000010683 " -append append the database to the end of the file\n"
drh2ce15c32017-07-11 13:34:40 +000010684 " -ascii set output mode to 'ascii'\n"
10685 " -bail stop after hitting an error\n"
10686 " -batch force batch I/O\n"
drh0908e382020-06-04 18:05:39 +000010687 " -box set output mode to 'box'\n"
drh2ce15c32017-07-11 13:34:40 +000010688 " -column set output mode to 'column'\n"
10689 " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
10690 " -csv set output mode to 'csv'\n"
drh6ca64482019-01-22 16:06:20 +000010691#if defined(SQLITE_ENABLE_DESERIALIZE)
10692 " -deserialize open the database using sqlite3_deserialize()\n"
10693#endif
drh2ce15c32017-07-11 13:34:40 +000010694 " -echo print commands before execution\n"
10695 " -init FILENAME read/process named file\n"
10696 " -[no]header turn headers on or off\n"
10697#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
10698 " -heap SIZE Size of heap for memsys3 or memsys5\n"
10699#endif
10700 " -help show this message\n"
10701 " -html set output mode to HTML\n"
10702 " -interactive force interactive I/O\n"
drh30c54a02020-05-28 23:49:50 +000010703 " -json set output mode to 'json'\n"
drh2ce15c32017-07-11 13:34:40 +000010704 " -line set output mode to 'line'\n"
10705 " -list set output mode to 'list'\n"
10706 " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
drh30c54a02020-05-28 23:49:50 +000010707 " -markdown set output mode to 'markdown'\n"
drh6ca64482019-01-22 16:06:20 +000010708#if defined(SQLITE_ENABLE_DESERIALIZE)
10709 " -maxsize N maximum size for a --deserialize database\n"
10710#endif
drhaf482572019-02-04 19:52:39 +000010711 " -memtrace trace all memory allocations and deallocations\n"
drh2ce15c32017-07-11 13:34:40 +000010712 " -mmap N default mmap size set to N\n"
10713#ifdef SQLITE_ENABLE_MULTIPLEX
10714 " -multiplex enable the multiplexor VFS\n"
10715#endif
10716 " -newline SEP set output row separator. Default: '\\n'\n"
drh0933aad2019-11-18 17:46:38 +000010717 " -nofollow refuse to open symbolic links to database files\n"
drh2ce15c32017-07-11 13:34:40 +000010718 " -nullvalue TEXT set text string for NULL values. Default ''\n"
10719 " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
10720 " -quote set output mode to 'quote'\n"
drhee269a62018-02-14 23:27:43 +000010721 " -readonly open the database read-only\n"
drh2ce15c32017-07-11 13:34:40 +000010722 " -separator SEP set output column separator. Default: '|'\n"
drha90d84f2018-04-18 15:21:13 +000010723#ifdef SQLITE_ENABLE_SORTER_REFERENCES
10724 " -sorterref SIZE sorter references threshold size\n"
10725#endif
drh2ce15c32017-07-11 13:34:40 +000010726 " -stats print memory stats before each finalize\n"
drh30c54a02020-05-28 23:49:50 +000010727 " -table set output mode to 'table'\n"
drh2fa78182020-10-31 18:58:37 +000010728 " -tabs set output mode to 'tabs'\n"
drh2ce15c32017-07-11 13:34:40 +000010729 " -version show SQLite version\n"
10730 " -vfs NAME use NAME as the default VFS\n"
10731#ifdef SQLITE_ENABLE_VFSTRACE
10732 " -vfstrace enable tracing of all VFS calls\n"
10733#endif
drh3baed312018-03-08 18:14:41 +000010734#ifdef SQLITE_HAVE_ZLIB
10735 " -zip open the file as a ZIP Archive\n"
10736#endif
drh2ce15c32017-07-11 13:34:40 +000010737;
10738static void usage(int showDetail){
10739 utf8_printf(stderr,
10740 "Usage: %s [OPTIONS] FILENAME [SQL]\n"
10741 "FILENAME is the name of an SQLite database. A new database is created\n"
10742 "if the file does not previously exist.\n", Argv0);
10743 if( showDetail ){
10744 utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
10745 }else{
10746 raw_printf(stderr, "Use the -help option for additional information\n");
10747 }
10748 exit(1);
10749}
10750
10751/*
drhe7df8922018-04-18 10:44:58 +000010752** Internal check: Verify that the SQLite is uninitialized. Print a
10753** error message if it is initialized.
10754*/
10755static void verify_uninitialized(void){
10756 if( sqlite3_config(-1)==SQLITE_MISUSE ){
drh8e02a182018-05-30 07:24:41 +000010757 utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
drhe7df8922018-04-18 10:44:58 +000010758 " initialization.\n");
10759 }
10760}
10761
10762/*
drh2ce15c32017-07-11 13:34:40 +000010763** Initialize the state information in data
10764*/
10765static void main_init(ShellState *data) {
10766 memset(data, 0, sizeof(*data));
10767 data->normalMode = data->cMode = data->mode = MODE_List;
10768 data->autoExplain = 1;
10769 memcpy(data->colSeparator,SEP_Column, 2);
10770 memcpy(data->rowSeparator,SEP_Row, 2);
10771 data->showHeader = 0;
10772 data->shellFlgs = SHFLG_Lookaside;
drhe7df8922018-04-18 10:44:58 +000010773 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000010774 sqlite3_config(SQLITE_CONFIG_URI, 1);
10775 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
10776 sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
10777 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
10778 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
10779}
10780
10781/*
10782** Output text to the console in a font that attracts extra attention.
10783*/
10784#ifdef _WIN32
10785static void printBold(const char *zText){
mistachkin43e86272020-04-09 15:31:22 +000010786#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000010787 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
10788 CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
10789 GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
10790 SetConsoleTextAttribute(out,
10791 FOREGROUND_RED|FOREGROUND_INTENSITY
10792 );
mistachkin43e86272020-04-09 15:31:22 +000010793#endif
drh2ce15c32017-07-11 13:34:40 +000010794 printf("%s", zText);
mistachkin43e86272020-04-09 15:31:22 +000010795#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000010796 SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
mistachkin43e86272020-04-09 15:31:22 +000010797#endif
drh2ce15c32017-07-11 13:34:40 +000010798}
10799#else
10800static void printBold(const char *zText){
10801 printf("\033[1m%s\033[0m", zText);
10802}
10803#endif
10804
10805/*
10806** Get the argument to an --option. Throw an error and die if no argument
10807** is available.
10808*/
10809static char *cmdline_option_value(int argc, char **argv, int i){
10810 if( i==argc ){
10811 utf8_printf(stderr, "%s: Error: missing argument to %s\n",
10812 argv[0], argv[argc-1]);
10813 exit(1);
10814 }
10815 return argv[i];
10816}
10817
10818#ifndef SQLITE_SHELL_IS_UTF8
10819# if (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
10820# define SQLITE_SHELL_IS_UTF8 (0)
10821# else
10822# define SQLITE_SHELL_IS_UTF8 (1)
10823# endif
10824#endif
10825
10826#if SQLITE_SHELL_IS_UTF8
10827int SQLITE_CDECL main(int argc, char **argv){
10828#else
10829int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
10830 char **argv;
10831#endif
10832 char *zErrMsg = 0;
10833 ShellState data;
10834 const char *zInitFile = 0;
10835 int i;
10836 int rc = 0;
10837 int warnInmemoryDb = 0;
10838 int readStdin = 1;
10839 int nCmd = 0;
10840 char **azCmd = 0;
dan16a47422018-04-18 09:16:11 +000010841 const char *zVfs = 0; /* Value of -vfs command-line option */
drh1f22f622018-05-17 13:29:14 +000010842#if !SQLITE_SHELL_IS_UTF8
10843 char **argvToFree = 0;
10844 int argcToFree = 0;
10845#endif
drh2ce15c32017-07-11 13:34:40 +000010846
10847 setBinaryMode(stdin, 0);
10848 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
10849 stdin_is_interactive = isatty(0);
10850 stdout_is_console = isatty(1);
10851
drh4a3a3eb2020-02-29 15:53:48 +000010852#ifdef SQLITE_DEBUG
10853 registerOomSimulator();
10854#endif
10855
mistachkin1e8487d2018-07-22 06:25:35 +000010856#if !defined(_WIN32_WCE)
10857 if( getenv("SQLITE_DEBUG_BREAK") ){
10858 if( isatty(0) && isatty(2) ){
10859 fprintf(stderr,
10860 "attach debugger to process %d and press any key to continue.\n",
10861 GETPID());
10862 fgetc(stdin);
10863 }else{
10864#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +000010865#if SQLITE_OS_WINRT
10866 __debugbreak();
10867#else
mistachkin1e8487d2018-07-22 06:25:35 +000010868 DebugBreak();
mistachkin43e86272020-04-09 15:31:22 +000010869#endif
mistachkin1e8487d2018-07-22 06:25:35 +000010870#elif defined(SIGTRAP)
10871 raise(SIGTRAP);
10872#endif
10873 }
10874 }
10875#endif
10876
drh2ce15c32017-07-11 13:34:40 +000010877#if USE_SYSTEM_SQLITE+0!=1
drhb3c45232017-08-28 14:33:27 +000010878 if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
drh2ce15c32017-07-11 13:34:40 +000010879 utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
10880 sqlite3_sourceid(), SQLITE_SOURCE_ID);
10881 exit(1);
10882 }
10883#endif
10884 main_init(&data);
drh501ea052018-02-15 01:03:37 +000010885
10886 /* On Windows, we must translate command-line arguments into UTF-8.
10887 ** The SQLite memory allocator subsystem has to be enabled in order to
10888 ** do this. But we want to run an sqlite3_shutdown() afterwards so that
10889 ** subsequent sqlite3_config() calls will work. So copy all results into
10890 ** memory that does not come from the SQLite memory allocator.
10891 */
drh4b18c1d2018-02-04 20:33:13 +000010892#if !SQLITE_SHELL_IS_UTF8
drh501ea052018-02-15 01:03:37 +000010893 sqlite3_initialize();
drh1f22f622018-05-17 13:29:14 +000010894 argvToFree = malloc(sizeof(argv[0])*argc*2);
10895 argcToFree = argc;
10896 argv = argvToFree + argc;
drh4b5345c2018-04-24 13:07:40 +000010897 if( argv==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +000010898 for(i=0; i<argc; i++){
drh501ea052018-02-15 01:03:37 +000010899 char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
10900 int n;
drh4b5345c2018-04-24 13:07:40 +000010901 if( z==0 ) shell_out_of_memory();
drh501ea052018-02-15 01:03:37 +000010902 n = (int)strlen(z);
10903 argv[i] = malloc( n+1 );
drh4b5345c2018-04-24 13:07:40 +000010904 if( argv[i]==0 ) shell_out_of_memory();
drh501ea052018-02-15 01:03:37 +000010905 memcpy(argv[i], z, n+1);
drh1f22f622018-05-17 13:29:14 +000010906 argvToFree[i] = argv[i];
drh501ea052018-02-15 01:03:37 +000010907 sqlite3_free(z);
drh2ce15c32017-07-11 13:34:40 +000010908 }
drh501ea052018-02-15 01:03:37 +000010909 sqlite3_shutdown();
drh2ce15c32017-07-11 13:34:40 +000010910#endif
drh501ea052018-02-15 01:03:37 +000010911
drh2ce15c32017-07-11 13:34:40 +000010912 assert( argc>=1 && argv && argv[0] );
10913 Argv0 = argv[0];
10914
10915 /* Make sure we have a valid signal handler early, before anything
10916 ** else is done.
10917 */
10918#ifdef SIGINT
10919 signal(SIGINT, interrupt_handler);
mistachkinb4bab902017-10-27 17:09:44 +000010920#elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
10921 SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
drh2ce15c32017-07-11 13:34:40 +000010922#endif
10923
10924#ifdef SQLITE_SHELL_DBNAME_PROC
10925 {
10926 /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
10927 ** of a C-function that will provide the name of the database file. Use
10928 ** this compile-time option to embed this shell program in larger
10929 ** applications. */
10930 extern void SQLITE_SHELL_DBNAME_PROC(const char**);
10931 SQLITE_SHELL_DBNAME_PROC(&data.zDbFilename);
10932 warnInmemoryDb = 0;
10933 }
10934#endif
10935
10936 /* Do an initial pass through the command-line argument to locate
10937 ** the name of the database file, the name of the initialization file,
10938 ** the size of the alternative malloc heap,
10939 ** and the first command to execute.
10940 */
drhe7df8922018-04-18 10:44:58 +000010941 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000010942 for(i=1; i<argc; i++){
10943 char *z;
10944 z = argv[i];
10945 if( z[0]!='-' ){
10946 if( data.zDbFilename==0 ){
10947 data.zDbFilename = z;
10948 }else{
10949 /* Excesss arguments are interpreted as SQL (or dot-commands) and
10950 ** mean that nothing is read from stdin */
10951 readStdin = 0;
10952 nCmd++;
10953 azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
drh4b5345c2018-04-24 13:07:40 +000010954 if( azCmd==0 ) shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +000010955 azCmd[nCmd-1] = z;
10956 }
10957 }
10958 if( z[1]=='-' ) z++;
10959 if( strcmp(z,"-separator")==0
10960 || strcmp(z,"-nullvalue")==0
10961 || strcmp(z,"-newline")==0
10962 || strcmp(z,"-cmd")==0
10963 ){
10964 (void)cmdline_option_value(argc, argv, ++i);
10965 }else if( strcmp(z,"-init")==0 ){
10966 zInitFile = cmdline_option_value(argc, argv, ++i);
10967 }else if( strcmp(z,"-batch")==0 ){
10968 /* Need to check for batch mode here to so we can avoid printing
10969 ** informational messages (like from process_sqliterc) before
10970 ** we do the actual processing of arguments later in a second pass.
10971 */
10972 stdin_is_interactive = 0;
10973 }else if( strcmp(z,"-heap")==0 ){
10974#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
10975 const char *zSize;
10976 sqlite3_int64 szHeap;
10977
10978 zSize = cmdline_option_value(argc, argv, ++i);
10979 szHeap = integerValue(zSize);
10980 if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
10981 sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
10982#else
10983 (void)cmdline_option_value(argc, argv, ++i);
10984#endif
drh2ce15c32017-07-11 13:34:40 +000010985 }else if( strcmp(z,"-pagecache")==0 ){
drhf573b4f2020-09-28 13:34:05 +000010986 sqlite3_int64 n, sz;
10987 sz = integerValue(cmdline_option_value(argc,argv,++i));
drh2ce15c32017-07-11 13:34:40 +000010988 if( sz>70000 ) sz = 70000;
10989 if( sz<0 ) sz = 0;
drhf573b4f2020-09-28 13:34:05 +000010990 n = integerValue(cmdline_option_value(argc,argv,++i));
10991 if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
10992 n = 0xffffffffffffLL/sz;
10993 }
drh2ce15c32017-07-11 13:34:40 +000010994 sqlite3_config(SQLITE_CONFIG_PAGECACHE,
10995 (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
10996 data.shellFlgs |= SHFLG_Pagecache;
10997 }else if( strcmp(z,"-lookaside")==0 ){
10998 int n, sz;
10999 sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
11000 if( sz<0 ) sz = 0;
11001 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
11002 if( n<0 ) n = 0;
11003 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
11004 if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
11005#ifdef SQLITE_ENABLE_VFSTRACE
11006 }else if( strcmp(z,"-vfstrace")==0 ){
11007 extern int vfstrace_register(
11008 const char *zTraceName,
11009 const char *zOldVfsName,
11010 int (*xOut)(const char*,void*),
11011 void *pOutArg,
11012 int makeDefault
11013 );
11014 vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
11015#endif
11016#ifdef SQLITE_ENABLE_MULTIPLEX
11017 }else if( strcmp(z,"-multiplex")==0 ){
11018 extern int sqlite3_multiple_initialize(const char*,int);
11019 sqlite3_multiplex_initialize(0, 1);
11020#endif
11021 }else if( strcmp(z,"-mmap")==0 ){
11022 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
11023 sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
drha90d84f2018-04-18 15:21:13 +000011024#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11025 }else if( strcmp(z,"-sorterref")==0 ){
11026 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
11027 sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz);
11028#endif
drh2ce15c32017-07-11 13:34:40 +000011029 }else if( strcmp(z,"-vfs")==0 ){
dan16a47422018-04-18 09:16:11 +000011030 zVfs = cmdline_option_value(argc, argv, ++i);
drh3baed312018-03-08 18:14:41 +000011031#ifdef SQLITE_HAVE_ZLIB
drh8682e122018-01-07 20:38:10 +000011032 }else if( strcmp(z,"-zip")==0 ){
11033 data.openMode = SHELL_OPEN_ZIPFILE;
11034#endif
11035 }else if( strcmp(z,"-append")==0 ){
11036 data.openMode = SHELL_OPEN_APPENDVFS;
drha751f392018-10-30 15:31:22 +000011037#ifdef SQLITE_ENABLE_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +000011038 }else if( strcmp(z,"-deserialize")==0 ){
11039 data.openMode = SHELL_OPEN_DESERIALIZE;
drh6ca64482019-01-22 16:06:20 +000011040 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
11041 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000011042#endif
drhee269a62018-02-14 23:27:43 +000011043 }else if( strcmp(z,"-readonly")==0 ){
11044 data.openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +000011045 }else if( strcmp(z,"-nofollow")==0 ){
11046 data.openFlags = SQLITE_OPEN_NOFOLLOW;
drhda57d962018-03-05 19:34:05 +000011047#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drh93b77312018-03-05 20:20:22 +000011048 }else if( strncmp(z, "-A",2)==0 ){
drhda57d962018-03-05 19:34:05 +000011049 /* All remaining command-line arguments are passed to the ".archive"
11050 ** command, so ignore them */
11051 break;
11052#endif
drh50b910a2019-01-21 14:55:03 +000011053 }else if( strcmp(z, "-memtrace")==0 ){
11054 sqlite3MemTraceActivate(stderr);
drhb7c46aa2020-11-25 13:59:47 +000011055 }else if( strcmp(z,"-bail")==0 ){
11056 bail_on_error = 1;
drh2ce15c32017-07-11 13:34:40 +000011057 }
11058 }
drhe7df8922018-04-18 10:44:58 +000011059 verify_uninitialized();
11060
dan16a47422018-04-18 09:16:11 +000011061
drhd11b8f62018-04-25 13:27:07 +000011062#ifdef SQLITE_SHELL_INIT_PROC
11063 {
11064 /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name
11065 ** of a C-function that will perform initialization actions on SQLite that
11066 ** occur just before or after sqlite3_initialize(). Use this compile-time
11067 ** option to embed this shell program in larger applications. */
11068 extern void SQLITE_SHELL_INIT_PROC(void);
11069 SQLITE_SHELL_INIT_PROC();
11070 }
11071#else
dan16a47422018-04-18 09:16:11 +000011072 /* All the sqlite3_config() calls have now been made. So it is safe
11073 ** to call sqlite3_initialize() and process any command line -vfs option. */
11074 sqlite3_initialize();
drhd11b8f62018-04-25 13:27:07 +000011075#endif
11076
dan16a47422018-04-18 09:16:11 +000011077 if( zVfs ){
11078 sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
11079 if( pVfs ){
11080 sqlite3_vfs_register(pVfs, 1);
11081 }else{
11082 utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
11083 exit(1);
11084 }
11085 }
11086
drh2ce15c32017-07-11 13:34:40 +000011087 if( data.zDbFilename==0 ){
11088#ifndef SQLITE_OMIT_MEMORYDB
11089 data.zDbFilename = ":memory:";
11090 warnInmemoryDb = argc==1;
11091#else
11092 utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
11093 return 1;
11094#endif
11095 }
11096 data.out = stdout;
drh8682e122018-01-07 20:38:10 +000011097 sqlite3_appendvfs_init(0,0,0);
drh2ce15c32017-07-11 13:34:40 +000011098
11099 /* Go ahead and open the database file if it already exists. If the
11100 ** file does not exist, delay opening it. This prevents empty database
11101 ** files from being created if a user mistypes the database name argument
11102 ** to the sqlite command-line tool.
11103 */
11104 if( access(data.zDbFilename, 0)==0 ){
11105 open_db(&data, 0);
11106 }
11107
11108 /* Process the initialization file if there is one. If no -init option
11109 ** is given on the command line, look for a file named ~/.sqliterc and
11110 ** try to process it.
11111 */
11112 process_sqliterc(&data,zInitFile);
11113
11114 /* Make a second pass through the command-line argument and set
11115 ** options. This second pass is delayed until after the initialization
11116 ** file is processed so that the command-line arguments will override
11117 ** settings in the initialization file.
11118 */
11119 for(i=1; i<argc; i++){
11120 char *z = argv[i];
11121 if( z[0]!='-' ) continue;
11122 if( z[1]=='-' ){ z++; }
11123 if( strcmp(z,"-init")==0 ){
11124 i++;
11125 }else if( strcmp(z,"-html")==0 ){
11126 data.mode = MODE_Html;
11127 }else if( strcmp(z,"-list")==0 ){
11128 data.mode = MODE_List;
11129 }else if( strcmp(z,"-quote")==0 ){
11130 data.mode = MODE_Quote;
drh9191c702020-08-17 09:11:21 +000011131 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma);
11132 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +000011133 }else if( strcmp(z,"-line")==0 ){
11134 data.mode = MODE_Line;
11135 }else if( strcmp(z,"-column")==0 ){
11136 data.mode = MODE_Column;
drh30c54a02020-05-28 23:49:50 +000011137 }else if( strcmp(z,"-json")==0 ){
11138 data.mode = MODE_Json;
11139 }else if( strcmp(z,"-markdown")==0 ){
11140 data.mode = MODE_Markdown;
11141 }else if( strcmp(z,"-table")==0 ){
11142 data.mode = MODE_Table;
drh0908e382020-06-04 18:05:39 +000011143 }else if( strcmp(z,"-box")==0 ){
11144 data.mode = MODE_Box;
drh2ce15c32017-07-11 13:34:40 +000011145 }else if( strcmp(z,"-csv")==0 ){
11146 data.mode = MODE_Csv;
11147 memcpy(data.colSeparator,",",2);
drh3baed312018-03-08 18:14:41 +000011148#ifdef SQLITE_HAVE_ZLIB
drh1fa6d9f2018-01-06 21:46:01 +000011149 }else if( strcmp(z,"-zip")==0 ){
11150 data.openMode = SHELL_OPEN_ZIPFILE;
11151#endif
11152 }else if( strcmp(z,"-append")==0 ){
11153 data.openMode = SHELL_OPEN_APPENDVFS;
drha751f392018-10-30 15:31:22 +000011154#ifdef SQLITE_ENABLE_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +000011155 }else if( strcmp(z,"-deserialize")==0 ){
11156 data.openMode = SHELL_OPEN_DESERIALIZE;
drh6ca64482019-01-22 16:06:20 +000011157 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
11158 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000011159#endif
drh4aafe592018-03-23 16:08:30 +000011160 }else if( strcmp(z,"-readonly")==0 ){
11161 data.openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +000011162 }else if( strcmp(z,"-nofollow")==0 ){
11163 data.openFlags |= SQLITE_OPEN_NOFOLLOW;
drh2ce15c32017-07-11 13:34:40 +000011164 }else if( strcmp(z,"-ascii")==0 ){
11165 data.mode = MODE_Ascii;
drh2fa78182020-10-31 18:58:37 +000011166 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit);
11167 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record);
11168 }else if( strcmp(z,"-tabs")==0 ){
11169 data.mode = MODE_List;
11170 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Tab);
11171 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +000011172 }else if( strcmp(z,"-separator")==0 ){
11173 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
11174 "%s",cmdline_option_value(argc,argv,++i));
11175 }else if( strcmp(z,"-newline")==0 ){
11176 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
11177 "%s",cmdline_option_value(argc,argv,++i));
11178 }else if( strcmp(z,"-nullvalue")==0 ){
11179 sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
11180 "%s",cmdline_option_value(argc,argv,++i));
11181 }else if( strcmp(z,"-header")==0 ){
11182 data.showHeader = 1;
11183 }else if( strcmp(z,"-noheader")==0 ){
11184 data.showHeader = 0;
11185 }else if( strcmp(z,"-echo")==0 ){
11186 ShellSetFlag(&data, SHFLG_Echo);
11187 }else if( strcmp(z,"-eqp")==0 ){
drhada70452017-12-21 21:02:27 +000011188 data.autoEQP = AUTOEQP_on;
drh2ce15c32017-07-11 13:34:40 +000011189 }else if( strcmp(z,"-eqpfull")==0 ){
drhada70452017-12-21 21:02:27 +000011190 data.autoEQP = AUTOEQP_full;
drh2ce15c32017-07-11 13:34:40 +000011191 }else if( strcmp(z,"-stats")==0 ){
11192 data.statsOn = 1;
11193 }else if( strcmp(z,"-scanstats")==0 ){
11194 data.scanstatsOn = 1;
11195 }else if( strcmp(z,"-backslash")==0 ){
11196 /* Undocumented command-line option: -backslash
11197 ** Causes C-style backslash escapes to be evaluated in SQL statements
11198 ** prior to sending the SQL into SQLite. Useful for injecting
11199 ** crazy bytes in the middle of SQL statements for testing and debugging.
11200 */
11201 ShellSetFlag(&data, SHFLG_Backslash);
11202 }else if( strcmp(z,"-bail")==0 ){
drhb7c46aa2020-11-25 13:59:47 +000011203 /* No-op. The bail_on_error flag should already be set. */
drh2ce15c32017-07-11 13:34:40 +000011204 }else if( strcmp(z,"-version")==0 ){
11205 printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
11206 return 0;
11207 }else if( strcmp(z,"-interactive")==0 ){
11208 stdin_is_interactive = 1;
11209 }else if( strcmp(z,"-batch")==0 ){
11210 stdin_is_interactive = 0;
11211 }else if( strcmp(z,"-heap")==0 ){
11212 i++;
drh2ce15c32017-07-11 13:34:40 +000011213 }else if( strcmp(z,"-pagecache")==0 ){
11214 i+=2;
11215 }else if( strcmp(z,"-lookaside")==0 ){
11216 i+=2;
11217 }else if( strcmp(z,"-mmap")==0 ){
11218 i++;
drh50b910a2019-01-21 14:55:03 +000011219 }else if( strcmp(z,"-memtrace")==0 ){
11220 i++;
drha90d84f2018-04-18 15:21:13 +000011221#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11222 }else if( strcmp(z,"-sorterref")==0 ){
11223 i++;
11224#endif
drh2ce15c32017-07-11 13:34:40 +000011225 }else if( strcmp(z,"-vfs")==0 ){
11226 i++;
11227#ifdef SQLITE_ENABLE_VFSTRACE
11228 }else if( strcmp(z,"-vfstrace")==0 ){
11229 i++;
11230#endif
11231#ifdef SQLITE_ENABLE_MULTIPLEX
11232 }else if( strcmp(z,"-multiplex")==0 ){
11233 i++;
11234#endif
11235 }else if( strcmp(z,"-help")==0 ){
11236 usage(1);
11237 }else if( strcmp(z,"-cmd")==0 ){
11238 /* Run commands that follow -cmd first and separately from commands
11239 ** that simply appear on the command-line. This seems goofy. It would
11240 ** be better if all commands ran in the order that they appear. But
11241 ** we retain the goofy behavior for historical compatibility. */
11242 if( i==argc-1 ) break;
11243 z = cmdline_option_value(argc,argv,++i);
11244 if( z[0]=='.' ){
11245 rc = do_meta_command(z, &data);
11246 if( rc && bail_on_error ) return rc==2 ? 0 : rc;
11247 }else{
11248 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000011249 rc = shell_exec(&data, z, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000011250 if( zErrMsg!=0 ){
11251 utf8_printf(stderr,"Error: %s\n", zErrMsg);
11252 if( bail_on_error ) return rc!=0 ? rc : 1;
11253 }else if( rc!=0 ){
11254 utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
11255 if( bail_on_error ) return rc;
11256 }
11257 }
drhda57d962018-03-05 19:34:05 +000011258#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drh93b77312018-03-05 20:20:22 +000011259 }else if( strncmp(z, "-A", 2)==0 ){
drhda57d962018-03-05 19:34:05 +000011260 if( nCmd>0 ){
11261 utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
11262 " with \"%s\"\n", z);
11263 return 1;
11264 }
drhbe4ccb22018-05-17 20:04:24 +000011265 open_db(&data, OPEN_DB_ZIPFILE);
drh93b77312018-03-05 20:20:22 +000011266 if( z[2] ){
11267 argv[i] = &z[2];
drhd0f9cdc2018-05-17 14:09:06 +000011268 arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
drh93b77312018-03-05 20:20:22 +000011269 }else{
drhd0f9cdc2018-05-17 14:09:06 +000011270 arDotCommand(&data, 1, argv+i, argc-i);
drh93b77312018-03-05 20:20:22 +000011271 }
drhda57d962018-03-05 19:34:05 +000011272 readStdin = 0;
11273 break;
11274#endif
drh2ce15c32017-07-11 13:34:40 +000011275 }else{
11276 utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
11277 raw_printf(stderr,"Use -help for a list of options.\n");
11278 return 1;
11279 }
11280 data.cMode = data.mode;
11281 }
11282
11283 if( !readStdin ){
11284 /* Run all arguments that do not begin with '-' as if they were separate
11285 ** command-line inputs, except for the argToSkip argument which contains
11286 ** the database filename.
11287 */
11288 for(i=0; i<nCmd; i++){
11289 if( azCmd[i][0]=='.' ){
11290 rc = do_meta_command(azCmd[i], &data);
danaff1a572020-11-17 21:09:56 +000011291 if( rc ){
11292 free(azCmd);
11293 return rc==2 ? 0 : rc;
11294 }
drh2ce15c32017-07-11 13:34:40 +000011295 }else{
11296 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000011297 rc = shell_exec(&data, azCmd[i], &zErrMsg);
danaff1a572020-11-17 21:09:56 +000011298 if( zErrMsg || rc ){
11299 if( zErrMsg!=0 ){
11300 utf8_printf(stderr,"Error: %s\n", zErrMsg);
11301 }else{
11302 utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
11303 }
11304 sqlite3_free(zErrMsg);
11305 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000011306 return rc!=0 ? rc : 1;
drh2ce15c32017-07-11 13:34:40 +000011307 }
11308 }
11309 }
drh2ce15c32017-07-11 13:34:40 +000011310 }else{
11311 /* Run commands received from standard input
11312 */
11313 if( stdin_is_interactive ){
11314 char *zHome;
drha9e4be32018-10-10 18:56:40 +000011315 char *zHistory;
drh2ce15c32017-07-11 13:34:40 +000011316 int nHistory;
11317 printf(
11318 "SQLite version %s %.19s\n" /*extra-version-info*/
11319 "Enter \".help\" for usage hints.\n",
11320 sqlite3_libversion(), sqlite3_sourceid()
11321 );
11322 if( warnInmemoryDb ){
11323 printf("Connected to a ");
11324 printBold("transient in-memory database");
11325 printf(".\nUse \".open FILENAME\" to reopen on a "
11326 "persistent database.\n");
11327 }
drha9e4be32018-10-10 18:56:40 +000011328 zHistory = getenv("SQLITE_HISTORY");
11329 if( zHistory ){
11330 zHistory = strdup(zHistory);
11331 }else if( (zHome = find_home_dir(0))!=0 ){
drh2ce15c32017-07-11 13:34:40 +000011332 nHistory = strlen30(zHome) + 20;
11333 if( (zHistory = malloc(nHistory))!=0 ){
11334 sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
11335 }
11336 }
11337 if( zHistory ){ shell_read_history(zHistory); }
drh56eb09b2017-07-11 13:59:07 +000011338#if HAVE_READLINE || HAVE_EDITLINE
11339 rl_attempted_completion_function = readline_completion;
11340#elif HAVE_LINENOISE
11341 linenoiseSetCompletionCallback(linenoise_completion);
11342#endif
drh60379d42018-12-13 18:30:01 +000011343 data.in = 0;
11344 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000011345 if( zHistory ){
drh5a75dd82017-07-18 20:59:40 +000011346 shell_stifle_history(2000);
drh2ce15c32017-07-11 13:34:40 +000011347 shell_write_history(zHistory);
11348 free(zHistory);
11349 }
11350 }else{
drh60379d42018-12-13 18:30:01 +000011351 data.in = stdin;
11352 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000011353 }
11354 }
danaff1a572020-11-17 21:09:56 +000011355 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000011356 set_table_name(&data, 0);
11357 if( data.db ){
11358 session_close_all(&data);
drh9e804032018-05-18 17:11:50 +000011359 close_db(data.db);
drh2ce15c32017-07-11 13:34:40 +000011360 }
11361 sqlite3_free(data.zFreeOnClose);
11362 find_home_dir(1);
drh536c3452018-01-11 00:38:39 +000011363 output_reset(&data);
11364 data.doXdgOpen = 0;
drh13c20932018-01-10 21:41:55 +000011365 clearTempFile(&data);
drh2ce15c32017-07-11 13:34:40 +000011366#if !SQLITE_SHELL_IS_UTF8
drh1f22f622018-05-17 13:29:14 +000011367 for(i=0; i<argcToFree; i++) free(argvToFree[i]);
11368 free(argvToFree);
drh2ce15c32017-07-11 13:34:40 +000011369#endif
drh0285d982020-05-29 14:38:43 +000011370 free(data.colWidth);
drh9e804032018-05-18 17:11:50 +000011371 /* Clear the global data structure so that valgrind will detect memory
11372 ** leaks */
11373 memset(&data, 0, sizeof(data));
drh2ce15c32017-07-11 13:34:40 +000011374 return rc;
11375}