blob: dba42e817f939a71613406460f0a4f55482e56c9 [file] [log] [blame]
drh2ce15c32017-07-11 13:34:40 +00001/*
2** 2001 September 15
3**
4** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
6**
7** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
10**
11*************************************************************************
12** This file contains code to implement the "sqlite" command line
13** utility for accessing SQLite databases.
14*/
15#if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
16/* This needs to come before any includes for MSVC compiler */
17#define _CRT_SECURE_NO_WARNINGS
18#endif
19
20/*
larrybra13c0c72021-07-09 00:12:05 +000021** Optionally #include a user-defined header, whereby compilation options
22** may be set prior to where they take effect, but after platform setup.
23** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include
24** file. Note that this macro has a like effect on sqlite3.c compilation.
25*/
larrybr78138392022-02-12 02:15:37 +000026# define SHELL_STRINGIFY_(f) #f
27# define SHELL_STRINGIFY(f) SHELL_STRINGIFY_(f)
larrybra13c0c72021-07-09 00:12:05 +000028#ifdef SQLITE_CUSTOM_INCLUDE
larrybr78138392022-02-12 02:15:37 +000029# include SHELL_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
larrybra13c0c72021-07-09 00:12:05 +000030#endif
31
32/*
mistachkin43e86272020-04-09 15:31:22 +000033** Determine if we are dealing with WinRT, which provides only a subset of
34** the full Win32 API.
35*/
36#if !defined(SQLITE_OS_WINRT)
37# define SQLITE_OS_WINRT 0
38#endif
39
40/*
drh2ce15c32017-07-11 13:34:40 +000041** Warning pragmas copied from msvc.h in the core.
42*/
43#if defined(_MSC_VER)
44#pragma warning(disable : 4054)
45#pragma warning(disable : 4055)
46#pragma warning(disable : 4100)
47#pragma warning(disable : 4127)
48#pragma warning(disable : 4130)
49#pragma warning(disable : 4152)
50#pragma warning(disable : 4189)
51#pragma warning(disable : 4206)
52#pragma warning(disable : 4210)
53#pragma warning(disable : 4232)
54#pragma warning(disable : 4244)
55#pragma warning(disable : 4305)
56#pragma warning(disable : 4306)
57#pragma warning(disable : 4702)
58#pragma warning(disable : 4706)
59#endif /* defined(_MSC_VER) */
60
61/*
62** No support for loadable extensions in VxWorks.
63*/
64#if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION
65# define SQLITE_OMIT_LOAD_EXTENSION 1
66#endif
67
68/*
69** Enable large-file support for fopen() and friends on unix.
70*/
71#ifndef SQLITE_DISABLE_LFS
72# define _LARGE_FILE 1
73# ifndef _FILE_OFFSET_BITS
74# define _FILE_OFFSET_BITS 64
75# endif
76# define _LARGEFILE_SOURCE 1
77#endif
78
79#include <stdlib.h>
80#include <string.h>
81#include <stdio.h>
82#include <assert.h>
83#include "sqlite3.h"
drh1e506b52018-01-05 21:01:37 +000084typedef sqlite3_int64 i64;
85typedef sqlite3_uint64 u64;
drh1fa6d9f2018-01-06 21:46:01 +000086typedef unsigned char u8;
drh2ce15c32017-07-11 13:34:40 +000087#if SQLITE_USER_AUTHENTICATION
88# include "sqlite3userauth.h"
89#endif
90#include <ctype.h>
91#include <stdarg.h>
92
93#if !defined(_WIN32) && !defined(WIN32)
94# include <signal.h>
95# if !defined(__RTP__) && !defined(_WRS_KERNEL)
96# include <pwd.h>
97# endif
mistachkinacae8c32018-01-05 20:08:46 +000098#endif
mistachkin562f0c82018-01-09 00:28:24 +000099#if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__)
drh2ce15c32017-07-11 13:34:40 +0000100# include <unistd.h>
mistachkinacae8c32018-01-05 20:08:46 +0000101# include <dirent.h>
mistachkin1e8487d2018-07-22 06:25:35 +0000102# define GETPID getpid
mistachkin562f0c82018-01-09 00:28:24 +0000103# if defined(__MINGW32__)
mistachkinacae8c32018-01-05 20:08:46 +0000104# define DIRENT dirent
mistachkin2f74b3c2018-01-05 20:26:06 +0000105# ifndef S_ISLNK
106# define S_ISLNK(mode) (0)
107# endif
mistachkinacae8c32018-01-05 20:08:46 +0000108# endif
mistachkin1e8487d2018-07-22 06:25:35 +0000109#else
110# define GETPID (int)GetCurrentProcessId
drh2ce15c32017-07-11 13:34:40 +0000111#endif
mistachkindfdfd8c2018-01-04 22:46:08 +0000112#include <sys/types.h>
113#include <sys/stat.h>
drh2ce15c32017-07-11 13:34:40 +0000114
115#if HAVE_READLINE
116# include <readline/readline.h>
117# include <readline/history.h>
118#endif
119
120#if HAVE_EDITLINE
121# include <editline/readline.h>
122#endif
123
124#if HAVE_EDITLINE || HAVE_READLINE
125
126# define shell_add_history(X) add_history(X)
127# define shell_read_history(X) read_history(X)
128# define shell_write_history(X) write_history(X)
129# define shell_stifle_history(X) stifle_history(X)
130# define shell_readline(X) readline(X)
131
132#elif HAVE_LINENOISE
133
134# include "linenoise.h"
135# define shell_add_history(X) linenoiseHistoryAdd(X)
136# define shell_read_history(X) linenoiseHistoryLoad(X)
137# define shell_write_history(X) linenoiseHistorySave(X)
138# define shell_stifle_history(X) linenoiseHistorySetMaxLen(X)
139# define shell_readline(X) linenoise(X)
140
141#else
142
143# define shell_read_history(X)
144# define shell_write_history(X)
145# define shell_stifle_history(X)
146
147# define SHELL_USE_LOCAL_GETLINE 1
148#endif
149
150
151#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +0000152# if SQLITE_OS_WINRT
153# define SQLITE_OMIT_POPEN 1
154# else
155# include <io.h>
156# include <fcntl.h>
157# define isatty(h) _isatty(h)
158# ifndef access
159# define access(f,m) _access((f),(m))
160# endif
161# ifndef unlink
162# define unlink _unlink
163# endif
164# ifndef strdup
165# define strdup _strdup
166# endif
167# undef popen
168# define popen _popen
169# undef pclose
170# define pclose _pclose
drh2ce15c32017-07-11 13:34:40 +0000171# endif
drh2ce15c32017-07-11 13:34:40 +0000172#else
173 /* Make sure isatty() has a prototype. */
174 extern int isatty(int);
175
176# if !defined(__RTP__) && !defined(_WRS_KERNEL)
177 /* popen and pclose are not C89 functions and so are
178 ** sometimes omitted from the <stdio.h> header */
179 extern FILE *popen(const char*,const char*);
180 extern int pclose(FILE*);
181# else
182# define SQLITE_OMIT_POPEN 1
183# endif
184#endif
185
186#if defined(_WIN32_WCE)
187/* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty()
188 * thus we always assume that we have a console. That can be
189 * overridden with the -batch command line option.
190 */
191#define isatty(x) 1
192#endif
193
194/* ctype macros that work with signed characters */
195#define IsSpace(X) isspace((unsigned char)X)
196#define IsDigit(X) isdigit((unsigned char)X)
197#define ToLower(X) (char)tolower((unsigned char)X)
198
199#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +0000200#if SQLITE_OS_WINRT
201#include <intrin.h>
202#endif
drh2ce15c32017-07-11 13:34:40 +0000203#include <windows.h>
204
205/* string conversion routines only needed on Win32 */
206extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
207extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int);
208extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int);
209extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
210#endif
211
212/* On Windows, we normally run with output mode of TEXT so that \n characters
213** are automatically translated into \r\n. However, this behavior needs
214** to be disabled in some cases (ex: when generating CSV output and when
215** rendering quoted strings that contain \n characters). The following
216** routines take care of that.
217*/
mistachkin43e86272020-04-09 15:31:22 +0000218#if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +0000219static void setBinaryMode(FILE *file, int isOutput){
220 if( isOutput ) fflush(file);
221 _setmode(_fileno(file), _O_BINARY);
222}
223static void setTextMode(FILE *file, int isOutput){
224 if( isOutput ) fflush(file);
225 _setmode(_fileno(file), _O_TEXT);
226}
227#else
228# define setBinaryMode(X,Y)
229# define setTextMode(X,Y)
230#endif
231
232
233/* True if the timer is enabled */
234static int enableTimer = 0;
235
236/* Return the current wall-clock time */
237static sqlite3_int64 timeOfDay(void){
238 static sqlite3_vfs *clockVfs = 0;
239 sqlite3_int64 t;
240 if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
drha959bf52021-06-15 15:15:40 +0000241 if( clockVfs==0 ) return 0; /* Never actually happens */
drh2ce15c32017-07-11 13:34:40 +0000242 if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
243 clockVfs->xCurrentTimeInt64(clockVfs, &t);
244 }else{
245 double r;
246 clockVfs->xCurrentTime(clockVfs, &r);
247 t = (sqlite3_int64)(r*86400000.0);
248 }
249 return t;
250}
251
252#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
253#include <sys/time.h>
254#include <sys/resource.h>
255
256/* VxWorks does not support getrusage() as far as we can determine */
257#if defined(_WRS_KERNEL) || defined(__RTP__)
258struct rusage {
259 struct timeval ru_utime; /* user CPU time used */
260 struct timeval ru_stime; /* system CPU time used */
261};
262#define getrusage(A,B) memset(B,0,sizeof(*B))
263#endif
264
265/* Saved resource information for the beginning of an operation */
266static struct rusage sBegin; /* CPU time at start */
267static sqlite3_int64 iBegin; /* Wall-clock time at start */
268
269/*
270** Begin timing an operation
271*/
272static void beginTimer(void){
273 if( enableTimer ){
274 getrusage(RUSAGE_SELF, &sBegin);
275 iBegin = timeOfDay();
276 }
277}
278
279/* Return the difference of two time_structs in seconds */
280static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
281 return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
282 (double)(pEnd->tv_sec - pStart->tv_sec);
283}
284
285/*
286** Print the timing results.
287*/
288static void endTimer(void){
289 if( enableTimer ){
290 sqlite3_int64 iEnd = timeOfDay();
291 struct rusage sEnd;
292 getrusage(RUSAGE_SELF, &sEnd);
293 printf("Run Time: real %.3f user %f sys %f\n",
294 (iEnd - iBegin)*0.001,
295 timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
296 timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
297 }
298}
299
300#define BEGIN_TIMER beginTimer()
301#define END_TIMER endTimer()
302#define HAS_TIMER 1
303
304#elif (defined(_WIN32) || defined(WIN32))
305
306/* Saved resource information for the beginning of an operation */
307static HANDLE hProcess;
308static FILETIME ftKernelBegin;
309static FILETIME ftUserBegin;
310static sqlite3_int64 ftWallBegin;
311typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
312 LPFILETIME, LPFILETIME);
313static GETPROCTIMES getProcessTimesAddr = NULL;
314
315/*
316** Check to see if we have timer support. Return 1 if necessary
317** support found (or found previously).
318*/
319static int hasTimer(void){
320 if( getProcessTimesAddr ){
321 return 1;
322 } else {
mistachkin43e86272020-04-09 15:31:22 +0000323#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +0000324 /* GetProcessTimes() isn't supported in WIN95 and some other Windows
325 ** versions. See if the version we are running on has it, and if it
326 ** does, save off a pointer to it and the current process handle.
327 */
328 hProcess = GetCurrentProcess();
329 if( hProcess ){
330 HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
331 if( NULL != hinstLib ){
332 getProcessTimesAddr =
333 (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
334 if( NULL != getProcessTimesAddr ){
335 return 1;
336 }
337 FreeLibrary(hinstLib);
338 }
339 }
mistachkin43e86272020-04-09 15:31:22 +0000340#endif
drh2ce15c32017-07-11 13:34:40 +0000341 }
342 return 0;
343}
344
345/*
346** Begin timing an operation
347*/
348static void beginTimer(void){
349 if( enableTimer && getProcessTimesAddr ){
350 FILETIME ftCreation, ftExit;
351 getProcessTimesAddr(hProcess,&ftCreation,&ftExit,
352 &ftKernelBegin,&ftUserBegin);
353 ftWallBegin = timeOfDay();
354 }
355}
356
357/* Return the difference of two FILETIME structs in seconds */
358static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
359 sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
360 sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
361 return (double) ((i64End - i64Start) / 10000000.0);
362}
363
364/*
365** Print the timing results.
366*/
367static void endTimer(void){
368 if( enableTimer && getProcessTimesAddr){
369 FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
370 sqlite3_int64 ftWallEnd = timeOfDay();
371 getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
372 printf("Run Time: real %.3f user %f sys %f\n",
373 (ftWallEnd - ftWallBegin)*0.001,
374 timeDiff(&ftUserBegin, &ftUserEnd),
375 timeDiff(&ftKernelBegin, &ftKernelEnd));
376 }
377}
378
379#define BEGIN_TIMER beginTimer()
380#define END_TIMER endTimer()
381#define HAS_TIMER hasTimer()
382
383#else
384#define BEGIN_TIMER
385#define END_TIMER
386#define HAS_TIMER 0
387#endif
388
389/*
390** Used to prevent warnings about unused parameters
391*/
392#define UNUSED_PARAMETER(x) (void)(x)
393
394/*
drh5af06982018-01-10 00:53:55 +0000395** Number of elements in an array
396*/
397#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
398
399/*
drh2ce15c32017-07-11 13:34:40 +0000400** If the following flag is set, then command execution stops
401** at an error if we are not interactive.
402*/
403static int bail_on_error = 0;
404
405/*
406** Threat stdin as an interactive input if the following variable
407** is true. Otherwise, assume stdin is connected to a file or pipe.
408*/
409static int stdin_is_interactive = 1;
410
411/*
412** On Windows systems we have to know if standard output is a console
413** in order to translate UTF-8 into MBCS. The following variable is
414** true if translation is required.
415*/
416static int stdout_is_console = 1;
417
418/*
419** The following is the open SQLite database. We make a pointer
420** to this database a static variable so that it can be accessed
421** by the SIGINT handler to interrupt database processing.
422*/
423static sqlite3 *globalDb = 0;
424
425/*
426** True if an interrupt (Control-C) has been received.
427*/
428static volatile int seenInterrupt = 0;
429
430/*
431** This is the name of our program. It is set in main(), used
432** in a number of other places, mostly for error messages.
433*/
434static char *Argv0;
435
436/*
437** Prompt strings. Initialized in main. Settable with
438** .prompt main continue
439*/
440static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/
441static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */
442
443/*
444** Render output like fprintf(). Except, if the output is going to the
445** console and if this is running on a Windows machine, translate the
446** output from UTF-8 into MBCS.
447*/
448#if defined(_WIN32) || defined(WIN32)
449void utf8_printf(FILE *out, const char *zFormat, ...){
450 va_list ap;
451 va_start(ap, zFormat);
452 if( stdout_is_console && (out==stdout || out==stderr) ){
453 char *z1 = sqlite3_vmprintf(zFormat, ap);
454 char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0);
455 sqlite3_free(z1);
456 fputs(z2, out);
457 sqlite3_free(z2);
458 }else{
459 vfprintf(out, zFormat, ap);
460 }
461 va_end(ap);
462}
463#elif !defined(utf8_printf)
464# define utf8_printf fprintf
465#endif
466
467/*
468** Render output like fprintf(). This should not be used on anything that
469** includes string formatting (e.g. "%s").
470*/
471#if !defined(raw_printf)
472# define raw_printf fprintf
473#endif
474
drh4b5345c2018-04-24 13:07:40 +0000475/* Indicate out-of-memory and exit. */
476static void shell_out_of_memory(void){
477 raw_printf(stderr,"Error: out of memory\n");
478 exit(1);
479}
480
drhe3e25652021-12-16 13:29:28 +0000481/* Check a pointer to see if it is NULL. If it is NULL, exit with an
482** out-of-memory error.
483*/
484static void shell_check_oom(void *p){
485 if( p==0 ) shell_out_of_memory();
486}
487
drh2ce15c32017-07-11 13:34:40 +0000488/*
489** Write I/O traces to the following stream.
490*/
491#ifdef SQLITE_ENABLE_IOTRACE
492static FILE *iotrace = 0;
493#endif
494
495/*
496** This routine works like printf in that its first argument is a
497** format string and subsequent arguments are values to be substituted
498** in place of % fields. The result of formatting this string
499** is written to iotrace.
500*/
501#ifdef SQLITE_ENABLE_IOTRACE
502static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
503 va_list ap;
504 char *z;
505 if( iotrace==0 ) return;
506 va_start(ap, zFormat);
507 z = sqlite3_vmprintf(zFormat, ap);
508 va_end(ap);
509 utf8_printf(iotrace, "%s", z);
510 sqlite3_free(z);
511}
512#endif
513
514/*
515** Output string zUtf to stream pOut as w characters. If w is negative,
516** then right-justify the text. W is the width in UTF-8 characters, not
517** in bytes. This is different from the %*.*s specification in printf
518** since with %*.*s the width is measured in bytes, not characters.
519*/
520static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
521 int i;
522 int n;
523 int aw = w<0 ? -w : w;
drh2ce15c32017-07-11 13:34:40 +0000524 for(i=n=0; zUtf[i]; i++){
525 if( (zUtf[i]&0xc0)!=0x80 ){
526 n++;
527 if( n==aw ){
528 do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
529 break;
530 }
531 }
532 }
533 if( n>=aw ){
534 utf8_printf(pOut, "%.*s", i, zUtf);
535 }else if( w<0 ){
536 utf8_printf(pOut, "%*s%s", aw-n, "", zUtf);
537 }else{
538 utf8_printf(pOut, "%s%*s", zUtf, aw-n, "");
539 }
540}
541
542
543/*
544** Determines if a string is a number of not.
545*/
546static int isNumber(const char *z, int *realnum){
547 if( *z=='-' || *z=='+' ) z++;
548 if( !IsDigit(*z) ){
549 return 0;
550 }
551 z++;
552 if( realnum ) *realnum = 0;
553 while( IsDigit(*z) ){ z++; }
554 if( *z=='.' ){
555 z++;
556 if( !IsDigit(*z) ) return 0;
557 while( IsDigit(*z) ){ z++; }
558 if( realnum ) *realnum = 1;
559 }
560 if( *z=='e' || *z=='E' ){
561 z++;
562 if( *z=='+' || *z=='-' ) z++;
563 if( !IsDigit(*z) ) return 0;
564 while( IsDigit(*z) ){ z++; }
565 if( realnum ) *realnum = 1;
566 }
567 return *z==0;
568}
569
570/*
571** Compute a string length that is limited to what can be stored in
572** lower 30 bits of a 32-bit signed integer.
573*/
574static int strlen30(const char *z){
575 const char *z2 = z;
576 while( *z2 ){ z2++; }
577 return 0x3fffffff & (int)(z2 - z);
578}
579
580/*
581** Return the length of a string in characters. Multibyte UTF8 characters
582** count as a single character.
583*/
584static int strlenChar(const char *z){
585 int n = 0;
586 while( *z ){
587 if( (0xc0&*(z++))!=0x80 ) n++;
588 }
589 return n;
590}
591
592/*
larrybrd96bcc72021-09-17 21:12:47 +0000593** Return open FILE * if zFile exists, can be opened for read
594** and is an ordinary file or a character stream source.
595** Otherwise return 0.
drhbbd620e2020-07-20 23:33:11 +0000596*/
larrybrd96bcc72021-09-17 21:12:47 +0000597static FILE * openChrSource(const char *zFile){
drhbbd620e2020-07-20 23:33:11 +0000598#ifdef _WIN32
larrybrd0007852021-09-13 23:11:46 +0000599 struct _stat x = {0};
larrybrd0007852021-09-13 23:11:46 +0000600# define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0)
larrybrd96bcc72021-09-17 21:12:47 +0000601 /* On Windows, open first, then check the stream nature. This order
602 ** is necessary because _stat() and sibs, when checking a named pipe,
603 ** effectively break the pipe as its supplier sees it. */
604 FILE *rv = fopen(zFile, "rb");
605 if( rv==0 ) return 0;
606 if( _fstat(_fileno(rv), &x) != 0
607 || !STAT_CHR_SRC(x.st_mode)){
608 fclose(rv);
609 rv = 0;
610 }
611 return rv;
drhbbd620e2020-07-20 23:33:11 +0000612#else
larrybrd0007852021-09-13 23:11:46 +0000613 struct stat x = {0};
614 int rc = stat(zFile, &x);
615# define STAT_CHR_SRC(mode) (S_ISREG(mode)||S_ISFIFO(mode)||S_ISCHR(mode))
larrybrd96bcc72021-09-17 21:12:47 +0000616 if( rc!=0 ) return 0;
617 if( STAT_CHR_SRC(x.st_mode) ){
618 return fopen(zFile, "rb");
619 }else{
620 return 0;
621 }
drhbbd620e2020-07-20 23:33:11 +0000622#endif
larrybrd0007852021-09-13 23:11:46 +0000623#undef STAT_CHR_SRC
624}
drhbbd620e2020-07-20 23:33:11 +0000625
626/*
drh2ce15c32017-07-11 13:34:40 +0000627** This routine reads a line of text from FILE in, stores
628** the text in memory obtained from malloc() and returns a pointer
629** to the text. NULL is returned at end of file, or if malloc()
630** fails.
631**
632** If zLine is not NULL then it is a malloced buffer returned from
633** a previous call to this routine that may be reused.
634*/
635static char *local_getline(char *zLine, FILE *in){
636 int nLine = zLine==0 ? 0 : 100;
637 int n = 0;
638
639 while( 1 ){
640 if( n+100>nLine ){
641 nLine = nLine*2 + 100;
642 zLine = realloc(zLine, nLine);
drhe3e25652021-12-16 13:29:28 +0000643 shell_check_oom(zLine);
drh2ce15c32017-07-11 13:34:40 +0000644 }
645 if( fgets(&zLine[n], nLine - n, in)==0 ){
646 if( n==0 ){
647 free(zLine);
648 return 0;
649 }
650 zLine[n] = 0;
651 break;
652 }
653 while( zLine[n] ) n++;
654 if( n>0 && zLine[n-1]=='\n' ){
655 n--;
656 if( n>0 && zLine[n-1]=='\r' ) n--;
657 zLine[n] = 0;
658 break;
659 }
660 }
661#if defined(_WIN32) || defined(WIN32)
662 /* For interactive input on Windows systems, translate the
663 ** multi-byte characterset characters into UTF-8. */
664 if( stdin_is_interactive && in==stdin ){
665 char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
666 if( zTrans ){
667 int nTrans = strlen30(zTrans)+1;
668 if( nTrans>nLine ){
669 zLine = realloc(zLine, nTrans);
drhe3e25652021-12-16 13:29:28 +0000670 shell_check_oom(zLine);
drh2ce15c32017-07-11 13:34:40 +0000671 }
672 memcpy(zLine, zTrans, nTrans);
673 sqlite3_free(zTrans);
674 }
675 }
676#endif /* defined(_WIN32) || defined(WIN32) */
677 return zLine;
678}
679
680/*
681** Retrieve a single line of input text.
682**
683** If in==0 then read from standard input and prompt before each line.
684** If isContinuation is true, then a continuation prompt is appropriate.
685** If isContinuation is zero, then the main prompt should be used.
686**
687** If zPrior is not NULL then it is a buffer from a prior call to this
688** routine that can be reused.
689**
690** The result is stored in space obtained from malloc() and must either
691** be freed by the caller or else passed back into this routine via the
692** zPrior argument for reuse.
693*/
694static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
695 char *zPrompt;
696 char *zResult;
697 if( in!=0 ){
698 zResult = local_getline(zPrior, in);
699 }else{
700 zPrompt = isContinuation ? continuePrompt : mainPrompt;
701#if SHELL_USE_LOCAL_GETLINE
702 printf("%s", zPrompt);
703 fflush(stdout);
704 zResult = local_getline(zPrior, stdin);
705#else
706 free(zPrior);
707 zResult = shell_readline(zPrompt);
708 if( zResult && *zResult ) shell_add_history(zResult);
709#endif
710 }
711 return zResult;
712}
drh5af06982018-01-10 00:53:55 +0000713
714
715/*
716** Return the value of a hexadecimal digit. Return -1 if the input
717** is not a hex digit.
718*/
719static int hexDigitValue(char c){
720 if( c>='0' && c<='9' ) return c - '0';
721 if( c>='a' && c<='f' ) return c - 'a' + 10;
722 if( c>='A' && c<='F' ) return c - 'A' + 10;
723 return -1;
724}
725
726/*
727** Interpret zArg as an integer value, possibly with suffixes.
728*/
729static sqlite3_int64 integerValue(const char *zArg){
730 sqlite3_int64 v = 0;
731 static const struct { char *zSuffix; int iMult; } aMult[] = {
732 { "KiB", 1024 },
733 { "MiB", 1024*1024 },
734 { "GiB", 1024*1024*1024 },
735 { "KB", 1000 },
736 { "MB", 1000000 },
737 { "GB", 1000000000 },
738 { "K", 1000 },
739 { "M", 1000000 },
740 { "G", 1000000000 },
741 };
742 int i;
743 int isNeg = 0;
744 if( zArg[0]=='-' ){
745 isNeg = 1;
746 zArg++;
747 }else if( zArg[0]=='+' ){
748 zArg++;
749 }
750 if( zArg[0]=='0' && zArg[1]=='x' ){
751 int x;
752 zArg += 2;
753 while( (x = hexDigitValue(zArg[0]))>=0 ){
754 v = (v<<4) + x;
755 zArg++;
756 }
757 }else{
758 while( IsDigit(zArg[0]) ){
759 v = v*10 + zArg[0] - '0';
760 zArg++;
761 }
762 }
763 for(i=0; i<ArraySize(aMult); i++){
764 if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
765 v *= aMult[i].iMult;
766 break;
767 }
768 }
769 return isNeg? -v : v;
770}
771
drh2ce15c32017-07-11 13:34:40 +0000772/*
773** A variable length string to which one can append text.
774*/
775typedef struct ShellText ShellText;
776struct ShellText {
777 char *z;
778 int n;
779 int nAlloc;
780};
781
782/*
783** Initialize and destroy a ShellText object
784*/
785static void initText(ShellText *p){
786 memset(p, 0, sizeof(*p));
787}
788static void freeText(ShellText *p){
789 free(p->z);
790 initText(p);
791}
792
793/* zIn is either a pointer to a NULL-terminated string in memory obtained
794** from malloc(), or a NULL pointer. The string pointed to by zAppend is
795** added to zIn, and the result returned in memory obtained from malloc().
796** zIn, if it was not NULL, is freed.
797**
798** If the third argument, quote, is not '\0', then it is used as a
799** quote character for zAppend.
800*/
801static void appendText(ShellText *p, char const *zAppend, char quote){
802 int len;
803 int i;
804 int nAppend = strlen30(zAppend);
805
806 len = nAppend+p->n+1;
807 if( quote ){
808 len += 2;
809 for(i=0; i<nAppend; i++){
810 if( zAppend[i]==quote ) len++;
811 }
812 }
813
drh11a9ad52021-10-04 18:21:14 +0000814 if( p->z==0 || p->n+len>=p->nAlloc ){
drh2ce15c32017-07-11 13:34:40 +0000815 p->nAlloc = p->nAlloc*2 + len + 20;
816 p->z = realloc(p->z, p->nAlloc);
drhe3e25652021-12-16 13:29:28 +0000817 shell_check_oom(p->z);
drh2ce15c32017-07-11 13:34:40 +0000818 }
819
820 if( quote ){
821 char *zCsr = p->z+p->n;
822 *zCsr++ = quote;
823 for(i=0; i<nAppend; i++){
824 *zCsr++ = zAppend[i];
825 if( zAppend[i]==quote ) *zCsr++ = quote;
826 }
827 *zCsr++ = quote;
828 p->n = (int)(zCsr - p->z);
829 *zCsr = '\0';
830 }else{
831 memcpy(p->z+p->n, zAppend, nAppend);
832 p->n += nAppend;
833 p->z[p->n] = '\0';
834 }
835}
836
837/*
838** Attempt to determine if identifier zName needs to be quoted, either
839** because it contains non-alphanumeric characters, or because it is an
840** SQLite keyword. Be conservative in this estimate: When in doubt assume
841** that quoting is required.
842**
843** Return '"' if quoting is required. Return 0 if no quoting is required.
844*/
845static char quoteChar(const char *zName){
drhfc0ec3e2018-04-25 19:02:48 +0000846 int i;
drh2ce15c32017-07-11 13:34:40 +0000847 if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
848 for(i=0; zName[i]; i++){
849 if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
850 }
drhfc0ec3e2018-04-25 19:02:48 +0000851 return sqlite3_keyword_check(zName, i) ? '"' : 0;
drh2ce15c32017-07-11 13:34:40 +0000852}
853
854/*
drh667a2a22018-01-02 00:04:37 +0000855** Construct a fake object name and column list to describe the structure
856** of the view, virtual table, or table valued function zSchema.zName.
drhceba7922018-01-01 21:28:25 +0000857*/
drh667a2a22018-01-02 00:04:37 +0000858static char *shellFakeSchema(
drhceba7922018-01-01 21:28:25 +0000859 sqlite3 *db, /* The database connection containing the vtab */
860 const char *zSchema, /* Schema of the database holding the vtab */
861 const char *zName /* The name of the virtual table */
862){
863 sqlite3_stmt *pStmt = 0;
864 char *zSql;
drh1d315cf2018-01-01 21:49:43 +0000865 ShellText s;
866 char cQuote;
867 char *zDiv = "(";
drh667a2a22018-01-02 00:04:37 +0000868 int nRow = 0;
drhceba7922018-01-01 21:28:25 +0000869
drh1d315cf2018-01-01 21:49:43 +0000870 zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
871 zSchema ? zSchema : "main", zName);
drhe3e25652021-12-16 13:29:28 +0000872 shell_check_oom(zSql);
drhceba7922018-01-01 21:28:25 +0000873 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
874 sqlite3_free(zSql);
drh1d315cf2018-01-01 21:49:43 +0000875 initText(&s);
876 if( zSchema ){
877 cQuote = quoteChar(zSchema);
878 if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0;
879 appendText(&s, zSchema, cQuote);
880 appendText(&s, ".", 0);
drhceba7922018-01-01 21:28:25 +0000881 }
drh1d315cf2018-01-01 21:49:43 +0000882 cQuote = quoteChar(zName);
883 appendText(&s, zName, cQuote);
884 while( sqlite3_step(pStmt)==SQLITE_ROW ){
885 const char *zCol = (const char*)sqlite3_column_text(pStmt, 1);
drh667a2a22018-01-02 00:04:37 +0000886 nRow++;
drh1d315cf2018-01-01 21:49:43 +0000887 appendText(&s, zDiv, 0);
888 zDiv = ",";
drh621a5e02021-12-16 17:35:27 +0000889 if( zCol==0 ) zCol = "";
drh1d315cf2018-01-01 21:49:43 +0000890 cQuote = quoteChar(zCol);
891 appendText(&s, zCol, cQuote);
892 }
893 appendText(&s, ")", 0);
drhceba7922018-01-01 21:28:25 +0000894 sqlite3_finalize(pStmt);
drh667a2a22018-01-02 00:04:37 +0000895 if( nRow==0 ){
896 freeText(&s);
897 s.z = 0;
898 }
drh1d315cf2018-01-01 21:49:43 +0000899 return s.z;
drhceba7922018-01-01 21:28:25 +0000900}
901
902/*
drh667a2a22018-01-02 00:04:37 +0000903** SQL function: shell_module_schema(X)
904**
905** Return a fake schema for the table-valued function or eponymous virtual
906** table X.
907*/
908static void shellModuleSchema(
909 sqlite3_context *pCtx,
910 int nVal,
911 sqlite3_value **apVal
912){
drh511b1182021-12-16 13:56:04 +0000913 const char *zName;
914 char *zFake;
drhb9685182018-01-17 13:15:23 +0000915 UNUSED_PARAMETER(nVal);
drh511b1182021-12-16 13:56:04 +0000916 zName = (const char*)sqlite3_value_text(apVal[0]);
917 zFake = zName ? shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName) : 0;
drh667a2a22018-01-02 00:04:37 +0000918 if( zFake ){
dandcfbff92018-01-08 17:05:32 +0000919 sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
drh667a2a22018-01-02 00:04:37 +0000920 -1, sqlite3_free);
dandcfbff92018-01-08 17:05:32 +0000921 free(zFake);
drh667a2a22018-01-02 00:04:37 +0000922 }
923}
924
925/*
drh2ce15c32017-07-11 13:34:40 +0000926** SQL function: shell_add_schema(S,X)
927**
928** Add the schema name X to the CREATE statement in S and return the result.
929** Examples:
930**
931** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x);
932**
933** Also works on
934**
935** CREATE INDEX
936** CREATE UNIQUE INDEX
937** CREATE VIEW
938** CREATE TRIGGER
939** CREATE VIRTUAL TABLE
940**
941** This UDF is used by the .schema command to insert the schema name of
drh067b92b2020-06-19 15:24:12 +0000942** attached databases into the middle of the sqlite_schema.sql field.
drh2ce15c32017-07-11 13:34:40 +0000943*/
944static void shellAddSchemaName(
945 sqlite3_context *pCtx,
946 int nVal,
947 sqlite3_value **apVal
948){
949 static const char *aPrefix[] = {
950 "TABLE",
951 "INDEX",
952 "UNIQUE INDEX",
953 "VIEW",
954 "TRIGGER",
955 "VIRTUAL TABLE"
956 };
957 int i = 0;
958 const char *zIn = (const char*)sqlite3_value_text(apVal[0]);
959 const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
drh667a2a22018-01-02 00:04:37 +0000960 const char *zName = (const char*)sqlite3_value_text(apVal[2]);
drhceba7922018-01-01 21:28:25 +0000961 sqlite3 *db = sqlite3_context_db_handle(pCtx);
drhb9685182018-01-17 13:15:23 +0000962 UNUSED_PARAMETER(nVal);
drh2ce15c32017-07-11 13:34:40 +0000963 if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
drh37407122021-07-23 18:43:58 +0000964 for(i=0; i<ArraySize(aPrefix); i++){
drh2ce15c32017-07-11 13:34:40 +0000965 int n = strlen30(aPrefix[i]);
966 if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
drhceba7922018-01-01 21:28:25 +0000967 char *z = 0;
drh667a2a22018-01-02 00:04:37 +0000968 char *zFake = 0;
drhceba7922018-01-01 21:28:25 +0000969 if( zSchema ){
970 char cQuote = quoteChar(zSchema);
971 if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){
972 z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8);
973 }else{
974 z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8);
975 }
drh2ce15c32017-07-11 13:34:40 +0000976 }
drh667a2a22018-01-02 00:04:37 +0000977 if( zName
978 && aPrefix[i][0]=='V'
979 && (zFake = shellFakeSchema(db, zSchema, zName))!=0
980 ){
981 if( z==0 ){
dandcfbff92018-01-08 17:05:32 +0000982 z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake);
drh667a2a22018-01-02 00:04:37 +0000983 }else{
dandcfbff92018-01-08 17:05:32 +0000984 z = sqlite3_mprintf("%z\n/* %s */", z, zFake);
drh667a2a22018-01-02 00:04:37 +0000985 }
dandcfbff92018-01-08 17:05:32 +0000986 free(zFake);
drhceba7922018-01-01 21:28:25 +0000987 }
988 if( z ){
989 sqlite3_result_text(pCtx, z, -1, sqlite3_free);
990 return;
991 }
drh2ce15c32017-07-11 13:34:40 +0000992 }
993 }
994 }
995 sqlite3_result_value(pCtx, apVal[0]);
996}
997
998/*
999** The source code for several run-time loadable extensions is inserted
1000** below by the ../tool/mkshellc.tcl script. Before processing that included
1001** code, we need to override some macros to make the included program code
1002** work here in the middle of this regular program.
1003*/
1004#define SQLITE_EXTENSION_INIT1
drh89997982017-07-11 18:11:33 +00001005#define SQLITE_EXTENSION_INIT2(X) (void)(X)
drh2ce15c32017-07-11 13:34:40 +00001006
mistachkinacae8c32018-01-05 20:08:46 +00001007#if defined(_WIN32) && defined(_MSC_VER)
drh03491a12018-01-07 21:58:17 +00001008INCLUDE test_windirent.h
mistachkindfdfd8c2018-01-04 22:46:08 +00001009INCLUDE test_windirent.c
1010#define dirent DIRENT
mistachkindfdfd8c2018-01-04 22:46:08 +00001011#endif
drh2ce15c32017-07-11 13:34:40 +00001012INCLUDE ../ext/misc/shathree.c
1013INCLUDE ../ext/misc/fileio.c
drh56eb09b2017-07-11 13:59:07 +00001014INCLUDE ../ext/misc/completion.c
drh8682e122018-01-07 20:38:10 +00001015INCLUDE ../ext/misc/appendvfs.c
drh50b910a2019-01-21 14:55:03 +00001016INCLUDE ../ext/misc/memtrace.c
drhf05dd032020-04-14 15:53:58 +00001017INCLUDE ../ext/misc/uint.c
drhbeb9def2020-06-22 19:12:23 +00001018INCLUDE ../ext/misc/decimal.c
drh8cda77d2020-06-24 15:06:29 +00001019INCLUDE ../ext/misc/ieee754.c
mistachkin72c38d82020-08-28 18:47:39 +00001020INCLUDE ../ext/misc/series.c
drh64689902021-06-03 13:51:31 +00001021INCLUDE ../ext/misc/regexp.c
dan72afc3c2017-12-05 18:32:40 +00001022#ifdef SQLITE_HAVE_ZLIB
dan9ebfaad2017-12-26 20:39:58 +00001023INCLUDE ../ext/misc/zipfile.c
dand1b51d42017-12-16 19:11:26 +00001024INCLUDE ../ext/misc/sqlar.c
dan72afc3c2017-12-05 18:32:40 +00001025#endif
dan43efc182017-12-19 17:42:13 +00001026INCLUDE ../ext/expert/sqlite3expert.h
1027INCLUDE ../ext/expert/sqlite3expert.c
drh2ce15c32017-07-11 13:34:40 +00001028
dan1b162162019-04-27 20:15:15 +00001029#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00001030INCLUDE ../ext/misc/dbdata.c
dan1b162162019-04-27 20:15:15 +00001031#endif
dan68cb86e2019-04-20 20:57:28 +00001032
drh2ce15c32017-07-11 13:34:40 +00001033#if defined(SQLITE_ENABLE_SESSION)
1034/*
1035** State information for a single open session
1036*/
1037typedef struct OpenSession OpenSession;
1038struct OpenSession {
1039 char *zName; /* Symbolic name for this session */
1040 int nFilter; /* Number of xFilter rejection GLOB patterns */
1041 char **azFilter; /* Array of xFilter rejection GLOB patterns */
1042 sqlite3_session *p; /* The open session */
1043};
1044#endif
1045
dan43efc182017-12-19 17:42:13 +00001046typedef struct ExpertInfo ExpertInfo;
1047struct ExpertInfo {
1048 sqlite3expert *pExpert;
1049 int bVerbose;
1050};
1051
drh4b5345c2018-04-24 13:07:40 +00001052/* A single line in the EQP output */
1053typedef struct EQPGraphRow EQPGraphRow;
1054struct EQPGraphRow {
drhe2ca99c2018-05-02 00:33:43 +00001055 int iEqpId; /* ID for this row */
1056 int iParentId; /* ID of the parent row */
drh4b5345c2018-04-24 13:07:40 +00001057 EQPGraphRow *pNext; /* Next row in sequence */
1058 char zText[1]; /* Text to display for this row */
1059};
1060
1061/* All EQP output is collected into an instance of the following */
1062typedef struct EQPGraph EQPGraph;
1063struct EQPGraph {
1064 EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */
1065 EQPGraphRow *pLast; /* Last element of the pRow list */
1066 char zPrefix[100]; /* Graph prefix */
1067};
1068
larrybrcc4d55c2022-02-01 02:50:45 +00001069/* Parameters affecting columnar mode result display (defaulting together) */
1070typedef struct ColModeOpts {
1071 int iWrap; /* In columnar modes, wrap lines reaching this limit */
1072 u8 bQuote; /* Quote results for .mode box and table */
1073 u8 bWordWrap; /* In columnar modes, wrap at word boundaries */
1074} ColModeOpts;
1075#define ColModeOpts_default { 60, 0, 0 }
1076#define ColModeOpts_default_qbox { 60, 1, 0 }
larrybrcc4d55c2022-02-01 02:50:45 +00001077
drh2ce15c32017-07-11 13:34:40 +00001078/*
1079** State information about the database connection is contained in an
1080** instance of the following structure.
1081*/
1082typedef struct ShellState ShellState;
1083struct ShellState {
1084 sqlite3 *db; /* The database */
drh1fa6d9f2018-01-06 21:46:01 +00001085 u8 autoExplain; /* Automatically turn on .explain mode */
1086 u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
drhe2ca99c2018-05-02 00:33:43 +00001087 u8 autoEQPtest; /* autoEQP is in test mode */
drhb4e50392019-01-26 15:40:04 +00001088 u8 autoEQPtrace; /* autoEQP is in trace mode */
drh1fa6d9f2018-01-06 21:46:01 +00001089 u8 scanstatsOn; /* True to display scan stats before each finalize */
1090 u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
drh13c20932018-01-10 21:41:55 +00001091 u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
drh4b5345c2018-04-24 13:07:40 +00001092 u8 nEqpLevel; /* Depth of the EQP output graph */
drh707821f2018-12-05 13:39:06 +00001093 u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
drhb97e2ad2021-08-26 18:31:39 +00001094 u8 bSafeMode; /* True to prohibit unsafe operations */
1095 u8 bSafeModePersist; /* The long-term value of bSafeMode */
larrybrcc4d55c2022-02-01 02:50:45 +00001096 ColModeOpts cmOpts; /* Option values affecting columnar mode output */
drha6e6cf22021-01-09 19:10:04 +00001097 unsigned statsOn; /* True to display memory stats before each finalize */
drh4b5345c2018-04-24 13:07:40 +00001098 unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */
larrybrd48e88e2022-01-24 06:36:16 +00001099 int inputNesting; /* Track nesting level of .read and other redirects */
drh2ce15c32017-07-11 13:34:40 +00001100 int outCount; /* Revert to stdout when reaching zero */
1101 int cnt; /* Number of records displayed so far */
drh2c8ee022018-12-13 18:59:30 +00001102 int lineno; /* Line number of last line read from in */
drh0933aad2019-11-18 17:46:38 +00001103 int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */
drh60379d42018-12-13 18:30:01 +00001104 FILE *in; /* Read commands from this stream */
drh2ce15c32017-07-11 13:34:40 +00001105 FILE *out; /* Write results here */
1106 FILE *traceOut; /* Output for sqlite3_trace() */
1107 int nErr; /* Number of errors seen */
1108 int mode; /* An output mode setting */
drh3c484e82018-01-10 22:27:21 +00001109 int modePrior; /* Saved mode */
drh2ce15c32017-07-11 13:34:40 +00001110 int cMode; /* temporary output mode for the current query */
1111 int normalMode; /* Output mode before ".explain on" */
1112 int writableSchema; /* True if PRAGMA writable_schema=ON */
1113 int showHeader; /* True to show column names in List or Column mode */
1114 int nCheck; /* Number of ".check" commands run */
drh3f83f592019-02-04 14:53:18 +00001115 unsigned nProgress; /* Number of progress callbacks encountered */
1116 unsigned mxProgress; /* Maximum progress callbacks before failing */
1117 unsigned flgProgress; /* Flags for the progress callback */
drh2ce15c32017-07-11 13:34:40 +00001118 unsigned shellFlgs; /* Various flags */
drh7a431002020-04-18 14:12:00 +00001119 unsigned priorShFlgs; /* Saved copy of flags */
drh6ca64482019-01-22 16:06:20 +00001120 sqlite3_int64 szMax; /* --maxsize argument to .open */
drh2ce15c32017-07-11 13:34:40 +00001121 char *zDestTable; /* Name of destination table when MODE_Insert */
drh13c20932018-01-10 21:41:55 +00001122 char *zTempFile; /* Temporary file that might need deleting */
drh2ce15c32017-07-11 13:34:40 +00001123 char zTestcase[30]; /* Name of current test case */
1124 char colSeparator[20]; /* Column separator character for several modes */
1125 char rowSeparator[20]; /* Row separator character for MODE_Ascii */
drh3c484e82018-01-10 22:27:21 +00001126 char colSepPrior[20]; /* Saved column separator */
1127 char rowSepPrior[20]; /* Saved row separator */
drh0285d982020-05-29 14:38:43 +00001128 int *colWidth; /* Requested width of each column in columnar modes */
1129 int *actualWidth; /* Actual width of each column */
1130 int nWidth; /* Number of slots in colWidth[] and actualWidth[] */
drh2ce15c32017-07-11 13:34:40 +00001131 char nullValue[20]; /* The text to print when a NULL comes back from
1132 ** the database */
1133 char outfile[FILENAME_MAX]; /* Filename for *out */
drh2ce15c32017-07-11 13:34:40 +00001134 sqlite3_stmt *pStmt; /* Current statement if any. */
1135 FILE *pLog; /* Write log output here */
drh37407122021-07-23 18:43:58 +00001136 struct AuxDb { /* Storage space for auxiliary database connections */
1137 sqlite3 *db; /* Connection pointer */
1138 const char *zDbFilename; /* Filename used to open the connection */
1139 char *zFreeOnClose; /* Free this memory allocation on close */
1140#if defined(SQLITE_ENABLE_SESSION)
1141 int nSession; /* Number of active sessions */
1142 OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */
1143#endif
1144 } aAuxDb[5], /* Array of all database connections */
1145 *pAuxDb; /* Currently active database connection */
drh2ce15c32017-07-11 13:34:40 +00001146 int *aiIndent; /* Array of indents used in MODE_Explain */
1147 int nIndent; /* Size of array aiIndent[] */
1148 int iIndent; /* Index of current op in aiIndent[] */
drhb97e2ad2021-08-26 18:31:39 +00001149 char *zNonce; /* Nonce for temporary safe-mode excapes */
drh4b5345c2018-04-24 13:07:40 +00001150 EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */
drhb97e2ad2021-08-26 18:31:39 +00001151 ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
drh2ce15c32017-07-11 13:34:40 +00001152};
1153
drh1fa6d9f2018-01-06 21:46:01 +00001154
drhada70452017-12-21 21:02:27 +00001155/* Allowed values for ShellState.autoEQP
1156*/
drhe2ca99c2018-05-02 00:33:43 +00001157#define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */
1158#define AUTOEQP_on 1 /* Automatic EQP is on */
1159#define AUTOEQP_trigger 2 /* On and also show plans for triggers */
1160#define AUTOEQP_full 3 /* Show full EXPLAIN */
drhada70452017-12-21 21:02:27 +00001161
drh1fa6d9f2018-01-06 21:46:01 +00001162/* Allowed values for ShellState.openMode
1163*/
drh60f34ae2018-10-30 13:19:49 +00001164#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
1165#define SHELL_OPEN_NORMAL 1 /* Normal database file */
1166#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
1167#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
1168#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
1169#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
drh33746482018-12-13 15:06:26 +00001170#define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */
drh1fa6d9f2018-01-06 21:46:01 +00001171
drh707821f2018-12-05 13:39:06 +00001172/* Allowed values for ShellState.eTraceType
1173*/
1174#define SHELL_TRACE_PLAIN 0 /* Show input SQL text */
1175#define SHELL_TRACE_EXPANDED 1 /* Show expanded SQL text */
1176#define SHELL_TRACE_NORMALIZED 2 /* Show normalized SQL text */
1177
drh3f83f592019-02-04 14:53:18 +00001178/* Bits in the ShellState.flgProgress variable */
drhfc4eeef2019-02-05 19:48:46 +00001179#define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */
1180#define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progres
1181 ** callback limit is reached, and for each
1182 ** top-level SQL statement */
1183#define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */
drh3f83f592019-02-04 14:53:18 +00001184
drh2ce15c32017-07-11 13:34:40 +00001185/*
1186** These are the allowed shellFlgs values
1187*/
drhb2a0f752017-08-28 15:51:35 +00001188#define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */
1189#define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */
1190#define SHFLG_Backslash 0x00000004 /* The --backslash option is used */
1191#define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */
1192#define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
1193#define SHFLG_CountChanges 0x00000020 /* .changes setting */
1194#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
larrybrae509122021-09-10 01:45:20 +00001195#define SHFLG_HeaderSet 0x00000080 /* showHeader has been specified */
drhc1962192020-10-12 16:54:28 +00001196#define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */
1197#define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */
drh2ce15c32017-07-11 13:34:40 +00001198
1199/*
1200** Macros for testing and setting shellFlgs
1201*/
1202#define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0)
1203#define ShellSetFlag(P,X) ((P)->shellFlgs|=(X))
1204#define ShellClearFlag(P,X) ((P)->shellFlgs&=(~(X)))
1205
1206/*
1207** These are the allowed modes.
1208*/
1209#define MODE_Line 0 /* One column per line. Blank line between records */
1210#define MODE_Column 1 /* One record per line in neat columns */
1211#define MODE_List 2 /* One record per line with a separator */
1212#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
1213#define MODE_Html 4 /* Generate an XHTML table */
1214#define MODE_Insert 5 /* Generate SQL "insert" statements */
1215#define MODE_Quote 6 /* Quote values as for SQL */
1216#define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */
1217#define MODE_Csv 8 /* Quote strings, numbers are plain */
1218#define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */
1219#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
1220#define MODE_Pretty 11 /* Pretty-print schemas */
drh4b5345c2018-04-24 13:07:40 +00001221#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
drh30c54a02020-05-28 23:49:50 +00001222#define MODE_Json 13 /* Output JSON */
1223#define MODE_Markdown 14 /* Markdown formatting */
1224#define MODE_Table 15 /* MySQL-style table formatting */
drh0908e382020-06-04 18:05:39 +00001225#define MODE_Box 16 /* Unicode box-drawing characters */
drh5d88be82021-12-09 16:17:43 +00001226#define MODE_Count 17 /* Output only a count of the rows of output */
1227#define MODE_Off 18 /* No query output shown */
drh2ce15c32017-07-11 13:34:40 +00001228
1229static const char *modeDescr[] = {
1230 "line",
1231 "column",
1232 "list",
1233 "semi",
1234 "html",
1235 "insert",
1236 "quote",
1237 "tcl",
1238 "csv",
1239 "explain",
1240 "ascii",
1241 "prettyprint",
drh30c54a02020-05-28 23:49:50 +00001242 "eqp",
1243 "json",
1244 "markdown",
drh0908e382020-06-04 18:05:39 +00001245 "table",
drh5d88be82021-12-09 16:17:43 +00001246 "box",
1247 "count",
1248 "off"
drh2ce15c32017-07-11 13:34:40 +00001249};
1250
1251/*
1252** These are the column/row/line separators used by the various
1253** import/export modes.
1254*/
1255#define SEP_Column "|"
1256#define SEP_Row "\n"
1257#define SEP_Tab "\t"
1258#define SEP_Space " "
1259#define SEP_Comma ","
1260#define SEP_CrLf "\r\n"
1261#define SEP_Unit "\x1F"
1262#define SEP_Record "\x1E"
1263
1264/*
larrybrd48e88e2022-01-24 06:36:16 +00001265** Limit input nesting via .read or any other input redirect.
1266** It's not too expensive, so a generous allowance can be made.
1267*/
1268#define MAX_INPUT_NESTING 25
1269
1270/*
drh2ce15c32017-07-11 13:34:40 +00001271** A callback for the sqlite3_log() interface.
1272*/
1273static void shellLog(void *pArg, int iErrCode, const char *zMsg){
1274 ShellState *p = (ShellState*)pArg;
1275 if( p->pLog==0 ) return;
1276 utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
1277 fflush(p->pLog);
1278}
1279
1280/*
drh634c70f2018-01-10 16:50:18 +00001281** SQL function: shell_putsnl(X)
1282**
1283** Write the text X to the screen (or whatever output is being directed)
1284** adding a newline at the end, and then return X.
1285*/
1286static void shellPutsFunc(
1287 sqlite3_context *pCtx,
1288 int nVal,
1289 sqlite3_value **apVal
1290){
1291 ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
drhb9685182018-01-17 13:15:23 +00001292 (void)nVal;
drh634c70f2018-01-10 16:50:18 +00001293 utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
1294 sqlite3_result_value(pCtx, apVal[0]);
1295}
1296
1297/*
drhb97e2ad2021-08-26 18:31:39 +00001298** If in safe mode, print an error message described by the arguments
1299** and exit immediately.
1300*/
1301static void failIfSafeMode(
1302 ShellState *p,
1303 const char *zErrMsg,
1304 ...
1305){
1306 if( p->bSafeMode ){
1307 va_list ap;
1308 char *zMsg;
1309 va_start(ap, zErrMsg);
1310 zMsg = sqlite3_vmprintf(zErrMsg, ap);
1311 va_end(ap);
1312 raw_printf(stderr, "line %d: ", p->lineno);
1313 utf8_printf(stderr, "%s\n", zMsg);
1314 exit(1);
1315 }
1316}
1317
1318/*
drh97913132018-01-11 00:04:00 +00001319** SQL function: edit(VALUE)
1320** edit(VALUE,EDITOR)
1321**
1322** These steps:
1323**
1324** (1) Write VALUE into a temporary file.
1325** (2) Run program EDITOR on that temporary file.
1326** (3) Read the temporary file back and return its content as the result.
1327** (4) Delete the temporary file
1328**
1329** If the EDITOR argument is omitted, use the value in the VISUAL
1330** environment variable. If still there is no EDITOR, through an error.
1331**
1332** Also throw an error if the EDITOR program returns a non-zero exit code.
1333*/
drh04a28c32018-01-31 01:38:44 +00001334#ifndef SQLITE_NOHAVE_SYSTEM
drh97913132018-01-11 00:04:00 +00001335static void editFunc(
1336 sqlite3_context *context,
1337 int argc,
1338 sqlite3_value **argv
1339){
1340 const char *zEditor;
1341 char *zTempFile = 0;
1342 sqlite3 *db;
1343 char *zCmd = 0;
1344 int bBin;
1345 int rc;
drhf018fd52018-08-06 02:08:53 +00001346 int hasCRNL = 0;
drh97913132018-01-11 00:04:00 +00001347 FILE *f = 0;
1348 sqlite3_int64 sz;
1349 sqlite3_int64 x;
1350 unsigned char *p = 0;
1351
1352 if( argc==2 ){
1353 zEditor = (const char*)sqlite3_value_text(argv[1]);
1354 }else{
1355 zEditor = getenv("VISUAL");
1356 }
1357 if( zEditor==0 ){
1358 sqlite3_result_error(context, "no editor for edit()", -1);
1359 return;
1360 }
1361 if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
1362 sqlite3_result_error(context, "NULL input to edit()", -1);
1363 return;
1364 }
1365 db = sqlite3_context_db_handle(context);
1366 zTempFile = 0;
1367 sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile);
1368 if( zTempFile==0 ){
1369 sqlite3_uint64 r = 0;
1370 sqlite3_randomness(sizeof(r), &r);
1371 zTempFile = sqlite3_mprintf("temp%llx", r);
1372 if( zTempFile==0 ){
1373 sqlite3_result_error_nomem(context);
1374 return;
1375 }
1376 }
1377 bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB;
drhf018fd52018-08-06 02:08:53 +00001378 /* When writing the file to be edited, do \n to \r\n conversions on systems
1379 ** that want \r\n line endings */
drh97913132018-01-11 00:04:00 +00001380 f = fopen(zTempFile, bBin ? "wb" : "w");
1381 if( f==0 ){
1382 sqlite3_result_error(context, "edit() cannot open temp file", -1);
1383 goto edit_func_end;
1384 }
1385 sz = sqlite3_value_bytes(argv[0]);
1386 if( bBin ){
dan4d02b5f2019-07-17 07:23:06 +00001387 x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001388 }else{
drhf018fd52018-08-06 02:08:53 +00001389 const char *z = (const char*)sqlite3_value_text(argv[0]);
1390 /* Remember whether or not the value originally contained \r\n */
1391 if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
dan4d02b5f2019-07-17 07:23:06 +00001392 x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001393 }
1394 fclose(f);
1395 f = 0;
1396 if( x!=sz ){
1397 sqlite3_result_error(context, "edit() could not write the whole file", -1);
1398 goto edit_func_end;
1399 }
1400 zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile);
1401 if( zCmd==0 ){
1402 sqlite3_result_error_nomem(context);
1403 goto edit_func_end;
1404 }
1405 rc = system(zCmd);
1406 sqlite3_free(zCmd);
1407 if( rc ){
1408 sqlite3_result_error(context, "EDITOR returned non-zero", -1);
1409 goto edit_func_end;
1410 }
drhf018fd52018-08-06 02:08:53 +00001411 f = fopen(zTempFile, "rb");
drh97913132018-01-11 00:04:00 +00001412 if( f==0 ){
1413 sqlite3_result_error(context,
1414 "edit() cannot reopen temp file after edit", -1);
1415 goto edit_func_end;
1416 }
1417 fseek(f, 0, SEEK_END);
1418 sz = ftell(f);
1419 rewind(f);
drhee37f8b2019-08-23 23:05:32 +00001420 p = sqlite3_malloc64( sz+1 );
drh97913132018-01-11 00:04:00 +00001421 if( p==0 ){
1422 sqlite3_result_error_nomem(context);
1423 goto edit_func_end;
1424 }
dan4d02b5f2019-07-17 07:23:06 +00001425 x = fread(p, 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001426 fclose(f);
1427 f = 0;
1428 if( x!=sz ){
1429 sqlite3_result_error(context, "could not read back the whole file", -1);
1430 goto edit_func_end;
1431 }
1432 if( bBin ){
mistachkinb71aa092018-01-23 00:05:18 +00001433 sqlite3_result_blob64(context, p, sz, sqlite3_free);
drh97913132018-01-11 00:04:00 +00001434 }else{
dan60bdcf52018-10-03 11:13:30 +00001435 sqlite3_int64 i, j;
drhf018fd52018-08-06 02:08:53 +00001436 if( hasCRNL ){
1437 /* If the original contains \r\n then do no conversions back to \n */
drhf018fd52018-08-06 02:08:53 +00001438 }else{
1439 /* If the file did not originally contain \r\n then convert any new
1440 ** \r\n back into \n */
1441 for(i=j=0; i<sz; i++){
1442 if( p[i]=='\r' && p[i+1]=='\n' ) i++;
1443 p[j++] = p[i];
1444 }
1445 sz = j;
1446 p[sz] = 0;
1447 }
mistachkinb71aa092018-01-23 00:05:18 +00001448 sqlite3_result_text64(context, (const char*)p, sz,
1449 sqlite3_free, SQLITE_UTF8);
drh97913132018-01-11 00:04:00 +00001450 }
1451 p = 0;
1452
1453edit_func_end:
1454 if( f ) fclose(f);
1455 unlink(zTempFile);
1456 sqlite3_free(zTempFile);
1457 sqlite3_free(p);
1458}
drh04a28c32018-01-31 01:38:44 +00001459#endif /* SQLITE_NOHAVE_SYSTEM */
drh97913132018-01-11 00:04:00 +00001460
1461/*
drh3c484e82018-01-10 22:27:21 +00001462** Save or restore the current output mode
1463*/
1464static void outputModePush(ShellState *p){
1465 p->modePrior = p->mode;
drh7a431002020-04-18 14:12:00 +00001466 p->priorShFlgs = p->shellFlgs;
drh3c484e82018-01-10 22:27:21 +00001467 memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));
1468 memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));
1469}
1470static void outputModePop(ShellState *p){
1471 p->mode = p->modePrior;
drh7a431002020-04-18 14:12:00 +00001472 p->shellFlgs = p->priorShFlgs;
drh3c484e82018-01-10 22:27:21 +00001473 memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
1474 memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
1475}
1476
1477/*
drh2ce15c32017-07-11 13:34:40 +00001478** Output the given string as a hex-encoded blob (eg. X'1234' )
1479*/
1480static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
1481 int i;
1482 char *zBlob = (char *)pBlob;
1483 raw_printf(out,"X'");
1484 for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); }
1485 raw_printf(out,"'");
1486}
1487
1488/*
1489** Find a string that is not found anywhere in z[]. Return a pointer
1490** to that string.
1491**
1492** Try to use zA and zB first. If both of those are already found in z[]
1493** then make up some string and store it in the buffer zBuf.
1494*/
1495static const char *unused_string(
1496 const char *z, /* Result must not appear anywhere in z */
1497 const char *zA, const char *zB, /* Try these first */
1498 char *zBuf /* Space to store a generated string */
1499){
1500 unsigned i = 0;
1501 if( strstr(z, zA)==0 ) return zA;
1502 if( strstr(z, zB)==0 ) return zB;
1503 do{
1504 sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
1505 }while( strstr(z,zBuf)!=0 );
1506 return zBuf;
1507}
1508
1509/*
1510** Output the given string as a quoted string using SQL quoting conventions.
1511**
1512** See also: output_quoted_escaped_string()
1513*/
1514static void output_quoted_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!='\''; i++){}
1519 if( c==0 ){
1520 utf8_printf(out,"'%s'",z);
1521 }else{
1522 raw_printf(out, "'");
1523 while( *z ){
1524 for(i=0; (c = z[i])!=0 && c!='\''; i++){}
1525 if( c=='\'' ) i++;
1526 if( i ){
1527 utf8_printf(out, "%.*s", i, z);
1528 z += i;
1529 }
1530 if( c=='\'' ){
1531 raw_printf(out, "'");
1532 continue;
1533 }
1534 if( c==0 ){
1535 break;
1536 }
1537 z++;
1538 }
1539 raw_printf(out, "'");
1540 }
1541 setTextMode(out, 1);
1542}
1543
1544/*
1545** Output the given string as a quoted string using SQL quoting conventions.
1546** Additionallly , escape the "\n" and "\r" characters so that they do not
1547** get corrupted by end-of-line translation facilities in some operating
1548** systems.
1549**
1550** This is like output_quoted_string() but with the addition of the \r\n
1551** escape mechanism.
1552*/
1553static void output_quoted_escaped_string(FILE *out, const char *z){
1554 int i;
1555 char c;
1556 setBinaryMode(out, 1);
1557 for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
1558 if( c==0 ){
1559 utf8_printf(out,"'%s'",z);
1560 }else{
1561 const char *zNL = 0;
1562 const char *zCR = 0;
1563 int nNL = 0;
1564 int nCR = 0;
1565 char zBuf1[20], zBuf2[20];
1566 for(i=0; z[i]; i++){
1567 if( z[i]=='\n' ) nNL++;
1568 if( z[i]=='\r' ) nCR++;
1569 }
1570 if( nNL ){
1571 raw_printf(out, "replace(");
1572 zNL = unused_string(z, "\\n", "\\012", zBuf1);
1573 }
1574 if( nCR ){
1575 raw_printf(out, "replace(");
1576 zCR = unused_string(z, "\\r", "\\015", zBuf2);
1577 }
1578 raw_printf(out, "'");
1579 while( *z ){
1580 for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
1581 if( c=='\'' ) i++;
1582 if( i ){
1583 utf8_printf(out, "%.*s", i, z);
1584 z += i;
1585 }
1586 if( c=='\'' ){
1587 raw_printf(out, "'");
1588 continue;
1589 }
1590 if( c==0 ){
1591 break;
1592 }
1593 z++;
1594 if( c=='\n' ){
1595 raw_printf(out, "%s", zNL);
1596 continue;
1597 }
1598 raw_printf(out, "%s", zCR);
1599 }
1600 raw_printf(out, "'");
1601 if( nCR ){
1602 raw_printf(out, ",'%s',char(13))", zCR);
1603 }
1604 if( nNL ){
1605 raw_printf(out, ",'%s',char(10))", zNL);
1606 }
1607 }
1608 setTextMode(out, 1);
1609}
1610
1611/*
1612** Output the given string as a quoted according to C or TCL quoting rules.
1613*/
1614static void output_c_string(FILE *out, const char *z){
1615 unsigned int c;
1616 fputc('"', out);
1617 while( (c = *(z++))!=0 ){
1618 if( c=='\\' ){
1619 fputc(c, out);
1620 fputc(c, out);
1621 }else if( c=='"' ){
1622 fputc('\\', out);
1623 fputc('"', out);
1624 }else if( c=='\t' ){
1625 fputc('\\', out);
1626 fputc('t', out);
1627 }else if( c=='\n' ){
1628 fputc('\\', out);
1629 fputc('n', out);
1630 }else if( c=='\r' ){
1631 fputc('\\', out);
1632 fputc('r', out);
1633 }else if( !isprint(c&0xff) ){
1634 raw_printf(out, "\\%03o", c&0xff);
1635 }else{
1636 fputc(c, out);
1637 }
1638 }
1639 fputc('"', out);
1640}
1641
1642/*
drh69c093d2020-05-29 00:21:43 +00001643** Output the given string as a quoted according to JSON quoting rules.
1644*/
1645static void output_json_string(FILE *out, const char *z, int n){
1646 unsigned int c;
1647 if( n<0 ) n = (int)strlen(z);
1648 fputc('"', out);
1649 while( n-- ){
1650 c = *(z++);
1651 if( c=='\\' || c=='"' ){
1652 fputc('\\', out);
1653 fputc(c, out);
1654 }else if( c<=0x1f ){
1655 fputc('\\', out);
1656 if( c=='\b' ){
1657 fputc('b', out);
1658 }else if( c=='\f' ){
1659 fputc('f', out);
1660 }else if( c=='\n' ){
1661 fputc('n', out);
1662 }else if( c=='\r' ){
1663 fputc('r', out);
1664 }else if( c=='\t' ){
1665 fputc('t', out);
1666 }else{
1667 raw_printf(out, "u%04x",c);
1668 }
1669 }else{
1670 fputc(c, out);
1671 }
1672 }
1673 fputc('"', out);
1674}
1675
1676/*
drh2ce15c32017-07-11 13:34:40 +00001677** Output the given string with characters that are special to
1678** HTML escaped.
1679*/
1680static void output_html_string(FILE *out, const char *z){
1681 int i;
1682 if( z==0 ) z = "";
1683 while( *z ){
1684 for(i=0; z[i]
1685 && z[i]!='<'
1686 && z[i]!='&'
1687 && z[i]!='>'
1688 && z[i]!='\"'
1689 && z[i]!='\'';
1690 i++){}
1691 if( i>0 ){
1692 utf8_printf(out,"%.*s",i,z);
1693 }
1694 if( z[i]=='<' ){
1695 raw_printf(out,"&lt;");
1696 }else if( z[i]=='&' ){
1697 raw_printf(out,"&amp;");
1698 }else if( z[i]=='>' ){
1699 raw_printf(out,"&gt;");
1700 }else if( z[i]=='\"' ){
1701 raw_printf(out,"&quot;");
1702 }else if( z[i]=='\'' ){
1703 raw_printf(out,"&#39;");
1704 }else{
1705 break;
1706 }
1707 z += i + 1;
1708 }
1709}
1710
1711/*
1712** If a field contains any character identified by a 1 in the following
1713** array, then the string must be quoted for CSV.
1714*/
1715static const char needCsvQuote[] = {
1716 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1717 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1718 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1719 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1720 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1721 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1722 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1723 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1724 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1725 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1726 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1727 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1728 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1729 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1730 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1731 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1732};
1733
1734/*
1735** Output a single term of CSV. Actually, p->colSeparator is used for
1736** the separator, which may or may not be a comma. p->nullValue is
1737** the null value. Strings are quoted if necessary. The separator
1738** is only issued if bSep is true.
1739*/
1740static void output_csv(ShellState *p, const char *z, int bSep){
1741 FILE *out = p->out;
1742 if( z==0 ){
1743 utf8_printf(out,"%s",p->nullValue);
1744 }else{
drh9cd0c3d2021-11-18 15:40:05 +00001745 unsigned i;
1746 for(i=0; z[i]; i++){
1747 if( needCsvQuote[((unsigned char*)z)[i]] ){
drh2ce15c32017-07-11 13:34:40 +00001748 i = 0;
1749 break;
1750 }
1751 }
drh9cd0c3d2021-11-18 15:40:05 +00001752 if( i==0 || strstr(z, p->colSeparator)!=0 ){
drh9b7affc2017-11-26 02:14:18 +00001753 char *zQuoted = sqlite3_mprintf("\"%w\"", z);
drhe3e25652021-12-16 13:29:28 +00001754 shell_check_oom(zQuoted);
drh9b7affc2017-11-26 02:14:18 +00001755 utf8_printf(out, "%s", zQuoted);
1756 sqlite3_free(zQuoted);
drh2ce15c32017-07-11 13:34:40 +00001757 }else{
1758 utf8_printf(out, "%s", z);
1759 }
1760 }
1761 if( bSep ){
1762 utf8_printf(p->out, "%s", p->colSeparator);
1763 }
1764}
1765
drh2ce15c32017-07-11 13:34:40 +00001766/*
1767** This routine runs when the user presses Ctrl-C
1768*/
1769static void interrupt_handler(int NotUsed){
1770 UNUSED_PARAMETER(NotUsed);
1771 seenInterrupt++;
1772 if( seenInterrupt>2 ) exit(1);
1773 if( globalDb ) sqlite3_interrupt(globalDb);
1774}
mistachkinb4bab902017-10-27 17:09:44 +00001775
1776#if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
1777/*
1778** This routine runs for console events (e.g. Ctrl-C) on Win32
1779*/
1780static BOOL WINAPI ConsoleCtrlHandler(
1781 DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */
1782){
1783 if( dwCtrlType==CTRL_C_EVENT ){
1784 interrupt_handler(0);
1785 return TRUE;
1786 }
1787 return FALSE;
1788}
drh2ce15c32017-07-11 13:34:40 +00001789#endif
1790
1791#ifndef SQLITE_OMIT_AUTHORIZATION
1792/*
drhb97e2ad2021-08-26 18:31:39 +00001793** This authorizer runs in safe mode.
1794*/
1795static int safeModeAuth(
1796 void *pClientData,
1797 int op,
1798 const char *zA1,
1799 const char *zA2,
1800 const char *zA3,
1801 const char *zA4
1802){
1803 ShellState *p = (ShellState*)pClientData;
1804 static const char *azProhibitedFunctions[] = {
1805 "edit",
1806 "fts3_tokenizer",
1807 "load_extension",
1808 "readfile",
1809 "writefile",
1810 "zipfile",
1811 "zipfile_cds",
1812 };
1813 UNUSED_PARAMETER(zA2);
1814 UNUSED_PARAMETER(zA3);
1815 UNUSED_PARAMETER(zA4);
1816 switch( op ){
1817 case SQLITE_ATTACH: {
1818 failIfSafeMode(p, "cannot run ATTACH in safe mode");
1819 break;
1820 }
1821 case SQLITE_FUNCTION: {
1822 int i;
1823 for(i=0; i<ArraySize(azProhibitedFunctions); i++){
1824 if( sqlite3_stricmp(zA1, azProhibitedFunctions[i])==0 ){
1825 failIfSafeMode(p, "cannot use the %s() function in safe mode",
1826 azProhibitedFunctions[i]);
1827 }
1828 }
1829 break;
1830 }
1831 }
1832 return SQLITE_OK;
1833}
1834
1835/*
drh2ce15c32017-07-11 13:34:40 +00001836** When the ".auth ON" is set, the following authorizer callback is
1837** invoked. It always returns SQLITE_OK.
1838*/
1839static int shellAuth(
1840 void *pClientData,
1841 int op,
1842 const char *zA1,
1843 const char *zA2,
1844 const char *zA3,
1845 const char *zA4
1846){
1847 ShellState *p = (ShellState*)pClientData;
1848 static const char *azAction[] = { 0,
1849 "CREATE_INDEX", "CREATE_TABLE", "CREATE_TEMP_INDEX",
1850 "CREATE_TEMP_TABLE", "CREATE_TEMP_TRIGGER", "CREATE_TEMP_VIEW",
1851 "CREATE_TRIGGER", "CREATE_VIEW", "DELETE",
1852 "DROP_INDEX", "DROP_TABLE", "DROP_TEMP_INDEX",
1853 "DROP_TEMP_TABLE", "DROP_TEMP_TRIGGER", "DROP_TEMP_VIEW",
1854 "DROP_TRIGGER", "DROP_VIEW", "INSERT",
1855 "PRAGMA", "READ", "SELECT",
1856 "TRANSACTION", "UPDATE", "ATTACH",
1857 "DETACH", "ALTER_TABLE", "REINDEX",
1858 "ANALYZE", "CREATE_VTABLE", "DROP_VTABLE",
1859 "FUNCTION", "SAVEPOINT", "RECURSIVE"
1860 };
1861 int i;
1862 const char *az[4];
1863 az[0] = zA1;
1864 az[1] = zA2;
1865 az[2] = zA3;
1866 az[3] = zA4;
1867 utf8_printf(p->out, "authorizer: %s", azAction[op]);
1868 for(i=0; i<4; i++){
1869 raw_printf(p->out, " ");
1870 if( az[i] ){
1871 output_c_string(p->out, az[i]);
1872 }else{
1873 raw_printf(p->out, "NULL");
1874 }
1875 }
1876 raw_printf(p->out, "\n");
drhb97e2ad2021-08-26 18:31:39 +00001877 if( p->bSafeMode ) (void)safeModeAuth(pClientData, op, zA1, zA2, zA3, zA4);
drh2ce15c32017-07-11 13:34:40 +00001878 return SQLITE_OK;
1879}
1880#endif
1881
1882/*
1883** Print a schema statement. Part of MODE_Semi and MODE_Pretty output.
1884**
1885** This routine converts some CREATE TABLE statements for shadow tables
1886** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
1887*/
1888static void printSchemaLine(FILE *out, const char *z, const char *zTail){
drh0a0536a2019-05-09 18:13:30 +00001889 if( z==0 ) return;
1890 if( zTail==0 ) return;
drh2ce15c32017-07-11 13:34:40 +00001891 if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
1892 utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
1893 }else{
1894 utf8_printf(out, "%s%s", z, zTail);
1895 }
1896}
1897static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
1898 char c = z[n];
1899 z[n] = 0;
1900 printSchemaLine(out, z, zTail);
1901 z[n] = c;
1902}
1903
1904/*
drh11be81d2018-01-06 15:46:20 +00001905** Return true if string z[] has nothing but whitespace and comments to the
1906** end of the first line.
1907*/
1908static int wsToEol(const char *z){
1909 int i;
1910 for(i=0; z[i]; i++){
1911 if( z[i]=='\n' ) return 1;
1912 if( IsSpace(z[i]) ) continue;
1913 if( z[i]=='-' && z[i+1]=='-' ) return 1;
1914 return 0;
1915 }
1916 return 1;
1917}
drh4b5345c2018-04-24 13:07:40 +00001918
1919/*
1920** Add a new entry to the EXPLAIN QUERY PLAN data
1921*/
drhe2ca99c2018-05-02 00:33:43 +00001922static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
drh4b5345c2018-04-24 13:07:40 +00001923 EQPGraphRow *pNew;
1924 int nText = strlen30(zText);
drhe2ca99c2018-05-02 00:33:43 +00001925 if( p->autoEQPtest ){
1926 utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
1927 }
drh4b5345c2018-04-24 13:07:40 +00001928 pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
drhe3e25652021-12-16 13:29:28 +00001929 shell_check_oom(pNew);
drhe2ca99c2018-05-02 00:33:43 +00001930 pNew->iEqpId = iEqpId;
1931 pNew->iParentId = p2;
drh4b5345c2018-04-24 13:07:40 +00001932 memcpy(pNew->zText, zText, nText+1);
1933 pNew->pNext = 0;
1934 if( p->sGraph.pLast ){
1935 p->sGraph.pLast->pNext = pNew;
1936 }else{
1937 p->sGraph.pRow = pNew;
1938 }
1939 p->sGraph.pLast = pNew;
1940}
1941
1942/*
1943** Free and reset the EXPLAIN QUERY PLAN data that has been collected
1944** in p->sGraph.
1945*/
1946static void eqp_reset(ShellState *p){
1947 EQPGraphRow *pRow, *pNext;
1948 for(pRow = p->sGraph.pRow; pRow; pRow = pNext){
1949 pNext = pRow->pNext;
1950 sqlite3_free(pRow);
1951 }
1952 memset(&p->sGraph, 0, sizeof(p->sGraph));
1953}
1954
drhe2ca99c2018-05-02 00:33:43 +00001955/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after
drh4b5345c2018-04-24 13:07:40 +00001956** pOld, or return the first such line if pOld is NULL
1957*/
drhe2ca99c2018-05-02 00:33:43 +00001958static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){
drh4b5345c2018-04-24 13:07:40 +00001959 EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow;
drhe2ca99c2018-05-02 00:33:43 +00001960 while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext;
drh4b5345c2018-04-24 13:07:40 +00001961 return pRow;
1962}
1963
drhe2ca99c2018-05-02 00:33:43 +00001964/* Render a single level of the graph that has iEqpId as its parent. Called
drh4b5345c2018-04-24 13:07:40 +00001965** recursively to render sublevels.
1966*/
drhe2ca99c2018-05-02 00:33:43 +00001967static void eqp_render_level(ShellState *p, int iEqpId){
drh4b5345c2018-04-24 13:07:40 +00001968 EQPGraphRow *pRow, *pNext;
drh4b5345c2018-04-24 13:07:40 +00001969 int n = strlen30(p->sGraph.zPrefix);
1970 char *z;
drhe2ca99c2018-05-02 00:33:43 +00001971 for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
1972 pNext = eqp_next_row(p, iEqpId, pRow);
drh4b5345c2018-04-24 13:07:40 +00001973 z = pRow->zText;
drhe2754c12019-08-26 12:50:01 +00001974 utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
1975 pNext ? "|--" : "`--", z);
drhe2188f02018-05-07 11:37:34 +00001976 if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){
drh4b5345c2018-04-24 13:07:40 +00001977 memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4);
drhe2ca99c2018-05-02 00:33:43 +00001978 eqp_render_level(p, pRow->iEqpId);
drh4b5345c2018-04-24 13:07:40 +00001979 p->sGraph.zPrefix[n] = 0;
1980 }
1981 }
1982}
1983
1984/*
1985** Display and reset the EXPLAIN QUERY PLAN data
1986*/
1987static void eqp_render(ShellState *p){
1988 EQPGraphRow *pRow = p->sGraph.pRow;
1989 if( pRow ){
1990 if( pRow->zText[0]=='-' ){
1991 if( pRow->pNext==0 ){
1992 eqp_reset(p);
1993 return;
1994 }
1995 utf8_printf(p->out, "%s\n", pRow->zText+3);
1996 p->sGraph.pRow = pRow->pNext;
1997 sqlite3_free(pRow);
1998 }else{
1999 utf8_printf(p->out, "QUERY PLAN\n");
2000 }
2001 p->sGraph.zPrefix[0] = 0;
2002 eqp_render_level(p, 0);
2003 eqp_reset(p);
2004 }
2005}
drh11be81d2018-01-06 15:46:20 +00002006
drh569b1d92019-02-05 20:51:41 +00002007#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh11be81d2018-01-06 15:46:20 +00002008/*
drh3f83f592019-02-04 14:53:18 +00002009** Progress handler callback.
2010*/
2011static int progress_handler(void *pClientData) {
2012 ShellState *p = (ShellState*)pClientData;
2013 p->nProgress++;
2014 if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
2015 raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
drhfc4eeef2019-02-05 19:48:46 +00002016 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
2017 if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
drh3f83f592019-02-04 14:53:18 +00002018 return 1;
2019 }
drhfc4eeef2019-02-05 19:48:46 +00002020 if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
drh3f83f592019-02-04 14:53:18 +00002021 raw_printf(p->out, "Progress %u\n", p->nProgress);
2022 }
2023 return 0;
2024}
drh569b1d92019-02-05 20:51:41 +00002025#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
drh3f83f592019-02-04 14:53:18 +00002026
2027/*
drh30c54a02020-05-28 23:49:50 +00002028** Print N dashes
2029*/
2030static void print_dashes(FILE *out, int N){
2031 const char zDash[] = "--------------------------------------------------";
2032 const int nDash = sizeof(zDash) - 1;
2033 while( N>nDash ){
2034 fputs(zDash, out);
2035 N -= nDash;
2036 }
2037 raw_printf(out, "%.*s", N, zDash);
2038}
2039
2040/*
drh0908e382020-06-04 18:05:39 +00002041** Print a markdown or table-style row separator using ascii-art
drh30c54a02020-05-28 23:49:50 +00002042*/
2043static void print_row_separator(
2044 ShellState *p,
2045 int nArg,
2046 const char *zSep
2047){
2048 int i;
drh0908e382020-06-04 18:05:39 +00002049 if( nArg>0 ){
drh30c54a02020-05-28 23:49:50 +00002050 fputs(zSep, p->out);
drh0908e382020-06-04 18:05:39 +00002051 print_dashes(p->out, p->actualWidth[0]+2);
2052 for(i=1; i<nArg; i++){
2053 fputs(zSep, p->out);
2054 print_dashes(p->out, p->actualWidth[i]+2);
2055 }
2056 fputs(zSep, p->out);
drh30c54a02020-05-28 23:49:50 +00002057 }
drh30c54a02020-05-28 23:49:50 +00002058 fputs("\n", p->out);
2059}
2060
2061/*
drh2ce15c32017-07-11 13:34:40 +00002062** This is the callback routine that the shell
2063** invokes for each row of a query result.
2064*/
2065static int shell_callback(
2066 void *pArg,
2067 int nArg, /* Number of result columns */
2068 char **azArg, /* Text of each result column */
2069 char **azCol, /* Column names */
drhd6f25242020-05-29 12:31:53 +00002070 int *aiType /* Column types. Might be NULL */
drh2ce15c32017-07-11 13:34:40 +00002071){
2072 int i;
2073 ShellState *p = (ShellState*)pArg;
2074
drhb3c45232017-08-28 14:33:27 +00002075 if( azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00002076 switch( p->cMode ){
drh5d88be82021-12-09 16:17:43 +00002077 case MODE_Count:
2078 case MODE_Off: {
2079 break;
2080 }
drh2ce15c32017-07-11 13:34:40 +00002081 case MODE_Line: {
2082 int w = 5;
2083 if( azArg==0 ) break;
2084 for(i=0; i<nArg; i++){
2085 int len = strlen30(azCol[i] ? azCol[i] : "");
2086 if( len>w ) w = len;
2087 }
2088 if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
2089 for(i=0; i<nArg; i++){
2090 utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
2091 azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
2092 }
2093 break;
2094 }
drh8c748632020-05-29 16:15:58 +00002095 case MODE_Explain: {
2096 static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
2097 if( nArg>ArraySize(aExplainWidth) ){
2098 nArg = ArraySize(aExplainWidth);
drh2ce15c32017-07-11 13:34:40 +00002099 }
2100 if( p->cnt++==0 ){
2101 for(i=0; i<nArg; i++){
drh8c748632020-05-29 16:15:58 +00002102 int w = aExplainWidth[i];
2103 utf8_width_print(p->out, w, azCol[i]);
2104 fputs(i==nArg-1 ? "\n" : " ", p->out);
drh2ce15c32017-07-11 13:34:40 +00002105 }
drhe566ceb2020-05-30 15:34:49 +00002106 for(i=0; i<nArg; i++){
2107 int w = aExplainWidth[i];
2108 print_dashes(p->out, w);
2109 fputs(i==nArg-1 ? "\n" : " ", p->out);
2110 }
drh2ce15c32017-07-11 13:34:40 +00002111 }
2112 if( azArg==0 ) break;
2113 for(i=0; i<nArg; i++){
drh8c748632020-05-29 16:15:58 +00002114 int w = aExplainWidth[i];
drhaa556b02021-01-13 12:59:20 +00002115 if( i==nArg-1 ) w = 0;
drh8c748632020-05-29 16:15:58 +00002116 if( azArg[i] && strlenChar(azArg[i])>w ){
2117 w = strlenChar(azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00002118 }
drh8c748632020-05-29 16:15:58 +00002119 if( i==1 && p->aiIndent && p->pStmt ){
2120 if( p->iIndent<p->nIndent ){
2121 utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
drh2ce15c32017-07-11 13:34:40 +00002122 }
drh8c748632020-05-29 16:15:58 +00002123 p->iIndent++;
drh2ce15c32017-07-11 13:34:40 +00002124 }
2125 utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
drh8c748632020-05-29 16:15:58 +00002126 fputs(i==nArg-1 ? "\n" : " ", p->out);
drh2ce15c32017-07-11 13:34:40 +00002127 }
2128 break;
2129 }
2130 case MODE_Semi: { /* .schema and .fullschema output */
2131 printSchemaLine(p->out, azArg[0], ";\n");
2132 break;
2133 }
2134 case MODE_Pretty: { /* .schema and .fullschema with --indent */
2135 char *z;
2136 int j;
2137 int nParen = 0;
2138 char cEnd = 0;
2139 char c;
2140 int nLine = 0;
2141 assert( nArg==1 );
2142 if( azArg[0]==0 ) break;
2143 if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
2144 || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
2145 ){
2146 utf8_printf(p->out, "%s;\n", azArg[0]);
2147 break;
2148 }
2149 z = sqlite3_mprintf("%s", azArg[0]);
drhe3e25652021-12-16 13:29:28 +00002150 shell_check_oom(z);
drh2ce15c32017-07-11 13:34:40 +00002151 j = 0;
2152 for(i=0; IsSpace(z[i]); i++){}
2153 for(; (c = z[i])!=0; i++){
2154 if( IsSpace(c) ){
drhc3cbd672017-10-05 19:12:10 +00002155 if( z[j-1]=='\r' ) z[j-1] = '\n';
drh2ce15c32017-07-11 13:34:40 +00002156 if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
2157 }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
2158 j--;
2159 }
2160 z[j++] = c;
2161 }
2162 while( j>0 && IsSpace(z[j-1]) ){ j--; }
2163 z[j] = 0;
2164 if( strlen30(z)>=79 ){
drhe2754c12019-08-26 12:50:01 +00002165 for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */
drh2ce15c32017-07-11 13:34:40 +00002166 if( c==cEnd ){
2167 cEnd = 0;
2168 }else if( c=='"' || c=='\'' || c=='`' ){
2169 cEnd = c;
2170 }else if( c=='[' ){
2171 cEnd = ']';
drh11be81d2018-01-06 15:46:20 +00002172 }else if( c=='-' && z[i+1]=='-' ){
2173 cEnd = '\n';
drh2ce15c32017-07-11 13:34:40 +00002174 }else if( c=='(' ){
2175 nParen++;
2176 }else if( c==')' ){
2177 nParen--;
2178 if( nLine>0 && nParen==0 && j>0 ){
2179 printSchemaLineN(p->out, z, j, "\n");
2180 j = 0;
2181 }
2182 }
2183 z[j++] = c;
drh11be81d2018-01-06 15:46:20 +00002184 if( nParen==1 && cEnd==0
2185 && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
2186 ){
drh2ce15c32017-07-11 13:34:40 +00002187 if( c=='\n' ) j--;
2188 printSchemaLineN(p->out, z, j, "\n ");
2189 j = 0;
2190 nLine++;
2191 while( IsSpace(z[i+1]) ){ i++; }
2192 }
2193 }
2194 z[j] = 0;
2195 }
2196 printSchemaLine(p->out, z, ";\n");
2197 sqlite3_free(z);
2198 break;
2199 }
2200 case MODE_List: {
2201 if( p->cnt++==0 && p->showHeader ){
2202 for(i=0; i<nArg; i++){
2203 utf8_printf(p->out,"%s%s",azCol[i],
2204 i==nArg-1 ? p->rowSeparator : p->colSeparator);
2205 }
2206 }
2207 if( azArg==0 ) break;
2208 for(i=0; i<nArg; i++){
2209 char *z = azArg[i];
2210 if( z==0 ) z = p->nullValue;
2211 utf8_printf(p->out, "%s", z);
2212 if( i<nArg-1 ){
2213 utf8_printf(p->out, "%s", p->colSeparator);
2214 }else{
2215 utf8_printf(p->out, "%s", p->rowSeparator);
2216 }
2217 }
2218 break;
2219 }
2220 case MODE_Html: {
2221 if( p->cnt++==0 && p->showHeader ){
2222 raw_printf(p->out,"<TR>");
2223 for(i=0; i<nArg; i++){
2224 raw_printf(p->out,"<TH>");
2225 output_html_string(p->out, azCol[i]);
2226 raw_printf(p->out,"</TH>\n");
2227 }
2228 raw_printf(p->out,"</TR>\n");
2229 }
2230 if( azArg==0 ) break;
2231 raw_printf(p->out,"<TR>");
2232 for(i=0; i<nArg; i++){
2233 raw_printf(p->out,"<TD>");
2234 output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
2235 raw_printf(p->out,"</TD>\n");
2236 }
2237 raw_printf(p->out,"</TR>\n");
2238 break;
2239 }
2240 case MODE_Tcl: {
2241 if( p->cnt++==0 && p->showHeader ){
2242 for(i=0; i<nArg; i++){
2243 output_c_string(p->out,azCol[i] ? azCol[i] : "");
2244 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
2245 }
2246 utf8_printf(p->out, "%s", p->rowSeparator);
2247 }
2248 if( azArg==0 ) break;
2249 for(i=0; i<nArg; i++){
2250 output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
2251 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
2252 }
2253 utf8_printf(p->out, "%s", p->rowSeparator);
2254 break;
2255 }
2256 case MODE_Csv: {
2257 setBinaryMode(p->out, 1);
2258 if( p->cnt++==0 && p->showHeader ){
2259 for(i=0; i<nArg; i++){
2260 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
2261 }
2262 utf8_printf(p->out, "%s", p->rowSeparator);
2263 }
2264 if( nArg>0 ){
2265 for(i=0; i<nArg; i++){
2266 output_csv(p, azArg[i], i<nArg-1);
2267 }
2268 utf8_printf(p->out, "%s", p->rowSeparator);
2269 }
2270 setTextMode(p->out, 1);
2271 break;
2272 }
2273 case MODE_Insert: {
2274 if( azArg==0 ) break;
2275 utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
2276 if( p->showHeader ){
2277 raw_printf(p->out,"(");
2278 for(i=0; i<nArg; i++){
2279 if( i>0 ) raw_printf(p->out, ",");
2280 if( quoteChar(azCol[i]) ){
2281 char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
drhe3e25652021-12-16 13:29:28 +00002282 shell_check_oom(z);
drh2ce15c32017-07-11 13:34:40 +00002283 utf8_printf(p->out, "%s", z);
2284 sqlite3_free(z);
2285 }else{
2286 raw_printf(p->out, "%s", azCol[i]);
2287 }
2288 }
2289 raw_printf(p->out,")");
2290 }
2291 p->cnt++;
2292 for(i=0; i<nArg; i++){
2293 raw_printf(p->out, i>0 ? "," : " VALUES(");
2294 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2295 utf8_printf(p->out,"NULL");
2296 }else if( aiType && aiType[i]==SQLITE_TEXT ){
2297 if( ShellHasFlag(p, SHFLG_Newlines) ){
2298 output_quoted_string(p->out, azArg[i]);
2299 }else{
2300 output_quoted_escaped_string(p->out, azArg[i]);
2301 }
2302 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
2303 utf8_printf(p->out,"%s", azArg[i]);
2304 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2305 char z[50];
2306 double r = sqlite3_column_double(p->pStmt, i);
drh2f1f8802018-06-13 17:19:20 +00002307 sqlite3_uint64 ur;
2308 memcpy(&ur,&r,sizeof(r));
2309 if( ur==0x7ff0000000000000LL ){
2310 raw_printf(p->out, "1e999");
2311 }else if( ur==0xfff0000000000000LL ){
2312 raw_printf(p->out, "-1e999");
2313 }else{
2314 sqlite3_snprintf(50,z,"%!.20g", r);
2315 raw_printf(p->out, "%s", z);
2316 }
drh2ce15c32017-07-11 13:34:40 +00002317 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2318 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2319 int nBlob = sqlite3_column_bytes(p->pStmt, i);
2320 output_hex_blob(p->out, pBlob, nBlob);
2321 }else if( isNumber(azArg[i], 0) ){
2322 utf8_printf(p->out,"%s", azArg[i]);
2323 }else if( ShellHasFlag(p, SHFLG_Newlines) ){
2324 output_quoted_string(p->out, azArg[i]);
2325 }else{
2326 output_quoted_escaped_string(p->out, azArg[i]);
2327 }
2328 }
2329 raw_printf(p->out,");\n");
2330 break;
2331 }
drh30c54a02020-05-28 23:49:50 +00002332 case MODE_Json: {
2333 if( azArg==0 ) break;
2334 if( p->cnt==0 ){
2335 fputs("[{", p->out);
2336 }else{
2337 fputs(",\n{", p->out);
2338 }
2339 p->cnt++;
2340 for(i=0; i<nArg; i++){
drh69c093d2020-05-29 00:21:43 +00002341 output_json_string(p->out, azCol[i], -1);
drh30c54a02020-05-28 23:49:50 +00002342 putc(':', p->out);
2343 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2344 fputs("null",p->out);
2345 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2346 char z[50];
2347 double r = sqlite3_column_double(p->pStmt, i);
2348 sqlite3_uint64 ur;
2349 memcpy(&ur,&r,sizeof(r));
2350 if( ur==0x7ff0000000000000LL ){
2351 raw_printf(p->out, "1e999");
2352 }else if( ur==0xfff0000000000000LL ){
2353 raw_printf(p->out, "-1e999");
2354 }else{
2355 sqlite3_snprintf(50,z,"%!.20g", r);
2356 raw_printf(p->out, "%s", z);
2357 }
2358 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2359 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2360 int nBlob = sqlite3_column_bytes(p->pStmt, i);
drh69c093d2020-05-29 00:21:43 +00002361 output_json_string(p->out, pBlob, nBlob);
drh30c54a02020-05-28 23:49:50 +00002362 }else if( aiType && aiType[i]==SQLITE_TEXT ){
drh69c093d2020-05-29 00:21:43 +00002363 output_json_string(p->out, azArg[i], -1);
drh30c54a02020-05-28 23:49:50 +00002364 }else{
2365 utf8_printf(p->out,"%s", azArg[i]);
2366 }
2367 if( i<nArg-1 ){
2368 putc(',', p->out);
2369 }
2370 }
2371 putc('}', p->out);
2372 break;
2373 }
drh2ce15c32017-07-11 13:34:40 +00002374 case MODE_Quote: {
2375 if( azArg==0 ) break;
2376 if( p->cnt==0 && p->showHeader ){
2377 for(i=0; i<nArg; i++){
drhc6835732020-05-28 20:37:17 +00002378 if( i>0 ) fputs(p->colSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002379 output_quoted_string(p->out, azCol[i]);
2380 }
drhc6835732020-05-28 20:37:17 +00002381 fputs(p->rowSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002382 }
2383 p->cnt++;
2384 for(i=0; i<nArg; i++){
drhc6835732020-05-28 20:37:17 +00002385 if( i>0 ) fputs(p->colSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002386 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2387 utf8_printf(p->out,"NULL");
2388 }else if( aiType && aiType[i]==SQLITE_TEXT ){
2389 output_quoted_string(p->out, azArg[i]);
2390 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
2391 utf8_printf(p->out,"%s", azArg[i]);
2392 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2393 char z[50];
2394 double r = sqlite3_column_double(p->pStmt, i);
2395 sqlite3_snprintf(50,z,"%!.20g", r);
2396 raw_printf(p->out, "%s", z);
2397 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2398 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2399 int nBlob = sqlite3_column_bytes(p->pStmt, i);
2400 output_hex_blob(p->out, pBlob, nBlob);
2401 }else if( isNumber(azArg[i], 0) ){
2402 utf8_printf(p->out,"%s", azArg[i]);
2403 }else{
2404 output_quoted_string(p->out, azArg[i]);
2405 }
2406 }
drhc6835732020-05-28 20:37:17 +00002407 fputs(p->rowSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002408 break;
2409 }
2410 case MODE_Ascii: {
2411 if( p->cnt++==0 && p->showHeader ){
2412 for(i=0; i<nArg; i++){
2413 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
2414 utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
2415 }
2416 utf8_printf(p->out, "%s", p->rowSeparator);
2417 }
2418 if( azArg==0 ) break;
2419 for(i=0; i<nArg; i++){
2420 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
2421 utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
2422 }
2423 utf8_printf(p->out, "%s", p->rowSeparator);
2424 break;
2425 }
drh4b5345c2018-04-24 13:07:40 +00002426 case MODE_EQP: {
drhe2ca99c2018-05-02 00:33:43 +00002427 eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]);
drh4b5345c2018-04-24 13:07:40 +00002428 break;
2429 }
drh2ce15c32017-07-11 13:34:40 +00002430 }
2431 return 0;
2432}
2433
2434/*
2435** This is the callback routine that the SQLite library
2436** invokes for each row of a query result.
2437*/
2438static int callback(void *pArg, int nArg, char **azArg, char **azCol){
2439 /* since we don't have type info, call the shell_callback with a NULL value */
2440 return shell_callback(pArg, nArg, azArg, azCol, NULL);
2441}
2442
2443/*
2444** This is the callback routine from sqlite3_exec() that appends all
2445** output onto the end of a ShellText object.
2446*/
2447static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
2448 ShellText *p = (ShellText*)pArg;
2449 int i;
2450 UNUSED_PARAMETER(az);
drhb3c45232017-08-28 14:33:27 +00002451 if( azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00002452 if( p->n ) appendText(p, "|", 0);
2453 for(i=0; i<nArg; i++){
2454 if( i ) appendText(p, ",", 0);
2455 if( azArg[i] ) appendText(p, azArg[i], 0);
2456 }
2457 return 0;
2458}
2459
2460/*
2461** Generate an appropriate SELFTEST table in the main database.
2462*/
2463static void createSelftestTable(ShellState *p){
2464 char *zErrMsg = 0;
2465 sqlite3_exec(p->db,
2466 "SAVEPOINT selftest_init;\n"
2467 "CREATE TABLE IF NOT EXISTS selftest(\n"
2468 " tno INTEGER PRIMARY KEY,\n" /* Test number */
2469 " op TEXT,\n" /* Operator: memo run */
2470 " cmd TEXT,\n" /* Command text */
2471 " ans TEXT\n" /* Desired answer */
2472 ");"
2473 "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n"
2474 "INSERT INTO [_shell$self](rowid,op,cmd)\n"
2475 " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n"
2476 " 'memo','Tests generated by --init');\n"
2477 "INSERT INTO [_shell$self]\n"
2478 " SELECT 'run',\n"
2479 " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql "
drh067b92b2020-06-19 15:24:12 +00002480 "FROM sqlite_schema ORDER BY 2'',224))',\n"
drh2ce15c32017-07-11 13:34:40 +00002481 " hex(sha3_query('SELECT type,name,tbl_name,sql "
drh067b92b2020-06-19 15:24:12 +00002482 "FROM sqlite_schema ORDER BY 2',224));\n"
drh2ce15c32017-07-11 13:34:40 +00002483 "INSERT INTO [_shell$self]\n"
2484 " SELECT 'run',"
2485 " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||"
2486 " printf('%w',name) || '\" NOT INDEXED'',224))',\n"
2487 " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"
2488 " FROM (\n"
drh067b92b2020-06-19 15:24:12 +00002489 " SELECT name FROM sqlite_schema\n"
drh2ce15c32017-07-11 13:34:40 +00002490 " WHERE type='table'\n"
2491 " AND name<>'selftest'\n"
2492 " AND coalesce(rootpage,0)>0\n"
2493 " )\n"
2494 " ORDER BY name;\n"
2495 "INSERT INTO [_shell$self]\n"
2496 " VALUES('run','PRAGMA integrity_check','ok');\n"
2497 "INSERT INTO selftest(tno,op,cmd,ans)"
2498 " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n"
2499 "DROP TABLE [_shell$self];"
2500 ,0,0,&zErrMsg);
2501 if( zErrMsg ){
2502 utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
2503 sqlite3_free(zErrMsg);
2504 }
2505 sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
2506}
2507
2508
2509/*
2510** Set the destination table field of the ShellState structure to
2511** the name of the table given. Escape any quote characters in the
2512** table name.
2513*/
2514static void set_table_name(ShellState *p, const char *zName){
2515 int i, n;
mistachkin2158a0c2017-09-09 00:51:36 +00002516 char cQuote;
drh2ce15c32017-07-11 13:34:40 +00002517 char *z;
2518
2519 if( p->zDestTable ){
2520 free(p->zDestTable);
2521 p->zDestTable = 0;
2522 }
2523 if( zName==0 ) return;
2524 cQuote = quoteChar(zName);
2525 n = strlen30(zName);
2526 if( cQuote ) n += n+2;
2527 z = p->zDestTable = malloc( n+1 );
drhe3e25652021-12-16 13:29:28 +00002528 shell_check_oom(z);
drh2ce15c32017-07-11 13:34:40 +00002529 n = 0;
2530 if( cQuote ) z[n++] = cQuote;
2531 for(i=0; zName[i]; i++){
2532 z[n++] = zName[i];
2533 if( zName[i]==cQuote ) z[n++] = cQuote;
2534 }
2535 if( cQuote ) z[n++] = cQuote;
2536 z[n] = 0;
2537}
2538
drhf62641e2021-12-24 20:22:13 +00002539/*
2540** Maybe construct two lines of text that point out the position of a
2541** syntax error. Return a pointer to the text, in memory obtained from
2542** sqlite3_malloc(). Or, if the most recent error does not involve a
2543** specific token that we can point to, return an empty string.
2544**
2545** In all cases, the memory returned is obtained from sqlite3_malloc64()
2546** and should be released by the caller invoking sqlite3_free().
2547*/
2548static char *shell_error_context(const char *zSql, sqlite3 *db){
2549 int iOffset;
2550 size_t len;
2551 char *zCode;
2552 char *zMsg;
2553 int i;
2554 if( db==0
2555 || zSql==0
2556 || (iOffset = sqlite3_error_offset(db))<0
2557 ){
2558 return sqlite3_mprintf("");
2559 }
2560 while( iOffset>50 ){
2561 iOffset--;
2562 zSql++;
2563 while( (zSql[0]&0xc0)==0x80 ){ zSql++; iOffset--; }
2564 }
2565 len = strlen(zSql);
2566 if( len>78 ){
2567 len = 78;
2568 while( (zSql[len]&0xc0)==0x80 ) len--;
2569 }
2570 zCode = sqlite3_mprintf("%.*s", len, zSql);
2571 for(i=0; zCode[i]; i++){ if( IsSpace(zSql[i]) ) zCode[i] = ' '; }
2572 if( iOffset<25 ){
2573 zMsg = sqlite3_mprintf("\n %z\n %*s^--- error here", zCode, iOffset, "");
2574 }else{
2575 zMsg = sqlite3_mprintf("\n %z\n %*serror here ---^", zCode, iOffset-14, "");
2576 }
2577 return zMsg;
2578}
2579
drh2ce15c32017-07-11 13:34:40 +00002580
2581/*
2582** Execute a query statement that will generate SQL output. Print
2583** the result columns, comma-separated, on a line and then add a
2584** semicolon terminator to the end of that line.
2585**
2586** If the number of columns is 1 and that column contains text "--"
2587** then write the semicolon on a separate line. That way, if a
2588** "--" comment occurs at the end of the statement, the comment
2589** won't consume the semicolon terminator.
2590*/
2591static int run_table_dump_query(
2592 ShellState *p, /* Query context */
drh8e9297f2020-03-25 12:50:13 +00002593 const char *zSelect /* SELECT statement to extract content */
drh2ce15c32017-07-11 13:34:40 +00002594){
2595 sqlite3_stmt *pSelect;
2596 int rc;
2597 int nResult;
2598 int i;
2599 const char *z;
2600 rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
2601 if( rc!=SQLITE_OK || !pSelect ){
drhf62641e2021-12-24 20:22:13 +00002602 char *zContext = shell_error_context(zSelect, p->db);
2603 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n%s", rc,
2604 sqlite3_errmsg(p->db), zContext);
2605 sqlite3_free(zContext);
drh2ce15c32017-07-11 13:34:40 +00002606 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
2607 return rc;
2608 }
2609 rc = sqlite3_step(pSelect);
2610 nResult = sqlite3_column_count(pSelect);
2611 while( rc==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00002612 z = (const char*)sqlite3_column_text(pSelect, 0);
2613 utf8_printf(p->out, "%s", z);
2614 for(i=1; i<nResult; i++){
2615 utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
2616 }
2617 if( z==0 ) z = "";
2618 while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
2619 if( z[0] ){
2620 raw_printf(p->out, "\n;\n");
2621 }else{
2622 raw_printf(p->out, ";\n");
2623 }
2624 rc = sqlite3_step(pSelect);
2625 }
2626 rc = sqlite3_finalize(pSelect);
2627 if( rc!=SQLITE_OK ){
2628 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
2629 sqlite3_errmsg(p->db));
2630 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
2631 }
2632 return rc;
2633}
2634
2635/*
larrybrf9a49b02021-10-26 16:57:09 +00002636** Allocate space and save off string indicating current error.
drh2ce15c32017-07-11 13:34:40 +00002637*/
2638static char *save_err_msg(
larrybrf9a49b02021-10-26 16:57:09 +00002639 sqlite3 *db, /* Database to query */
drh633c7982022-02-08 12:13:16 +00002640 const char *zPhase, /* When the error occcurs */
drhf62641e2021-12-24 20:22:13 +00002641 int rc, /* Error code returned from API */
2642 const char *zSql /* SQL string, or NULL */
drh2ce15c32017-07-11 13:34:40 +00002643){
drhe3e25652021-12-16 13:29:28 +00002644 char *zErr;
drhf62641e2021-12-24 20:22:13 +00002645 char *zContext;
drh633c7982022-02-08 12:13:16 +00002646 sqlite3_str *pStr = sqlite3_str_new(0);
2647 sqlite3_str_appendf(pStr, "%s, %s", zPhase, sqlite3_errmsg(db));
2648 if( rc>1 ){
2649 sqlite3_str_appendf(pStr, " (%d)", rc);
2650 }
drhf62641e2021-12-24 20:22:13 +00002651 zContext = shell_error_context(zSql, db);
drh633c7982022-02-08 12:13:16 +00002652 if( zContext ){
2653 sqlite3_str_appendall(pStr, zContext);
2654 sqlite3_free(zContext);
2655 }
2656 zErr = sqlite3_str_finish(pStr);
drhe3e25652021-12-16 13:29:28 +00002657 shell_check_oom(zErr);
2658 return zErr;
drh2ce15c32017-07-11 13:34:40 +00002659}
2660
2661#ifdef __linux__
2662/*
2663** Attempt to display I/O stats on Linux using /proc/PID/io
2664*/
2665static void displayLinuxIoStats(FILE *out){
2666 FILE *in;
2667 char z[200];
2668 sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
2669 in = fopen(z, "rb");
2670 if( in==0 ) return;
2671 while( fgets(z, sizeof(z), in)!=0 ){
2672 static const struct {
2673 const char *zPattern;
2674 const char *zDesc;
2675 } aTrans[] = {
2676 { "rchar: ", "Bytes received by read():" },
2677 { "wchar: ", "Bytes sent to write():" },
2678 { "syscr: ", "Read() system calls:" },
2679 { "syscw: ", "Write() system calls:" },
2680 { "read_bytes: ", "Bytes read from storage:" },
2681 { "write_bytes: ", "Bytes written to storage:" },
2682 { "cancelled_write_bytes: ", "Cancelled write bytes:" },
2683 };
2684 int i;
2685 for(i=0; i<ArraySize(aTrans); i++){
drhaf2770f2018-01-05 14:55:43 +00002686 int n = strlen30(aTrans[i].zPattern);
drh2ce15c32017-07-11 13:34:40 +00002687 if( strncmp(aTrans[i].zPattern, z, n)==0 ){
2688 utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
2689 break;
2690 }
2691 }
2692 }
2693 fclose(in);
2694}
2695#endif
2696
2697/*
2698** Display a single line of status using 64-bit values.
2699*/
2700static void displayStatLine(
2701 ShellState *p, /* The shell context */
2702 char *zLabel, /* Label for this one line */
2703 char *zFormat, /* Format for the result */
2704 int iStatusCtrl, /* Which status to display */
2705 int bReset /* True to reset the stats */
2706){
2707 sqlite3_int64 iCur = -1;
2708 sqlite3_int64 iHiwtr = -1;
2709 int i, nPercent;
2710 char zLine[200];
2711 sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset);
2712 for(i=0, nPercent=0; zFormat[i]; i++){
2713 if( zFormat[i]=='%' ) nPercent++;
2714 }
2715 if( nPercent>1 ){
2716 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr);
2717 }else{
2718 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
2719 }
2720 raw_printf(p->out, "%-36s %s\n", zLabel, zLine);
2721}
2722
2723/*
2724** Display memory stats.
2725*/
2726static int display_stats(
2727 sqlite3 *db, /* Database to query */
2728 ShellState *pArg, /* Pointer to ShellState */
2729 int bReset /* True to reset the stats */
2730){
2731 int iCur;
2732 int iHiwtr;
drh393344f2018-03-09 16:37:05 +00002733 FILE *out;
2734 if( pArg==0 || pArg->out==0 ) return 0;
2735 out = pArg->out;
drh2ce15c32017-07-11 13:34:40 +00002736
drha6e6cf22021-01-09 19:10:04 +00002737 if( pArg->pStmt && pArg->statsOn==2 ){
drh393344f2018-03-09 16:37:05 +00002738 int nCol, i, x;
2739 sqlite3_stmt *pStmt = pArg->pStmt;
2740 char z[100];
2741 nCol = sqlite3_column_count(pStmt);
2742 raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
2743 for(i=0; i<nCol; i++){
2744 sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
2745 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
drh929cce82018-03-17 16:26:36 +00002746#ifndef SQLITE_OMIT_DECLTYPE
drh393344f2018-03-09 16:37:05 +00002747 sqlite3_snprintf(30, z+x, "declared type:");
2748 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
drh929cce82018-03-17 16:26:36 +00002749#endif
2750#ifdef SQLITE_ENABLE_COLUMN_METADATA
drh393344f2018-03-09 16:37:05 +00002751 sqlite3_snprintf(30, z+x, "database name:");
2752 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
2753 sqlite3_snprintf(30, z+x, "table name:");
2754 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
2755 sqlite3_snprintf(30, z+x, "origin name:");
2756 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
drh929cce82018-03-17 16:26:36 +00002757#endif
drh2ce15c32017-07-11 13:34:40 +00002758 }
drh929cce82018-03-17 16:26:36 +00002759 }
drh2ce15c32017-07-11 13:34:40 +00002760
drha6e6cf22021-01-09 19:10:04 +00002761 if( pArg->statsOn==3 ){
2762 if( pArg->pStmt ){
2763 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
2764 raw_printf(pArg->out, "VM-steps: %d\n", iCur);
2765 }
2766 return 0;
2767 }
2768
drh393344f2018-03-09 16:37:05 +00002769 displayStatLine(pArg, "Memory Used:",
2770 "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
2771 displayStatLine(pArg, "Number of Outstanding Allocations:",
2772 "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
2773 if( pArg->shellFlgs & SHFLG_Pagecache ){
2774 displayStatLine(pArg, "Number of Pcache Pages Used:",
2775 "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
2776 }
2777 displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
2778 "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
2779 displayStatLine(pArg, "Largest Allocation:",
2780 "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
2781 displayStatLine(pArg, "Largest Pcache Allocation:",
2782 "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
2783#ifdef YYTRACKMAXSTACKDEPTH
2784 displayStatLine(pArg, "Deepest Parser Stack:",
2785 "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
2786#endif
2787
2788 if( db ){
drh2ce15c32017-07-11 13:34:40 +00002789 if( pArg->shellFlgs & SHFLG_Lookaside ){
2790 iHiwtr = iCur = -1;
2791 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
2792 &iCur, &iHiwtr, bReset);
2793 raw_printf(pArg->out,
2794 "Lookaside Slots Used: %d (max %d)\n",
2795 iCur, iHiwtr);
2796 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
2797 &iCur, &iHiwtr, bReset);
2798 raw_printf(pArg->out, "Successful lookaside attempts: %d\n",
2799 iHiwtr);
2800 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
2801 &iCur, &iHiwtr, bReset);
2802 raw_printf(pArg->out, "Lookaside failures due to size: %d\n",
2803 iHiwtr);
2804 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
2805 &iCur, &iHiwtr, bReset);
2806 raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n",
2807 iHiwtr);
2808 }
2809 iHiwtr = iCur = -1;
2810 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
2811 raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n",
2812 iCur);
2813 iHiwtr = iCur = -1;
2814 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
2815 raw_printf(pArg->out, "Page cache hits: %d\n", iCur);
2816 iHiwtr = iCur = -1;
2817 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
2818 raw_printf(pArg->out, "Page cache misses: %d\n", iCur);
2819 iHiwtr = iCur = -1;
2820 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
2821 raw_printf(pArg->out, "Page cache writes: %d\n", iCur);
2822 iHiwtr = iCur = -1;
drhffc78a42018-03-14 14:53:50 +00002823 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
2824 raw_printf(pArg->out, "Page cache spills: %d\n", iCur);
2825 iHiwtr = iCur = -1;
drh2ce15c32017-07-11 13:34:40 +00002826 sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
2827 raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n",
2828 iCur);
2829 iHiwtr = iCur = -1;
2830 sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
2831 raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
2832 iCur);
2833 }
2834
drh393344f2018-03-09 16:37:05 +00002835 if( pArg->pStmt ){
drh23d41e62021-12-06 21:45:31 +00002836 int iHit, iMiss;
drh2ce15c32017-07-11 13:34:40 +00002837 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
2838 bReset);
2839 raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
2840 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
2841 raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
2842 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
2843 raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
drh23d41e62021-12-06 21:45:31 +00002844 iHit = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_HIT, bReset);
2845 iMiss = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_MISS, bReset);
2846 if( iHit || iMiss ){
2847 raw_printf(pArg->out, "Bloom filter bypass taken: %d/%d\n",
2848 iHit, iHit+iMiss);
2849 }
drh2ce15c32017-07-11 13:34:40 +00002850 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
2851 raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
drhe2754c12019-08-26 12:50:01 +00002852 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
drh393344f2018-03-09 16:37:05 +00002853 raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
2854 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
2855 raw_printf(pArg->out, "Number of times run: %d\n", iCur);
2856 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
2857 raw_printf(pArg->out, "Memory used by prepared stmt: %d\n", iCur);
drh2ce15c32017-07-11 13:34:40 +00002858 }
2859
2860#ifdef __linux__
2861 displayLinuxIoStats(pArg->out);
2862#endif
2863
2864 /* Do not remove this machine readable comment: extra-stats-output-here */
2865
2866 return 0;
2867}
2868
2869/*
2870** Display scan stats.
2871*/
2872static void display_scanstats(
2873 sqlite3 *db, /* Database to query */
2874 ShellState *pArg /* Pointer to ShellState */
2875){
2876#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
2877 UNUSED_PARAMETER(db);
2878 UNUSED_PARAMETER(pArg);
2879#else
2880 int i, k, n, mx;
2881 raw_printf(pArg->out, "-------- scanstats --------\n");
2882 mx = 0;
2883 for(k=0; k<=mx; k++){
2884 double rEstLoop = 1.0;
2885 for(i=n=0; 1; i++){
2886 sqlite3_stmt *p = pArg->pStmt;
2887 sqlite3_int64 nLoop, nVisit;
2888 double rEst;
2889 int iSid;
2890 const char *zExplain;
2891 if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){
2892 break;
2893 }
2894 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
2895 if( iSid>mx ) mx = iSid;
2896 if( iSid!=k ) continue;
2897 if( n==0 ){
2898 rEstLoop = (double)nLoop;
2899 if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k);
2900 }
2901 n++;
2902 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
2903 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
2904 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
2905 utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
2906 rEstLoop *= rEst;
2907 raw_printf(pArg->out,
2908 " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
2909 nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
2910 );
2911 }
2912 }
2913 raw_printf(pArg->out, "---------------------------\n");
2914#endif
2915}
2916
2917/*
2918** Parameter azArray points to a zero-terminated array of strings. zStr
2919** points to a single nul-terminated string. Return non-zero if zStr
2920** is equal, according to strcmp(), to any of the strings in the array.
2921** Otherwise, return zero.
2922*/
2923static int str_in_array(const char *zStr, const char **azArray){
2924 int i;
2925 for(i=0; azArray[i]; i++){
2926 if( 0==strcmp(zStr, azArray[i]) ) return 1;
2927 }
2928 return 0;
2929}
2930
2931/*
2932** If compiled statement pSql appears to be an EXPLAIN statement, allocate
2933** and populate the ShellState.aiIndent[] array with the number of
2934** spaces each opcode should be indented before it is output.
2935**
2936** The indenting rules are:
2937**
2938** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
2939** all opcodes that occur between the p2 jump destination and the opcode
2940** itself by 2 spaces.
2941**
2942** * For each "Goto", if the jump destination is earlier in the program
2943** and ends on one of:
2944** Yield SeekGt SeekLt RowSetRead Rewind
2945** or if the P1 parameter is one instead of zero,
2946** then indent all opcodes between the earlier instruction
2947** and "Goto" by 2 spaces.
2948*/
2949static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
2950 const char *zSql; /* The text of the SQL statement */
2951 const char *z; /* Used to check if this is an EXPLAIN */
2952 int *abYield = 0; /* True if op is an OP_Yield */
2953 int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
2954 int iOp; /* Index of operation in p->aiIndent[] */
2955
drhf1949b62018-06-07 17:32:59 +00002956 const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
drh2ce15c32017-07-11 13:34:40 +00002957 const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
2958 "Rewind", 0 };
2959 const char *azGoto[] = { "Goto", 0 };
2960
2961 /* Try to figure out if this is really an EXPLAIN statement. If this
2962 ** cannot be verified, return early. */
2963 if( sqlite3_column_count(pSql)!=8 ){
2964 p->cMode = p->mode;
2965 return;
2966 }
2967 zSql = sqlite3_sql(pSql);
2968 if( zSql==0 ) return;
2969 for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
2970 if( sqlite3_strnicmp(z, "explain", 7) ){
2971 p->cMode = p->mode;
2972 return;
2973 }
2974
2975 for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
2976 int i;
2977 int iAddr = sqlite3_column_int(pSql, 0);
2978 const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
2979
2980 /* Set p2 to the P2 field of the current opcode. Then, assuming that
2981 ** p2 is an instruction address, set variable p2op to the index of that
2982 ** instruction in the aiIndent[] array. p2 and p2op may be different if
2983 ** the current instruction is part of a sub-program generated by an
2984 ** SQL trigger or foreign key. */
2985 int p2 = sqlite3_column_int(pSql, 3);
2986 int p2op = (p2 + (iOp-iAddr));
2987
2988 /* Grow the p->aiIndent array as required */
2989 if( iOp>=nAlloc ){
2990 if( iOp==0 ){
2991 /* Do further verfication that this is explain output. Abort if
2992 ** it is not */
2993 static const char *explainCols[] = {
2994 "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" };
2995 int jj;
2996 for(jj=0; jj<ArraySize(explainCols); jj++){
2997 if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
2998 p->cMode = p->mode;
2999 sqlite3_reset(pSql);
3000 return;
3001 }
3002 }
3003 }
3004 nAlloc += 100;
3005 p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
drhe3e25652021-12-16 13:29:28 +00003006 shell_check_oom(p->aiIndent);
drh2ce15c32017-07-11 13:34:40 +00003007 abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
drhe3e25652021-12-16 13:29:28 +00003008 shell_check_oom(abYield);
drh2ce15c32017-07-11 13:34:40 +00003009 }
3010 abYield[iOp] = str_in_array(zOp, azYield);
3011 p->aiIndent[iOp] = 0;
3012 p->nIndent = iOp+1;
3013
3014 if( str_in_array(zOp, azNext) ){
3015 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
3016 }
3017 if( str_in_array(zOp, azGoto) && p2op<p->nIndent
3018 && (abYield[p2op] || sqlite3_column_int(pSql, 2))
3019 ){
3020 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
3021 }
3022 }
3023
3024 p->iIndent = 0;
3025 sqlite3_free(abYield);
3026 sqlite3_reset(pSql);
3027}
3028
3029/*
3030** Free the array allocated by explain_data_prepare().
3031*/
3032static void explain_data_delete(ShellState *p){
3033 sqlite3_free(p->aiIndent);
3034 p->aiIndent = 0;
3035 p->nIndent = 0;
3036 p->iIndent = 0;
3037}
3038
3039/*
3040** Disable and restore .wheretrace and .selecttrace settings.
3041*/
drhc0622a42020-12-04 01:17:57 +00003042static unsigned int savedSelectTrace;
3043static unsigned int savedWhereTrace;
drh2ce15c32017-07-11 13:34:40 +00003044static void disable_debug_trace_modes(void){
drh0a2fb792020-12-04 16:58:20 +00003045 unsigned int zero = 0;
drhc0622a42020-12-04 01:17:57 +00003046 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace);
drh0a2fb792020-12-04 16:58:20 +00003047 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero);
drhc0622a42020-12-04 01:17:57 +00003048 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace);
drh0a2fb792020-12-04 16:58:20 +00003049 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero);
drh2ce15c32017-07-11 13:34:40 +00003050}
3051static void restore_debug_trace_modes(void){
drhc0622a42020-12-04 01:17:57 +00003052 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &savedSelectTrace);
3053 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &savedWhereTrace);
drh2ce15c32017-07-11 13:34:40 +00003054}
3055
drh9cb02642019-02-28 20:10:52 +00003056/* Create the TEMP table used to store parameter bindings */
3057static void bind_table_init(ShellState *p){
drh346f4e22019-03-25 21:35:41 +00003058 int wrSchema = 0;
drh4b86e202020-01-19 20:37:26 +00003059 int defensiveMode = 0;
3060 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
3061 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
drh346f4e22019-03-25 21:35:41 +00003062 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
3063 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
drh9cb02642019-02-28 20:10:52 +00003064 sqlite3_exec(p->db,
drh65c29fd2019-03-25 21:56:26 +00003065 "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
drh9cb02642019-02-28 20:10:52 +00003066 " key TEXT PRIMARY KEY,\n"
larrybrdabada62021-04-04 12:52:58 +00003067 " value\n"
drh9cb02642019-02-28 20:10:52 +00003068 ") WITHOUT ROWID;",
3069 0, 0, 0);
drh346f4e22019-03-25 21:35:41 +00003070 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
drh4b86e202020-01-19 20:37:26 +00003071 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0);
drh9cb02642019-02-28 20:10:52 +00003072}
3073
drh8b738d02019-02-25 18:43:54 +00003074/*
3075** Bind parameters on a prepared statement.
3076**
3077** Parameter bindings are taken from a TEMP table of the form:
3078**
drh1cb02632019-03-25 22:05:22 +00003079** CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
drh8b738d02019-02-25 18:43:54 +00003080** WITHOUT ROWID;
3081**
drh91654b22020-04-02 13:21:10 +00003082** No bindings occur if this table does not exist. The name of the table
3083** begins with "sqlite_" so that it will not collide with ordinary application
3084** tables. The table must be in the TEMP schema.
drh8b738d02019-02-25 18:43:54 +00003085*/
3086static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
3087 int nVar;
3088 int i;
3089 int rc;
3090 sqlite3_stmt *pQ = 0;
3091
3092 nVar = sqlite3_bind_parameter_count(pStmt);
3093 if( nVar==0 ) return; /* Nothing to do */
drh65c29fd2019-03-25 21:56:26 +00003094 if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters",
drh8b738d02019-02-25 18:43:54 +00003095 "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
3096 return; /* Parameter table does not exist */
3097 }
3098 rc = sqlite3_prepare_v2(pArg->db,
drh65c29fd2019-03-25 21:56:26 +00003099 "SELECT value FROM temp.sqlite_parameters"
drh8b738d02019-02-25 18:43:54 +00003100 " WHERE key=?1", -1, &pQ, 0);
3101 if( rc || pQ==0 ) return;
3102 for(i=1; i<=nVar; i++){
3103 char zNum[30];
3104 const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
3105 if( zVar==0 ){
3106 sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
3107 zVar = zNum;
3108 }
3109 sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
3110 if( sqlite3_step(pQ)==SQLITE_ROW ){
3111 sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
3112 }else{
3113 sqlite3_bind_null(pStmt, i);
3114 }
3115 sqlite3_reset(pQ);
3116 }
3117 sqlite3_finalize(pQ);
3118}
3119
drh30c54a02020-05-28 23:49:50 +00003120/*
drh0908e382020-06-04 18:05:39 +00003121** UTF8 box-drawing characters. Imagine box lines like this:
3122**
3123** 1
3124** |
3125** 4 --+-- 2
3126** |
3127** 3
3128**
3129** Each box characters has between 2 and 4 of the lines leading from
3130** the center. The characters are here identified by the numbers of
3131** their corresponding lines.
3132*/
3133#define BOX_24 "\342\224\200" /* U+2500 --- */
3134#define BOX_13 "\342\224\202" /* U+2502 | */
3135#define BOX_23 "\342\224\214" /* U+250c ,- */
3136#define BOX_34 "\342\224\220" /* U+2510 -, */
3137#define BOX_12 "\342\224\224" /* U+2514 '- */
3138#define BOX_14 "\342\224\230" /* U+2518 -' */
3139#define BOX_123 "\342\224\234" /* U+251c |- */
3140#define BOX_134 "\342\224\244" /* U+2524 -| */
3141#define BOX_234 "\342\224\254" /* U+252c -,- */
3142#define BOX_124 "\342\224\264" /* U+2534 -'- */
3143#define BOX_1234 "\342\224\274" /* U+253c -|- */
3144
3145/* Draw horizontal line N characters long using unicode box
3146** characters
3147*/
3148static void print_box_line(FILE *out, int N){
3149 const char zDash[] =
3150 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
3151 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
3152 const int nDash = sizeof(zDash) - 1;
3153 N *= 3;
3154 while( N>nDash ){
3155 utf8_printf(out, zDash);
3156 N -= nDash;
3157 }
3158 utf8_printf(out, "%.*s", N, zDash);
3159}
3160
3161/*
3162** Draw a horizontal separator for a MODE_Box table.
3163*/
3164static void print_box_row_separator(
3165 ShellState *p,
3166 int nArg,
3167 const char *zSep1,
3168 const char *zSep2,
3169 const char *zSep3
3170){
3171 int i;
3172 if( nArg>0 ){
3173 utf8_printf(p->out, "%s", zSep1);
3174 print_box_line(p->out, p->actualWidth[0]+2);
3175 for(i=1; i<nArg; i++){
3176 utf8_printf(p->out, "%s", zSep2);
3177 print_box_line(p->out, p->actualWidth[i]+2);
3178 }
3179 utf8_printf(p->out, "%s", zSep3);
3180 }
3181 fputs("\n", p->out);
3182}
3183
drh09a39ed2022-01-30 21:09:03 +00003184/*
3185** z[] is a line of text that is to be displayed the .mode box or table or
3186** similar tabular formats. z[] might contain control characters such
3187** as \n, \t, \f, or \r.
3188**
3189** Compute characters to display on the first line of z[]. Stop at the
3190** first \r, \n, or \f. Expand \t into spaces. Return a copy (obtained
larrybrcc4d55c2022-02-01 02:50:45 +00003191** from malloc()) of that first line, which caller should free sometime.
3192** Write anything to display on the next line into *pzTail. If this is
3193** the last line, write a NULL into *pzTail. (*pzTail is not allocated.)
drh09a39ed2022-01-30 21:09:03 +00003194*/
3195static char *translateForDisplayAndDup(
drhca1776b2022-02-01 12:28:17 +00003196 const unsigned char *z, /* Input text to be transformed */
3197 const unsigned char **pzTail, /* OUT: Tail of the input for next line */
3198 int mxWidth, /* Max width. 0 means no limit */
3199 u8 bWordWrap /* If true, avoid breaking mid-word */
drh09a39ed2022-01-30 21:09:03 +00003200){
drhca1776b2022-02-01 12:28:17 +00003201 int i; /* Input bytes consumed */
3202 int j; /* Output bytes generated */
3203 int k; /* Input bytes to be displayed */
3204 int n; /* Output column number */
3205 unsigned char *zOut; /* Output text */
3206
drh09a39ed2022-01-30 21:09:03 +00003207 if( z==0 ){
3208 *pzTail = 0;
3209 return 0;
3210 }
3211 if( mxWidth<0 ) mxWidth = -mxWidth;
3212 if( mxWidth==0 ) mxWidth = 1000000;
drhca1776b2022-02-01 12:28:17 +00003213 i = j = n = 0;
drh09a39ed2022-01-30 21:09:03 +00003214 while( n<mxWidth ){
3215 if( z[i]>=' ' ){
3216 n++;
drhb6172192022-01-31 10:55:50 +00003217 do{ i++; j++; }while( (z[i]&0xc0)==0x80 );
drh09a39ed2022-01-30 21:09:03 +00003218 continue;
3219 }
3220 if( z[i]=='\t' ){
drhb6172192022-01-31 10:55:50 +00003221 do{
3222 n++;
3223 j++;
3224 }while( (n&7)!=0 && n<mxWidth );
drh09a39ed2022-01-30 21:09:03 +00003225 i++;
3226 continue;
3227 }
3228 break;
3229 }
drhca1776b2022-02-01 12:28:17 +00003230 if( n>=mxWidth && bWordWrap ){
3231 /* Perhaps try to back up to a better place to break the line */
3232 for(k=i; k>i/2; k--){
3233 if( isspace(z[k-1]) ) break;
3234 }
3235 if( k<=i/2 ){
3236 for(k=i; k>i/2; k--){
drhe66532a2022-02-01 13:17:11 +00003237 if( isalnum(z[k-1])!=isalnum(z[k]) && (z[k]&0xc0)!=0x80 ) break;
drhca1776b2022-02-01 12:28:17 +00003238 }
3239 }
3240 if( k<=i/2 ){
3241 k = i;
3242 }else{
3243 i = k;
3244 while( z[i]==' ' ) i++;
3245 }
3246 }else{
3247 k = i;
larrybrcc4d55c2022-02-01 02:50:45 +00003248 }
drh09a39ed2022-01-30 21:09:03 +00003249 if( n>=mxWidth && z[i]>=' ' ){
3250 *pzTail = &z[i];
3251 }else if( z[i]=='\r' && z[i+1]=='\n' ){
3252 *pzTail = z[i+2] ? &z[i+2] : 0;
drhb6172192022-01-31 10:55:50 +00003253 }else if( z[i]==0 || z[i+1]==0 ){
drh09a39ed2022-01-30 21:09:03 +00003254 *pzTail = 0;
3255 }else{
3256 *pzTail = &z[i+1];
3257 }
drhb6172192022-01-31 10:55:50 +00003258 zOut = malloc( j+1 );
drh09a39ed2022-01-30 21:09:03 +00003259 shell_check_oom(zOut);
drhb6172192022-01-31 10:55:50 +00003260 i = j = n = 0;
drhca1776b2022-02-01 12:28:17 +00003261 while( i<k ){
drh09a39ed2022-01-30 21:09:03 +00003262 if( z[i]>=' ' ){
drhb6172192022-01-31 10:55:50 +00003263 n++;
3264 do{ zOut[j++] = z[i++]; }while( (z[i]&0xc0)==0x80 );
drh09a39ed2022-01-30 21:09:03 +00003265 continue;
3266 }
3267 if( z[i]=='\t' ){
3268 do{
drhb6172192022-01-31 10:55:50 +00003269 n++;
3270 zOut[j++] = ' ';
drh09a39ed2022-01-30 21:09:03 +00003271 }while( (n&7)!=0 && n<mxWidth );
3272 i++;
3273 continue;
3274 }
3275 break;
3276 }
drhb6172192022-01-31 10:55:50 +00003277 zOut[j] = 0;
drh09a39ed2022-01-30 21:09:03 +00003278 return (char*)zOut;
3279}
3280
drhe40f2862022-01-31 14:14:29 +00003281/* Extract the value of the i-th current column for pStmt as an SQL literal
3282** value. Memory is obtained from sqlite3_malloc64() and must be freed by
3283** the caller.
3284*/
3285static char *quoted_column(sqlite3_stmt *pStmt, int i){
3286 switch( sqlite3_column_type(pStmt, i) ){
3287 case SQLITE_NULL: {
3288 return sqlite3_mprintf("NULL");
3289 }
3290 case SQLITE_INTEGER:
3291 case SQLITE_FLOAT: {
3292 return sqlite3_mprintf("%s",sqlite3_column_text(pStmt,i));
3293 }
3294 case SQLITE_TEXT: {
3295 return sqlite3_mprintf("%Q",sqlite3_column_text(pStmt,i));
3296 }
3297 case SQLITE_BLOB: {
3298 int j;
3299 sqlite3_str *pStr = sqlite3_str_new(0);
3300 const unsigned char *a = sqlite3_column_blob(pStmt,i);
3301 int n = sqlite3_column_bytes(pStmt,i);
3302 sqlite3_str_append(pStr, "x'", 2);
3303 for(j=0; j<n; j++){
3304 sqlite3_str_appendf(pStr, "%02x", a[j]);
3305 }
3306 sqlite3_str_append(pStr, "'", 1);
3307 return sqlite3_str_finish(pStr);
3308 }
3309 }
3310 return 0; /* Not reached */
3311}
drh0908e382020-06-04 18:05:39 +00003312
3313/*
drh30c54a02020-05-28 23:49:50 +00003314** Run a prepared statement and output the result in one of the
drh0908e382020-06-04 18:05:39 +00003315** table-oriented formats: MODE_Column, MODE_Markdown, MODE_Table,
3316** or MODE_Box.
drh30c54a02020-05-28 23:49:50 +00003317**
3318** This is different from ordinary exec_prepared_stmt() in that
3319** it has to run the entire query and gather the results into memory
3320** first, in order to determine column widths, before providing
3321** any output.
3322*/
drh8c748632020-05-29 16:15:58 +00003323static void exec_prepared_stmt_columnar(
3324 ShellState *p, /* Pointer to ShellState */
3325 sqlite3_stmt *pStmt /* Statment to run */
drh30c54a02020-05-28 23:49:50 +00003326){
drhf82ce382020-08-06 16:45:22 +00003327 sqlite3_int64 nRow = 0;
drh8c748632020-05-29 16:15:58 +00003328 int nColumn = 0;
3329 char **azData = 0;
drhf82ce382020-08-06 16:45:22 +00003330 sqlite3_int64 nAlloc = 0;
drh09a39ed2022-01-30 21:09:03 +00003331 char *abRowDiv = 0;
3332 const unsigned char *uz;
drh8c748632020-05-29 16:15:58 +00003333 const char *z;
drhe40f2862022-01-31 14:14:29 +00003334 char **azQuoted = 0;
drh8c748632020-05-29 16:15:58 +00003335 int rc;
drhf82ce382020-08-06 16:45:22 +00003336 sqlite3_int64 i, nData;
3337 int j, nTotal, w, n;
drh0908e382020-06-04 18:05:39 +00003338 const char *colSep = 0;
3339 const char *rowSep = 0;
drh09a39ed2022-01-30 21:09:03 +00003340 const unsigned char **azNextLine = 0;
3341 int bNextLine = 0;
3342 int bMultiLineRowExists = 0;
drhca1776b2022-02-01 12:28:17 +00003343 int bw = p->cmOpts.bWordWrap;
drh30c54a02020-05-28 23:49:50 +00003344
drhf82ce382020-08-06 16:45:22 +00003345 rc = sqlite3_step(pStmt);
3346 if( rc!=SQLITE_ROW ) return;
3347 nColumn = sqlite3_column_count(pStmt);
3348 nAlloc = nColumn*4;
drh01a8ad22021-03-20 23:15:52 +00003349 if( nAlloc<=0 ) nAlloc = 1;
drhf82ce382020-08-06 16:45:22 +00003350 azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
drhe3e25652021-12-16 13:29:28 +00003351 shell_check_oom(azData);
drh09a39ed2022-01-30 21:09:03 +00003352 azNextLine = sqlite3_malloc64( nColumn*sizeof(char*) );
drh5dce6f92022-01-31 16:29:06 +00003353 shell_check_oom((void*)azNextLine);
3354 memset((void*)azNextLine, 0, nColumn*sizeof(char*) );
larrybrcc4d55c2022-02-01 02:50:45 +00003355 if( p->cmOpts.bQuote ){
drhe40f2862022-01-31 14:14:29 +00003356 azQuoted = sqlite3_malloc64( nColumn*sizeof(char*) );
3357 shell_check_oom(azQuoted);
3358 memset(azQuoted, 0, nColumn*sizeof(char*) );
3359 }
drh09a39ed2022-01-30 21:09:03 +00003360 abRowDiv = sqlite3_malloc64( nAlloc/nColumn );
3361 shell_check_oom(abRowDiv);
drh8c748632020-05-29 16:15:58 +00003362 if( nColumn>p->nWidth ){
drh76fc88f2021-10-02 16:39:16 +00003363 p->colWidth = realloc(p->colWidth, (nColumn+1)*2*sizeof(int));
drhe3e25652021-12-16 13:29:28 +00003364 shell_check_oom(p->colWidth);
drh8c748632020-05-29 16:15:58 +00003365 for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0;
3366 p->nWidth = nColumn;
3367 p->actualWidth = &p->colWidth[nColumn];
3368 }
3369 memset(p->actualWidth, 0, nColumn*sizeof(int));
3370 for(i=0; i<nColumn; i++){
3371 w = p->colWidth[i];
3372 if( w<0 ) w = -w;
3373 p->actualWidth[i] = w;
3374 }
drh09a39ed2022-01-30 21:09:03 +00003375 for(i=0; i<nColumn; i++){
drh47741b82022-01-31 22:14:53 +00003376 const unsigned char *zNotUsed;
3377 int wx = p->colWidth[i];
larrybrcc4d55c2022-02-01 02:50:45 +00003378 if( wx==0 ){
3379 wx = p->cmOpts.iWrap;
larrybrcc4d55c2022-02-01 02:50:45 +00003380 }
drh47741b82022-01-31 22:14:53 +00003381 if( wx<0 ) wx = -wx;
3382 uz = (const unsigned char*)sqlite3_column_name(pStmt,i);
larrybrcc4d55c2022-02-01 02:50:45 +00003383 azData[i] = translateForDisplayAndDup(uz, &zNotUsed, wx, bw);
drh09a39ed2022-01-30 21:09:03 +00003384 }
3385 do{
3386 int useNextLine = bNextLine;
3387 bNextLine = 0;
3388 if( (nRow+2)*nColumn >= nAlloc ){
3389 nAlloc *= 2;
3390 azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*));
3391 shell_check_oom(azData);
3392 abRowDiv = sqlite3_realloc64(abRowDiv, nAlloc/nColumn);
3393 shell_check_oom(abRowDiv);
3394 }
3395 abRowDiv[nRow] = 1;
3396 nRow++;
3397 for(i=0; i<nColumn; i++){
drh5dce6f92022-01-31 16:29:06 +00003398 int wx = p->colWidth[i];
larrybrcc4d55c2022-02-01 02:50:45 +00003399 if( wx==0 ){
3400 wx = p->cmOpts.iWrap;
larrybrcc4d55c2022-02-01 02:50:45 +00003401 }
drh47741b82022-01-31 22:14:53 +00003402 if( wx<0 ) wx = -wx;
drh09a39ed2022-01-30 21:09:03 +00003403 if( useNextLine ){
3404 uz = azNextLine[i];
larrybrcc4d55c2022-02-01 02:50:45 +00003405 }else if( p->cmOpts.bQuote ){
drhe40f2862022-01-31 14:14:29 +00003406 sqlite3_free(azQuoted[i]);
3407 azQuoted[i] = quoted_column(pStmt,i);
3408 uz = (const unsigned char*)azQuoted[i];
drh09a39ed2022-01-30 21:09:03 +00003409 }else{
3410 uz = (const unsigned char*)sqlite3_column_text(pStmt,i);
3411 }
larrybrcc4d55c2022-02-01 02:50:45 +00003412 azData[nRow*nColumn + i]
3413 = translateForDisplayAndDup(uz, &azNextLine[i], wx, bw);
drh09a39ed2022-01-30 21:09:03 +00003414 if( azNextLine[i] ){
3415 bNextLine = 1;
3416 abRowDiv[nRow-1] = 0;
3417 bMultiLineRowExists = 1;
3418 }
3419 }
3420 }while( bNextLine || sqlite3_step(pStmt)==SQLITE_ROW );
drh8c748632020-05-29 16:15:58 +00003421 nTotal = nColumn*(nRow+1);
3422 for(i=0; i<nTotal; i++){
3423 z = azData[i];
3424 if( z==0 ) z = p->nullValue;
3425 n = strlenChar(z);
3426 j = i%nColumn;
3427 if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
3428 }
drh99942982020-06-15 20:05:37 +00003429 if( seenInterrupt ) goto columnar_end;
drh01a8ad22021-03-20 23:15:52 +00003430 if( nColumn==0 ) goto columnar_end;
drh0908e382020-06-04 18:05:39 +00003431 switch( p->cMode ){
3432 case MODE_Column: {
3433 colSep = " ";
3434 rowSep = "\n";
3435 if( p->showHeader ){
3436 for(i=0; i<nColumn; i++){
3437 w = p->actualWidth[i];
3438 if( p->colWidth[i]<0 ) w = -w;
3439 utf8_width_print(p->out, w, azData[i]);
3440 fputs(i==nColumn-1?"\n":" ", p->out);
3441 }
3442 for(i=0; i<nColumn; i++){
3443 print_dashes(p->out, p->actualWidth[i]);
3444 fputs(i==nColumn-1?"\n":" ", p->out);
3445 }
3446 }
3447 break;
3448 }
3449 case MODE_Table: {
3450 colSep = " | ";
3451 rowSep = " |\n";
3452 print_row_separator(p, nColumn, "+");
3453 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003454 for(i=0; i<nColumn; i++){
3455 w = p->actualWidth[i];
drh0908e382020-06-04 18:05:39 +00003456 n = strlenChar(azData[i]);
3457 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
3458 fputs(i==nColumn-1?" |\n":" | ", p->out);
drh8c748632020-05-29 16:15:58 +00003459 }
drh0908e382020-06-04 18:05:39 +00003460 print_row_separator(p, nColumn, "+");
3461 break;
3462 }
3463 case MODE_Markdown: {
3464 colSep = " | ";
3465 rowSep = " |\n";
3466 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003467 for(i=0; i<nColumn; i++){
drh0908e382020-06-04 18:05:39 +00003468 w = p->actualWidth[i];
3469 n = strlenChar(azData[i]);
3470 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
3471 fputs(i==nColumn-1?" |\n":" | ", p->out);
drh8c748632020-05-29 16:15:58 +00003472 }
drh0908e382020-06-04 18:05:39 +00003473 print_row_separator(p, nColumn, "|");
3474 break;
drh8c748632020-05-29 16:15:58 +00003475 }
drh0908e382020-06-04 18:05:39 +00003476 case MODE_Box: {
3477 colSep = " " BOX_13 " ";
3478 rowSep = " " BOX_13 "\n";
3479 print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34);
3480 utf8_printf(p->out, BOX_13 " ");
3481 for(i=0; i<nColumn; i++){
3482 w = p->actualWidth[i];
3483 n = strlenChar(azData[i]);
3484 utf8_printf(p->out, "%*s%s%*s%s",
3485 (w-n)/2, "", azData[i], (w-n+1)/2, "",
3486 i==nColumn-1?" "BOX_13"\n":" "BOX_13" ");
3487 }
3488 print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
3489 break;
drh8c748632020-05-29 16:15:58 +00003490 }
drh8c748632020-05-29 16:15:58 +00003491 }
3492 for(i=nColumn, j=0; i<nTotal; i++, j++){
drh0908e382020-06-04 18:05:39 +00003493 if( j==0 && p->cMode!=MODE_Column ){
3494 utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| ");
3495 }
drh8c748632020-05-29 16:15:58 +00003496 z = azData[i];
3497 if( z==0 ) z = p->nullValue;
3498 w = p->actualWidth[j];
3499 if( p->colWidth[j]<0 ) w = -w;
3500 utf8_width_print(p->out, w, z);
3501 if( j==nColumn-1 ){
drh0908e382020-06-04 18:05:39 +00003502 utf8_printf(p->out, "%s", rowSep);
drh09a39ed2022-01-30 21:09:03 +00003503 if( bMultiLineRowExists && abRowDiv[i/nColumn-1] && i+1<nTotal ){
3504 if( p->cMode==MODE_Table ){
3505 print_row_separator(p, nColumn, "+");
3506 }else if( p->cMode==MODE_Box ){
3507 print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
drh5aabdae2022-02-01 00:00:08 +00003508 }else if( p->cMode==MODE_Column ){
3509 raw_printf(p->out, "\n");
drh09a39ed2022-01-30 21:09:03 +00003510 }
3511 }
drh8c748632020-05-29 16:15:58 +00003512 j = -1;
drhdd853c32020-06-16 17:34:40 +00003513 if( seenInterrupt ) goto columnar_end;
drh8c748632020-05-29 16:15:58 +00003514 }else{
drh0908e382020-06-04 18:05:39 +00003515 utf8_printf(p->out, "%s", colSep);
drh8c748632020-05-29 16:15:58 +00003516 }
3517 }
3518 if( p->cMode==MODE_Table ){
3519 print_row_separator(p, nColumn, "+");
drh0908e382020-06-04 18:05:39 +00003520 }else if( p->cMode==MODE_Box ){
3521 print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14);
drh8c748632020-05-29 16:15:58 +00003522 }
drh99942982020-06-15 20:05:37 +00003523columnar_end:
drhdd853c32020-06-16 17:34:40 +00003524 if( seenInterrupt ){
3525 utf8_printf(p->out, "Interrupt\n");
3526 }
drhf82ce382020-08-06 16:45:22 +00003527 nData = (nRow+1)*nColumn;
3528 for(i=0; i<nData; i++) free(azData[i]);
3529 sqlite3_free(azData);
drh5dce6f92022-01-31 16:29:06 +00003530 sqlite3_free((void*)azNextLine);
drh09a39ed2022-01-30 21:09:03 +00003531 sqlite3_free(abRowDiv);
drhe40f2862022-01-31 14:14:29 +00003532 if( azQuoted ){
3533 for(i=0; i<nColumn; i++) sqlite3_free(azQuoted[i]);
3534 sqlite3_free(azQuoted);
3535 }
drh30c54a02020-05-28 23:49:50 +00003536}
drh30c54a02020-05-28 23:49:50 +00003537
drh2ce15c32017-07-11 13:34:40 +00003538/*
3539** Run a prepared statement
3540*/
3541static void exec_prepared_stmt(
3542 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003543 sqlite3_stmt *pStmt /* Statment to run */
drh2ce15c32017-07-11 13:34:40 +00003544){
3545 int rc;
drh5d88be82021-12-09 16:17:43 +00003546 sqlite3_uint64 nRow = 0;
drh2ce15c32017-07-11 13:34:40 +00003547
drh8c748632020-05-29 16:15:58 +00003548 if( pArg->cMode==MODE_Column
3549 || pArg->cMode==MODE_Table
drh0908e382020-06-04 18:05:39 +00003550 || pArg->cMode==MODE_Box
drh8c748632020-05-29 16:15:58 +00003551 || pArg->cMode==MODE_Markdown
3552 ){
3553 exec_prepared_stmt_columnar(pArg, pStmt);
3554 return;
3555 }
3556
drh2ce15c32017-07-11 13:34:40 +00003557 /* perform the first step. this will tell us if we
3558 ** have a result set or not and how wide it is.
3559 */
3560 rc = sqlite3_step(pStmt);
3561 /* if we have a result set... */
3562 if( SQLITE_ROW == rc ){
drha10b9992018-03-09 15:24:33 +00003563 /* allocate space for col name ptr, value ptr, and type */
3564 int nCol = sqlite3_column_count(pStmt);
3565 void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
3566 if( !pData ){
drhe85e1da2021-10-01 21:01:07 +00003567 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00003568 }else{
drha10b9992018-03-09 15:24:33 +00003569 char **azCols = (char **)pData; /* Names of result columns */
3570 char **azVals = &azCols[nCol]; /* Results */
3571 int *aiTypes = (int *)&azVals[nCol]; /* Result types */
3572 int i, x;
3573 assert(sizeof(int) <= sizeof(char *));
3574 /* save off ptrs to column names */
3575 for(i=0; i<nCol; i++){
3576 azCols[i] = (char *)sqlite3_column_name(pStmt, i);
3577 }
drh2ce15c32017-07-11 13:34:40 +00003578 do{
drh5d88be82021-12-09 16:17:43 +00003579 nRow++;
drha10b9992018-03-09 15:24:33 +00003580 /* extract the data and data types */
3581 for(i=0; i<nCol; i++){
3582 aiTypes[i] = x = sqlite3_column_type(pStmt, i);
drh5d1bf4f2022-01-02 20:54:33 +00003583 if( x==SQLITE_BLOB
3584 && pArg
3585 && (pArg->cMode==MODE_Insert || pArg->cMode==MODE_Quote)
3586 ){
drha10b9992018-03-09 15:24:33 +00003587 azVals[i] = "";
3588 }else{
3589 azVals[i] = (char*)sqlite3_column_text(pStmt, i);
3590 }
3591 if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
3592 rc = SQLITE_NOMEM;
3593 break; /* from for */
3594 }
3595 } /* end for */
3596
3597 /* if data and types extracted successfully... */
3598 if( SQLITE_ROW == rc ){
3599 /* call the supplied callback with the result row data */
3600 if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){
3601 rc = SQLITE_ABORT;
3602 }else{
3603 rc = sqlite3_step(pStmt);
3604 }
3605 }
3606 } while( SQLITE_ROW == rc );
3607 sqlite3_free(pData);
drh0908e382020-06-04 18:05:39 +00003608 if( pArg->cMode==MODE_Json ){
drh30c54a02020-05-28 23:49:50 +00003609 fputs("]\n", pArg->out);
drh5d88be82021-12-09 16:17:43 +00003610 }else if( pArg->cMode==MODE_Count ){
mistachkinc158c072021-12-31 19:08:20 +00003611 char zBuf[200];
3612 sqlite3_snprintf(sizeof(zBuf), zBuf, "%llu row%s\n",
3613 nRow, nRow!=1 ? "s" : "");
3614 printf("%s", zBuf);
drh30c54a02020-05-28 23:49:50 +00003615 }
drh2ce15c32017-07-11 13:34:40 +00003616 }
3617 }
3618}
3619
dan6b046be2018-01-09 15:25:55 +00003620#ifndef SQLITE_OMIT_VIRTUALTABLE
drh2ce15c32017-07-11 13:34:40 +00003621/*
dan43efc182017-12-19 17:42:13 +00003622** This function is called to process SQL if the previous shell command
3623** was ".expert". It passes the SQL in the second argument directly to
3624** the sqlite3expert object.
3625**
3626** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3627** code. In this case, (*pzErr) may be set to point to a buffer containing
3628** an English language error message. It is the responsibility of the
3629** caller to eventually free this buffer using sqlite3_free().
3630*/
3631static int expertHandleSQL(
3632 ShellState *pState,
3633 const char *zSql,
3634 char **pzErr
3635){
3636 assert( pState->expert.pExpert );
3637 assert( pzErr==0 || *pzErr==0 );
3638 return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr);
3639}
3640
3641/*
3642** This function is called either to silently clean up the object
3643** created by the ".expert" command (if bCancel==1), or to generate a
3644** report from it and then clean it up (if bCancel==0).
3645**
3646** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3647** code. In this case, (*pzErr) may be set to point to a buffer containing
3648** an English language error message. It is the responsibility of the
3649** caller to eventually free this buffer using sqlite3_free().
3650*/
3651static int expertFinish(
3652 ShellState *pState,
3653 int bCancel,
3654 char **pzErr
3655){
3656 int rc = SQLITE_OK;
3657 sqlite3expert *p = pState->expert.pExpert;
3658 assert( p );
3659 assert( bCancel || pzErr==0 || *pzErr==0 );
3660 if( bCancel==0 ){
3661 FILE *out = pState->out;
3662 int bVerbose = pState->expert.bVerbose;
3663
3664 rc = sqlite3_expert_analyze(p, pzErr);
3665 if( rc==SQLITE_OK ){
3666 int nQuery = sqlite3_expert_count(p);
3667 int i;
3668
3669 if( bVerbose ){
3670 const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
3671 raw_printf(out, "-- Candidates -----------------------------\n");
3672 raw_printf(out, "%s\n", zCand);
3673 }
3674 for(i=0; i<nQuery; i++){
3675 const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
3676 const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
3677 const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
3678 if( zIdx==0 ) zIdx = "(no new indexes)\n";
3679 if( bVerbose ){
3680 raw_printf(out, "-- Query %d --------------------------------\n",i+1);
3681 raw_printf(out, "%s\n\n", zSql);
3682 }
3683 raw_printf(out, "%s\n", zIdx);
3684 raw_printf(out, "%s\n", zEQP);
3685 }
3686 }
3687 }
3688 sqlite3_expert_destroy(p);
3689 pState->expert.pExpert = 0;
3690 return rc;
3691}
3692
dan6b046be2018-01-09 15:25:55 +00003693/*
3694** Implementation of ".expert" dot command.
3695*/
3696static int expertDotCommand(
3697 ShellState *pState, /* Current shell tool state */
3698 char **azArg, /* Array of arguments passed to dot command */
3699 int nArg /* Number of entries in azArg[] */
3700){
3701 int rc = SQLITE_OK;
3702 char *zErr = 0;
3703 int i;
3704 int iSample = 0;
3705
3706 assert( pState->expert.pExpert==0 );
3707 memset(&pState->expert, 0, sizeof(ExpertInfo));
3708
3709 for(i=1; rc==SQLITE_OK && i<nArg; i++){
3710 char *z = azArg[i];
3711 int n;
3712 if( z[0]=='-' && z[1]=='-' ) z++;
3713 n = strlen30(z);
3714 if( n>=2 && 0==strncmp(z, "-verbose", n) ){
3715 pState->expert.bVerbose = 1;
3716 }
3717 else if( n>=2 && 0==strncmp(z, "-sample", n) ){
3718 if( i==(nArg-1) ){
3719 raw_printf(stderr, "option requires an argument: %s\n", z);
3720 rc = SQLITE_ERROR;
3721 }else{
3722 iSample = (int)integerValue(azArg[++i]);
3723 if( iSample<0 || iSample>100 ){
3724 raw_printf(stderr, "value out of range: %s\n", azArg[i]);
3725 rc = SQLITE_ERROR;
3726 }
3727 }
3728 }
3729 else{
3730 raw_printf(stderr, "unknown option: %s\n", z);
3731 rc = SQLITE_ERROR;
3732 }
3733 }
3734
3735 if( rc==SQLITE_OK ){
3736 pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
3737 if( pState->expert.pExpert==0 ){
drhe0adf602021-12-16 14:26:16 +00003738 raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr ? zErr : "out of memory");
dan6b046be2018-01-09 15:25:55 +00003739 rc = SQLITE_ERROR;
3740 }else{
3741 sqlite3_expert_config(
3742 pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
3743 );
3744 }
3745 }
drhe0adf602021-12-16 14:26:16 +00003746 sqlite3_free(zErr);
dan6b046be2018-01-09 15:25:55 +00003747
3748 return rc;
3749}
3750#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
dan43efc182017-12-19 17:42:13 +00003751
3752/*
drh2ce15c32017-07-11 13:34:40 +00003753** Execute a statement or set of statements. Print
3754** any result rows/columns depending on the current mode
3755** set via the supplied callback.
3756**
3757** This is very similar to SQLite's built-in sqlite3_exec()
3758** function except it takes a slightly different callback
3759** and callback data argument.
3760*/
3761static int shell_exec(
drh2ce15c32017-07-11 13:34:40 +00003762 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003763 const char *zSql, /* SQL to be evaluated */
drh2ce15c32017-07-11 13:34:40 +00003764 char **pzErrMsg /* Error msg written here */
3765){
3766 sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
3767 int rc = SQLITE_OK; /* Return Code */
3768 int rc2;
3769 const char *zLeftover; /* Tail of unprocessed SQL */
drha10b9992018-03-09 15:24:33 +00003770 sqlite3 *db = pArg->db;
drh2ce15c32017-07-11 13:34:40 +00003771
3772 if( pzErrMsg ){
3773 *pzErrMsg = NULL;
3774 }
3775
dan6b046be2018-01-09 15:25:55 +00003776#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00003777 if( pArg->expert.pExpert ){
3778 rc = expertHandleSQL(pArg, zSql, pzErrMsg);
3779 return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
3780 }
dan6b046be2018-01-09 15:25:55 +00003781#endif
dan43efc182017-12-19 17:42:13 +00003782
drh2ce15c32017-07-11 13:34:40 +00003783 while( zSql[0] && (SQLITE_OK == rc) ){
3784 static const char *zStmtSql;
3785 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
3786 if( SQLITE_OK != rc ){
3787 if( pzErrMsg ){
drh633c7982022-02-08 12:13:16 +00003788 *pzErrMsg = save_err_msg(db, "in prepare", rc, zSql);
drh2ce15c32017-07-11 13:34:40 +00003789 }
3790 }else{
3791 if( !pStmt ){
3792 /* this happens for a comment or white-space */
3793 zSql = zLeftover;
3794 while( IsSpace(zSql[0]) ) zSql++;
3795 continue;
3796 }
3797 zStmtSql = sqlite3_sql(pStmt);
3798 if( zStmtSql==0 ) zStmtSql = "";
3799 while( IsSpace(zStmtSql[0]) ) zStmtSql++;
3800
3801 /* save off the prepared statment handle and reset row count */
3802 if( pArg ){
3803 pArg->pStmt = pStmt;
3804 pArg->cnt = 0;
3805 }
3806
3807 /* echo the sql statement if echo on */
3808 if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
3809 utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
3810 }
3811
3812 /* Show the EXPLAIN QUERY PLAN if .eqp is on */
drh39c5c4a2019-03-06 14:53:27 +00003813 if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
drh2ce15c32017-07-11 13:34:40 +00003814 sqlite3_stmt *pExplain;
3815 char *zEQP;
drhada70452017-12-21 21:02:27 +00003816 int triggerEQP = 0;
drh2ce15c32017-07-11 13:34:40 +00003817 disable_debug_trace_modes();
drhada70452017-12-21 21:02:27 +00003818 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
3819 if( pArg->autoEQP>=AUTOEQP_trigger ){
3820 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
3821 }
drh2ce15c32017-07-11 13:34:40 +00003822 zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
drhe3e25652021-12-16 13:29:28 +00003823 shell_check_oom(zEQP);
drh2ce15c32017-07-11 13:34:40 +00003824 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3825 if( rc==SQLITE_OK ){
3826 while( sqlite3_step(pExplain)==SQLITE_ROW ){
drh4b5345c2018-04-24 13:07:40 +00003827 const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
drhe2ca99c2018-05-02 00:33:43 +00003828 int iEqpId = sqlite3_column_int(pExplain, 0);
3829 int iParentId = sqlite3_column_int(pExplain, 1);
drh7e088a62020-05-02 00:01:39 +00003830 if( zEQPLine==0 ) zEQPLine = "";
drh4b5345c2018-04-24 13:07:40 +00003831 if( zEQPLine[0]=='-' ) eqp_render(pArg);
drhe2ca99c2018-05-02 00:33:43 +00003832 eqp_append(pArg, iEqpId, iParentId, zEQPLine);
drh2ce15c32017-07-11 13:34:40 +00003833 }
drh4b5345c2018-04-24 13:07:40 +00003834 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003835 }
3836 sqlite3_finalize(pExplain);
3837 sqlite3_free(zEQP);
drhada70452017-12-21 21:02:27 +00003838 if( pArg->autoEQP>=AUTOEQP_full ){
drh2ce15c32017-07-11 13:34:40 +00003839 /* Also do an EXPLAIN for ".eqp full" mode */
3840 zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
drhe3e25652021-12-16 13:29:28 +00003841 shell_check_oom(zEQP);
drh2ce15c32017-07-11 13:34:40 +00003842 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3843 if( rc==SQLITE_OK ){
3844 pArg->cMode = MODE_Explain;
3845 explain_data_prepare(pArg, pExplain);
drha10b9992018-03-09 15:24:33 +00003846 exec_prepared_stmt(pArg, pExplain);
drh2ce15c32017-07-11 13:34:40 +00003847 explain_data_delete(pArg);
3848 }
3849 sqlite3_finalize(pExplain);
3850 sqlite3_free(zEQP);
3851 }
drh51efe092018-03-20 12:04:38 +00003852 if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
3853 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
3854 /* Reprepare pStmt before reactiving trace modes */
3855 sqlite3_finalize(pStmt);
3856 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
drh3c49eaf2018-06-07 15:23:43 +00003857 if( pArg ) pArg->pStmt = pStmt;
drh51efe092018-03-20 12:04:38 +00003858 }
drh2ce15c32017-07-11 13:34:40 +00003859 restore_debug_trace_modes();
3860 }
3861
3862 if( pArg ){
3863 pArg->cMode = pArg->mode;
drh4b5345c2018-04-24 13:07:40 +00003864 if( pArg->autoExplain ){
drh39c5c4a2019-03-06 14:53:27 +00003865 if( sqlite3_stmt_isexplain(pStmt)==1 ){
drh4b5345c2018-04-24 13:07:40 +00003866 pArg->cMode = MODE_Explain;
3867 }
drh39c5c4a2019-03-06 14:53:27 +00003868 if( sqlite3_stmt_isexplain(pStmt)==2 ){
drh4b5345c2018-04-24 13:07:40 +00003869 pArg->cMode = MODE_EQP;
3870 }
drh2ce15c32017-07-11 13:34:40 +00003871 }
3872
3873 /* If the shell is currently in ".explain" mode, gather the extra
3874 ** data required to add indents to the output.*/
3875 if( pArg->cMode==MODE_Explain ){
3876 explain_data_prepare(pArg, pStmt);
3877 }
3878 }
3879
drh8b738d02019-02-25 18:43:54 +00003880 bind_prepared_stmt(pArg, pStmt);
drha10b9992018-03-09 15:24:33 +00003881 exec_prepared_stmt(pArg, pStmt);
drh2ce15c32017-07-11 13:34:40 +00003882 explain_data_delete(pArg);
drh4b5345c2018-04-24 13:07:40 +00003883 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003884
3885 /* print usage stats if stats on */
3886 if( pArg && pArg->statsOn ){
3887 display_stats(db, pArg, 0);
3888 }
3889
3890 /* print loop-counters if required */
3891 if( pArg && pArg->scanstatsOn ){
3892 display_scanstats(db, pArg);
3893 }
3894
3895 /* Finalize the statement just executed. If this fails, save a
3896 ** copy of the error message. Otherwise, set zSql to point to the
3897 ** next statement to execute. */
3898 rc2 = sqlite3_finalize(pStmt);
3899 if( rc!=SQLITE_NOMEM ) rc = rc2;
3900 if( rc==SQLITE_OK ){
3901 zSql = zLeftover;
3902 while( IsSpace(zSql[0]) ) zSql++;
3903 }else if( pzErrMsg ){
drh633c7982022-02-08 12:13:16 +00003904 *pzErrMsg = save_err_msg(db, "stepping", rc, 0);
drh2ce15c32017-07-11 13:34:40 +00003905 }
3906
3907 /* clear saved stmt handle */
3908 if( pArg ){
3909 pArg->pStmt = NULL;
3910 }
3911 }
3912 } /* end while */
3913
3914 return rc;
3915}
3916
3917/*
3918** Release memory previously allocated by tableColumnList().
3919*/
3920static void freeColumnList(char **azCol){
3921 int i;
3922 for(i=1; azCol[i]; i++){
3923 sqlite3_free(azCol[i]);
3924 }
3925 /* azCol[0] is a static string */
3926 sqlite3_free(azCol);
3927}
3928
3929/*
3930** Return a list of pointers to strings which are the names of all
3931** columns in table zTab. The memory to hold the names is dynamically
3932** allocated and must be released by the caller using a subsequent call
3933** to freeColumnList().
3934**
3935** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
3936** value that needs to be preserved, then azCol[0] is filled in with the
3937** name of the rowid column.
3938**
3939** The first regular column in the table is azCol[1]. The list is terminated
3940** by an entry with azCol[i]==0.
3941*/
3942static char **tableColumnList(ShellState *p, const char *zTab){
3943 char **azCol = 0;
3944 sqlite3_stmt *pStmt;
3945 char *zSql;
3946 int nCol = 0;
3947 int nAlloc = 0;
3948 int nPK = 0; /* Number of PRIMARY KEY columns seen */
3949 int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
3950 int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
3951 int rc;
3952
3953 zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
drhe3e25652021-12-16 13:29:28 +00003954 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +00003955 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3956 sqlite3_free(zSql);
3957 if( rc ) return 0;
3958 while( sqlite3_step(pStmt)==SQLITE_ROW ){
3959 if( nCol>=nAlloc-2 ){
3960 nAlloc = nAlloc*2 + nCol + 10;
3961 azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
drhe3e25652021-12-16 13:29:28 +00003962 shell_check_oom(azCol);
drh2ce15c32017-07-11 13:34:40 +00003963 }
3964 azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
drhe3e25652021-12-16 13:29:28 +00003965 shell_check_oom(azCol[nCol]);
drh2ce15c32017-07-11 13:34:40 +00003966 if( sqlite3_column_int(pStmt, 5) ){
3967 nPK++;
3968 if( nPK==1
3969 && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
3970 "INTEGER")==0
3971 ){
3972 isIPK = 1;
3973 }else{
3974 isIPK = 0;
3975 }
3976 }
3977 }
3978 sqlite3_finalize(pStmt);
drh4c6cddc2017-10-12 10:28:30 +00003979 if( azCol==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00003980 azCol[0] = 0;
3981 azCol[nCol+1] = 0;
3982
3983 /* The decision of whether or not a rowid really needs to be preserved
3984 ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
3985 ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
3986 ** rowids on tables where the rowid is inaccessible because there are other
3987 ** columns in the table named "rowid", "_rowid_", and "oid".
3988 */
3989 if( preserveRowid && isIPK ){
3990 /* If a single PRIMARY KEY column with type INTEGER was seen, then it
3991 ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID
3992 ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
3993 ** ROWID aliases. To distinguish these cases, check to see if
3994 ** there is a "pk" entry in "PRAGMA index_list". There will be
3995 ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
3996 */
3997 zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
3998 " WHERE origin='pk'", zTab);
drhe3e25652021-12-16 13:29:28 +00003999 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +00004000 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
4001 sqlite3_free(zSql);
4002 if( rc ){
4003 freeColumnList(azCol);
4004 return 0;
4005 }
4006 rc = sqlite3_step(pStmt);
4007 sqlite3_finalize(pStmt);
4008 preserveRowid = rc==SQLITE_ROW;
4009 }
4010 if( preserveRowid ){
4011 /* Only preserve the rowid if we can find a name to use for the
4012 ** rowid */
4013 static char *azRowid[] = { "rowid", "_rowid_", "oid" };
4014 int i, j;
4015 for(j=0; j<3; j++){
4016 for(i=1; i<=nCol; i++){
4017 if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
4018 }
4019 if( i>nCol ){
4020 /* At this point, we know that azRowid[j] is not the name of any
4021 ** ordinary column in the table. Verify that azRowid[j] is a valid
4022 ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
4023 ** tables will fail this last check */
4024 rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
4025 if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
4026 break;
4027 }
4028 }
4029 }
4030 return azCol;
4031}
4032
4033/*
4034** Toggle the reverse_unordered_selects setting.
4035*/
4036static void toggleSelectOrder(sqlite3 *db){
4037 sqlite3_stmt *pStmt = 0;
4038 int iSetting = 0;
4039 char zStmt[100];
4040 sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0);
4041 if( sqlite3_step(pStmt)==SQLITE_ROW ){
4042 iSetting = sqlite3_column_int(pStmt, 0);
4043 }
4044 sqlite3_finalize(pStmt);
4045 sqlite3_snprintf(sizeof(zStmt), zStmt,
4046 "PRAGMA reverse_unordered_selects(%d)", !iSetting);
4047 sqlite3_exec(db, zStmt, 0, 0, 0);
4048}
4049
4050/*
4051** This is a different callback routine used for dumping the database.
4052** Each row received by this callback consists of a table name,
4053** the table type ("index" or "table") and SQL to create the table.
4054** This routine should print text sufficient to recreate the table.
4055*/
4056static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
4057 int rc;
4058 const char *zTable;
4059 const char *zType;
4060 const char *zSql;
4061 ShellState *p = (ShellState *)pArg;
mistachkina00a0162020-10-18 18:35:34 +00004062 int dataOnly;
4063 int noSys;
drh2ce15c32017-07-11 13:34:40 +00004064
4065 UNUSED_PARAMETER(azNotUsed);
drhb3c45232017-08-28 14:33:27 +00004066 if( nArg!=3 || azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00004067 zTable = azArg[0];
4068 zType = azArg[1];
4069 zSql = azArg[2];
mistachkina00a0162020-10-18 18:35:34 +00004070 dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
4071 noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
drh2ce15c32017-07-11 13:34:40 +00004072
drhc1962192020-10-12 16:54:28 +00004073 if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
4074 if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
4075 }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
4076 if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00004077 }else if( strncmp(zTable, "sqlite_", 7)==0 ){
4078 return 0;
drhc1962192020-10-12 16:54:28 +00004079 }else if( dataOnly ){
4080 /* no-op */
drh2ce15c32017-07-11 13:34:40 +00004081 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
4082 char *zIns;
4083 if( !p->writableSchema ){
4084 raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
4085 p->writableSchema = 1;
4086 }
4087 zIns = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00004088 "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
drh2ce15c32017-07-11 13:34:40 +00004089 "VALUES('table','%q','%q',0,'%q');",
4090 zTable, zTable, zSql);
drhe3e25652021-12-16 13:29:28 +00004091 shell_check_oom(zIns);
drh2ce15c32017-07-11 13:34:40 +00004092 utf8_printf(p->out, "%s\n", zIns);
4093 sqlite3_free(zIns);
4094 return 0;
4095 }else{
4096 printSchemaLine(p->out, zSql, ";\n");
4097 }
4098
4099 if( strcmp(zType, "table")==0 ){
4100 ShellText sSelect;
4101 ShellText sTable;
4102 char **azCol;
4103 int i;
4104 char *savedDestTable;
4105 int savedMode;
4106
4107 azCol = tableColumnList(p, zTable);
4108 if( azCol==0 ){
4109 p->nErr++;
4110 return 0;
4111 }
4112
4113 /* Always quote the table name, even if it appears to be pure ascii,
4114 ** in case it is a keyword. Ex: INSERT INTO "table" ... */
4115 initText(&sTable);
4116 appendText(&sTable, zTable, quoteChar(zTable));
4117 /* If preserving the rowid, add a column list after the table name.
4118 ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
4119 ** instead of the usual "INSERT INTO tab VALUES(...)".
4120 */
4121 if( azCol[0] ){
4122 appendText(&sTable, "(", 0);
4123 appendText(&sTable, azCol[0], 0);
4124 for(i=1; azCol[i]; i++){
4125 appendText(&sTable, ",", 0);
4126 appendText(&sTable, azCol[i], quoteChar(azCol[i]));
4127 }
4128 appendText(&sTable, ")", 0);
4129 }
4130
4131 /* Build an appropriate SELECT statement */
4132 initText(&sSelect);
4133 appendText(&sSelect, "SELECT ", 0);
4134 if( azCol[0] ){
4135 appendText(&sSelect, azCol[0], 0);
4136 appendText(&sSelect, ",", 0);
4137 }
4138 for(i=1; azCol[i]; i++){
4139 appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
4140 if( azCol[i+1] ){
4141 appendText(&sSelect, ",", 0);
4142 }
4143 }
4144 freeColumnList(azCol);
4145 appendText(&sSelect, " FROM ", 0);
4146 appendText(&sSelect, zTable, quoteChar(zTable));
4147
4148 savedDestTable = p->zDestTable;
4149 savedMode = p->mode;
4150 p->zDestTable = sTable.z;
4151 p->mode = p->cMode = MODE_Insert;
drha10b9992018-03-09 15:24:33 +00004152 rc = shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00004153 if( (rc&0xff)==SQLITE_CORRUPT ){
4154 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
4155 toggleSelectOrder(p->db);
drha10b9992018-03-09 15:24:33 +00004156 shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00004157 toggleSelectOrder(p->db);
4158 }
4159 p->zDestTable = savedDestTable;
4160 p->mode = savedMode;
4161 freeText(&sTable);
4162 freeText(&sSelect);
4163 if( rc ) p->nErr++;
4164 }
4165 return 0;
4166}
4167
4168/*
4169** Run zQuery. Use dump_callback() as the callback routine so that
4170** the contents of the query are output as SQL statements.
4171**
4172** If we get a SQLITE_CORRUPT error, rerun the query after appending
4173** "ORDER BY rowid DESC" to the end.
4174*/
4175static int run_schema_dump_query(
4176 ShellState *p,
4177 const char *zQuery
4178){
4179 int rc;
4180 char *zErr = 0;
4181 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
4182 if( rc==SQLITE_CORRUPT ){
4183 char *zQ2;
4184 int len = strlen30(zQuery);
4185 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
4186 if( zErr ){
4187 utf8_printf(p->out, "/****** %s ******/\n", zErr);
4188 sqlite3_free(zErr);
4189 zErr = 0;
4190 }
4191 zQ2 = malloc( len+100 );
4192 if( zQ2==0 ) return rc;
4193 sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
4194 rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
4195 if( rc ){
4196 utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
4197 }else{
4198 rc = SQLITE_CORRUPT;
4199 }
4200 sqlite3_free(zErr);
4201 free(zQ2);
4202 }
4203 return rc;
4204}
4205
4206/*
drh98aa2ab2018-09-26 16:53:51 +00004207** Text of help messages.
4208**
4209** The help text for each individual command begins with a line that starts
4210** with ".". Subsequent lines are supplimental information.
4211**
4212** There must be two or more spaces between the end of the command and the
4213** start of the description of what that command does.
drh2ce15c32017-07-11 13:34:40 +00004214*/
drh98aa2ab2018-09-26 16:53:51 +00004215static const char *(azHelp[]) = {
drhe37c0e12018-01-06 19:19:50 +00004216#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drh98aa2ab2018-09-26 16:53:51 +00004217 ".archive ... Manage SQL archives",
4218 " Each command must have exactly one of the following options:",
4219 " -c, --create Create a new archive",
drhe2754c12019-08-26 12:50:01 +00004220 " -u, --update Add or update files with changed mtime",
4221 " -i, --insert Like -u but always add even if unchanged",
larrybr47061b92021-11-01 17:22:52 +00004222 " -r, --remove Remove files from archive",
drh98aa2ab2018-09-26 16:53:51 +00004223 " -t, --list List contents of archive",
4224 " -x, --extract Extract files from archive",
4225 " Optional arguments:",
4226 " -v, --verbose Print each filename as it is processed",
drhe2754c12019-08-26 12:50:01 +00004227 " -f FILE, --file FILE Use archive FILE (default is current db)",
4228 " -a FILE, --append FILE Open FILE using the apndvfs VFS",
4229 " -C DIR, --directory DIR Read/extract files from directory DIR",
larrybr8f09f4b2021-11-02 00:18:11 +00004230 " -g, --glob Use glob matching for names in archive",
drh98aa2ab2018-09-26 16:53:51 +00004231 " -n, --dryrun Show the SQL that would have occurred",
4232 " Examples:",
drhe2754c12019-08-26 12:50:01 +00004233 " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
4234 " .ar -tf ARCHIVE # List members of ARCHIVE",
4235 " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE",
drh98aa2ab2018-09-26 16:53:51 +00004236 " See also:",
larrybrbd0d62c2021-06-13 08:23:28 +00004237 " http://sqlite.org/cli.html#sqlite_archive_support",
drhe37c0e12018-01-06 19:19:50 +00004238#endif
drh2ce15c32017-07-11 13:34:40 +00004239#ifndef SQLITE_OMIT_AUTHORIZATION
drh98aa2ab2018-09-26 16:53:51 +00004240 ".auth ON|OFF Show authorizer callbacks",
drh2ce15c32017-07-11 13:34:40 +00004241#endif
drh98aa2ab2018-09-26 16:53:51 +00004242 ".backup ?DB? FILE Backup DB (default \"main\") to FILE",
4243 " --append Use the appendvfs",
drhe2754c12019-08-26 12:50:01 +00004244 " --async Write to FILE without journal and fsync()",
drh98aa2ab2018-09-26 16:53:51 +00004245 ".bail on|off Stop after hitting an error. Default OFF",
4246 ".binary on|off Turn binary output on or off. Default OFF",
4247 ".cd DIRECTORY Change the working directory to DIRECTORY",
4248 ".changes on|off Show number of rows changed by SQL",
4249 ".check GLOB Fail if output since .testcase does not match",
4250 ".clone NEWDB Clone data into NEWDB from the existing database",
drh37407122021-07-23 18:43:58 +00004251 ".connection [close] [#] Open or close an auxiliary database connection",
drh98aa2ab2018-09-26 16:53:51 +00004252 ".databases List names and files of attached databases",
4253 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
4254 ".dbinfo ?DB? Show status information about the database",
larrybr7bdbe592021-03-15 12:56:00 +00004255 ".dump ?OBJECTS? Render database content as SQL",
drheb7f2a02018-09-26 18:02:32 +00004256 " Options:",
drhc1962192020-10-12 16:54:28 +00004257 " --data-only Output only INSERT statements",
drheb7f2a02018-09-26 18:02:32 +00004258 " --newlines Allow unescaped newline characters in output",
drhc1962192020-10-12 16:54:28 +00004259 " --nosys Omit system tables (ex: \"sqlite_stat1\")",
4260 " --preserve-rowids Include ROWID values in the output",
larrybr7bdbe592021-03-15 12:56:00 +00004261 " OBJECTS is a LIKE pattern for tables, indexes, triggers or views to dump",
drh8e9297f2020-03-25 12:50:13 +00004262 " Additional LIKE patterns can be given in subsequent arguments",
drh98aa2ab2018-09-26 16:53:51 +00004263 ".echo on|off Turn command echo on or off",
drhb4e50392019-01-26 15:40:04 +00004264 ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
4265 " Other Modes:",
4266#ifdef SQLITE_DEBUG
4267 " test Show raw EXPLAIN QUERY PLAN output",
drhe2754c12019-08-26 12:50:01 +00004268 " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"",
drhb4e50392019-01-26 15:40:04 +00004269#endif
4270 " trigger Like \"full\" but also show trigger bytecode",
drhe2754c12019-08-26 12:50:01 +00004271 ".excel Display the output of next command in spreadsheet",
drh7a431002020-04-18 14:12:00 +00004272 " --bom Put a UTF8 byte-order mark on intermediate file",
drheb7f2a02018-09-26 18:02:32 +00004273 ".exit ?CODE? Exit this program with return-code CODE",
drhe2754c12019-08-26 12:50:01 +00004274 ".expert EXPERIMENTAL. Suggest indexes for queries",
drh978256f2019-11-02 00:00:14 +00004275 ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto",
drhd985f722019-06-05 14:29:53 +00004276 ".filectrl CMD ... Run various sqlite3_file_control() operations",
drh541ef2c2020-04-20 16:21:30 +00004277 " --schema SCHEMA Use SCHEMA instead of \"main\"",
4278 " --help Show CMD details",
drh98aa2ab2018-09-26 16:53:51 +00004279 ".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
4280 ".headers on|off Turn display of headers on or off",
4281 ".help ?-all? ?PATTERN? Show help text for PATTERN",
4282 ".import FILE TABLE Import data from FILE into TABLE",
drhccb37812020-03-09 15:39:39 +00004283 " Options:",
4284 " --ascii Use \\037 and \\036 as column and row separators",
4285 " --csv Use , and \\n as column and row separators",
4286 " --skip N Skip the first N rows of input",
larrybr738d7b92022-01-13 21:22:54 +00004287 " --schema S Target table to be S.TABLE",
drhccb37812020-03-09 15:39:39 +00004288 " -v \"Verbose\" - increase auxiliary output",
4289 " Notes:",
4290 " * If TABLE does not exist, it is created. The first row of input",
4291 " determines the column names.",
4292 " * If neither --csv or --ascii are used, the input mode is derived",
4293 " from the \".mode\" output mode",
4294 " * If FILE begins with \"|\" then it is a command that generates the",
4295 " input text.",
drh2ce15c32017-07-11 13:34:40 +00004296#ifndef SQLITE_OMIT_TEST_CONTROL
drh98aa2ab2018-09-26 16:53:51 +00004297 ".imposter INDEX TABLE Create imposter table TABLE on index INDEX",
drh2ce15c32017-07-11 13:34:40 +00004298#endif
drh98aa2ab2018-09-26 16:53:51 +00004299 ".indexes ?TABLE? Show names of indexes",
4300 " If TABLE is specified, only show indexes for",
4301 " tables matching TABLE using the LIKE operator.",
drh2ce15c32017-07-11 13:34:40 +00004302#ifdef SQLITE_ENABLE_IOTRACE
drh98aa2ab2018-09-26 16:53:51 +00004303 ".iotrace FILE Enable I/O diagnostic logging to FILE",
drh2ce15c32017-07-11 13:34:40 +00004304#endif
drh98aa2ab2018-09-26 16:53:51 +00004305 ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
4306 ".lint OPTIONS Report potential schema issues.",
4307 " Options:",
4308 " fkey-indexes Find missing foreign key indexes",
drh2ce15c32017-07-11 13:34:40 +00004309#ifndef SQLITE_OMIT_LOAD_EXTENSION
drh98aa2ab2018-09-26 16:53:51 +00004310 ".load FILE ?ENTRY? Load an extension library",
drh2ce15c32017-07-11 13:34:40 +00004311#endif
drh98aa2ab2018-09-26 16:53:51 +00004312 ".log FILE|off Turn logging on or off. FILE can be stderr/stdout",
drh47741b82022-01-31 22:14:53 +00004313 ".mode MODE ?OPTIONS? Set output mode",
drh98aa2ab2018-09-26 16:53:51 +00004314 " MODE is one of:",
drhe40f2862022-01-31 14:14:29 +00004315 " ascii Columns/rows delimited by 0x1F and 0x1E",
4316 " box Tables using unicode box-drawing characters",
4317 " csv Comma-separated values",
4318 " column Output in columns. (See .width)",
4319 " html HTML <table> code",
4320 " insert SQL insert statements for TABLE",
4321 " json Results in a JSON array",
4322 " line One value per line",
4323 " list Values delimited by \"|\"",
4324 " markdown Markdown table format",
4325 " qbox Shorthand for \"box --width 60 --quote\"",
4326 " quote Escape answers as for SQL",
4327 " table ASCII-art table",
4328 " tabs Tab-separated values",
4329 " tcl TCL list elements",
larrybrcc4d55c2022-02-01 02:50:45 +00004330 " OPTIONS: (for columnar modes or insert mode):",
4331 " --wrap N Wrap output lines to no longer than N characters",
drhca1776b2022-02-01 12:28:17 +00004332 " --wordwrap B Wrap or not at word boundaries per B (on/off)",
4333 " --ww Shorthand for \"--wordwrap 1\"",
larrybrcc4d55c2022-02-01 02:50:45 +00004334 " --quote Quote output text as SQL literals",
4335 " --noquote Do not quote output text",
4336 " TABLE The name of SQL table used for \"insert\" mode",
4337 ".nonce STRING Suspend safe mode for one command if nonce matches",
drh98aa2ab2018-09-26 16:53:51 +00004338 ".nullvalue STRING Use STRING in place of NULL values",
drh7a431002020-04-18 14:12:00 +00004339 ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE",
drh98aa2ab2018-09-26 16:53:51 +00004340 " If FILE begins with '|' then open as a pipe",
drh7a431002020-04-18 14:12:00 +00004341 " --bom Put a UTF8 byte-order mark at the beginning",
4342 " -e Send output to the system text editor",
4343 " -x Send output as CSV to a spreadsheet (same as \".excel\")",
drh98aa2ab2018-09-26 16:53:51 +00004344 ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
4345 " Options:",
drh60f34ae2018-10-30 13:19:49 +00004346 " --append Use appendvfs to append database to the end of FILE",
drh8d889af2021-05-08 17:18:23 +00004347#ifndef SQLITE_OMIT_DESERIALIZE
drhd10c3ca2021-05-08 11:57:35 +00004348 " --deserialize Load into memory using sqlite3_deserialize()",
drhe2754c12019-08-26 12:50:01 +00004349 " --hexdb Load the output of \"dbtotxt\" as an in-memory db",
drh6ca64482019-01-22 16:06:20 +00004350 " --maxsize N Maximum size for --hexdb or --deserialized database",
drha751f392018-10-30 15:31:22 +00004351#endif
drh60f34ae2018-10-30 13:19:49 +00004352 " --new Initialize FILE to an empty database",
drh0933aad2019-11-18 17:46:38 +00004353 " --nofollow Do not follow symbolic links",
drh60f34ae2018-10-30 13:19:49 +00004354 " --readonly Open FILE readonly",
4355 " --zip FILE is a ZIP archive",
drh98aa2ab2018-09-26 16:53:51 +00004356 ".output ?FILE? Send output to FILE or stdout if FILE is omitted",
drh7a431002020-04-18 14:12:00 +00004357 " If FILE begins with '|' then open it as a pipe.",
4358 " Options:",
4359 " --bom Prefix output with a UTF8 byte-order mark",
4360 " -e Send output to the system text editor",
4361 " -x Send output as CSV to a spreadsheet",
drh9cb02642019-02-28 20:10:52 +00004362 ".parameter CMD ... Manage SQL parameter bindings",
4363 " clear Erase all bindings",
4364 " init Initialize the TEMP table that holds bindings",
4365 " list List the current parameter bindings",
4366 " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE",
drhe2754c12019-08-26 12:50:01 +00004367 " PARAMETER should start with one of: $ : @ ?",
drh9cb02642019-02-28 20:10:52 +00004368 " unset PARAMETER Remove PARAMETER from the binding table",
drh98aa2ab2018-09-26 16:53:51 +00004369 ".print STRING... Print literal STRING",
drh569b1d92019-02-05 20:51:41 +00004370#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh3f83f592019-02-04 14:53:18 +00004371 ".progress N Invoke progress handler after every N opcodes",
4372 " --limit N Interrupt after N progress callbacks",
4373 " --once Do no more than one progress interrupt",
4374 " --quiet|-q No output except at interrupts",
4375 " --reset Reset the count for each input and interrupt",
drh569b1d92019-02-05 20:51:41 +00004376#endif
drh98aa2ab2018-09-26 16:53:51 +00004377 ".prompt MAIN CONTINUE Replace the standard prompts",
4378 ".quit Exit this program",
larrybra2ba25b2021-12-28 05:08:38 +00004379 ".read FILE Read input from FILE or command output",
4380 " If FILE begins with \"|\", it is a command that generates the input.",
dan1b162162019-04-27 20:15:15 +00004381#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan42ebb012019-04-27 18:47:03 +00004382 ".recover Recover as much data as possible from corrupt db.",
drhe2754c12019-08-26 12:50:01 +00004383 " --freelist-corrupt Assume the freelist is corrupt",
4384 " --recovery-db NAME Store recovery metadata in database file NAME",
4385 " --lost-and-found TABLE Alternative name for the lost-and-found table",
dan8cce6b82019-09-14 16:44:51 +00004386 " --no-rowids Do not attempt to recover rowid values",
4387 " that are not also INTEGER PRIMARY KEYs",
dan1b162162019-04-27 20:15:15 +00004388#endif
drh98aa2ab2018-09-26 16:53:51 +00004389 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
4390 ".save FILE Write in-memory database into FILE",
4391 ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
4392 ".schema ?PATTERN? Show the CREATE statements matching PATTERN",
drhbbb29ec2020-10-12 14:56:47 +00004393 " Options:",
4394 " --indent Try to pretty-print the schema",
4395 " --nosys Omit objects whose names start with \"sqlite_\"",
drheb7f2a02018-09-26 18:02:32 +00004396 ".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
4397 " Options:",
4398 " --init Create a new SELFTEST table",
4399 " -v Verbose output",
drh98aa2ab2018-09-26 16:53:51 +00004400 ".separator COL ?ROW? Change the column and row separators",
drh2ce15c32017-07-11 13:34:40 +00004401#if defined(SQLITE_ENABLE_SESSION)
drheb7f2a02018-09-26 18:02:32 +00004402 ".session ?NAME? CMD ... Create or control sessions",
4403 " Subcommands:",
4404 " attach TABLE Attach TABLE",
4405 " changeset FILE Write a changeset into FILE",
4406 " close Close one session",
4407 " enable ?BOOLEAN? Set or query the enable bit",
4408 " filter GLOB... Reject tables matching GLOBs",
4409 " indirect ?BOOLEAN? Mark or query the indirect status",
4410 " isempty Query whether the session is empty",
4411 " list List currently open session names",
4412 " open DB NAME Open a new session on DB",
4413 " patchset FILE Write a patchset into FILE",
4414 " If ?NAME? is omitted, the first defined session is used.",
drh2ce15c32017-07-11 13:34:40 +00004415#endif
drheb7f2a02018-09-26 18:02:32 +00004416 ".sha3sum ... Compute a SHA3 hash of database content",
4417 " Options:",
drh067b92b2020-06-19 15:24:12 +00004418 " --schema Also hash the sqlite_schema table",
drheb7f2a02018-09-26 18:02:32 +00004419 " --sha3-224 Use the sha3-224 algorithm",
drhe2754c12019-08-26 12:50:01 +00004420 " --sha3-256 Use the sha3-256 algorithm (default)",
drheb7f2a02018-09-26 18:02:32 +00004421 " --sha3-384 Use the sha3-384 algorithm",
4422 " --sha3-512 Use the sha3-512 algorithm",
4423 " Any other argument is a LIKE pattern for tables to hash",
drh04a28c32018-01-31 01:38:44 +00004424#ifndef SQLITE_NOHAVE_SYSTEM
drh98aa2ab2018-09-26 16:53:51 +00004425 ".shell CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004426#endif
drh98aa2ab2018-09-26 16:53:51 +00004427 ".show Show the current values for various settings",
drha6e6cf22021-01-09 19:10:04 +00004428 ".stats ?ARG? Show stats or turn stats on or off",
4429 " off Turn off automatic stat display",
4430 " on Turn on automatic stat display",
4431 " stmt Show statement stats",
4432 " vmstep Show the virtual machine step count only",
drh04a28c32018-01-31 01:38:44 +00004433#ifndef SQLITE_NOHAVE_SYSTEM
drh98aa2ab2018-09-26 16:53:51 +00004434 ".system CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004435#endif
drh98aa2ab2018-09-26 16:53:51 +00004436 ".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
4437 ".testcase NAME Begin redirecting output to 'testcase-out.txt'",
drhd985f722019-06-05 14:29:53 +00004438 ".testctrl CMD ... Run various sqlite3_test_control() operations",
4439 " Run \".testctrl\" with no arguments for details",
drh98aa2ab2018-09-26 16:53:51 +00004440 ".timeout MS Try opening locked tables for MS milliseconds",
4441 ".timer on|off Turn SQL timer on or off",
drh707821f2018-12-05 13:39:06 +00004442#ifndef SQLITE_OMIT_TRACE
4443 ".trace ?OPTIONS? Output each SQL statement as it is run",
4444 " FILE Send output to FILE",
4445 " stdout Send output to stdout",
4446 " stderr Send output to stderr",
4447 " off Disable tracing",
4448 " --expanded Expand query parameters",
4449#ifdef SQLITE_ENABLE_NORMALIZE
4450 " --normalized Normal the SQL statements",
4451#endif
4452 " --plain Show SQL as it is input",
4453 " --stmt Trace statement execution (SQLITE_TRACE_STMT)",
4454 " --profile Profile statements (SQLITE_TRACE_PROFILE)",
4455 " --row Trace each row (SQLITE_TRACE_ROW)",
4456 " --close Trace connection close (SQLITE_TRACE_CLOSE)",
4457#endif /* SQLITE_OMIT_TRACE */
drhcc5979d2019-08-16 22:58:29 +00004458#ifdef SQLITE_DEBUG
4459 ".unmodule NAME ... Unregister virtual table modules",
drh5df84282019-08-17 19:45:25 +00004460 " --allexcept Unregister everything except those named",
drhcc5979d2019-08-16 22:58:29 +00004461#endif
drh98aa2ab2018-09-26 16:53:51 +00004462 ".vfsinfo ?AUX? Information about the top-level VFS",
4463 ".vfslist List all available VFSes",
4464 ".vfsname ?AUX? Print the name of the VFS stack",
drh7da29a32020-05-29 19:17:20 +00004465 ".width NUM1 NUM2 ... Set minimum column widths for columnar output",
drh98aa2ab2018-09-26 16:53:51 +00004466 " Negative values right-justify",
4467};
4468
4469/*
4470** Output help text.
4471**
4472** zPattern describes the set of commands for which help text is provided.
4473** If zPattern is NULL, then show all commands, but only give a one-line
4474** description of each.
4475**
4476** Return the number of matches.
4477*/
4478static int showHelp(FILE *out, const char *zPattern){
drhe93f8262018-10-11 16:53:37 +00004479 int i = 0;
4480 int j = 0;
drh98aa2ab2018-09-26 16:53:51 +00004481 int n = 0;
4482 char *zPat;
drh488cddf2018-10-06 14:38:17 +00004483 if( zPattern==0
4484 || zPattern[0]=='0'
4485 || strcmp(zPattern,"-a")==0
4486 || strcmp(zPattern,"-all")==0
drh7a431002020-04-18 14:12:00 +00004487 || strcmp(zPattern,"--all")==0
drh488cddf2018-10-06 14:38:17 +00004488 ){
drh98aa2ab2018-09-26 16:53:51 +00004489 /* Show all commands, but only one line per command */
drh488cddf2018-10-06 14:38:17 +00004490 if( zPattern==0 ) zPattern = "";
drh98aa2ab2018-09-26 16:53:51 +00004491 for(i=0; i<ArraySize(azHelp); i++){
drh488cddf2018-10-06 14:38:17 +00004492 if( azHelp[i][0]=='.' || zPattern[0] ){
drh98aa2ab2018-09-26 16:53:51 +00004493 utf8_printf(out, "%s\n", azHelp[i]);
4494 n++;
4495 }
4496 }
4497 }else{
4498 /* Look for commands that for which zPattern is an exact prefix */
4499 zPat = sqlite3_mprintf(".%s*", zPattern);
drhe3e25652021-12-16 13:29:28 +00004500 shell_check_oom(zPat);
drh98aa2ab2018-09-26 16:53:51 +00004501 for(i=0; i<ArraySize(azHelp); i++){
4502 if( sqlite3_strglob(zPat, azHelp[i])==0 ){
4503 utf8_printf(out, "%s\n", azHelp[i]);
drheb7f2a02018-09-26 18:02:32 +00004504 j = i+1;
drh98aa2ab2018-09-26 16:53:51 +00004505 n++;
4506 }
4507 }
4508 sqlite3_free(zPat);
drheb7f2a02018-09-26 18:02:32 +00004509 if( n ){
4510 if( n==1 ){
4511 /* when zPattern is a prefix of exactly one command, then include the
4512 ** details of that command, which should begin at offset j */
4513 while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){
4514 utf8_printf(out, "%s\n", azHelp[j]);
4515 j++;
4516 }
4517 }
4518 return n;
4519 }
4520 /* Look for commands that contain zPattern anywhere. Show the complete
4521 ** text of all commands that match. */
drh98aa2ab2018-09-26 16:53:51 +00004522 zPat = sqlite3_mprintf("%%%s%%", zPattern);
drhe3e25652021-12-16 13:29:28 +00004523 shell_check_oom(zPat);
drh98aa2ab2018-09-26 16:53:51 +00004524 for(i=0; i<ArraySize(azHelp); i++){
4525 if( azHelp[i][0]=='.' ) j = i;
4526 if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
4527 utf8_printf(out, "%s\n", azHelp[j]);
4528 while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
4529 j++;
4530 utf8_printf(out, "%s\n", azHelp[j]);
4531 }
4532 i = j;
4533 n++;
4534 }
4535 }
4536 sqlite3_free(zPat);
4537 }
4538 return n;
4539}
drh2ce15c32017-07-11 13:34:40 +00004540
drh2ce15c32017-07-11 13:34:40 +00004541/* Forward reference */
drh60379d42018-12-13 18:30:01 +00004542static int process_input(ShellState *p);
drh2ce15c32017-07-11 13:34:40 +00004543
4544/*
4545** Read the content of file zName into memory obtained from sqlite3_malloc64()
4546** and return a pointer to the buffer. The caller is responsible for freeing
4547** the memory.
4548**
4549** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
4550** read.
4551**
4552** For convenience, a nul-terminator byte is always appended to the data read
4553** from the file before the buffer is returned. This byte is not included in
4554** the final value of (*pnByte), if applicable.
4555**
4556** NULL is returned if any error is encountered. The final value of *pnByte
4557** is undefined in this case.
4558*/
4559static char *readFile(const char *zName, int *pnByte){
4560 FILE *in = fopen(zName, "rb");
4561 long nIn;
4562 size_t nRead;
4563 char *pBuf;
4564 if( in==0 ) return 0;
4565 fseek(in, 0, SEEK_END);
4566 nIn = ftell(in);
4567 rewind(in);
4568 pBuf = sqlite3_malloc64( nIn+1 );
drh1dbb1472018-10-11 10:37:24 +00004569 if( pBuf==0 ){ fclose(in); return 0; }
drh2ce15c32017-07-11 13:34:40 +00004570 nRead = fread(pBuf, nIn, 1, in);
4571 fclose(in);
4572 if( nRead!=1 ){
4573 sqlite3_free(pBuf);
4574 return 0;
4575 }
4576 pBuf[nIn] = 0;
4577 if( pnByte ) *pnByte = nIn;
4578 return pBuf;
4579}
4580
4581#if defined(SQLITE_ENABLE_SESSION)
4582/*
4583** Close a single OpenSession object and release all of its associated
4584** resources.
4585*/
4586static void session_close(OpenSession *pSession){
4587 int i;
4588 sqlite3session_delete(pSession->p);
4589 sqlite3_free(pSession->zName);
4590 for(i=0; i<pSession->nFilter; i++){
4591 sqlite3_free(pSession->azFilter[i]);
4592 }
4593 sqlite3_free(pSession->azFilter);
4594 memset(pSession, 0, sizeof(OpenSession));
4595}
4596#endif
4597
4598/*
4599** Close all OpenSession objects and release all associated resources.
4600*/
4601#if defined(SQLITE_ENABLE_SESSION)
drh37407122021-07-23 18:43:58 +00004602static void session_close_all(ShellState *p, int i){
4603 int j;
4604 struct AuxDb *pAuxDb = i<0 ? p->pAuxDb : &p->aAuxDb[i];
4605 for(j=0; j<pAuxDb->nSession; j++){
4606 session_close(&pAuxDb->aSession[j]);
drh2ce15c32017-07-11 13:34:40 +00004607 }
drh37407122021-07-23 18:43:58 +00004608 pAuxDb->nSession = 0;
drh2ce15c32017-07-11 13:34:40 +00004609}
4610#else
drh37407122021-07-23 18:43:58 +00004611# define session_close_all(X,Y)
drh2ce15c32017-07-11 13:34:40 +00004612#endif
4613
4614/*
4615** Implementation of the xFilter function for an open session. Omit
4616** any tables named by ".session filter" but let all other table through.
4617*/
4618#if defined(SQLITE_ENABLE_SESSION)
4619static int session_filter(void *pCtx, const char *zTab){
4620 OpenSession *pSession = (OpenSession*)pCtx;
4621 int i;
4622 for(i=0; i<pSession->nFilter; i++){
4623 if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
4624 }
4625 return 1;
4626}
4627#endif
4628
4629/*
drh1fa6d9f2018-01-06 21:46:01 +00004630** Try to deduce the type of file for zName based on its content. Return
4631** one of the SHELL_OPEN_* constants.
drh1bf208c2018-03-09 21:54:01 +00004632**
4633** If the file does not exist or is empty but its name looks like a ZIP
4634** archive and the dfltZip flag is true, then assume it is a ZIP archive.
4635** Otherwise, assume an ordinary database regardless of the filename if
4636** the type cannot be determined from content.
drh1fa6d9f2018-01-06 21:46:01 +00004637*/
drhfc97c1c2018-05-14 00:41:12 +00004638int deduceDatabaseType(const char *zName, int dfltZip){
drh1fa6d9f2018-01-06 21:46:01 +00004639 FILE *f = fopen(zName, "rb");
4640 size_t n;
4641 int rc = SHELL_OPEN_UNSPEC;
4642 char zBuf[100];
drh1bf208c2018-03-09 21:54:01 +00004643 if( f==0 ){
drhbe4ccb22018-05-17 20:04:24 +00004644 if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
4645 return SHELL_OPEN_ZIPFILE;
4646 }else{
4647 return SHELL_OPEN_NORMAL;
4648 }
drh1bf208c2018-03-09 21:54:01 +00004649 }
drh2b3c4af2018-10-30 14:36:21 +00004650 n = fread(zBuf, 16, 1, f);
4651 if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
4652 fclose(f);
4653 return SHELL_OPEN_NORMAL;
4654 }
drh1fa6d9f2018-01-06 21:46:01 +00004655 fseek(f, -25, SEEK_END);
4656 n = fread(zBuf, 25, 1, f);
4657 if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
4658 rc = SHELL_OPEN_APPENDVFS;
4659 }else{
4660 fseek(f, -22, SEEK_END);
4661 n = fread(zBuf, 22, 1, f);
4662 if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
4663 && zBuf[3]==0x06 ){
4664 rc = SHELL_OPEN_ZIPFILE;
drh1bf208c2018-03-09 21:54:01 +00004665 }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
mistachkina3926f42018-05-14 12:23:04 +00004666 rc = SHELL_OPEN_ZIPFILE;
drh1fa6d9f2018-01-06 21:46:01 +00004667 }
4668 }
4669 fclose(f);
4670 return rc;
4671}
4672
drh8d889af2021-05-08 17:18:23 +00004673#ifndef SQLITE_OMIT_DESERIALIZE
drh33746482018-12-13 15:06:26 +00004674/*
4675** Reconstruct an in-memory database using the output from the "dbtotxt"
drh37407122021-07-23 18:43:58 +00004676** program. Read content from the file in p->aAuxDb[].zDbFilename.
4677** If p->aAuxDb[].zDbFilename is 0, then read from standard input.
drh33746482018-12-13 15:06:26 +00004678*/
4679static unsigned char *readHexDb(ShellState *p, int *pnData){
4680 unsigned char *a = 0;
drh2c8ee022018-12-13 18:59:30 +00004681 int nLine;
drh33746482018-12-13 15:06:26 +00004682 int n = 0;
4683 int pgsz = 0;
4684 int iOffset = 0;
4685 int j, k;
4686 int rc;
4687 FILE *in;
drh37407122021-07-23 18:43:58 +00004688 const char *zDbFilename = p->pAuxDb->zDbFilename;
drh3ea557e2019-04-23 15:30:58 +00004689 unsigned int x[16];
drh2c8ee022018-12-13 18:59:30 +00004690 char zLine[1000];
drh37407122021-07-23 18:43:58 +00004691 if( zDbFilename ){
4692 in = fopen(zDbFilename, "r");
drh33746482018-12-13 15:06:26 +00004693 if( in==0 ){
drh37407122021-07-23 18:43:58 +00004694 utf8_printf(stderr, "cannot open \"%s\" for reading\n", zDbFilename);
drh33746482018-12-13 15:06:26 +00004695 return 0;
4696 }
drh2c8ee022018-12-13 18:59:30 +00004697 nLine = 0;
drh33746482018-12-13 15:06:26 +00004698 }else{
drh60379d42018-12-13 18:30:01 +00004699 in = p->in;
drh2c8ee022018-12-13 18:59:30 +00004700 nLine = p->lineno;
drh5bf46442019-05-03 02:41:36 +00004701 if( in==0 ) in = stdin;
drh33746482018-12-13 15:06:26 +00004702 }
4703 *pnData = 0;
drh2c8ee022018-12-13 18:59:30 +00004704 nLine++;
drh33746482018-12-13 15:06:26 +00004705 if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
4706 rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
4707 if( rc!=2 ) goto readHexDb_error;
drh68feae52019-05-09 11:18:41 +00004708 if( n<0 ) goto readHexDb_error;
drh09ea1252019-07-17 15:05:16 +00004709 if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
4710 n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */
drh68feae52019-05-09 11:18:41 +00004711 a = sqlite3_malloc( n ? n : 1 );
drhe3e25652021-12-16 13:29:28 +00004712 shell_check_oom(a);
drh33746482018-12-13 15:06:26 +00004713 memset(a, 0, n);
4714 if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
4715 utf8_printf(stderr, "invalid pagesize\n");
4716 goto readHexDb_error;
4717 }
drh2c8ee022018-12-13 18:59:30 +00004718 for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
drh33746482018-12-13 15:06:26 +00004719 rc = sscanf(zLine, "| page %d offset %d", &j, &k);
4720 if( rc==2 ){
4721 iOffset = k;
4722 continue;
4723 }
4724 if( strncmp(zLine, "| end ", 6)==0 ){
4725 break;
4726 }
drh3ea557e2019-04-23 15:30:58 +00004727 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 +00004728 &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
4729 &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
4730 if( rc==17 ){
4731 k = iOffset+j;
drh82978ac2021-10-01 17:06:44 +00004732 if( k+16<=n && k>=0 ){
drh3ea557e2019-04-23 15:30:58 +00004733 int ii;
4734 for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
drh33746482018-12-13 15:06:26 +00004735 }
drh33746482018-12-13 15:06:26 +00004736 }
4737 }
4738 *pnData = n;
drh2c8ee022018-12-13 18:59:30 +00004739 if( in!=p->in ){
4740 fclose(in);
4741 }else{
4742 p->lineno = nLine;
4743 }
drh33746482018-12-13 15:06:26 +00004744 return a;
4745
4746readHexDb_error:
drh68feae52019-05-09 11:18:41 +00004747 if( in!=p->in ){
drh33746482018-12-13 15:06:26 +00004748 fclose(in);
4749 }else{
drh60379d42018-12-13 18:30:01 +00004750 while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
drh2c8ee022018-12-13 18:59:30 +00004751 nLine++;
drh33746482018-12-13 15:06:26 +00004752 if(strncmp(zLine, "| end ", 6)==0 ) break;
4753 }
drh2c8ee022018-12-13 18:59:30 +00004754 p->lineno = nLine;
drh33746482018-12-13 15:06:26 +00004755 }
4756 sqlite3_free(a);
4757 utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
4758 return 0;
4759}
drh8d889af2021-05-08 17:18:23 +00004760#endif /* SQLITE_OMIT_DESERIALIZE */
drh33746482018-12-13 15:06:26 +00004761
danb1825882019-04-23 20:48:32 +00004762/*
dan9c014f82019-04-25 19:23:15 +00004763** Scalar function "shell_int32". The first argument to this function
4764** must be a blob. The second a non-negative integer. This function
4765** reads and returns a 32-bit big-endian integer from byte
4766** offset (4*<arg2>) of the blob.
4767*/
4768static void shellInt32(
4769 sqlite3_context *context,
4770 int argc,
4771 sqlite3_value **argv
4772){
4773 const unsigned char *pBlob;
4774 int nBlob;
4775 int iInt;
drh9546c762019-05-10 17:50:33 +00004776
4777 UNUSED_PARAMETER(argc);
dan9c014f82019-04-25 19:23:15 +00004778 nBlob = sqlite3_value_bytes(argv[0]);
4779 pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
4780 iInt = sqlite3_value_int(argv[1]);
4781
4782 if( iInt>=0 && (iInt+1)*4<=nBlob ){
4783 const unsigned char *a = &pBlob[iInt*4];
4784 sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24)
4785 + ((sqlite3_int64)a[1]<<16)
4786 + ((sqlite3_int64)a[2]<< 8)
4787 + ((sqlite3_int64)a[3]<< 0);
4788 sqlite3_result_int64(context, iVal);
4789 }
4790}
4791
4792/*
drha2de66c2019-08-06 20:26:17 +00004793** Scalar function "shell_idquote(X)" returns string X quoted as an identifier,
4794** using "..." with internal double-quote characters doubled.
4795*/
4796static void shellIdQuote(
4797 sqlite3_context *context,
4798 int argc,
4799 sqlite3_value **argv
4800){
4801 const char *zName = (const char*)sqlite3_value_text(argv[0]);
drh51755a72019-08-08 19:40:29 +00004802 UNUSED_PARAMETER(argc);
drha2de66c2019-08-06 20:26:17 +00004803 if( zName ){
4804 char *z = sqlite3_mprintf("\"%w\"", zName);
4805 sqlite3_result_text(context, z, -1, sqlite3_free);
4806 }
4807}
4808
4809/*
drhddcfe922020-09-15 12:29:35 +00004810** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
4811*/
4812static void shellUSleepFunc(
4813 sqlite3_context *context,
drhd36f5882020-11-25 16:28:04 +00004814 int argcUnused,
drhddcfe922020-09-15 12:29:35 +00004815 sqlite3_value **argv
4816){
4817 int sleep = sqlite3_value_int(argv[0]);
drhd36f5882020-11-25 16:28:04 +00004818 (void)argcUnused;
drhddcfe922020-09-15 12:29:35 +00004819 sqlite3_sleep(sleep/1000);
4820 sqlite3_result_int(context, sleep);
4821}
4822
4823/*
danb1825882019-04-23 20:48:32 +00004824** Scalar function "shell_escape_crnl" used by the .recover command.
4825** The argument passed to this function is the output of built-in
4826** function quote(). If the first character of the input is "'",
4827** indicating that the value passed to quote() was a text value,
4828** then this function searches the input for "\n" and "\r" characters
4829** and adds a wrapper similar to the following:
4830**
4831** replace(replace(<input>, '\n', char(10), '\r', char(13));
4832**
4833** Or, if the first character of the input is not "'", then a copy
4834** of the input is returned.
4835*/
4836static void shellEscapeCrnl(
4837 sqlite3_context *context,
4838 int argc,
4839 sqlite3_value **argv
4840){
4841 const char *zText = (const char*)sqlite3_value_text(argv[0]);
drh9546c762019-05-10 17:50:33 +00004842 UNUSED_PARAMETER(argc);
drh621a5e02021-12-16 17:35:27 +00004843 if( zText && zText[0]=='\'' ){
danb1825882019-04-23 20:48:32 +00004844 int nText = sqlite3_value_bytes(argv[0]);
4845 int i;
4846 char zBuf1[20];
4847 char zBuf2[20];
4848 const char *zNL = 0;
4849 const char *zCR = 0;
4850 int nCR = 0;
4851 int nNL = 0;
4852
4853 for(i=0; zText[i]; i++){
4854 if( zNL==0 && zText[i]=='\n' ){
4855 zNL = unused_string(zText, "\\n", "\\012", zBuf1);
4856 nNL = (int)strlen(zNL);
4857 }
4858 if( zCR==0 && zText[i]=='\r' ){
4859 zCR = unused_string(zText, "\\r", "\\015", zBuf2);
4860 nCR = (int)strlen(zCR);
4861 }
4862 }
4863
4864 if( zNL || zCR ){
4865 int iOut = 0;
4866 i64 nMax = (nNL > nCR) ? nNL : nCR;
dan51f5ffa2019-04-29 11:41:46 +00004867 i64 nAlloc = nMax * nText + (nMax+64)*2;
danb1825882019-04-23 20:48:32 +00004868 char *zOut = (char*)sqlite3_malloc64(nAlloc);
4869 if( zOut==0 ){
4870 sqlite3_result_error_nomem(context);
4871 return;
4872 }
4873
4874 if( zNL && zCR ){
4875 memcpy(&zOut[iOut], "replace(replace(", 16);
4876 iOut += 16;
4877 }else{
4878 memcpy(&zOut[iOut], "replace(", 8);
4879 iOut += 8;
4880 }
4881 for(i=0; zText[i]; i++){
4882 if( zText[i]=='\n' ){
4883 memcpy(&zOut[iOut], zNL, nNL);
4884 iOut += nNL;
4885 }else if( zText[i]=='\r' ){
4886 memcpy(&zOut[iOut], zCR, nCR);
4887 iOut += nCR;
4888 }else{
4889 zOut[iOut] = zText[i];
4890 iOut++;
4891 }
4892 }
4893
4894 if( zNL ){
4895 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
4896 memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
4897 memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
4898 }
4899 if( zCR ){
4900 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
4901 memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
4902 memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
4903 }
4904
4905 sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
4906 sqlite3_free(zOut);
4907 return;
4908 }
4909 }
4910
4911 sqlite3_result_value(context, argv[0]);
4912}
4913
drhbe4ccb22018-05-17 20:04:24 +00004914/* Flags for open_db().
4915**
4916** The default behavior of open_db() is to exit(1) if the database fails to
4917** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
4918** but still returns without calling exit.
4919**
4920** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a
4921** ZIP archive if the file does not exist or is empty and its name matches
4922** the *.zip pattern.
4923*/
4924#define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */
4925#define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */
4926
drh1fa6d9f2018-01-06 21:46:01 +00004927/*
drh2ce15c32017-07-11 13:34:40 +00004928** Make sure the database is open. If it is not, then open it. If
4929** the database fails to open, print an error message and exit.
4930*/
drhbe4ccb22018-05-17 20:04:24 +00004931static void open_db(ShellState *p, int openFlags){
drh2ce15c32017-07-11 13:34:40 +00004932 if( p->db==0 ){
drh37407122021-07-23 18:43:58 +00004933 const char *zDbFilename = p->pAuxDb->zDbFilename;
drhf2072d12018-05-11 15:10:11 +00004934 if( p->openMode==SHELL_OPEN_UNSPEC ){
drh37407122021-07-23 18:43:58 +00004935 if( zDbFilename==0 || zDbFilename[0]==0 ){
drhf2072d12018-05-11 15:10:11 +00004936 p->openMode = SHELL_OPEN_NORMAL;
drhbe4ccb22018-05-17 20:04:24 +00004937 }else{
drh37407122021-07-23 18:43:58 +00004938 p->openMode = (u8)deduceDatabaseType(zDbFilename,
drhbe4ccb22018-05-17 20:04:24 +00004939 (openFlags & OPEN_DB_ZIPFILE)!=0);
drhf2072d12018-05-11 15:10:11 +00004940 }
drh1fa6d9f2018-01-06 21:46:01 +00004941 }
4942 switch( p->openMode ){
4943 case SHELL_OPEN_APPENDVFS: {
drh37407122021-07-23 18:43:58 +00004944 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004945 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
drh1fa6d9f2018-01-06 21:46:01 +00004946 break;
4947 }
drh33746482018-12-13 15:06:26 +00004948 case SHELL_OPEN_HEXDB:
drh60f34ae2018-10-30 13:19:49 +00004949 case SHELL_OPEN_DESERIALIZE: {
4950 sqlite3_open(0, &p->db);
4951 break;
4952 }
drh1fa6d9f2018-01-06 21:46:01 +00004953 case SHELL_OPEN_ZIPFILE: {
4954 sqlite3_open(":memory:", &p->db);
4955 break;
4956 }
drhee269a62018-02-14 23:27:43 +00004957 case SHELL_OPEN_READONLY: {
drh37407122021-07-23 18:43:58 +00004958 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004959 SQLITE_OPEN_READONLY|p->openFlags, 0);
drhee269a62018-02-14 23:27:43 +00004960 break;
4961 }
drh1fa6d9f2018-01-06 21:46:01 +00004962 case SHELL_OPEN_UNSPEC:
4963 case SHELL_OPEN_NORMAL: {
drh37407122021-07-23 18:43:58 +00004964 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004965 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
drh1fa6d9f2018-01-06 21:46:01 +00004966 break;
4967 }
4968 }
drh2ce15c32017-07-11 13:34:40 +00004969 globalDb = p->db;
4970 if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
4971 utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
drh37407122021-07-23 18:43:58 +00004972 zDbFilename, sqlite3_errmsg(p->db));
drhf25cc4f2019-01-04 14:29:21 +00004973 if( openFlags & OPEN_DB_KEEPALIVE ){
4974 sqlite3_open(":memory:", &p->db);
4975 return;
4976 }
drh2ce15c32017-07-11 13:34:40 +00004977 exit(1);
4978 }
4979#ifndef SQLITE_OMIT_LOAD_EXTENSION
4980 sqlite3_enable_load_extension(p->db, 1);
4981#endif
4982 sqlite3_fileio_init(p->db, 0, 0);
4983 sqlite3_shathree_init(p->db, 0, 0);
drh56eb09b2017-07-11 13:59:07 +00004984 sqlite3_completion_init(p->db, 0, 0);
drhf05dd032020-04-14 15:53:58 +00004985 sqlite3_uint_init(p->db, 0, 0);
drhbeb9def2020-06-22 19:12:23 +00004986 sqlite3_decimal_init(p->db, 0, 0);
drh64689902021-06-03 13:51:31 +00004987 sqlite3_regexp_init(p->db, 0, 0);
drh8cda77d2020-06-24 15:06:29 +00004988 sqlite3_ieee_init(p->db, 0, 0);
mistachkin72c38d82020-08-28 18:47:39 +00004989 sqlite3_series_init(p->db, 0, 0);
dan1b162162019-04-27 20:15:15 +00004990#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00004991 sqlite3_dbdata_init(p->db, 0, 0);
dan1b162162019-04-27 20:15:15 +00004992#endif
dan72afc3c2017-12-05 18:32:40 +00004993#ifdef SQLITE_HAVE_ZLIB
dan9ebfaad2017-12-26 20:39:58 +00004994 sqlite3_zipfile_init(p->db, 0, 0);
dand1b51d42017-12-16 19:11:26 +00004995 sqlite3_sqlar_init(p->db, 0, 0);
dan72afc3c2017-12-05 18:32:40 +00004996#endif
drhceba7922018-01-01 21:28:25 +00004997 sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
drh2ce15c32017-07-11 13:34:40 +00004998 shellAddSchemaName, 0, 0);
drh667a2a22018-01-02 00:04:37 +00004999 sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
5000 shellModuleSchema, 0, 0);
drh634c70f2018-01-10 16:50:18 +00005001 sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
5002 shellPutsFunc, 0, 0);
danb1825882019-04-23 20:48:32 +00005003 sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0,
5004 shellEscapeCrnl, 0, 0);
dan9c014f82019-04-25 19:23:15 +00005005 sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
5006 shellInt32, 0, 0);
drha2de66c2019-08-06 20:26:17 +00005007 sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
5008 shellIdQuote, 0, 0);
drhddcfe922020-09-15 12:29:35 +00005009 sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
5010 shellUSleepFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00005011#ifndef SQLITE_NOHAVE_SYSTEM
drh97913132018-01-11 00:04:00 +00005012 sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
5013 editFunc, 0, 0);
5014 sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
5015 editFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00005016#endif
drh1fa6d9f2018-01-06 21:46:01 +00005017 if( p->openMode==SHELL_OPEN_ZIPFILE ){
5018 char *zSql = sqlite3_mprintf(
drh37407122021-07-23 18:43:58 +00005019 "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename);
drhe3e25652021-12-16 13:29:28 +00005020 shell_check_oom(zSql);
drh1fa6d9f2018-01-06 21:46:01 +00005021 sqlite3_exec(p->db, zSql, 0, 0, 0);
5022 sqlite3_free(zSql);
drha751f392018-10-30 15:31:22 +00005023 }
drh8d889af2021-05-08 17:18:23 +00005024#ifndef SQLITE_OMIT_DESERIALIZE
drh33746482018-12-13 15:06:26 +00005025 else
5026 if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
mistachkin99490932018-12-17 22:19:57 +00005027 int rc;
drh60f34ae2018-10-30 13:19:49 +00005028 int nData = 0;
drh33746482018-12-13 15:06:26 +00005029 unsigned char *aData;
5030 if( p->openMode==SHELL_OPEN_DESERIALIZE ){
drh37407122021-07-23 18:43:58 +00005031 aData = (unsigned char*)readFile(zDbFilename, &nData);
drh33746482018-12-13 15:06:26 +00005032 }else{
5033 aData = readHexDb(p, &nData);
5034 if( aData==0 ){
drh33746482018-12-13 15:06:26 +00005035 return;
5036 }
5037 }
mistachkin99490932018-12-17 22:19:57 +00005038 rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
drh60f34ae2018-10-30 13:19:49 +00005039 SQLITE_DESERIALIZE_RESIZEABLE |
5040 SQLITE_DESERIALIZE_FREEONCLOSE);
5041 if( rc ){
5042 utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
5043 }
drh6ca64482019-01-22 16:06:20 +00005044 if( p->szMax>0 ){
5045 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
5046 }
drh1fa6d9f2018-01-06 21:46:01 +00005047 }
drha751f392018-10-30 15:31:22 +00005048#endif
drh2ce15c32017-07-11 13:34:40 +00005049 }
drhb97e2ad2021-08-26 18:31:39 +00005050 if( p->bSafeModePersist && p->db!=0 ){
5051 sqlite3_set_authorizer(p->db, safeModeAuth, p);
5052 }
drh2ce15c32017-07-11 13:34:40 +00005053}
5054
drh9e804032018-05-18 17:11:50 +00005055/*
5056** Attempt to close the databaes connection. Report errors.
5057*/
5058void close_db(sqlite3 *db){
5059 int rc = sqlite3_close(db);
5060 if( rc ){
5061 utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
5062 rc, sqlite3_errmsg(db));
5063 }
5064}
5065
drh56eb09b2017-07-11 13:59:07 +00005066#if HAVE_READLINE || HAVE_EDITLINE
5067/*
5068** Readline completion callbacks
5069*/
5070static char *readline_completion_generator(const char *text, int state){
5071 static sqlite3_stmt *pStmt = 0;
5072 char *zRet;
5073 if( state==0 ){
5074 char *zSql;
drh56eb09b2017-07-11 13:59:07 +00005075 sqlite3_finalize(pStmt);
5076 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
5077 " FROM completion(%Q) ORDER BY 1", text);
drhe3e25652021-12-16 13:29:28 +00005078 shell_check_oom(zSql);
drh56eb09b2017-07-11 13:59:07 +00005079 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
5080 sqlite3_free(zSql);
5081 }
5082 if( sqlite3_step(pStmt)==SQLITE_ROW ){
drh621a5e02021-12-16 17:35:27 +00005083 const char *z = (const char*)sqlite3_column_text(pStmt,0);
5084 zRet = z ? strdup(z) : 0;
drh56eb09b2017-07-11 13:59:07 +00005085 }else{
5086 sqlite3_finalize(pStmt);
5087 pStmt = 0;
5088 zRet = 0;
5089 }
5090 return zRet;
5091}
5092static char **readline_completion(const char *zText, int iStart, int iEnd){
5093 rl_attempted_completion_over = 1;
5094 return rl_completion_matches(zText, readline_completion_generator);
5095}
5096
5097#elif HAVE_LINENOISE
5098/*
5099** Linenoise completion callback
5100*/
5101static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
drhaf2770f2018-01-05 14:55:43 +00005102 int nLine = strlen30(zLine);
drh56eb09b2017-07-11 13:59:07 +00005103 int i, iStart;
5104 sqlite3_stmt *pStmt = 0;
5105 char *zSql;
5106 char zBuf[1000];
5107
5108 if( nLine>sizeof(zBuf)-30 ) return;
drh1615c372018-05-12 23:56:22 +00005109 if( zLine[0]=='.' || zLine[0]=='#') return;
drh56eb09b2017-07-11 13:59:07 +00005110 for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
5111 if( i==nLine-1 ) return;
5112 iStart = i+1;
5113 memcpy(zBuf, zLine, iStart);
5114 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
5115 " FROM completion(%Q,%Q) ORDER BY 1",
5116 &zLine[iStart], zLine);
drhe3e25652021-12-16 13:29:28 +00005117 shell_check_oom(zSql);
drh56eb09b2017-07-11 13:59:07 +00005118 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
5119 sqlite3_free(zSql);
5120 sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
5121 while( sqlite3_step(pStmt)==SQLITE_ROW ){
5122 const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
5123 int nCompletion = sqlite3_column_bytes(pStmt, 0);
drh621a5e02021-12-16 17:35:27 +00005124 if( iStart+nCompletion < sizeof(zBuf)-1 && zCompletion ){
drh56eb09b2017-07-11 13:59:07 +00005125 memcpy(zBuf+iStart, zCompletion, nCompletion+1);
5126 linenoiseAddCompletion(lc, zBuf);
5127 }
5128 }
5129 sqlite3_finalize(pStmt);
5130}
5131#endif
5132
drh2ce15c32017-07-11 13:34:40 +00005133/*
5134** Do C-language style dequoting.
5135**
5136** \a -> alarm
5137** \b -> backspace
5138** \t -> tab
5139** \n -> newline
5140** \v -> vertical tab
5141** \f -> form feed
5142** \r -> carriage return
5143** \s -> space
5144** \" -> "
5145** \' -> '
5146** \\ -> backslash
5147** \NNN -> ascii character NNN in octal
5148*/
5149static void resolve_backslashes(char *z){
5150 int i, j;
5151 char c;
5152 while( *z && *z!='\\' ) z++;
5153 for(i=j=0; (c = z[i])!=0; i++, j++){
5154 if( c=='\\' && z[i+1]!=0 ){
5155 c = z[++i];
5156 if( c=='a' ){
5157 c = '\a';
5158 }else if( c=='b' ){
5159 c = '\b';
5160 }else if( c=='t' ){
5161 c = '\t';
5162 }else if( c=='n' ){
5163 c = '\n';
5164 }else if( c=='v' ){
5165 c = '\v';
5166 }else if( c=='f' ){
5167 c = '\f';
5168 }else if( c=='r' ){
5169 c = '\r';
5170 }else if( c=='"' ){
5171 c = '"';
5172 }else if( c=='\'' ){
5173 c = '\'';
5174 }else if( c=='\\' ){
5175 c = '\\';
5176 }else if( c>='0' && c<='7' ){
5177 c -= '0';
5178 if( z[i+1]>='0' && z[i+1]<='7' ){
5179 i++;
5180 c = (c<<3) + z[i] - '0';
5181 if( z[i+1]>='0' && z[i+1]<='7' ){
5182 i++;
5183 c = (c<<3) + z[i] - '0';
5184 }
5185 }
5186 }
5187 }
5188 z[j] = c;
5189 }
5190 if( j<i ) z[j] = 0;
5191}
5192
5193/*
drh2ce15c32017-07-11 13:34:40 +00005194** Interpret zArg as either an integer or a boolean value. Return 1 or 0
5195** for TRUE and FALSE. Return the integer value if appropriate.
5196*/
5197static int booleanValue(const char *zArg){
5198 int i;
5199 if( zArg[0]=='0' && zArg[1]=='x' ){
5200 for(i=2; hexDigitValue(zArg[i])>=0; i++){}
5201 }else{
5202 for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
5203 }
5204 if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
5205 if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
5206 return 1;
5207 }
5208 if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
5209 return 0;
5210 }
5211 utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
5212 zArg);
5213 return 0;
5214}
5215
5216/*
5217** Set or clear a shell flag according to a boolean value.
5218*/
5219static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){
5220 if( booleanValue(zArg) ){
5221 ShellSetFlag(p, mFlag);
5222 }else{
5223 ShellClearFlag(p, mFlag);
5224 }
5225}
5226
5227/*
5228** Close an output file, assuming it is not stderr or stdout
5229*/
5230static void output_file_close(FILE *f){
5231 if( f && f!=stdout && f!=stderr ) fclose(f);
5232}
5233
5234/*
5235** Try to open an output file. The names "stdout" and "stderr" are
5236** recognized and do the right thing. NULL is returned if the output
5237** filename is "off".
5238*/
drha92a01a2018-01-10 22:15:37 +00005239static FILE *output_file_open(const char *zFile, int bTextMode){
drh2ce15c32017-07-11 13:34:40 +00005240 FILE *f;
5241 if( strcmp(zFile,"stdout")==0 ){
5242 f = stdout;
5243 }else if( strcmp(zFile, "stderr")==0 ){
5244 f = stderr;
5245 }else if( strcmp(zFile, "off")==0 ){
5246 f = 0;
5247 }else{
drha92a01a2018-01-10 22:15:37 +00005248 f = fopen(zFile, bTextMode ? "w" : "wb");
drh2ce15c32017-07-11 13:34:40 +00005249 if( f==0 ){
5250 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
5251 }
5252 }
5253 return f;
5254}
5255
drh707821f2018-12-05 13:39:06 +00005256#ifndef SQLITE_OMIT_TRACE
drh2ce15c32017-07-11 13:34:40 +00005257/*
5258** A routine for handling output from sqlite3_trace().
5259*/
5260static int sql_trace_callback(
drh707821f2018-12-05 13:39:06 +00005261 unsigned mType, /* The trace type */
5262 void *pArg, /* The ShellState pointer */
5263 void *pP, /* Usually a pointer to sqlite_stmt */
5264 void *pX /* Auxiliary output */
drh2ce15c32017-07-11 13:34:40 +00005265){
drh707821f2018-12-05 13:39:06 +00005266 ShellState *p = (ShellState*)pArg;
5267 sqlite3_stmt *pStmt;
5268 const char *zSql;
5269 int nSql;
5270 if( p->traceOut==0 ) return 0;
5271 if( mType==SQLITE_TRACE_CLOSE ){
5272 utf8_printf(p->traceOut, "-- closing database connection\n");
5273 return 0;
5274 }
5275 if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){
5276 zSql = (const char*)pX;
5277 }else{
5278 pStmt = (sqlite3_stmt*)pP;
5279 switch( p->eTraceType ){
5280 case SHELL_TRACE_EXPANDED: {
5281 zSql = sqlite3_expanded_sql(pStmt);
5282 break;
5283 }
5284#ifdef SQLITE_ENABLE_NORMALIZE
5285 case SHELL_TRACE_NORMALIZED: {
5286 zSql = sqlite3_normalized_sql(pStmt);
5287 break;
5288 }
5289#endif
5290 default: {
5291 zSql = sqlite3_sql(pStmt);
5292 break;
5293 }
5294 }
5295 }
5296 if( zSql==0 ) return 0;
5297 nSql = strlen30(zSql);
5298 while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
5299 switch( mType ){
5300 case SQLITE_TRACE_ROW:
5301 case SQLITE_TRACE_STMT: {
5302 utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql);
5303 break;
5304 }
5305 case SQLITE_TRACE_PROFILE: {
5306 sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
5307 utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec);
5308 break;
5309 }
drh2ce15c32017-07-11 13:34:40 +00005310 }
5311 return 0;
5312}
5313#endif
drh2ce15c32017-07-11 13:34:40 +00005314
5315/*
5316** A no-op routine that runs with the ".breakpoint" doc-command. This is
5317** a useful spot to set a debugger breakpoint.
5318*/
5319static void test_breakpoint(void){
5320 static int nCall = 0;
5321 nCall++;
5322}
5323
5324/*
5325** An object used to read a CSV and other files for import.
5326*/
5327typedef struct ImportCtx ImportCtx;
5328struct ImportCtx {
5329 const char *zFile; /* Name of the input file */
5330 FILE *in; /* Read the CSV text from this input stream */
drh97767842020-05-29 19:39:35 +00005331 int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */
drh2ce15c32017-07-11 13:34:40 +00005332 char *z; /* Accumulated text for a field */
5333 int n; /* Number of bytes in z */
5334 int nAlloc; /* Space allocated for z[] */
5335 int nLine; /* Current line number */
drhccb37812020-03-09 15:39:39 +00005336 int nRow; /* Number of rows imported */
5337 int nErr; /* Number of errors encountered */
drh2ce15c32017-07-11 13:34:40 +00005338 int bNotFirst; /* True if one or more bytes already read */
5339 int cTerm; /* Character that terminated the most recent field */
5340 int cColSep; /* The column separator character. (Usually ",") */
5341 int cRowSep; /* The row separator character. (Usually "\n") */
5342};
5343
drh97767842020-05-29 19:39:35 +00005344/* Clean up resourced used by an ImportCtx */
5345static void import_cleanup(ImportCtx *p){
drh42c2a042020-05-29 20:16:19 +00005346 if( p->in!=0 && p->xCloser!=0 ){
drh97767842020-05-29 19:39:35 +00005347 p->xCloser(p->in);
5348 p->in = 0;
5349 }
5350 sqlite3_free(p->z);
5351 p->z = 0;
5352}
5353
drh2ce15c32017-07-11 13:34:40 +00005354/* Append a single byte to z[] */
5355static void import_append_char(ImportCtx *p, int c){
5356 if( p->n+1>=p->nAlloc ){
5357 p->nAlloc += p->nAlloc + 100;
5358 p->z = sqlite3_realloc64(p->z, p->nAlloc);
drhe3e25652021-12-16 13:29:28 +00005359 shell_check_oom(p->z);
drh2ce15c32017-07-11 13:34:40 +00005360 }
5361 p->z[p->n++] = (char)c;
5362}
5363
5364/* Read a single field of CSV text. Compatible with rfc4180 and extended
5365** with the option of having a separator other than ",".
5366**
5367** + Input comes from p->in.
5368** + Store results in p->z of length p->n. Space to hold p->z comes
5369** from sqlite3_malloc64().
5370** + Use p->cSep as the column separator. The default is ",".
5371** + Use p->rSep as the row separator. The default is "\n".
5372** + Keep track of the line number in p->nLine.
5373** + Store the character that terminates the field in p->cTerm. Store
5374** EOF on end-of-file.
5375** + Report syntax errors on stderr
5376*/
5377static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
5378 int c;
5379 int cSep = p->cColSep;
5380 int rSep = p->cRowSep;
5381 p->n = 0;
5382 c = fgetc(p->in);
5383 if( c==EOF || seenInterrupt ){
5384 p->cTerm = EOF;
5385 return 0;
5386 }
5387 if( c=='"' ){
5388 int pc, ppc;
5389 int startLine = p->nLine;
5390 int cQuote = c;
5391 pc = ppc = 0;
5392 while( 1 ){
5393 c = fgetc(p->in);
5394 if( c==rSep ) p->nLine++;
5395 if( c==cQuote ){
5396 if( pc==cQuote ){
5397 pc = 0;
5398 continue;
5399 }
5400 }
5401 if( (c==cSep && pc==cQuote)
5402 || (c==rSep && pc==cQuote)
5403 || (c==rSep && pc=='\r' && ppc==cQuote)
5404 || (c==EOF && pc==cQuote)
5405 ){
5406 do{ p->n--; }while( p->z[p->n]!=cQuote );
5407 p->cTerm = c;
5408 break;
5409 }
5410 if( pc==cQuote && c!='\r' ){
5411 utf8_printf(stderr, "%s:%d: unescaped %c character\n",
5412 p->zFile, p->nLine, cQuote);
5413 }
5414 if( c==EOF ){
5415 utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
5416 p->zFile, startLine, cQuote);
5417 p->cTerm = c;
5418 break;
5419 }
5420 import_append_char(p, c);
5421 ppc = pc;
5422 pc = c;
5423 }
5424 }else{
5425 /* If this is the first field being parsed and it begins with the
5426 ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
5427 if( (c&0xff)==0xef && p->bNotFirst==0 ){
5428 import_append_char(p, c);
5429 c = fgetc(p->in);
5430 if( (c&0xff)==0xbb ){
5431 import_append_char(p, c);
5432 c = fgetc(p->in);
5433 if( (c&0xff)==0xbf ){
5434 p->bNotFirst = 1;
5435 p->n = 0;
5436 return csv_read_one_field(p);
5437 }
5438 }
5439 }
5440 while( c!=EOF && c!=cSep && c!=rSep ){
5441 import_append_char(p, c);
5442 c = fgetc(p->in);
5443 }
5444 if( c==rSep ){
5445 p->nLine++;
5446 if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
5447 }
5448 p->cTerm = c;
5449 }
5450 if( p->z ) p->z[p->n] = 0;
5451 p->bNotFirst = 1;
5452 return p->z;
5453}
5454
5455/* Read a single field of ASCII delimited text.
5456**
5457** + Input comes from p->in.
5458** + Store results in p->z of length p->n. Space to hold p->z comes
5459** from sqlite3_malloc64().
5460** + Use p->cSep as the column separator. The default is "\x1F".
5461** + Use p->rSep as the row separator. The default is "\x1E".
5462** + Keep track of the row number in p->nLine.
5463** + Store the character that terminates the field in p->cTerm. Store
5464** EOF on end-of-file.
5465** + Report syntax errors on stderr
5466*/
5467static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
5468 int c;
5469 int cSep = p->cColSep;
5470 int rSep = p->cRowSep;
5471 p->n = 0;
5472 c = fgetc(p->in);
5473 if( c==EOF || seenInterrupt ){
5474 p->cTerm = EOF;
5475 return 0;
5476 }
5477 while( c!=EOF && c!=cSep && c!=rSep ){
5478 import_append_char(p, c);
5479 c = fgetc(p->in);
5480 }
5481 if( c==rSep ){
5482 p->nLine++;
5483 }
5484 p->cTerm = c;
5485 if( p->z ) p->z[p->n] = 0;
5486 return p->z;
5487}
5488
5489/*
5490** Try to transfer data for table zTable. If an error is seen while
5491** moving forward, try to go backwards. The backwards movement won't
5492** work for WITHOUT ROWID tables.
5493*/
5494static void tryToCloneData(
5495 ShellState *p,
5496 sqlite3 *newDb,
5497 const char *zTable
5498){
5499 sqlite3_stmt *pQuery = 0;
5500 sqlite3_stmt *pInsert = 0;
5501 char *zQuery = 0;
5502 char *zInsert = 0;
5503 int rc;
5504 int i, j, n;
drhaf2770f2018-01-05 14:55:43 +00005505 int nTable = strlen30(zTable);
drh2ce15c32017-07-11 13:34:40 +00005506 int k = 0;
5507 int cnt = 0;
5508 const int spinRate = 10000;
5509
5510 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
drhe3e25652021-12-16 13:29:28 +00005511 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005512 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5513 if( rc ){
5514 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5515 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5516 zQuery);
5517 goto end_data_xfer;
5518 }
5519 n = sqlite3_column_count(pQuery);
5520 zInsert = sqlite3_malloc64(200 + nTable + n*3);
drhe3e25652021-12-16 13:29:28 +00005521 shell_check_oom(zInsert);
drh2ce15c32017-07-11 13:34:40 +00005522 sqlite3_snprintf(200+nTable,zInsert,
5523 "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
drhaf2770f2018-01-05 14:55:43 +00005524 i = strlen30(zInsert);
drh2ce15c32017-07-11 13:34:40 +00005525 for(j=1; j<n; j++){
5526 memcpy(zInsert+i, ",?", 2);
5527 i += 2;
5528 }
5529 memcpy(zInsert+i, ");", 3);
5530 rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
5531 if( rc ){
5532 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5533 sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
5534 zQuery);
5535 goto end_data_xfer;
5536 }
5537 for(k=0; k<2; k++){
5538 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5539 for(i=0; i<n; i++){
5540 switch( sqlite3_column_type(pQuery, i) ){
5541 case SQLITE_NULL: {
5542 sqlite3_bind_null(pInsert, i+1);
5543 break;
5544 }
5545 case SQLITE_INTEGER: {
5546 sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
5547 break;
5548 }
5549 case SQLITE_FLOAT: {
5550 sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
5551 break;
5552 }
5553 case SQLITE_TEXT: {
5554 sqlite3_bind_text(pInsert, i+1,
5555 (const char*)sqlite3_column_text(pQuery,i),
5556 -1, SQLITE_STATIC);
5557 break;
5558 }
5559 case SQLITE_BLOB: {
5560 sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
5561 sqlite3_column_bytes(pQuery,i),
5562 SQLITE_STATIC);
5563 break;
5564 }
5565 }
5566 } /* End for */
5567 rc = sqlite3_step(pInsert);
5568 if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
5569 utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
5570 sqlite3_errmsg(newDb));
5571 }
5572 sqlite3_reset(pInsert);
5573 cnt++;
5574 if( (cnt%spinRate)==0 ){
5575 printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
5576 fflush(stdout);
5577 }
5578 } /* End while */
5579 if( rc==SQLITE_DONE ) break;
5580 sqlite3_finalize(pQuery);
5581 sqlite3_free(zQuery);
5582 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
5583 zTable);
drhe3e25652021-12-16 13:29:28 +00005584 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005585 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5586 if( rc ){
5587 utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
5588 break;
5589 }
5590 } /* End for(k=0...) */
5591
5592end_data_xfer:
5593 sqlite3_finalize(pQuery);
5594 sqlite3_finalize(pInsert);
5595 sqlite3_free(zQuery);
5596 sqlite3_free(zInsert);
5597}
5598
5599
5600/*
5601** Try to transfer all rows of the schema that match zWhere. For
5602** each row, invoke xForEach() on the object defined by that row.
5603** If an error is encountered while moving forward through the
drh067b92b2020-06-19 15:24:12 +00005604** sqlite_schema table, try again moving backwards.
drh2ce15c32017-07-11 13:34:40 +00005605*/
5606static void tryToCloneSchema(
5607 ShellState *p,
5608 sqlite3 *newDb,
5609 const char *zWhere,
5610 void (*xForEach)(ShellState*,sqlite3*,const char*)
5611){
5612 sqlite3_stmt *pQuery = 0;
5613 char *zQuery = 0;
5614 int rc;
5615 const unsigned char *zName;
5616 const unsigned char *zSql;
5617 char *zErrMsg = 0;
5618
drh067b92b2020-06-19 15:24:12 +00005619 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005620 " WHERE %s", zWhere);
drhe3e25652021-12-16 13:29:28 +00005621 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005622 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5623 if( rc ){
5624 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5625 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5626 zQuery);
5627 goto end_schema_xfer;
5628 }
5629 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5630 zName = sqlite3_column_text(pQuery, 0);
5631 zSql = sqlite3_column_text(pQuery, 1);
drh621a5e02021-12-16 17:35:27 +00005632 if( zName==0 || zSql==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00005633 printf("%s... ", zName); fflush(stdout);
5634 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5635 if( zErrMsg ){
5636 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5637 sqlite3_free(zErrMsg);
5638 zErrMsg = 0;
5639 }
5640 if( xForEach ){
5641 xForEach(p, newDb, (const char*)zName);
5642 }
5643 printf("done\n");
5644 }
5645 if( rc!=SQLITE_DONE ){
5646 sqlite3_finalize(pQuery);
5647 sqlite3_free(zQuery);
drh067b92b2020-06-19 15:24:12 +00005648 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005649 " WHERE %s ORDER BY rowid DESC", zWhere);
drhe3e25652021-12-16 13:29:28 +00005650 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005651 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5652 if( rc ){
5653 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5654 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5655 zQuery);
5656 goto end_schema_xfer;
5657 }
drh76fc88f2021-10-02 16:39:16 +00005658 while( sqlite3_step(pQuery)==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00005659 zName = sqlite3_column_text(pQuery, 0);
5660 zSql = sqlite3_column_text(pQuery, 1);
drh621a5e02021-12-16 17:35:27 +00005661 if( zName==0 || zSql==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00005662 printf("%s... ", zName); fflush(stdout);
5663 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5664 if( zErrMsg ){
5665 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5666 sqlite3_free(zErrMsg);
5667 zErrMsg = 0;
5668 }
5669 if( xForEach ){
5670 xForEach(p, newDb, (const char*)zName);
5671 }
5672 printf("done\n");
5673 }
5674 }
5675end_schema_xfer:
5676 sqlite3_finalize(pQuery);
5677 sqlite3_free(zQuery);
5678}
5679
5680/*
5681** Open a new database file named "zNewDb". Try to recover as much information
5682** as possible out of the main database (which might be corrupt) and write it
5683** into zNewDb.
5684*/
5685static void tryToClone(ShellState *p, const char *zNewDb){
5686 int rc;
5687 sqlite3 *newDb = 0;
5688 if( access(zNewDb,0)==0 ){
5689 utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
5690 return;
5691 }
5692 rc = sqlite3_open(zNewDb, &newDb);
5693 if( rc ){
5694 utf8_printf(stderr, "Cannot create output database: %s\n",
5695 sqlite3_errmsg(newDb));
5696 }else{
5697 sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
5698 sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
5699 tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
5700 tryToCloneSchema(p, newDb, "type!='table'", 0);
5701 sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
5702 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
5703 }
drh9e804032018-05-18 17:11:50 +00005704 close_db(newDb);
drh2ce15c32017-07-11 13:34:40 +00005705}
5706
5707/*
drh13c20932018-01-10 21:41:55 +00005708** Change the output file back to stdout.
5709**
5710** If the p->doXdgOpen flag is set, that means the output was being
5711** redirected to a temporary file named by p->zTempFile. In that case,
5712** launch start/open/xdg-open on that temporary file.
drh2ce15c32017-07-11 13:34:40 +00005713*/
5714static void output_reset(ShellState *p){
5715 if( p->outfile[0]=='|' ){
5716#ifndef SQLITE_OMIT_POPEN
5717 pclose(p->out);
5718#endif
5719 }else{
5720 output_file_close(p->out);
drh04a28c32018-01-31 01:38:44 +00005721#ifndef SQLITE_NOHAVE_SYSTEM
drh13c20932018-01-10 21:41:55 +00005722 if( p->doXdgOpen ){
5723 const char *zXdgOpenCmd =
5724#if defined(_WIN32)
5725 "start";
5726#elif defined(__APPLE__)
5727 "open";
5728#else
5729 "xdg-open";
5730#endif
5731 char *zCmd;
5732 zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
drha92a01a2018-01-10 22:15:37 +00005733 if( system(zCmd) ){
5734 utf8_printf(stderr, "Failed: [%s]\n", zCmd);
drh1d9ea272020-04-17 23:46:54 +00005735 }else{
5736 /* Give the start/open/xdg-open command some time to get
5737 ** going before we continue, and potential delete the
5738 ** p->zTempFile data file out from under it */
5739 sqlite3_sleep(2000);
drha92a01a2018-01-10 22:15:37 +00005740 }
drh13c20932018-01-10 21:41:55 +00005741 sqlite3_free(zCmd);
drh3c484e82018-01-10 22:27:21 +00005742 outputModePop(p);
drh13c20932018-01-10 21:41:55 +00005743 p->doXdgOpen = 0;
5744 }
drh04a28c32018-01-31 01:38:44 +00005745#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
drh2ce15c32017-07-11 13:34:40 +00005746 }
5747 p->outfile[0] = 0;
5748 p->out = stdout;
5749}
5750
5751/*
5752** Run an SQL command and return the single integer result.
5753*/
larrybr58a53d62022-02-10 03:21:48 +00005754static int db_int(sqlite3 *db, const char *zSql){
drh2ce15c32017-07-11 13:34:40 +00005755 sqlite3_stmt *pStmt;
5756 int res = 0;
larrybr58a53d62022-02-10 03:21:48 +00005757 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
drh2ce15c32017-07-11 13:34:40 +00005758 if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
5759 res = sqlite3_column_int(pStmt,0);
5760 }
5761 sqlite3_finalize(pStmt);
5762 return res;
5763}
5764
5765/*
5766** Convert a 2-byte or 4-byte big-endian integer into a native integer
5767*/
5768static unsigned int get2byteInt(unsigned char *a){
5769 return (a[0]<<8) + a[1];
5770}
5771static unsigned int get4byteInt(unsigned char *a){
5772 return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
5773}
5774
5775/*
drh76c12062020-01-14 13:13:19 +00005776** Implementation of the ".dbinfo" command.
drh2ce15c32017-07-11 13:34:40 +00005777**
5778** Return 1 on error, 2 to exit, and 0 otherwise.
5779*/
5780static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
5781 static const struct { const char *zName; int ofst; } aField[] = {
5782 { "file change counter:", 24 },
5783 { "database page count:", 28 },
5784 { "freelist page count:", 36 },
5785 { "schema cookie:", 40 },
5786 { "schema format:", 44 },
5787 { "default cache size:", 48 },
5788 { "autovacuum top root:", 52 },
5789 { "incremental vacuum:", 64 },
5790 { "text encoding:", 56 },
5791 { "user version:", 60 },
5792 { "application id:", 68 },
5793 { "software version:", 96 },
5794 };
5795 static const struct { const char *zName; const char *zSql; } aQuery[] = {
5796 { "number of tables:",
5797 "SELECT count(*) FROM %s WHERE type='table'" },
5798 { "number of indexes:",
5799 "SELECT count(*) FROM %s WHERE type='index'" },
5800 { "number of triggers:",
5801 "SELECT count(*) FROM %s WHERE type='trigger'" },
5802 { "number of views:",
5803 "SELECT count(*) FROM %s WHERE type='view'" },
5804 { "schema size:",
5805 "SELECT total(length(sql)) FROM %s" },
5806 };
drh87c889c2019-03-20 18:22:51 +00005807 int i, rc;
drhea99a312018-07-18 19:09:07 +00005808 unsigned iDataVersion;
drh2ce15c32017-07-11 13:34:40 +00005809 char *zSchemaTab;
5810 char *zDb = nArg>=2 ? azArg[1] : "main";
drh512e6c32017-10-11 17:51:08 +00005811 sqlite3_stmt *pStmt = 0;
drh2ce15c32017-07-11 13:34:40 +00005812 unsigned char aHdr[100];
5813 open_db(p, 0);
5814 if( p->db==0 ) return 1;
drh87c889c2019-03-20 18:22:51 +00005815 rc = sqlite3_prepare_v2(p->db,
5816 "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
5817 -1, &pStmt, 0);
5818 if( rc ){
drh451f89a2020-04-28 23:09:56 +00005819 utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
drh87c889c2019-03-20 18:22:51 +00005820 sqlite3_finalize(pStmt);
5821 return 1;
5822 }
drh512e6c32017-10-11 17:51:08 +00005823 sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
5824 if( sqlite3_step(pStmt)==SQLITE_ROW
5825 && sqlite3_column_bytes(pStmt,0)>100
5826 ){
5827 memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
5828 sqlite3_finalize(pStmt);
5829 }else{
drh2ce15c32017-07-11 13:34:40 +00005830 raw_printf(stderr, "unable to read database header\n");
drh512e6c32017-10-11 17:51:08 +00005831 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00005832 return 1;
5833 }
5834 i = get2byteInt(aHdr+16);
5835 if( i==1 ) i = 65536;
5836 utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
5837 utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
5838 utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
5839 utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
5840 for(i=0; i<ArraySize(aField); i++){
5841 int ofst = aField[i].ofst;
5842 unsigned int val = get4byteInt(aHdr + ofst);
5843 utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
5844 switch( ofst ){
5845 case 56: {
5846 if( val==1 ) raw_printf(p->out, " (utf8)");
5847 if( val==2 ) raw_printf(p->out, " (utf16le)");
5848 if( val==3 ) raw_printf(p->out, " (utf16be)");
5849 }
5850 }
5851 raw_printf(p->out, "\n");
5852 }
5853 if( zDb==0 ){
drh067b92b2020-06-19 15:24:12 +00005854 zSchemaTab = sqlite3_mprintf("main.sqlite_schema");
drh2ce15c32017-07-11 13:34:40 +00005855 }else if( strcmp(zDb,"temp")==0 ){
drh067b92b2020-06-19 15:24:12 +00005856 zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
drh2ce15c32017-07-11 13:34:40 +00005857 }else{
drh067b92b2020-06-19 15:24:12 +00005858 zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
drh2ce15c32017-07-11 13:34:40 +00005859 }
5860 for(i=0; i<ArraySize(aQuery); i++){
5861 char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
larrybr58a53d62022-02-10 03:21:48 +00005862 int val = db_int(p->db, zSql);
drh2ce15c32017-07-11 13:34:40 +00005863 sqlite3_free(zSql);
5864 utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
5865 }
5866 sqlite3_free(zSchemaTab);
drhea99a312018-07-18 19:09:07 +00005867 sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
5868 utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
drh2ce15c32017-07-11 13:34:40 +00005869 return 0;
5870}
5871
5872/*
5873** Print the current sqlite3_errmsg() value to stderr and return 1.
5874*/
5875static int shellDatabaseError(sqlite3 *db){
5876 const char *zErr = sqlite3_errmsg(db);
5877 utf8_printf(stderr, "Error: %s\n", zErr);
5878 return 1;
5879}
5880
5881/*
drh2ce15c32017-07-11 13:34:40 +00005882** Compare the pattern in zGlob[] against the text in z[]. Return TRUE
5883** if they match and FALSE (0) if they do not match.
5884**
5885** Globbing rules:
5886**
5887** '*' Matches any sequence of zero or more characters.
5888**
5889** '?' Matches exactly one character.
5890**
5891** [...] Matches one character from the enclosed list of
5892** characters.
5893**
5894** [^...] Matches one character not in the enclosed list.
5895**
5896** '#' Matches any sequence of one or more digits with an
5897** optional + or - sign in front
5898**
5899** ' ' Any span of whitespace matches any other span of
5900** whitespace.
5901**
5902** Extra whitespace at the end of z[] is ignored.
5903*/
5904static int testcase_glob(const char *zGlob, const char *z){
5905 int c, c2;
5906 int invert;
5907 int seen;
5908
5909 while( (c = (*(zGlob++)))!=0 ){
5910 if( IsSpace(c) ){
5911 if( !IsSpace(*z) ) return 0;
5912 while( IsSpace(*zGlob) ) zGlob++;
5913 while( IsSpace(*z) ) z++;
5914 }else if( c=='*' ){
5915 while( (c=(*(zGlob++))) == '*' || c=='?' ){
5916 if( c=='?' && (*(z++))==0 ) return 0;
5917 }
5918 if( c==0 ){
5919 return 1;
5920 }else if( c=='[' ){
5921 while( *z && testcase_glob(zGlob-1,z)==0 ){
5922 z++;
5923 }
5924 return (*z)!=0;
5925 }
5926 while( (c2 = (*(z++)))!=0 ){
5927 while( c2!=c ){
5928 c2 = *(z++);
5929 if( c2==0 ) return 0;
5930 }
5931 if( testcase_glob(zGlob,z) ) return 1;
5932 }
5933 return 0;
5934 }else if( c=='?' ){
5935 if( (*(z++))==0 ) return 0;
5936 }else if( c=='[' ){
5937 int prior_c = 0;
5938 seen = 0;
5939 invert = 0;
5940 c = *(z++);
5941 if( c==0 ) return 0;
5942 c2 = *(zGlob++);
5943 if( c2=='^' ){
5944 invert = 1;
5945 c2 = *(zGlob++);
5946 }
5947 if( c2==']' ){
5948 if( c==']' ) seen = 1;
5949 c2 = *(zGlob++);
5950 }
5951 while( c2 && c2!=']' ){
5952 if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
5953 c2 = *(zGlob++);
5954 if( c>=prior_c && c<=c2 ) seen = 1;
5955 prior_c = 0;
5956 }else{
5957 if( c==c2 ){
5958 seen = 1;
5959 }
5960 prior_c = c2;
5961 }
5962 c2 = *(zGlob++);
5963 }
5964 if( c2==0 || (seen ^ invert)==0 ) return 0;
5965 }else if( c=='#' ){
5966 if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++;
5967 if( !IsDigit(z[0]) ) return 0;
5968 z++;
5969 while( IsDigit(z[0]) ){ z++; }
5970 }else{
5971 if( c!=(*(z++)) ) return 0;
5972 }
5973 }
5974 while( IsSpace(*z) ){ z++; }
5975 return *z==0;
5976}
5977
5978
5979/*
5980** Compare the string as a command-line option with either one or two
5981** initial "-" characters.
5982*/
5983static int optionMatch(const char *zStr, const char *zOpt){
5984 if( zStr[0]!='-' ) return 0;
5985 zStr++;
5986 if( zStr[0]=='-' ) zStr++;
5987 return strcmp(zStr, zOpt)==0;
5988}
5989
5990/*
5991** Delete a file.
5992*/
5993int shellDeleteFile(const char *zFilename){
5994 int rc;
5995#ifdef _WIN32
5996 wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
5997 rc = _wunlink(z);
5998 sqlite3_free(z);
5999#else
6000 rc = unlink(zFilename);
6001#endif
6002 return rc;
6003}
6004
drh13c20932018-01-10 21:41:55 +00006005/*
6006** Try to delete the temporary file (if there is one) and free the
6007** memory used to hold the name of the temp file.
6008*/
6009static void clearTempFile(ShellState *p){
6010 if( p->zTempFile==0 ) return;
drh536c3452018-01-11 00:38:39 +00006011 if( p->doXdgOpen ) return;
drh13c20932018-01-10 21:41:55 +00006012 if( shellDeleteFile(p->zTempFile) ) return;
6013 sqlite3_free(p->zTempFile);
6014 p->zTempFile = 0;
6015}
6016
6017/*
6018** Create a new temp file name with the given suffix.
6019*/
6020static void newTempFile(ShellState *p, const char *zSuffix){
6021 clearTempFile(p);
6022 sqlite3_free(p->zTempFile);
6023 p->zTempFile = 0;
drh7f3bf8a2018-01-10 21:50:08 +00006024 if( p->db ){
6025 sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
6026 }
drh13c20932018-01-10 21:41:55 +00006027 if( p->zTempFile==0 ){
drh1d9ea272020-04-17 23:46:54 +00006028 /* If p->db is an in-memory database then the TEMPFILENAME file-control
6029 ** will not work and we will need to fallback to guessing */
6030 char *zTemp;
drh13c20932018-01-10 21:41:55 +00006031 sqlite3_uint64 r;
6032 sqlite3_randomness(sizeof(r), &r);
drh1d9ea272020-04-17 23:46:54 +00006033 zTemp = getenv("TEMP");
6034 if( zTemp==0 ) zTemp = getenv("TMP");
6035 if( zTemp==0 ){
6036#ifdef _WIN32
6037 zTemp = "\\tmp";
6038#else
6039 zTemp = "/tmp";
6040#endif
6041 }
6042 p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix);
drh13c20932018-01-10 21:41:55 +00006043 }else{
6044 p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
6045 }
drhe3e25652021-12-16 13:29:28 +00006046 shell_check_oom(p->zTempFile);
drh13c20932018-01-10 21:41:55 +00006047}
6048
drh2ce15c32017-07-11 13:34:40 +00006049
6050/*
6051** The implementation of SQL scalar function fkey_collate_clause(), used
6052** by the ".lint fkey-indexes" command. This scalar function is always
6053** called with four arguments - the parent table name, the parent column name,
6054** the child table name and the child column name.
6055**
6056** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
6057**
6058** If either of the named tables or columns do not exist, this function
6059** returns an empty string. An empty string is also returned if both tables
6060** and columns exist but have the same default collation sequence. Or,
6061** if both exist but the default collation sequences are different, this
6062** function returns the string " COLLATE <parent-collation>", where
6063** <parent-collation> is the default collation sequence of the parent column.
6064*/
6065static void shellFkeyCollateClause(
6066 sqlite3_context *pCtx,
6067 int nVal,
6068 sqlite3_value **apVal
6069){
6070 sqlite3 *db = sqlite3_context_db_handle(pCtx);
6071 const char *zParent;
6072 const char *zParentCol;
6073 const char *zParentSeq;
6074 const char *zChild;
6075 const char *zChildCol;
6076 const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */
6077 int rc;
6078
6079 assert( nVal==4 );
6080 zParent = (const char*)sqlite3_value_text(apVal[0]);
6081 zParentCol = (const char*)sqlite3_value_text(apVal[1]);
6082 zChild = (const char*)sqlite3_value_text(apVal[2]);
6083 zChildCol = (const char*)sqlite3_value_text(apVal[3]);
6084
6085 sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
6086 rc = sqlite3_table_column_metadata(
6087 db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0
6088 );
6089 if( rc==SQLITE_OK ){
6090 rc = sqlite3_table_column_metadata(
6091 db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0
6092 );
6093 }
6094
6095 if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){
6096 char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq);
6097 sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
6098 sqlite3_free(z);
6099 }
6100}
6101
6102
6103/*
6104** The implementation of dot-command ".lint fkey-indexes".
6105*/
6106static int lintFkeyIndexes(
6107 ShellState *pState, /* Current shell tool state */
6108 char **azArg, /* Array of arguments passed to dot command */
6109 int nArg /* Number of entries in azArg[] */
6110){
6111 sqlite3 *db = pState->db; /* Database handle to query "main" db of */
6112 FILE *out = pState->out; /* Stream to write non-error output to */
6113 int bVerbose = 0; /* If -verbose is present */
6114 int bGroupByParent = 0; /* If -groupbyparent is present */
6115 int i; /* To iterate through azArg[] */
6116 const char *zIndent = ""; /* How much to indent CREATE INDEX by */
6117 int rc; /* Return code */
6118 sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */
6119
6120 /*
6121 ** This SELECT statement returns one row for each foreign key constraint
6122 ** in the schema of the main database. The column values are:
6123 **
6124 ** 0. The text of an SQL statement similar to:
6125 **
danf9679312017-12-01 18:40:18 +00006126 ** "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?"
drh2ce15c32017-07-11 13:34:40 +00006127 **
danf9679312017-12-01 18:40:18 +00006128 ** This SELECT is similar to the one that the foreign keys implementation
6129 ** needs to run internally on child tables. If there is an index that can
drh2ce15c32017-07-11 13:34:40 +00006130 ** be used to optimize this query, then it can also be used by the FK
6131 ** implementation to optimize DELETE or UPDATE statements on the parent
6132 ** table.
6133 **
6134 ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by
6135 ** the EXPLAIN QUERY PLAN command matches this pattern, then the schema
6136 ** contains an index that can be used to optimize the query.
6137 **
6138 ** 2. Human readable text that describes the child table and columns. e.g.
6139 **
6140 ** "child_table(child_key1, child_key2)"
6141 **
6142 ** 3. Human readable text that describes the parent table and columns. e.g.
6143 **
6144 ** "parent_table(parent_key1, parent_key2)"
6145 **
6146 ** 4. A full CREATE INDEX statement for an index that could be used to
6147 ** optimize DELETE or UPDATE statements on the parent table. e.g.
6148 **
6149 ** "CREATE INDEX child_table_child_key ON child_table(child_key)"
6150 **
6151 ** 5. The name of the parent table.
6152 **
6153 ** These six values are used by the C logic below to generate the report.
6154 */
6155 const char *zSql =
6156 "SELECT "
danf9679312017-12-01 18:40:18 +00006157 " 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
drh2ce15c32017-07-11 13:34:40 +00006158 " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
6159 " || fkey_collate_clause("
6160 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
6161 ", "
drh82102332021-03-20 15:11:29 +00006162 " 'SEARCH ' || s.name || ' USING COVERING INDEX*('"
drh2ce15c32017-07-11 13:34:40 +00006163 " || group_concat('*=?', ' AND ') || ')'"
6164 ", "
6165 " s.name || '(' || group_concat(f.[from], ', ') || ')'"
6166 ", "
6167 " f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
6168 ", "
6169 " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
6170 " || ' ON ' || quote(s.name) || '('"
6171 " || group_concat(quote(f.[from]) ||"
6172 " fkey_collate_clause("
6173 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
6174 " || ');'"
6175 ", "
6176 " f.[table] "
drh067b92b2020-06-19 15:24:12 +00006177 "FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f "
drh2ce15c32017-07-11 13:34:40 +00006178 "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
6179 "GROUP BY s.name, f.id "
6180 "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
6181 ;
drh82102332021-03-20 15:11:29 +00006182 const char *zGlobIPK = "SEARCH * USING INTEGER PRIMARY KEY (rowid=?)";
drh2ce15c32017-07-11 13:34:40 +00006183
6184 for(i=2; i<nArg; i++){
drhaf2770f2018-01-05 14:55:43 +00006185 int n = strlen30(azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00006186 if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
6187 bVerbose = 1;
6188 }
6189 else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
6190 bGroupByParent = 1;
6191 zIndent = " ";
6192 }
6193 else{
6194 raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
6195 azArg[0], azArg[1]
6196 );
6197 return SQLITE_ERROR;
6198 }
6199 }
6200
6201 /* Register the fkey_collate_clause() SQL function */
6202 rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
6203 0, shellFkeyCollateClause, 0, 0
6204 );
6205
6206
6207 if( rc==SQLITE_OK ){
6208 rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
6209 }
6210 if( rc==SQLITE_OK ){
6211 sqlite3_bind_int(pSql, 1, bGroupByParent);
6212 }
6213
6214 if( rc==SQLITE_OK ){
6215 int rc2;
6216 char *zPrev = 0;
6217 while( SQLITE_ROW==sqlite3_step(pSql) ){
6218 int res = -1;
6219 sqlite3_stmt *pExplain = 0;
6220 const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
6221 const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
6222 const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
6223 const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
6224 const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
6225 const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
6226
drh621a5e02021-12-16 17:35:27 +00006227 if( zEQP==0 ) continue;
6228 if( zGlob==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00006229 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
6230 if( rc!=SQLITE_OK ) break;
6231 if( SQLITE_ROW==sqlite3_step(pExplain) ){
6232 const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
drh621a5e02021-12-16 17:35:27 +00006233 res = zPlan!=0 && ( 0==sqlite3_strglob(zGlob, zPlan)
6234 || 0==sqlite3_strglob(zGlobIPK, zPlan));
drh2ce15c32017-07-11 13:34:40 +00006235 }
6236 rc = sqlite3_finalize(pExplain);
6237 if( rc!=SQLITE_OK ) break;
6238
6239 if( res<0 ){
6240 raw_printf(stderr, "Error: internal error");
6241 break;
6242 }else{
6243 if( bGroupByParent
6244 && (bVerbose || res==0)
6245 && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
6246 ){
6247 raw_printf(out, "-- Parent table %s\n", zParent);
6248 sqlite3_free(zPrev);
6249 zPrev = sqlite3_mprintf("%s", zParent);
6250 }
6251
6252 if( res==0 ){
6253 raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
6254 }else if( bVerbose ){
6255 raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
6256 zIndent, zFrom, zTarget
6257 );
6258 }
6259 }
6260 }
6261 sqlite3_free(zPrev);
6262
6263 if( rc!=SQLITE_OK ){
6264 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
6265 }
6266
6267 rc2 = sqlite3_finalize(pSql);
6268 if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
6269 rc = rc2;
6270 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
6271 }
6272 }else{
6273 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
6274 }
6275
6276 return rc;
6277}
6278
6279/*
6280** Implementation of ".lint" dot command.
6281*/
6282static int lintDotCommand(
6283 ShellState *pState, /* Current shell tool state */
6284 char **azArg, /* Array of arguments passed to dot command */
6285 int nArg /* Number of entries in azArg[] */
6286){
6287 int n;
drhaf2770f2018-01-05 14:55:43 +00006288 n = (nArg>=2 ? strlen30(azArg[1]) : 0);
drh2ce15c32017-07-11 13:34:40 +00006289 if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
6290 return lintFkeyIndexes(pState, azArg, nArg);
6291
6292 usage:
6293 raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
6294 raw_printf(stderr, "Where sub-commands are:\n");
6295 raw_printf(stderr, " fkey-indexes\n");
6296 return SQLITE_ERROR;
6297}
6298
dan1b162162019-04-27 20:15:15 +00006299#if !defined SQLITE_OMIT_VIRTUALTABLE
danfd0245d2017-12-07 15:44:29 +00006300static void shellPrepare(
dand4b56e52017-12-12 20:04:59 +00006301 sqlite3 *db,
danfd0245d2017-12-07 15:44:29 +00006302 int *pRc,
6303 const char *zSql,
6304 sqlite3_stmt **ppStmt
6305){
6306 *ppStmt = 0;
6307 if( *pRc==SQLITE_OK ){
dand4b56e52017-12-12 20:04:59 +00006308 int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
danfd0245d2017-12-07 15:44:29 +00006309 if( rc!=SQLITE_OK ){
6310 raw_printf(stderr, "sql error: %s (%d)\n",
dand4b56e52017-12-12 20:04:59 +00006311 sqlite3_errmsg(db), sqlite3_errcode(db)
danfd0245d2017-12-07 15:44:29 +00006312 );
6313 *pRc = rc;
6314 }
6315 }
6316}
6317
drh9546c762019-05-10 17:50:33 +00006318/*
6319** Create a prepared statement using printf-style arguments for the SQL.
6320**
6321** This routine is could be marked "static". But it is not always used,
6322** depending on compile-time options. By omitting the "static", we avoid
6323** nuisance compiler warnings about "defined but not used".
6324*/
6325void shellPreparePrintf(
dan3f67ddf2017-12-13 20:04:53 +00006326 sqlite3 *db,
6327 int *pRc,
danac15e2d2017-12-14 19:15:07 +00006328 sqlite3_stmt **ppStmt,
6329 const char *zFmt,
6330 ...
dan3f67ddf2017-12-13 20:04:53 +00006331){
danac15e2d2017-12-14 19:15:07 +00006332 *ppStmt = 0;
6333 if( *pRc==SQLITE_OK ){
6334 va_list ap;
6335 char *z;
6336 va_start(ap, zFmt);
6337 z = sqlite3_vmprintf(zFmt, ap);
drh1dbb1472018-10-11 10:37:24 +00006338 va_end(ap);
dan3f67ddf2017-12-13 20:04:53 +00006339 if( z==0 ){
6340 *pRc = SQLITE_NOMEM;
6341 }else{
6342 shellPrepare(db, pRc, z, ppStmt);
6343 sqlite3_free(z);
6344 }
dan3f67ddf2017-12-13 20:04:53 +00006345 }
6346}
6347
drh9546c762019-05-10 17:50:33 +00006348/* Finalize the prepared statement created using shellPreparePrintf().
6349**
6350** This routine is could be marked "static". But it is not always used,
6351** depending on compile-time options. By omitting the "static", we avoid
6352** nuisance compiler warnings about "defined but not used".
6353*/
6354void shellFinalize(
danfd0245d2017-12-07 15:44:29 +00006355 int *pRc,
6356 sqlite3_stmt *pStmt
6357){
dan25c12182017-12-07 21:03:33 +00006358 if( pStmt ){
6359 sqlite3 *db = sqlite3_db_handle(pStmt);
6360 int rc = sqlite3_finalize(pStmt);
6361 if( *pRc==SQLITE_OK ){
6362 if( rc!=SQLITE_OK ){
6363 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
6364 }
6365 *pRc = rc;
6366 }
6367 }
danfd0245d2017-12-07 15:44:29 +00006368}
6369
drh9546c762019-05-10 17:50:33 +00006370/* Reset the prepared statement created using shellPreparePrintf().
6371**
6372** This routine is could be marked "static". But it is not always used,
6373** depending on compile-time options. By omitting the "static", we avoid
6374** nuisance compiler warnings about "defined but not used".
6375*/
6376void shellReset(
danfd0245d2017-12-07 15:44:29 +00006377 int *pRc,
6378 sqlite3_stmt *pStmt
6379){
6380 int rc = sqlite3_reset(pStmt);
dan5a78b812017-12-27 18:54:11 +00006381 if( *pRc==SQLITE_OK ){
6382 if( rc!=SQLITE_OK ){
6383 sqlite3 *db = sqlite3_db_handle(pStmt);
6384 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
6385 }
6386 *pRc = rc;
6387 }
danfd0245d2017-12-07 15:44:29 +00006388}
dan1b162162019-04-27 20:15:15 +00006389#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
6390
6391#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drhe2754c12019-08-26 12:50:01 +00006392/******************************************************************************
dan1b162162019-04-27 20:15:15 +00006393** The ".archive" or ".ar" command.
6394*/
drhe37c0e12018-01-06 19:19:50 +00006395/*
dan88be0202017-12-09 17:58:02 +00006396** Structure representing a single ".ar" command.
6397*/
6398typedef struct ArCommand ArCommand;
6399struct ArCommand {
drhb376b3d2018-01-10 13:11:51 +00006400 u8 eCmd; /* An AR_CMD_* value */
6401 u8 bVerbose; /* True if --verbose */
drha5676c42018-01-10 15:17:34 +00006402 u8 bZip; /* True if the archive is a ZIP */
drhb376b3d2018-01-10 13:11:51 +00006403 u8 bDryRun; /* True if --dry-run */
drha5676c42018-01-10 15:17:34 +00006404 u8 bAppend; /* True if --append */
larrybr8f09f4b2021-11-02 00:18:11 +00006405 u8 bGlob; /* True if --glob */
drhd0f9cdc2018-05-17 14:09:06 +00006406 u8 fromCmdLine; /* Run from -A instead of .archive */
drhb376b3d2018-01-10 13:11:51 +00006407 int nArg; /* Number of command arguments */
drha5676c42018-01-10 15:17:34 +00006408 char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
dan88be0202017-12-09 17:58:02 +00006409 const char *zFile; /* --file argument, or NULL */
6410 const char *zDir; /* --directory argument, or NULL */
dan88be0202017-12-09 17:58:02 +00006411 char **azArg; /* Array of command arguments */
drhb376b3d2018-01-10 13:11:51 +00006412 ShellState *p; /* Shell state */
6413 sqlite3 *db; /* Database containing the archive */
dan88be0202017-12-09 17:58:02 +00006414};
6415
6416/*
6417** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
6418*/
dan0d0547f2017-12-14 15:40:42 +00006419static int arUsage(FILE *f){
drh98aa2ab2018-09-26 16:53:51 +00006420 showHelp(f,"archive");
dan0d0547f2017-12-14 15:40:42 +00006421 return SQLITE_ERROR;
6422}
6423
6424/*
6425** Print an error message for the .ar command to stderr and return
6426** SQLITE_ERROR.
6427*/
drhd0f9cdc2018-05-17 14:09:06 +00006428static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
dan0d0547f2017-12-14 15:40:42 +00006429 va_list ap;
6430 char *z;
6431 va_start(ap, zFmt);
6432 z = sqlite3_vmprintf(zFmt, ap);
6433 va_end(ap);
drhd0f9cdc2018-05-17 14:09:06 +00006434 utf8_printf(stderr, "Error: %s\n", z);
6435 if( pAr->fromCmdLine ){
6436 utf8_printf(stderr, "Use \"-A\" for more help\n");
6437 }else{
6438 utf8_printf(stderr, "Use \".archive --help\" for more help\n");
6439 }
dan0d0547f2017-12-14 15:40:42 +00006440 sqlite3_free(z);
dan88be0202017-12-09 17:58:02 +00006441 return SQLITE_ERROR;
6442}
6443
6444/*
6445** Values for ArCommand.eCmd.
6446*/
dand4b56e52017-12-12 20:04:59 +00006447#define AR_CMD_CREATE 1
drhb17ea912019-03-25 14:24:19 +00006448#define AR_CMD_UPDATE 2
6449#define AR_CMD_INSERT 3
6450#define AR_CMD_EXTRACT 4
6451#define AR_CMD_LIST 5
6452#define AR_CMD_HELP 6
larrybr47061b92021-11-01 17:22:52 +00006453#define AR_CMD_REMOVE 7
dand4b56e52017-12-12 20:04:59 +00006454
6455/*
6456** Other (non-command) switches.
6457*/
larrybr47061b92021-11-01 17:22:52 +00006458#define AR_SWITCH_VERBOSE 8
6459#define AR_SWITCH_FILE 9
6460#define AR_SWITCH_DIRECTORY 10
6461#define AR_SWITCH_APPEND 11
larrybr719506f2021-11-01 22:33:20 +00006462#define AR_SWITCH_DRYRUN 12
larrybr8f09f4b2021-11-02 00:18:11 +00006463#define AR_SWITCH_GLOB 13
dand4b56e52017-12-12 20:04:59 +00006464
6465static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
6466 switch( eSwitch ){
6467 case AR_CMD_CREATE:
6468 case AR_CMD_EXTRACT:
6469 case AR_CMD_LIST:
larrybr47061b92021-11-01 17:22:52 +00006470 case AR_CMD_REMOVE:
dand4b56e52017-12-12 20:04:59 +00006471 case AR_CMD_UPDATE:
drhb17ea912019-03-25 14:24:19 +00006472 case AR_CMD_INSERT:
dan0d0547f2017-12-14 15:40:42 +00006473 case AR_CMD_HELP:
6474 if( pAr->eCmd ){
drhd0f9cdc2018-05-17 14:09:06 +00006475 return arErrorMsg(pAr, "multiple command options");
dan0d0547f2017-12-14 15:40:42 +00006476 }
dand4b56e52017-12-12 20:04:59 +00006477 pAr->eCmd = eSwitch;
6478 break;
6479
drhb376b3d2018-01-10 13:11:51 +00006480 case AR_SWITCH_DRYRUN:
6481 pAr->bDryRun = 1;
6482 break;
larrybr8f09f4b2021-11-02 00:18:11 +00006483 case AR_SWITCH_GLOB:
6484 pAr->bGlob = 1;
6485 break;
dand4b56e52017-12-12 20:04:59 +00006486 case AR_SWITCH_VERBOSE:
6487 pAr->bVerbose = 1;
6488 break;
drha5676c42018-01-10 15:17:34 +00006489 case AR_SWITCH_APPEND:
6490 pAr->bAppend = 1;
drhca7733b2018-01-10 18:09:20 +00006491 /* Fall thru into --file */
dand4b56e52017-12-12 20:04:59 +00006492 case AR_SWITCH_FILE:
6493 pAr->zFile = zArg;
6494 break;
6495 case AR_SWITCH_DIRECTORY:
6496 pAr->zDir = zArg;
6497 break;
6498 }
6499
6500 return SQLITE_OK;
6501}
dan88be0202017-12-09 17:58:02 +00006502
6503/*
6504** Parse the command line for an ".ar" command. The results are written into
6505** structure (*pAr). SQLITE_OK is returned if the command line is parsed
6506** successfully, otherwise an error message is written to stderr and
6507** SQLITE_ERROR returned.
6508*/
6509static int arParseCommand(
6510 char **azArg, /* Array of arguments passed to dot command */
6511 int nArg, /* Number of entries in azArg[] */
6512 ArCommand *pAr /* Populate this object */
6513){
dand4b56e52017-12-12 20:04:59 +00006514 struct ArSwitch {
dand4b56e52017-12-12 20:04:59 +00006515 const char *zLong;
drhb376b3d2018-01-10 13:11:51 +00006516 char cShort;
6517 u8 eSwitch;
6518 u8 bArg;
dand4b56e52017-12-12 20:04:59 +00006519 } aSwitch[] = {
drhb376b3d2018-01-10 13:11:51 +00006520 { "create", 'c', AR_CMD_CREATE, 0 },
6521 { "extract", 'x', AR_CMD_EXTRACT, 0 },
drhb17ea912019-03-25 14:24:19 +00006522 { "insert", 'i', AR_CMD_INSERT, 0 },
drhb376b3d2018-01-10 13:11:51 +00006523 { "list", 't', AR_CMD_LIST, 0 },
larrybr47061b92021-11-01 17:22:52 +00006524 { "remove", 'r', AR_CMD_REMOVE, 0 },
drhb376b3d2018-01-10 13:11:51 +00006525 { "update", 'u', AR_CMD_UPDATE, 0 },
6526 { "help", 'h', AR_CMD_HELP, 0 },
6527 { "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
6528 { "file", 'f', AR_SWITCH_FILE, 1 },
drhca7733b2018-01-10 18:09:20 +00006529 { "append", 'a', AR_SWITCH_APPEND, 1 },
drhb376b3d2018-01-10 13:11:51 +00006530 { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
drhb376b3d2018-01-10 13:11:51 +00006531 { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
larrybr8f09f4b2021-11-02 00:18:11 +00006532 { "glob", 'g', AR_SWITCH_GLOB, 0 },
dand4b56e52017-12-12 20:04:59 +00006533 };
6534 int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
6535 struct ArSwitch *pEnd = &aSwitch[nSwitch];
6536
dan88be0202017-12-09 17:58:02 +00006537 if( nArg<=1 ){
drh98aa2ab2018-09-26 16:53:51 +00006538 utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
dan0d0547f2017-12-14 15:40:42 +00006539 return arUsage(stderr);
dan88be0202017-12-09 17:58:02 +00006540 }else{
6541 char *z = azArg[1];
dan88be0202017-12-09 17:58:02 +00006542 if( z[0]!='-' ){
6543 /* Traditional style [tar] invocation */
6544 int i;
6545 int iArg = 2;
6546 for(i=0; z[i]; i++){
dand4b56e52017-12-12 20:04:59 +00006547 const char *zArg = 0;
6548 struct ArSwitch *pOpt;
6549 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6550 if( z[i]==pOpt->cShort ) break;
dan88be0202017-12-09 17:58:02 +00006551 }
dan0d0547f2017-12-14 15:40:42 +00006552 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006553 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006554 }
dand4b56e52017-12-12 20:04:59 +00006555 if( pOpt->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006556 if( iArg>=nArg ){
drhd0f9cdc2018-05-17 14:09:06 +00006557 return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
dan0d0547f2017-12-14 15:40:42 +00006558 }
dand4b56e52017-12-12 20:04:59 +00006559 zArg = azArg[iArg++];
6560 }
6561 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
dan88be0202017-12-09 17:58:02 +00006562 }
dan88be0202017-12-09 17:58:02 +00006563 pAr->nArg = nArg-iArg;
6564 if( pAr->nArg>0 ){
6565 pAr->azArg = &azArg[iArg];
6566 }
dand4b56e52017-12-12 20:04:59 +00006567 }else{
6568 /* Non-traditional invocation */
6569 int iArg;
6570 for(iArg=1; iArg<nArg; iArg++){
6571 int n;
6572 z = azArg[iArg];
6573 if( z[0]!='-' ){
6574 /* All remaining command line words are command arguments. */
6575 pAr->azArg = &azArg[iArg];
6576 pAr->nArg = nArg-iArg;
6577 break;
6578 }
drhaf2770f2018-01-05 14:55:43 +00006579 n = strlen30(z);
dand4b56e52017-12-12 20:04:59 +00006580
6581 if( z[1]!='-' ){
6582 int i;
6583 /* One or more short options */
6584 for(i=1; i<n; i++){
6585 const char *zArg = 0;
6586 struct ArSwitch *pOpt;
6587 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6588 if( z[i]==pOpt->cShort ) break;
6589 }
dan0d0547f2017-12-14 15:40:42 +00006590 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006591 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006592 }
dand4b56e52017-12-12 20:04:59 +00006593 if( pOpt->bArg ){
6594 if( i<(n-1) ){
6595 zArg = &z[i+1];
6596 i = n;
6597 }else{
dan0d0547f2017-12-14 15:40:42 +00006598 if( iArg>=(nArg-1) ){
drhe2754c12019-08-26 12:50:01 +00006599 return arErrorMsg(pAr, "option requires an argument: %c",
6600 z[i]);
dan0d0547f2017-12-14 15:40:42 +00006601 }
dand4b56e52017-12-12 20:04:59 +00006602 zArg = azArg[++iArg];
6603 }
6604 }
6605 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
6606 }
6607 }else if( z[2]=='\0' ){
6608 /* A -- option, indicating that all remaining command line words
6609 ** are command arguments. */
6610 pAr->azArg = &azArg[iArg+1];
6611 pAr->nArg = nArg-iArg-1;
6612 break;
6613 }else{
6614 /* A long option */
6615 const char *zArg = 0; /* Argument for option, if any */
6616 struct ArSwitch *pMatch = 0; /* Matching option */
6617 struct ArSwitch *pOpt; /* Iterator */
6618 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6619 const char *zLong = pOpt->zLong;
drhaf2770f2018-01-05 14:55:43 +00006620 if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
dand4b56e52017-12-12 20:04:59 +00006621 if( pMatch ){
drhd0f9cdc2018-05-17 14:09:06 +00006622 return arErrorMsg(pAr, "ambiguous option: %s",z);
dand4b56e52017-12-12 20:04:59 +00006623 }else{
6624 pMatch = pOpt;
6625 }
6626 }
6627 }
6628
6629 if( pMatch==0 ){
drhd0f9cdc2018-05-17 14:09:06 +00006630 return arErrorMsg(pAr, "unrecognized option: %s", z);
dand4b56e52017-12-12 20:04:59 +00006631 }
6632 if( pMatch->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006633 if( iArg>=(nArg-1) ){
drhd0f9cdc2018-05-17 14:09:06 +00006634 return arErrorMsg(pAr, "option requires an argument: %s", z);
dan0d0547f2017-12-14 15:40:42 +00006635 }
dand4b56e52017-12-12 20:04:59 +00006636 zArg = azArg[++iArg];
6637 }
6638 if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
6639 }
6640 }
dan88be0202017-12-09 17:58:02 +00006641 }
6642 }
6643
6644 return SQLITE_OK;
6645}
6646
6647/*
dan3f67ddf2017-12-13 20:04:53 +00006648** This function assumes that all arguments within the ArCommand.azArg[]
larrybr47061b92021-11-01 17:22:52 +00006649** array refer to archive members, as for the --extract, --list or --remove
larrybr8f09f4b2021-11-02 00:18:11 +00006650** commands. It checks that each of them are "present". If any specified
6651** file is not present in the archive, an error is printed to stderr and an
larrybr47061b92021-11-01 17:22:52 +00006652** error code returned. Otherwise, if all specified arguments are present
larrybr8f09f4b2021-11-02 00:18:11 +00006653** in the archive, SQLITE_OK is returned. Here, "present" means either an
6654** exact equality when pAr->bGlob is false or a "name GLOB pattern" match
drh0c0fb9c2021-11-02 10:54:39 +00006655** when pAr->bGlob is true.
dan3f67ddf2017-12-13 20:04:53 +00006656**
6657** This function strips any trailing '/' characters from each argument.
6658** This is consistent with the way the [tar] command seems to work on
6659** Linux.
6660*/
drhb376b3d2018-01-10 13:11:51 +00006661static int arCheckEntries(ArCommand *pAr){
dan3f67ddf2017-12-13 20:04:53 +00006662 int rc = SQLITE_OK;
6663 if( pAr->nArg ){
drhb376b3d2018-01-10 13:11:51 +00006664 int i, j;
dan3f67ddf2017-12-13 20:04:53 +00006665 sqlite3_stmt *pTest = 0;
larrybr8f09f4b2021-11-02 00:18:11 +00006666 const char *zSel = (pAr->bGlob)
6667 ? "SELECT name FROM %s WHERE glob($name,name)"
6668 : "SELECT name FROM %s WHERE name=$name";
dan3f67ddf2017-12-13 20:04:53 +00006669
larrybr8f09f4b2021-11-02 00:18:11 +00006670 shellPreparePrintf(pAr->db, &rc, &pTest, zSel, pAr->zSrcTable);
drhb376b3d2018-01-10 13:11:51 +00006671 j = sqlite3_bind_parameter_index(pTest, "$name");
dan3f67ddf2017-12-13 20:04:53 +00006672 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
6673 char *z = pAr->azArg[i];
drhaf2770f2018-01-05 14:55:43 +00006674 int n = strlen30(z);
dan3f67ddf2017-12-13 20:04:53 +00006675 int bOk = 0;
6676 while( n>0 && z[n-1]=='/' ) n--;
6677 z[n] = '\0';
drhb376b3d2018-01-10 13:11:51 +00006678 sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
dan3f67ddf2017-12-13 20:04:53 +00006679 if( SQLITE_ROW==sqlite3_step(pTest) ){
6680 bOk = 1;
6681 }
6682 shellReset(&rc, pTest);
6683 if( rc==SQLITE_OK && bOk==0 ){
drhb376b3d2018-01-10 13:11:51 +00006684 utf8_printf(stderr, "not found in archive: %s\n", z);
dan3f67ddf2017-12-13 20:04:53 +00006685 rc = SQLITE_ERROR;
6686 }
6687 }
6688 shellFinalize(&rc, pTest);
6689 }
dan3f67ddf2017-12-13 20:04:53 +00006690 return rc;
6691}
6692
6693/*
6694** Format a WHERE clause that can be used against the "sqlar" table to
6695** identify all archive members that match the command arguments held
6696** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
6697** The caller is responsible for eventually calling sqlite3_free() on
larrybr8f09f4b2021-11-02 00:18:11 +00006698** any non-NULL (*pzWhere) value. Here, "match" means strict equality
6699** when pAr->bGlob is false and GLOB match when pAr->bGlob is true.
dan3f67ddf2017-12-13 20:04:53 +00006700*/
6701static void arWhereClause(
6702 int *pRc,
larrybr8f09f4b2021-11-02 00:18:11 +00006703 ArCommand *pAr,
danac15e2d2017-12-14 19:15:07 +00006704 char **pzWhere /* OUT: New WHERE clause */
dan3f67ddf2017-12-13 20:04:53 +00006705){
6706 char *zWhere = 0;
larrybr8f09f4b2021-11-02 00:18:11 +00006707 const char *zSameOp = (pAr->bGlob)? "GLOB" : "=";
dan3f67ddf2017-12-13 20:04:53 +00006708 if( *pRc==SQLITE_OK ){
danac15e2d2017-12-14 19:15:07 +00006709 if( pAr->nArg==0 ){
6710 zWhere = sqlite3_mprintf("1");
6711 }else{
6712 int i;
6713 const char *zSep = "";
6714 for(i=0; i<pAr->nArg; i++){
6715 const char *z = pAr->azArg[i];
6716 zWhere = sqlite3_mprintf(
larrybr8f09f4b2021-11-02 00:18:11 +00006717 "%z%s name %s '%q' OR substr(name,1,%d) %s '%q/'",
6718 zWhere, zSep, zSameOp, z, strlen30(z)+1, zSameOp, z
drhb376b3d2018-01-10 13:11:51 +00006719 );
danac15e2d2017-12-14 19:15:07 +00006720 if( zWhere==0 ){
6721 *pRc = SQLITE_NOMEM;
6722 break;
6723 }
6724 zSep = " OR ";
dan3f67ddf2017-12-13 20:04:53 +00006725 }
dan3f67ddf2017-12-13 20:04:53 +00006726 }
6727 }
6728 *pzWhere = zWhere;
6729}
6730
6731/*
dan88be0202017-12-09 17:58:02 +00006732** Implementation of .ar "lisT" command.
6733*/
drhb376b3d2018-01-10 13:11:51 +00006734static int arListCommand(ArCommand *pAr){
danb5090e42017-12-27 21:13:21 +00006735 const char *zSql = "SELECT %s FROM %s WHERE %s";
danb5090e42017-12-27 21:13:21 +00006736 const char *azCols[] = {
6737 "name",
drh410cad92018-01-10 17:19:16 +00006738 "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
danb5090e42017-12-27 21:13:21 +00006739 };
dan5a78b812017-12-27 18:54:11 +00006740
dan3f67ddf2017-12-13 20:04:53 +00006741 char *zWhere = 0;
6742 sqlite3_stmt *pSql = 0;
6743 int rc;
6744
drhb376b3d2018-01-10 13:11:51 +00006745 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006746 arWhereClause(&rc, pAr, &zWhere);
6747
drhb376b3d2018-01-10 13:11:51 +00006748 shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
6749 pAr->zSrcTable, zWhere);
drhb376b3d2018-01-10 13:11:51 +00006750 if( pAr->bDryRun ){
6751 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
6752 }else{
6753 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
6754 if( pAr->bVerbose ){
drh410cad92018-01-10 17:19:16 +00006755 utf8_printf(pAr->p->out, "%s % 10d %s %s\n",
6756 sqlite3_column_text(pSql, 0),
drhb376b3d2018-01-10 13:11:51 +00006757 sqlite3_column_int(pSql, 1),
6758 sqlite3_column_text(pSql, 2),
6759 sqlite3_column_text(pSql, 3)
6760 );
6761 }else{
6762 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
6763 }
danb5090e42017-12-27 21:13:21 +00006764 }
dan3f67ddf2017-12-13 20:04:53 +00006765 }
dan5a78b812017-12-27 18:54:11 +00006766 shellFinalize(&rc, pSql);
drhd0f9cdc2018-05-17 14:09:06 +00006767 sqlite3_free(zWhere);
dan3f67ddf2017-12-13 20:04:53 +00006768 return rc;
dan88be0202017-12-09 17:58:02 +00006769}
6770
6771
danfd0245d2017-12-07 15:44:29 +00006772/*
larrybr47061b92021-11-01 17:22:52 +00006773** Implementation of .ar "Remove" command.
6774*/
6775static int arRemoveCommand(ArCommand *pAr){
larrybr7774fc02021-11-01 22:30:24 +00006776 int rc = 0;
larrybr47061b92021-11-01 17:22:52 +00006777 char *zSql = 0;
6778 char *zWhere = 0;
6779
6780 if( pAr->nArg ){
6781 /* Verify that args actually exist within the archive before proceeding.
6782 ** And formulate a WHERE clause to match them. */
6783 rc = arCheckEntries(pAr);
6784 arWhereClause(&rc, pAr, &zWhere);
6785 }
6786 if( rc==SQLITE_OK ){
6787 zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;",
6788 pAr->zSrcTable, zWhere);
6789 if( pAr->bDryRun ){
6790 utf8_printf(pAr->p->out, "%s\n", zSql);
6791 }else{
6792 char *zErr = 0;
6793 rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0);
6794 if( rc==SQLITE_OK ){
6795 rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
6796 if( rc!=SQLITE_OK ){
6797 sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
6798 }else{
6799 rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0);
6800 }
6801 }
6802 if( zErr ){
6803 utf8_printf(stdout, "ERROR: %s\n", zErr);
6804 sqlite3_free(zErr);
6805 }
6806 }
6807 }
6808 sqlite3_free(zWhere);
6809 sqlite3_free(zSql);
6810 return rc;
6811}
6812
6813/*
danfd0245d2017-12-07 15:44:29 +00006814** Implementation of .ar "eXtract" command.
6815*/
drhb376b3d2018-01-10 13:11:51 +00006816static int arExtractCommand(ArCommand *pAr){
dan25c12182017-12-07 21:03:33 +00006817 const char *zSql1 =
dand1b51d42017-12-16 19:11:26 +00006818 "SELECT "
drhb376b3d2018-01-10 13:11:51 +00006819 " ($dir || name),"
6820 " writefile(($dir || name), %s, mode, mtime) "
drh0cfd46a2018-06-06 01:18:01 +00006821 "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
6822 " AND name NOT GLOB '*..[/\\]*'";
dan5a78b812017-12-27 18:54:11 +00006823
6824 const char *azExtraArg[] = {
6825 "sqlar_uncompress(data, sz)",
dan7c15ac12018-01-08 19:59:59 +00006826 "data"
dan5a78b812017-12-27 18:54:11 +00006827 };
dan5a78b812017-12-27 18:54:11 +00006828
danfd0245d2017-12-07 15:44:29 +00006829 sqlite3_stmt *pSql = 0;
6830 int rc = SQLITE_OK;
dan2ad09492017-12-09 18:28:22 +00006831 char *zDir = 0;
dan3f67ddf2017-12-13 20:04:53 +00006832 char *zWhere = 0;
drhb376b3d2018-01-10 13:11:51 +00006833 int i, j;
dan2ad09492017-12-09 18:28:22 +00006834
dan3f67ddf2017-12-13 20:04:53 +00006835 /* If arguments are specified, check that they actually exist within
6836 ** the archive before proceeding. And formulate a WHERE clause to
6837 ** match them. */
drhb376b3d2018-01-10 13:11:51 +00006838 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006839 arWhereClause(&rc, pAr, &zWhere);
6840
6841 if( rc==SQLITE_OK ){
6842 if( pAr->zDir ){
6843 zDir = sqlite3_mprintf("%s/", pAr->zDir);
6844 }else{
6845 zDir = sqlite3_mprintf("");
6846 }
6847 if( zDir==0 ) rc = SQLITE_NOMEM;
dan2ad09492017-12-09 18:28:22 +00006848 }
danfd0245d2017-12-07 15:44:29 +00006849
drhb376b3d2018-01-10 13:11:51 +00006850 shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
6851 azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
dan5a78b812017-12-27 18:54:11 +00006852 );
6853
dan2ad09492017-12-09 18:28:22 +00006854 if( rc==SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00006855 j = sqlite3_bind_parameter_index(pSql, "$dir");
6856 sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
dan25c12182017-12-07 21:03:33 +00006857
danac15e2d2017-12-14 19:15:07 +00006858 /* Run the SELECT statement twice. The first time, writefile() is called
6859 ** for all archive members that should be extracted. The second time,
6860 ** only for the directories. This is because the timestamps for
6861 ** extracted directories must be reset after they are populated (as
6862 ** populating them changes the timestamp). */
6863 for(i=0; i<2; i++){
drhb376b3d2018-01-10 13:11:51 +00006864 j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
6865 sqlite3_bind_int(pSql, j, i);
6866 if( pAr->bDryRun ){
6867 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
6868 }else{
6869 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
6870 if( i==0 && pAr->bVerbose ){
6871 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
6872 }
danac15e2d2017-12-14 19:15:07 +00006873 }
6874 }
6875 shellReset(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00006876 }
danac15e2d2017-12-14 19:15:07 +00006877 shellFinalize(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00006878 }
dan25c12182017-12-07 21:03:33 +00006879
dan2ad09492017-12-09 18:28:22 +00006880 sqlite3_free(zDir);
dan3f67ddf2017-12-13 20:04:53 +00006881 sqlite3_free(zWhere);
danfd0245d2017-12-07 15:44:29 +00006882 return rc;
6883}
6884
drhb376b3d2018-01-10 13:11:51 +00006885/*
6886** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out.
6887*/
6888static int arExecSql(ArCommand *pAr, const char *zSql){
6889 int rc;
6890 if( pAr->bDryRun ){
6891 utf8_printf(pAr->p->out, "%s\n", zSql);
6892 rc = SQLITE_OK;
6893 }else{
drh410cad92018-01-10 17:19:16 +00006894 char *zErr = 0;
6895 rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
6896 if( zErr ){
6897 utf8_printf(stdout, "ERROR: %s\n", zErr);
6898 sqlite3_free(zErr);
6899 }
drhb376b3d2018-01-10 13:11:51 +00006900 }
6901 return rc;
6902}
6903
dan1ad3f612017-12-11 20:22:02 +00006904
danfd0245d2017-12-07 15:44:29 +00006905/*
drhb17ea912019-03-25 14:24:19 +00006906** Implementation of .ar "create", "insert", and "update" commands.
6907**
6908** create -> Create a new SQL archive
6909** insert -> Insert or reinsert all files listed
6910** update -> Insert files that have changed or that were not
6911** previously in the archive
danfd0245d2017-12-07 15:44:29 +00006912**
6913** Create the "sqlar" table in the database if it does not already exist.
6914** Then add each file in the azFile[] array to the archive. Directories
6915** are added recursively. If argument bVerbose is non-zero, a message is
6916** printed on stdout for each file archived.
dan06741a32017-12-13 20:17:18 +00006917**
6918** The create command is the same as update, except that it drops
drhb17ea912019-03-25 14:24:19 +00006919** any existing "sqlar" table before beginning. The "insert" command
6920** always overwrites every file named on the command-line, where as
6921** "update" only overwrites if the size or mtime or mode has changed.
danfd0245d2017-12-07 15:44:29 +00006922*/
drhb376b3d2018-01-10 13:11:51 +00006923static int arCreateOrUpdateCommand(
dan06741a32017-12-13 20:17:18 +00006924 ArCommand *pAr, /* Command arguments and options */
drhb17ea912019-03-25 14:24:19 +00006925 int bUpdate, /* true for a --create. */
6926 int bOnlyIfChanged /* Only update if file has changed */
danfd0245d2017-12-07 15:44:29 +00006927){
dand4b56e52017-12-12 20:04:59 +00006928 const char *zCreate =
drhafba1802018-01-06 15:49:57 +00006929 "CREATE TABLE IF NOT EXISTS sqlar(\n"
6930 " name TEXT PRIMARY KEY, -- name of the file\n"
6931 " mode INT, -- access permissions\n"
6932 " mtime INT, -- last modification time\n"
6933 " sz INT, -- original file size\n"
6934 " data BLOB -- compressed content\n"
6935 ")";
dand4b56e52017-12-12 20:04:59 +00006936 const char *zDrop = "DROP TABLE IF EXISTS sqlar";
drh1bf208c2018-03-09 21:54:01 +00006937 const char *zInsertFmt[2] = {
6938 "REPLACE INTO %s(name,mode,mtime,sz,data)\n"
drh634c70f2018-01-10 16:50:18 +00006939 " SELECT\n"
6940 " %s,\n"
6941 " mode,\n"
6942 " mtime,\n"
drh410cad92018-01-10 17:19:16 +00006943 " CASE substr(lsmode(mode),1,1)\n"
6944 " WHEN '-' THEN length(data)\n"
6945 " WHEN 'd' THEN 0\n"
drh634c70f2018-01-10 16:50:18 +00006946 " ELSE -1 END,\n"
drh69d2d352018-03-09 22:18:53 +00006947 " sqlar_compress(data)\n"
drhb17ea912019-03-25 14:24:19 +00006948 " FROM fsdir(%Q,%Q) AS disk\n"
6949 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
6950 ,
drh1bf208c2018-03-09 21:54:01 +00006951 "REPLACE INTO %s(name,mode,mtime,data)\n"
6952 " SELECT\n"
6953 " %s,\n"
6954 " mode,\n"
6955 " mtime,\n"
6956 " data\n"
drhb17ea912019-03-25 14:24:19 +00006957 " FROM fsdir(%Q,%Q) AS disk\n"
6958 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
drh1bf208c2018-03-09 21:54:01 +00006959 };
danfd0245d2017-12-07 15:44:29 +00006960 int i; /* For iterating through azFile[] */
6961 int rc; /* Return code */
drh1bf208c2018-03-09 21:54:01 +00006962 const char *zTab = 0; /* SQL table into which to insert */
6963 char *zSql;
6964 char zTemp[50];
drhb17ea912019-03-25 14:24:19 +00006965 char *zExists = 0;
danfd0245d2017-12-07 15:44:29 +00006966
drh1bf208c2018-03-09 21:54:01 +00006967 arExecSql(pAr, "PRAGMA page_size=512");
drhb376b3d2018-01-10 13:11:51 +00006968 rc = arExecSql(pAr, "SAVEPOINT ar;");
danfd0245d2017-12-07 15:44:29 +00006969 if( rc!=SQLITE_OK ) return rc;
drh1bf208c2018-03-09 21:54:01 +00006970 zTemp[0] = 0;
6971 if( pAr->bZip ){
6972 /* Initialize the zipfile virtual table, if necessary */
6973 if( pAr->zFile ){
6974 sqlite3_uint64 r;
6975 sqlite3_randomness(sizeof(r),&r);
6976 sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
6977 zTab = zTemp;
6978 zSql = sqlite3_mprintf(
6979 "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)",
6980 zTab, pAr->zFile
6981 );
6982 rc = arExecSql(pAr, zSql);
6983 sqlite3_free(zSql);
6984 }else{
6985 zTab = "zip";
6986 }
6987 }else{
6988 /* Initialize the table for an SQLAR */
6989 zTab = "sqlar";
6990 if( bUpdate==0 ){
6991 rc = arExecSql(pAr, zDrop);
6992 if( rc!=SQLITE_OK ) goto end_ar_transaction;
6993 }
6994 rc = arExecSql(pAr, zCreate);
dan06741a32017-12-13 20:17:18 +00006995 }
drhb17ea912019-03-25 14:24:19 +00006996 if( bOnlyIfChanged ){
6997 zExists = sqlite3_mprintf(
6998 " AND NOT EXISTS("
6999 "SELECT 1 FROM %s AS mem"
7000 " WHERE mem.name=disk.name"
7001 " AND mem.mtime=disk.mtime"
7002 " AND mem.mode=disk.mode)", zTab);
7003 }else{
7004 zExists = sqlite3_mprintf("");
7005 }
7006 if( zExists==0 ) rc = SQLITE_NOMEM;
dan88be0202017-12-09 17:58:02 +00007007 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
mistachkince2052b2018-03-23 00:31:53 +00007008 char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
drh634c70f2018-01-10 16:50:18 +00007009 pAr->bVerbose ? "shell_putsnl(name)" : "name",
drhb17ea912019-03-25 14:24:19 +00007010 pAr->azArg[i], pAr->zDir, zExists);
mistachkince2052b2018-03-23 00:31:53 +00007011 rc = arExecSql(pAr, zSql2);
7012 sqlite3_free(zSql2);
danfd0245d2017-12-07 15:44:29 +00007013 }
drh1bf208c2018-03-09 21:54:01 +00007014end_ar_transaction:
danfd0245d2017-12-07 15:44:29 +00007015 if( rc!=SQLITE_OK ){
drh2bd207f2019-01-11 17:19:59 +00007016 sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
danfd0245d2017-12-07 15:44:29 +00007017 }else{
drhb376b3d2018-01-10 13:11:51 +00007018 rc = arExecSql(pAr, "RELEASE ar;");
drh1bf208c2018-03-09 21:54:01 +00007019 if( pAr->bZip && pAr->zFile ){
7020 zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
7021 arExecSql(pAr, zSql);
7022 sqlite3_free(zSql);
7023 }
danfd0245d2017-12-07 15:44:29 +00007024 }
drhb17ea912019-03-25 14:24:19 +00007025 sqlite3_free(zExists);
danfd0245d2017-12-07 15:44:29 +00007026 return rc;
7027}
7028
7029/*
7030** Implementation of ".ar" dot command.
7031*/
7032static int arDotCommand(
drhe2754c12019-08-26 12:50:01 +00007033 ShellState *pState, /* Current shell tool state */
7034 int fromCmdLine, /* True if -A command-line option, not .ar cmd */
7035 char **azArg, /* Array of arguments passed to dot command */
7036 int nArg /* Number of entries in azArg[] */
danfd0245d2017-12-07 15:44:29 +00007037){
dan88be0202017-12-09 17:58:02 +00007038 ArCommand cmd;
7039 int rc;
drh34660642018-01-10 17:39:54 +00007040 memset(&cmd, 0, sizeof(cmd));
drhd0f9cdc2018-05-17 14:09:06 +00007041 cmd.fromCmdLine = fromCmdLine;
dan88be0202017-12-09 17:58:02 +00007042 rc = arParseCommand(azArg, nArg, &cmd);
7043 if( rc==SQLITE_OK ){
drha5676c42018-01-10 15:17:34 +00007044 int eDbType = SHELL_OPEN_UNSPEC;
drhb376b3d2018-01-10 13:11:51 +00007045 cmd.p = pState;
7046 cmd.db = pState->db;
drha5676c42018-01-10 15:17:34 +00007047 if( cmd.zFile ){
drh1bf208c2018-03-09 21:54:01 +00007048 eDbType = deduceDatabaseType(cmd.zFile, 1);
drha5676c42018-01-10 15:17:34 +00007049 }else{
7050 eDbType = pState->openMode;
7051 }
7052 if( eDbType==SHELL_OPEN_ZIPFILE ){
drh1bf208c2018-03-09 21:54:01 +00007053 if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){
7054 if( cmd.zFile==0 ){
7055 cmd.zSrcTable = sqlite3_mprintf("zip");
7056 }else{
7057 cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
7058 }
dan5a78b812017-12-27 18:54:11 +00007059 }
drha5676c42018-01-10 15:17:34 +00007060 cmd.bZip = 1;
dan5a78b812017-12-27 18:54:11 +00007061 }else if( cmd.zFile ){
dand4b56e52017-12-12 20:04:59 +00007062 int flags;
drha5676c42018-01-10 15:17:34 +00007063 if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
drhb17ea912019-03-25 14:24:19 +00007064 if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
larrybr47061b92021-11-01 17:22:52 +00007065 || cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){
dand4b56e52017-12-12 20:04:59 +00007066 flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
7067 }else{
7068 flags = SQLITE_OPEN_READONLY;
7069 }
drha82c95b2018-01-10 14:00:00 +00007070 cmd.db = 0;
drha5676c42018-01-10 15:17:34 +00007071 if( cmd.bDryRun ){
7072 utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
7073 eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
7074 }
7075 rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
7076 eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
dand4b56e52017-12-12 20:04:59 +00007077 if( rc!=SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00007078 utf8_printf(stderr, "cannot open file: %s (%s)\n",
7079 cmd.zFile, sqlite3_errmsg(cmd.db)
dand4b56e52017-12-12 20:04:59 +00007080 );
drha5676c42018-01-10 15:17:34 +00007081 goto end_ar_command;
dand4b56e52017-12-12 20:04:59 +00007082 }
drhb376b3d2018-01-10 13:11:51 +00007083 sqlite3_fileio_init(cmd.db, 0, 0);
drhb376b3d2018-01-10 13:11:51 +00007084 sqlite3_sqlar_init(cmd.db, 0, 0);
drh34660642018-01-10 17:39:54 +00007085 sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
7086 shellPutsFunc, 0, 0);
7087
dand4b56e52017-12-12 20:04:59 +00007088 }
drhd0f9cdc2018-05-17 14:09:06 +00007089 if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
drh634c70f2018-01-10 16:50:18 +00007090 if( cmd.eCmd!=AR_CMD_CREATE
7091 && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
7092 ){
drha5676c42018-01-10 15:17:34 +00007093 utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
7094 rc = SQLITE_ERROR;
7095 goto end_ar_command;
7096 }
7097 cmd.zSrcTable = sqlite3_mprintf("sqlar");
7098 }
dand4b56e52017-12-12 20:04:59 +00007099
dan88be0202017-12-09 17:58:02 +00007100 switch( cmd.eCmd ){
7101 case AR_CMD_CREATE:
drhb17ea912019-03-25 14:24:19 +00007102 rc = arCreateOrUpdateCommand(&cmd, 0, 0);
dan88be0202017-12-09 17:58:02 +00007103 break;
danfd0245d2017-12-07 15:44:29 +00007104
dan88be0202017-12-09 17:58:02 +00007105 case AR_CMD_EXTRACT:
drhb376b3d2018-01-10 13:11:51 +00007106 rc = arExtractCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00007107 break;
7108
7109 case AR_CMD_LIST:
drhb376b3d2018-01-10 13:11:51 +00007110 rc = arListCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00007111 break;
7112
dan0d0547f2017-12-14 15:40:42 +00007113 case AR_CMD_HELP:
7114 arUsage(pState->out);
7115 break;
7116
drhb17ea912019-03-25 14:24:19 +00007117 case AR_CMD_INSERT:
7118 rc = arCreateOrUpdateCommand(&cmd, 1, 0);
7119 break;
7120
larrybr47061b92021-11-01 17:22:52 +00007121 case AR_CMD_REMOVE:
7122 rc = arRemoveCommand(&cmd);
7123 break;
7124
dan88be0202017-12-09 17:58:02 +00007125 default:
7126 assert( cmd.eCmd==AR_CMD_UPDATE );
drhb17ea912019-03-25 14:24:19 +00007127 rc = arCreateOrUpdateCommand(&cmd, 1, 1);
dan88be0202017-12-09 17:58:02 +00007128 break;
danfd0245d2017-12-07 15:44:29 +00007129 }
7130 }
drha5676c42018-01-10 15:17:34 +00007131end_ar_command:
7132 if( cmd.db!=pState->db ){
drh9e804032018-05-18 17:11:50 +00007133 close_db(cmd.db);
drha5676c42018-01-10 15:17:34 +00007134 }
7135 sqlite3_free(cmd.zSrcTable);
danfd0245d2017-12-07 15:44:29 +00007136
dan88be0202017-12-09 17:58:02 +00007137 return rc;
danfd0245d2017-12-07 15:44:29 +00007138}
drhe37c0e12018-01-06 19:19:50 +00007139/* End of the ".archive" or ".ar" command logic
drhe2754c12019-08-26 12:50:01 +00007140*******************************************************************************/
drhe37c0e12018-01-06 19:19:50 +00007141#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
danfd0245d2017-12-07 15:44:29 +00007142
dan1b162162019-04-27 20:15:15 +00007143#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan42ebb012019-04-27 18:47:03 +00007144/*
7145** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
7146** Otherwise, the SQL statement or statements in zSql are executed using
7147** database connection db and the error code written to *pRc before
7148** this function returns.
7149*/
dan68cb86e2019-04-20 20:57:28 +00007150static void shellExec(sqlite3 *db, int *pRc, const char *zSql){
7151 int rc = *pRc;
7152 if( rc==SQLITE_OK ){
7153 char *zErr = 0;
7154 rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
7155 if( rc!=SQLITE_OK ){
7156 raw_printf(stderr, "SQL error: %s\n", zErr);
7157 }
drhf83d5012021-05-03 13:35:00 +00007158 sqlite3_free(zErr);
dan68cb86e2019-04-20 20:57:28 +00007159 *pRc = rc;
7160 }
7161}
7162
dan42ebb012019-04-27 18:47:03 +00007163/*
7164** Like shellExec(), except that zFmt is a printf() style format string.
7165*/
danc0b42432019-04-26 15:14:53 +00007166static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){
7167 char *z = 0;
7168 if( *pRc==SQLITE_OK ){
7169 va_list ap;
7170 va_start(ap, zFmt);
7171 z = sqlite3_vmprintf(zFmt, ap);
7172 va_end(ap);
7173 if( z==0 ){
7174 *pRc = SQLITE_NOMEM;
7175 }else{
7176 shellExec(db, pRc, z);
7177 }
7178 sqlite3_free(z);
7179 }
7180}
7181
dan42ebb012019-04-27 18:47:03 +00007182/*
7183** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
7184** Otherwise, an attempt is made to allocate, zero and return a pointer
7185** to a buffer nByte bytes in size. If an OOM error occurs, *pRc is set
7186** to SQLITE_NOMEM and NULL returned.
7187*/
dan68cb86e2019-04-20 20:57:28 +00007188static void *shellMalloc(int *pRc, sqlite3_int64 nByte){
7189 void *pRet = 0;
7190 if( *pRc==SQLITE_OK ){
7191 pRet = sqlite3_malloc64(nByte);
7192 if( pRet==0 ){
7193 *pRc = SQLITE_NOMEM;
7194 }else{
7195 memset(pRet, 0, nByte);
7196 }
7197 }
7198 return pRet;
7199}
7200
dan42ebb012019-04-27 18:47:03 +00007201/*
7202** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
7203** Otherwise, zFmt is treated as a printf() style string. The result of
7204** formatting it along with any trailing arguments is written into a
7205** buffer obtained from sqlite3_malloc(), and pointer to which is returned.
7206** It is the responsibility of the caller to eventually free this buffer
7207** using a call to sqlite3_free().
7208**
7209** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL
7210** pointer returned.
7211*/
dan68cb86e2019-04-20 20:57:28 +00007212static char *shellMPrintf(int *pRc, const char *zFmt, ...){
7213 char *z = 0;
7214 if( *pRc==SQLITE_OK ){
7215 va_list ap;
7216 va_start(ap, zFmt);
7217 z = sqlite3_vmprintf(zFmt, ap);
7218 va_end(ap);
7219 if( z==0 ){
7220 *pRc = SQLITE_NOMEM;
7221 }
7222 }
7223 return z;
7224}
7225
larrybr58a53d62022-02-10 03:21:48 +00007226
dan42ebb012019-04-27 18:47:03 +00007227/*
7228** When running the ".recover" command, each output table, and the special
7229** orphaned row table if it is required, is represented by an instance
7230** of the following struct.
7231*/
dan68cb86e2019-04-20 20:57:28 +00007232typedef struct RecoverTable RecoverTable;
7233struct RecoverTable {
dan42ebb012019-04-27 18:47:03 +00007234 char *zQuoted; /* Quoted version of table name */
dan68cb86e2019-04-20 20:57:28 +00007235 int nCol; /* Number of columns in table */
7236 char **azlCol; /* Array of column lists */
dan42ebb012019-04-27 18:47:03 +00007237 int iPk; /* Index of IPK column */
dan68cb86e2019-04-20 20:57:28 +00007238};
7239
7240/*
dan42ebb012019-04-27 18:47:03 +00007241** Free a RecoverTable object allocated by recoverFindTable() or
7242** recoverOrphanTable().
dan68cb86e2019-04-20 20:57:28 +00007243*/
7244static void recoverFreeTable(RecoverTable *pTab){
7245 if( pTab ){
dan68cb86e2019-04-20 20:57:28 +00007246 sqlite3_free(pTab->zQuoted);
dan68cb86e2019-04-20 20:57:28 +00007247 if( pTab->azlCol ){
7248 int i;
dan98c5ad32019-04-26 21:11:37 +00007249 for(i=0; i<=pTab->nCol; i++){
dan68cb86e2019-04-20 20:57:28 +00007250 sqlite3_free(pTab->azlCol[i]);
7251 }
7252 sqlite3_free(pTab->azlCol);
7253 }
7254 sqlite3_free(pTab);
7255 }
7256}
7257
dan42ebb012019-04-27 18:47:03 +00007258/*
7259** This function is a no-op if (*pRc) is not SQLITE_OK when it is called.
7260** Otherwise, it allocates and returns a RecoverTable object based on the
7261** final four arguments passed to this function. It is the responsibility
7262** of the caller to eventually free the returned object using
7263** recoverFreeTable().
7264*/
7265static RecoverTable *recoverNewTable(
danb40af492019-04-22 20:52:12 +00007266 int *pRc, /* IN/OUT: Error code */
danb40af492019-04-22 20:52:12 +00007267 const char *zName, /* Name of table */
7268 const char *zSql, /* CREATE TABLE statement */
7269 int bIntkey,
7270 int nCol
7271){
7272 sqlite3 *dbtmp = 0; /* sqlite3 handle for testing CREATE TABLE */
7273 int rc = *pRc;
dan98c5ad32019-04-26 21:11:37 +00007274 RecoverTable *pTab = 0;
danb40af492019-04-22 20:52:12 +00007275
dan98c5ad32019-04-26 21:11:37 +00007276 pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable));
danb40af492019-04-22 20:52:12 +00007277 if( rc==SQLITE_OK ){
7278 int nSqlCol = 0;
7279 int bSqlIntkey = 0;
7280 sqlite3_stmt *pStmt = 0;
dan98c5ad32019-04-26 21:11:37 +00007281
danb40af492019-04-22 20:52:12 +00007282 rc = sqlite3_open("", &dbtmp);
7283 if( rc==SQLITE_OK ){
drha2de66c2019-08-06 20:26:17 +00007284 sqlite3_create_function(dbtmp, "shell_idquote", 1, SQLITE_UTF8, 0,
7285 shellIdQuote, 0, 0);
7286 }
7287 if( rc==SQLITE_OK ){
dan38f9c712019-04-23 18:03:02 +00007288 rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
7289 }
7290 if( rc==SQLITE_OK ){
danb40af492019-04-22 20:52:12 +00007291 rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0);
7292 if( rc==SQLITE_ERROR ){
7293 rc = SQLITE_OK;
7294 goto finished;
7295 }
7296 }
7297 shellPreparePrintf(dbtmp, &rc, &pStmt,
7298 "SELECT count(*) FROM pragma_table_info(%Q)", zName
7299 );
7300 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7301 nSqlCol = sqlite3_column_int(pStmt, 0);
7302 }
7303 shellFinalize(&rc, pStmt);
7304
7305 if( rc!=SQLITE_OK || nSqlCol<nCol ){
7306 goto finished;
7307 }
7308
7309 shellPreparePrintf(dbtmp, &rc, &pStmt,
7310 "SELECT ("
7311 " SELECT substr(data,1,1)==X'0D' FROM sqlite_dbpage WHERE pgno=rootpage"
drh067b92b2020-06-19 15:24:12 +00007312 ") FROM sqlite_schema WHERE name = %Q", zName
danb40af492019-04-22 20:52:12 +00007313 );
7314 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7315 bSqlIntkey = sqlite3_column_int(pStmt, 0);
7316 }
7317 shellFinalize(&rc, pStmt);
7318
7319 if( bIntkey==bSqlIntkey ){
dan98c5ad32019-04-26 21:11:37 +00007320 int i;
danb40af492019-04-22 20:52:12 +00007321 const char *zPk = "_rowid_";
7322 sqlite3_stmt *pPkFinder = 0;
7323
danf57bea32019-04-27 15:35:45 +00007324 /* If this is an intkey table and there is an INTEGER PRIMARY KEY,
7325 ** set zPk to the name of the PK column, and pTab->iPk to the index
7326 ** of the column, where columns are 0-numbered from left to right.
7327 ** Or, if this is a WITHOUT ROWID table or if there is no IPK column,
7328 ** leave zPk as "_rowid_" and pTab->iPk at -2. */
dan98c5ad32019-04-26 21:11:37 +00007329 pTab->iPk = -2;
7330 if( bIntkey ){
7331 shellPreparePrintf(dbtmp, &rc, &pPkFinder,
danb40af492019-04-22 20:52:12 +00007332 "SELECT cid, name FROM pragma_table_info(%Q) "
7333 " WHERE pk=1 AND type='integer' COLLATE nocase"
dan98c5ad32019-04-26 21:11:37 +00007334 " AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
7335 , zName, zName
7336 );
7337 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){
7338 pTab->iPk = sqlite3_column_int(pPkFinder, 0);
7339 zPk = (const char*)sqlite3_column_text(pPkFinder, 1);
drh621a5e02021-12-16 17:35:27 +00007340 if( zPk==0 ){ zPk = "_"; /* Defensive. Should never happen */ }
dan98c5ad32019-04-26 21:11:37 +00007341 }
danb40af492019-04-22 20:52:12 +00007342 }
7343
drha2de66c2019-08-06 20:26:17 +00007344 pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName);
dan98c5ad32019-04-26 21:11:37 +00007345 pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
danb40af492019-04-22 20:52:12 +00007346 pTab->nCol = nSqlCol;
7347
dan98c5ad32019-04-26 21:11:37 +00007348 if( bIntkey ){
drha2de66c2019-08-06 20:26:17 +00007349 pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk);
danb40af492019-04-22 20:52:12 +00007350 }else{
dan98c5ad32019-04-26 21:11:37 +00007351 pTab->azlCol[0] = shellMPrintf(&rc, "");
danb40af492019-04-22 20:52:12 +00007352 }
dan98c5ad32019-04-26 21:11:37 +00007353 i = 1;
7354 shellPreparePrintf(dbtmp, &rc, &pStmt,
drha2de66c2019-08-06 20:26:17 +00007355 "SELECT %Q || group_concat(shell_idquote(name), ', ') "
danf57bea32019-04-27 15:35:45 +00007356 " FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
dan98c5ad32019-04-26 21:11:37 +00007357 "FROM pragma_table_info(%Q)",
danf57bea32019-04-27 15:35:45 +00007358 bIntkey ? ", " : "", pTab->iPk,
7359 bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ",
7360 zName
dan98c5ad32019-04-26 21:11:37 +00007361 );
7362 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7363 const char *zText = (const char*)sqlite3_column_text(pStmt, 0);
7364 pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText);
7365 i++;
7366 }
7367 shellFinalize(&rc, pStmt);
7368
danb40af492019-04-22 20:52:12 +00007369 shellFinalize(&rc, pPkFinder);
7370 }
7371 }
7372
7373 finished:
7374 sqlite3_close(dbtmp);
7375 *pRc = rc;
dan98779652019-05-09 14:15:19 +00007376 if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){
dan98c5ad32019-04-26 21:11:37 +00007377 recoverFreeTable(pTab);
7378 pTab = 0;
7379 }
7380 return pTab;
danb40af492019-04-22 20:52:12 +00007381}
7382
dan0aa01ee2019-04-27 19:36:49 +00007383/*
7384** This function is called to search the schema recovered from the
drh067b92b2020-06-19 15:24:12 +00007385** sqlite_schema table of the (possibly) corrupt database as part
dan0aa01ee2019-04-27 19:36:49 +00007386** of a ".recover" command. Specifically, for a table with root page
7387** iRoot and at least nCol columns. Additionally, if bIntkey is 0, the
7388** table must be a WITHOUT ROWID table, or if non-zero, not one of
7389** those.
7390**
7391** If a table is found, a (RecoverTable*) object is returned. Or, if
7392** no such table is found, but bIntkey is false and iRoot is the
7393** root page of an index in the recovered schema, then (*pbNoop) is
7394** set to true and NULL returned. Or, if there is no such table or
7395** index, NULL is returned and (*pbNoop) set to 0, indicating that
7396** the caller should write data to the orphans table.
7397*/
dan42ebb012019-04-27 18:47:03 +00007398static RecoverTable *recoverFindTable(
dan0aa01ee2019-04-27 19:36:49 +00007399 ShellState *pState, /* Shell state object */
7400 int *pRc, /* IN/OUT: Error code */
7401 int iRoot, /* Root page of table */
7402 int bIntkey, /* True for an intkey table */
7403 int nCol, /* Number of columns in table */
7404 int *pbNoop /* OUT: True if iRoot is root of index */
dan68cb86e2019-04-20 20:57:28 +00007405){
danb40af492019-04-22 20:52:12 +00007406 sqlite3_stmt *pStmt = 0;
dan68cb86e2019-04-20 20:57:28 +00007407 RecoverTable *pRet = 0;
danb40af492019-04-22 20:52:12 +00007408 int bNoop = 0;
7409 const char *zSql = 0;
7410 const char *zName = 0;
dan68cb86e2019-04-20 20:57:28 +00007411
danb40af492019-04-22 20:52:12 +00007412 /* Search the recovered schema for an object with root page iRoot. */
7413 shellPreparePrintf(pState->db, pRc, &pStmt,
7414 "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot
7415 );
7416 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7417 const char *zType = (const char*)sqlite3_column_text(pStmt, 0);
7418 if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){
7419 bNoop = 1;
7420 break;
7421 }
7422 if( sqlite3_stricmp(zType, "table")==0 ){
7423 zName = (const char*)sqlite3_column_text(pStmt, 1);
7424 zSql = (const char*)sqlite3_column_text(pStmt, 2);
drh621a5e02021-12-16 17:35:27 +00007425 if( zName!=0 && zSql!=0 ){
7426 pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol);
7427 break;
7428 }
danb40af492019-04-22 20:52:12 +00007429 }
7430 }
dan98c5ad32019-04-26 21:11:37 +00007431
danb40af492019-04-22 20:52:12 +00007432 shellFinalize(pRc, pStmt);
dan98c5ad32019-04-26 21:11:37 +00007433 *pbNoop = bNoop;
7434 return pRet;
7435}
danb40af492019-04-22 20:52:12 +00007436
dan0aa01ee2019-04-27 19:36:49 +00007437/*
7438** Return a RecoverTable object representing the orphans table.
7439*/
dan98c5ad32019-04-26 21:11:37 +00007440static RecoverTable *recoverOrphanTable(
dan0aa01ee2019-04-27 19:36:49 +00007441 ShellState *pState, /* Shell state object */
7442 int *pRc, /* IN/OUT: Error code */
7443 const char *zLostAndFound, /* Base name for orphans table */
7444 int nCol /* Number of user data columns */
dan98c5ad32019-04-26 21:11:37 +00007445){
7446 RecoverTable *pTab = 0;
7447 if( nCol>=0 && *pRc==SQLITE_OK ){
7448 int i;
dan42ebb012019-04-27 18:47:03 +00007449
7450 /* This block determines the name of the orphan table. The prefered
7451 ** name is zLostAndFound. But if that clashes with another name
7452 ** in the recovered schema, try zLostAndFound_0, zLostAndFound_1
7453 ** and so on until a non-clashing name is found. */
7454 int iTab = 0;
7455 char *zTab = shellMPrintf(pRc, "%s", zLostAndFound);
7456 sqlite3_stmt *pTest = 0;
7457 shellPrepare(pState->db, pRc,
7458 "SELECT 1 FROM recovery.schema WHERE name=?", &pTest
dan68cb86e2019-04-20 20:57:28 +00007459 );
dan42ebb012019-04-27 18:47:03 +00007460 if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
7461 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){
7462 shellReset(pRc, pTest);
7463 sqlite3_free(zTab);
7464 zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++);
7465 sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
dan68cb86e2019-04-20 20:57:28 +00007466 }
dan42ebb012019-04-27 18:47:03 +00007467 shellFinalize(pRc, pTest);
dan68cb86e2019-04-20 20:57:28 +00007468
dan98c5ad32019-04-26 21:11:37 +00007469 pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
7470 if( pTab ){
drha2de66c2019-08-06 20:26:17 +00007471 pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab);
dan98c5ad32019-04-26 21:11:37 +00007472 pTab->nCol = nCol;
7473 pTab->iPk = -2;
7474 if( nCol>0 ){
7475 pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1));
7476 if( pTab->azlCol ){
7477 pTab->azlCol[nCol] = shellMPrintf(pRc, "");
7478 for(i=nCol-1; i>=0; i--){
7479 pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]);
7480 }
7481 }
danb40af492019-04-22 20:52:12 +00007482 }
dan68cb86e2019-04-20 20:57:28 +00007483
dan42ebb012019-04-27 18:47:03 +00007484 if( *pRc!=SQLITE_OK ){
7485 recoverFreeTable(pTab);
7486 pTab = 0;
7487 }else{
7488 raw_printf(pState->out,
7489 "CREATE TABLE %s(rootpgno INTEGER, "
7490 "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted
7491 );
7492 for(i=0; i<nCol; i++){
7493 raw_printf(pState->out, ", c%d", i);
7494 }
7495 raw_printf(pState->out, ");\n");
7496 }
dan98c5ad32019-04-26 21:11:37 +00007497 }
dan42ebb012019-04-27 18:47:03 +00007498 sqlite3_free(zTab);
dan68cb86e2019-04-20 20:57:28 +00007499 }
dan98c5ad32019-04-26 21:11:37 +00007500 return pTab;
dan68cb86e2019-04-20 20:57:28 +00007501}
7502
7503/*
7504** This function is called to recover data from the database. A script
7505** to construct a new database containing all recovered data is output
7506** on stream pState->out.
7507*/
danb9b71db2019-04-25 16:20:40 +00007508static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
dan68cb86e2019-04-20 20:57:28 +00007509 int rc = SQLITE_OK;
7510 sqlite3_stmt *pLoop = 0; /* Loop through all root pages */
danefa363b2019-04-24 20:48:55 +00007511 sqlite3_stmt *pPages = 0; /* Loop through all pages in a group */
7512 sqlite3_stmt *pCells = 0; /* Loop through all cells in a page */
danc0b42432019-04-26 15:14:53 +00007513 const char *zRecoveryDb = ""; /* Name of "recovery" database */
dan42ebb012019-04-27 18:47:03 +00007514 const char *zLostAndFound = "lost_and_found";
dan9c014f82019-04-25 19:23:15 +00007515 int i;
dan98c5ad32019-04-26 21:11:37 +00007516 int nOrphan = -1;
7517 RecoverTable *pOrphan = 0;
dan9c014f82019-04-25 19:23:15 +00007518
7519 int bFreelist = 1; /* 0 if --freelist-corrupt is specified */
dan8cce6b82019-09-14 16:44:51 +00007520 int bRowids = 1; /* 0 if --no-rowids */
dan9c014f82019-04-25 19:23:15 +00007521 for(i=1; i<nArg; i++){
7522 char *z = azArg[i];
7523 int n;
7524 if( z[0]=='-' && z[1]=='-' ) z++;
drh4245e042019-06-13 13:52:46 +00007525 n = strlen30(z);
dan9c014f82019-04-25 19:23:15 +00007526 if( n<=17 && memcmp("-freelist-corrupt", z, n)==0 ){
7527 bFreelist = 0;
dan42ebb012019-04-27 18:47:03 +00007528 }else
danc0b42432019-04-26 15:14:53 +00007529 if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
7530 i++;
7531 zRecoveryDb = azArg[i];
dan42ebb012019-04-27 18:47:03 +00007532 }else
7533 if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
7534 i++;
7535 zLostAndFound = azArg[i];
dan8cce6b82019-09-14 16:44:51 +00007536 }else
7537 if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
7538 bRowids = 0;
danc0b42432019-04-26 15:14:53 +00007539 }
dan9c014f82019-04-25 19:23:15 +00007540 else{
drhe2754c12019-08-26 12:50:01 +00007541 utf8_printf(stderr, "unexpected option: %s\n", azArg[i]);
7542 showHelp(pState->out, azArg[0]);
dan9c014f82019-04-25 19:23:15 +00007543 return 1;
7544 }
7545 }
dan68cb86e2019-04-20 20:57:28 +00007546
danc0b42432019-04-26 15:14:53 +00007547 shellExecPrintf(pState->db, &rc,
dan68cb86e2019-04-20 20:57:28 +00007548 /* Attach an in-memory database named 'recovery'. Create an indexed
7549 ** cache of the sqlite_dbptr virtual table. */
dan01c08bc2019-07-24 19:20:30 +00007550 "PRAGMA writable_schema = on;"
danc0b42432019-04-26 15:14:53 +00007551 "ATTACH %Q AS recovery;"
7552 "DROP TABLE IF EXISTS recovery.dbptr;"
7553 "DROP TABLE IF EXISTS recovery.freelist;"
7554 "DROP TABLE IF EXISTS recovery.map;"
7555 "DROP TABLE IF EXISTS recovery.schema;"
danc0b42432019-04-26 15:14:53 +00007556 "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb
dan9c014f82019-04-25 19:23:15 +00007557 );
7558
7559 if( bFreelist ){
7560 shellExec(pState->db, &rc,
7561 "WITH trunk(pgno) AS ("
7562 " SELECT shell_int32("
7563 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x "
7564 " WHERE x>0"
7565 " UNION"
7566 " SELECT shell_int32("
7567 " (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x "
7568 " FROM trunk WHERE x>0"
7569 "),"
7570 "freelist(data, n, freepgno) AS ("
danf6099e92019-05-09 16:57:39 +00007571 " SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno "
dan9c014f82019-04-25 19:23:15 +00007572 " FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno"
7573 " UNION ALL"
7574 " SELECT data, n-1, shell_int32(data, 2+n) "
7575 " FROM freelist WHERE n>=0"
7576 ")"
7577 "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;"
7578 );
7579 }
7580
dan95063c22019-07-24 08:15:09 +00007581 /* If this is an auto-vacuum database, add all pointer-map pages to
7582 ** the freelist table. Do this regardless of whether or not
7583 ** --freelist-corrupt was specified. */
7584 shellExec(pState->db, &rc,
7585 "WITH ptrmap(pgno) AS ("
7586 " SELECT 2 WHERE shell_int32("
7587 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 13"
7588 " )"
7589 " UNION ALL "
7590 " SELECT pgno+1+(SELECT page_size FROM pragma_page_size)/5 AS pp "
7591 " FROM ptrmap WHERE pp<=(SELECT page_count FROM pragma_page_count)"
7592 ")"
7593 "REPLACE INTO recovery.freelist SELECT pgno FROM ptrmap"
7594 );
7595
dan9c014f82019-04-25 19:23:15 +00007596 shellExec(pState->db, &rc,
danca424382019-04-26 15:40:27 +00007597 "CREATE TABLE recovery.dbptr("
7598 " pgno, child, PRIMARY KEY(child, pgno)"
7599 ") WITHOUT ROWID;"
7600 "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) "
7601 " SELECT * FROM sqlite_dbptr"
7602 " WHERE pgno NOT IN freelist AND child NOT IN freelist;"
7603
7604 /* Delete any pointer to page 1. This ensures that page 1 is considered
7605 ** a root page, regardless of how corrupt the db is. */
7606 "DELETE FROM recovery.dbptr WHERE child = 1;"
7607
7608 /* Delete all pointers to any pages that have more than one pointer
7609 ** to them. Such pages will be treated as root pages when recovering
7610 ** data. */
7611 "DELETE FROM recovery.dbptr WHERE child IN ("
7612 " SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1"
7613 ");"
7614
dan68cb86e2019-04-20 20:57:28 +00007615 /* Create the "map" table that will (eventually) contain instructions
7616 ** for dealing with each page in the db that contains one or more
7617 ** records. */
danb40af492019-04-22 20:52:12 +00007618 "CREATE TABLE recovery.map("
7619 "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT"
7620 ");"
dan68cb86e2019-04-20 20:57:28 +00007621
7622 /* Populate table [map]. If there are circular loops of pages in the
7623 ** database, the following adds all pages in such a loop to the map
7624 ** as individual root pages. This could be handled better. */
7625 "WITH pages(i, maxlen) AS ("
danb9b71db2019-04-25 16:20:40 +00007626 " SELECT page_count, ("
7627 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count"
dan13b87672019-05-09 11:45:21 +00007628 " ) FROM pragma_page_count WHERE page_count>0"
dan68cb86e2019-04-20 20:57:28 +00007629 " UNION ALL"
danb40af492019-04-22 20:52:12 +00007630 " SELECT i-1, ("
7631 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1"
7632 " ) FROM pages WHERE i>=2"
dan68cb86e2019-04-20 20:57:28 +00007633 ")"
danb40af492019-04-22 20:52:12 +00007634 "INSERT INTO recovery.map(pgno, maxlen, intkey, root) "
7635 " SELECT i, maxlen, NULL, ("
dan68cb86e2019-04-20 20:57:28 +00007636 " WITH p(orig, pgno, parent) AS ("
7637 " SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)"
dan39e04f82019-05-09 18:33:32 +00007638 " UNION "
dan68cb86e2019-04-20 20:57:28 +00007639 " SELECT i, p.parent, "
7640 " (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p"
7641 " )"
7642 " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
7643 ") "
dand790c9a2019-08-26 14:57:58 +00007644 "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;"
danb40af492019-04-22 20:52:12 +00007645 "UPDATE recovery.map AS o SET intkey = ("
7646 " SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
7647 ");"
dan68cb86e2019-04-20 20:57:28 +00007648
7649 /* Extract data from page 1 and any linked pages into table
drh067b92b2020-06-19 15:24:12 +00007650 ** recovery.schema. With the same schema as an sqlite_schema table. */
dan68cb86e2019-04-20 20:57:28 +00007651 "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
7652 "INSERT INTO recovery.schema SELECT "
7653 " max(CASE WHEN field=0 THEN value ELSE NULL END),"
7654 " max(CASE WHEN field=1 THEN value ELSE NULL END),"
7655 " max(CASE WHEN field=2 THEN value ELSE NULL END),"
7656 " max(CASE WHEN field=3 THEN value ELSE NULL END),"
7657 " max(CASE WHEN field=4 THEN value ELSE NULL END)"
7658 "FROM sqlite_dbdata WHERE pgno IN ("
7659 " SELECT pgno FROM recovery.map WHERE root=1"
7660 ")"
7661 "GROUP BY pgno, cell;"
dan98c5ad32019-04-26 21:11:37 +00007662 "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);"
dan68cb86e2019-04-20 20:57:28 +00007663 );
7664
danb40af492019-04-22 20:52:12 +00007665 /* Open a transaction, then print out all non-virtual, non-"sqlite_%"
7666 ** CREATE TABLE statements that extracted from the existing schema. */
7667 if( rc==SQLITE_OK ){
7668 sqlite3_stmt *pStmt = 0;
danf3210572019-08-06 18:40:36 +00007669 /* ".recover" might output content in an order which causes immediate
7670 ** foreign key constraints to be violated. So disable foreign-key
7671 ** constraint enforcement to prevent problems when running the output
7672 ** script. */
7673 raw_printf(pState->out, "PRAGMA foreign_keys=OFF;\n");
danb40af492019-04-22 20:52:12 +00007674 raw_printf(pState->out, "BEGIN;\n");
dan38f9c712019-04-23 18:03:02 +00007675 raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
7676 shellPrepare(pState->db, &rc,
danb40af492019-04-22 20:52:12 +00007677 "SELECT sql FROM recovery.schema "
dan38f9c712019-04-23 18:03:02 +00007678 "WHERE type='table' AND sql LIKE 'create table%'", &pStmt
danb40af492019-04-22 20:52:12 +00007679 );
7680 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7681 const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0);
dan38f9c712019-04-23 18:03:02 +00007682 raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n",
7683 &zCreateTable[12]
7684 );
danb40af492019-04-22 20:52:12 +00007685 }
7686 shellFinalize(&rc, pStmt);
7687 }
7688
dan98c5ad32019-04-26 21:11:37 +00007689 /* Figure out if an orphan table will be required. And if so, how many
7690 ** user columns it should contain */
7691 shellPrepare(pState->db, &rc,
dan98779652019-05-09 14:15:19 +00007692 "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1"
dan98c5ad32019-04-26 21:11:37 +00007693 , &pLoop
7694 );
7695 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
7696 nOrphan = sqlite3_column_int(pLoop, 0);
7697 }
7698 shellFinalize(&rc, pLoop);
7699 pLoop = 0;
dan98c5ad32019-04-26 21:11:37 +00007700
danefa363b2019-04-24 20:48:55 +00007701 shellPrepare(pState->db, &rc,
7702 "SELECT pgno FROM recovery.map WHERE root=?", &pPages
7703 );
dan8cce6b82019-09-14 16:44:51 +00007704
danefa363b2019-04-24 20:48:55 +00007705 shellPrepare(pState->db, &rc,
dan8cce6b82019-09-14 16:44:51 +00007706 "SELECT max(field), group_concat(shell_escape_crnl(quote"
7707 "(case when (? AND field<0) then NULL else value end)"
7708 "), ', ')"
dan9443dbc2019-07-24 20:10:27 +00007709 ", min(field) "
danefa363b2019-04-24 20:48:55 +00007710 "FROM sqlite_dbdata WHERE pgno = ? AND field != ?"
7711 "GROUP BY cell", &pCells
7712 );
7713
dan68cb86e2019-04-20 20:57:28 +00007714 /* Loop through each root page. */
danb40af492019-04-22 20:52:12 +00007715 shellPrepare(pState->db, &rc,
7716 "SELECT root, intkey, max(maxlen) FROM recovery.map"
dan38f9c712019-04-23 18:03:02 +00007717 " WHERE root>1 GROUP BY root, intkey ORDER BY root=("
7718 " SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'"
7719 ")", &pLoop
danb40af492019-04-22 20:52:12 +00007720 );
dan68cb86e2019-04-20 20:57:28 +00007721 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
7722 int iRoot = sqlite3_column_int(pLoop, 0);
danb40af492019-04-22 20:52:12 +00007723 int bIntkey = sqlite3_column_int(pLoop, 1);
7724 int nCol = sqlite3_column_int(pLoop, 2);
dan98c5ad32019-04-26 21:11:37 +00007725 int bNoop = 0;
dan68cb86e2019-04-20 20:57:28 +00007726 RecoverTable *pTab;
7727
dan9443dbc2019-07-24 20:10:27 +00007728 assert( bIntkey==0 || bIntkey==1 );
dan42ebb012019-04-27 18:47:03 +00007729 pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);
dan98c5ad32019-04-26 21:11:37 +00007730 if( bNoop || rc ) continue;
dan98779652019-05-09 14:15:19 +00007731 if( pTab==0 ){
7732 if( pOrphan==0 ){
7733 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
7734 }
7735 pTab = pOrphan;
7736 if( pTab==0 ) break;
7737 }
dan98c5ad32019-04-26 21:11:37 +00007738
drha2de66c2019-08-06 20:26:17 +00007739 if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){
dan98c5ad32019-04-26 21:11:37 +00007740 raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
7741 }
7742 sqlite3_bind_int(pPages, 1, iRoot);
dan8cce6b82019-09-14 16:44:51 +00007743 if( bRowids==0 && pTab->iPk<0 ){
7744 sqlite3_bind_int(pCells, 1, 1);
7745 }else{
7746 sqlite3_bind_int(pCells, 1, 0);
7747 }
7748 sqlite3_bind_int(pCells, 3, pTab->iPk);
dan98c5ad32019-04-26 21:11:37 +00007749
7750 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){
7751 int iPgno = sqlite3_column_int(pPages, 0);
dan8cce6b82019-09-14 16:44:51 +00007752 sqlite3_bind_int(pCells, 2, iPgno);
dan98c5ad32019-04-26 21:11:37 +00007753 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){
7754 int nField = sqlite3_column_int(pCells, 0);
dan9443dbc2019-07-24 20:10:27 +00007755 int iMin = sqlite3_column_int(pCells, 2);
dan98c5ad32019-04-26 21:11:37 +00007756 const char *zVal = (const char*)sqlite3_column_text(pCells, 1);
7757
dan9443dbc2019-07-24 20:10:27 +00007758 RecoverTable *pTab2 = pTab;
7759 if( pTab!=pOrphan && (iMin<0)!=bIntkey ){
7760 if( pOrphan==0 ){
7761 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
7762 }
7763 pTab2 = pOrphan;
7764 if( pTab2==0 ) break;
7765 }
7766
dan98c5ad32019-04-26 21:11:37 +00007767 nField = nField+1;
dan9443dbc2019-07-24 20:10:27 +00007768 if( pTab2==pOrphan ){
dan98c5ad32019-04-26 21:11:37 +00007769 raw_printf(pState->out,
7770 "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",
dan9443dbc2019-07-24 20:10:27 +00007771 pTab2->zQuoted, iRoot, iPgno, nField,
7772 iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField]
dan98c5ad32019-04-26 21:11:37 +00007773 );
7774 }else{
danefa363b2019-04-24 20:48:55 +00007775 raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n",
dan9443dbc2019-07-24 20:10:27 +00007776 pTab2->zQuoted, pTab2->azlCol[nField], zVal
danefa363b2019-04-24 20:48:55 +00007777 );
7778 }
dan68cb86e2019-04-20 20:57:28 +00007779 }
dan98c5ad32019-04-26 21:11:37 +00007780 shellReset(&rc, pCells);
dan68cb86e2019-04-20 20:57:28 +00007781 }
dan98c5ad32019-04-26 21:11:37 +00007782 shellReset(&rc, pPages);
7783 if( pTab!=pOrphan ) recoverFreeTable(pTab);
dan68cb86e2019-04-20 20:57:28 +00007784 }
7785 shellFinalize(&rc, pLoop);
danefa363b2019-04-24 20:48:55 +00007786 shellFinalize(&rc, pPages);
7787 shellFinalize(&rc, pCells);
dan98c5ad32019-04-26 21:11:37 +00007788 recoverFreeTable(pOrphan);
dan68cb86e2019-04-20 20:57:28 +00007789
dan38f9c712019-04-23 18:03:02 +00007790 /* The rest of the schema */
danb40af492019-04-22 20:52:12 +00007791 if( rc==SQLITE_OK ){
dan38f9c712019-04-23 18:03:02 +00007792 sqlite3_stmt *pStmt = 0;
7793 shellPrepare(pState->db, &rc,
7794 "SELECT sql, name FROM recovery.schema "
danb1825882019-04-23 20:48:32 +00007795 "WHERE sql NOT LIKE 'create table%'", &pStmt
dan38f9c712019-04-23 18:03:02 +00007796 );
7797 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7798 const char *zSql = (const char*)sqlite3_column_text(pStmt, 0);
7799 if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){
7800 const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
7801 char *zPrint = shellMPrintf(&rc,
drh067b92b2020-06-19 15:24:12 +00007802 "INSERT INTO sqlite_schema VALUES('table', %Q, %Q, 0, %Q)",
dan38f9c712019-04-23 18:03:02 +00007803 zName, zName, zSql
7804 );
7805 raw_printf(pState->out, "%s;\n", zPrint);
7806 sqlite3_free(zPrint);
7807 }else{
7808 raw_printf(pState->out, "%s;\n", zSql);
7809 }
7810 }
7811 shellFinalize(&rc, pStmt);
7812 }
7813
7814 if( rc==SQLITE_OK ){
7815 raw_printf(pState->out, "PRAGMA writable_schema = off;\n");
danb40af492019-04-22 20:52:12 +00007816 raw_printf(pState->out, "COMMIT;\n");
7817 }
dan68cb86e2019-04-20 20:57:28 +00007818 sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
7819 return rc;
7820}
dan1b162162019-04-27 20:15:15 +00007821#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
dan68cb86e2019-04-20 20:57:28 +00007822
larrybr42de1c52022-02-13 22:18:22 +00007823
7824/*
7825 * zAutoColumn(zCol, &db, ?) => Maybe init db, add column zCol to it.
7826 * zAutoColumn(0, &db, ?) => (db!=0) Form columns spec for CREATE TABLE,
7827 * close db and set it to 0, and return the columns spec, to later
7828 * be sqlite3_free()'ed by the caller.
7829 * The return is 0 when either:
7830 * (a) The db was not initialized and zCol==0 (There are no columns.)
7831 * (b) zCol!=0 (Column was added, db initialized as needed.)
7832 * The 3rd argument, pRenamed, references an out parameter. If the
larrybr33633862022-02-14 01:12:46 +00007833 * pointer is non-zero, its referent will be set to a summary of renames
7834 * done if renaming was necessary, or set to 0 if none was done. The out
7835 * string (if any) must be sqlite3_free()'ed by the caller.
larrybr42de1c52022-02-13 22:18:22 +00007836 */
7837#ifdef SHELL_DEBUG
7838#define rc_err_oom_die(rc) \
7839 if( rc==SQLITE_NOMEM ) shell_check_oom(0); \
7840 else if(!(rc==SQLITE_OK||rc==SQLITE_DONE)) \
7841 fprintf(stderr,"E:%d\n",rc), assert(0)
7842#else
7843static void rc_err_oom_die(int rc){
7844 if( rc==SQLITE_NOMEM ) shell_check_oom(0);
7845 assert(rc==SQLITE_OK||rc==SQLITE_DONE);
7846}
7847#endif
7848
7849#ifdef SHELL_COLFIX_DB /* If this is set, the DB can be in a file. */
7850static char zCOL_DB[] = SHELL_STRINGIFY(SHELL_COLFIX_DB);
7851#else /* Otherwise, memory is faster/better for the transient DB. */
7852static const char *zCOL_DB = ":memory:";
7853#endif
7854
7855/* Define character (as C string) to separate generated column ordinal
7856 * from protected part of incoming column names. This defaults to "_"
7857 * so that incoming column identifiers that did not need not be quoted
7858 * remain usable without being quoted. It must be one character.
7859 */
7860#ifndef SHELL_AUTOCOLUMN_SEP
7861# define AUTOCOLUMN_SEP "_"
7862#else
7863# define AUTOCOLUMN_SEP SHELL_STRINGIFY(SHELL_AUTOCOLUMN_SEP)
7864#endif
7865
larrybr33633862022-02-14 01:12:46 +00007866static char *zAutoColumn(const char *zColNew, sqlite3 **pDb, char **pzRenamed){
larrybr42de1c52022-02-13 22:18:22 +00007867 /* Queries and D{D,M}L used here */
7868 static const char * const zTabMake = "\
7869CREATE TABLE ColNames(\
7870 cpos INTEGER PRIMARY KEY,\
larrybr33633862022-02-14 01:12:46 +00007871 name TEXT, nlen INT, chop INT, reps INT, suff TEXT);\
7872CREATE VIEW RepeatedNames AS \
7873SELECT DISTINCT t.name FROM ColNames t \
7874WHERE t.name COLLATE NOCASE IN (\
7875 SELECT o.name FROM ColNames o WHERE o.cpos<>t.cpos\
7876);\
larrybr42de1c52022-02-13 22:18:22 +00007877";
7878 static const char * const zTabFill = "\
7879INSERT INTO ColNames(name,nlen,chop,reps,suff)\
7880 VALUES(iif(length(?1)>0,?1,'?'),max(length(?1),1),0,0,'')\
7881";
7882 static const char * const zHasDupes = "\
7883SELECT count(DISTINCT (substring(name,1,nlen-chop)||suff) COLLATE NOCASE)\
7884 <count(name) FROM ColNames\
7885";
larrybr33633862022-02-14 01:12:46 +00007886#ifdef SHELL_COLUMN_RENAME_CLEAN
larrybr42de1c52022-02-13 22:18:22 +00007887 static const char * const zDedoctor = "\
7888UPDATE ColNames SET chop=iif(\
7889 (substring(name,nlen,1) BETWEEN '0' AND '9')\
7890 AND (rtrim(name,'0123456790') glob '*"AUTOCOLUMN_SEP"'),\
7891 nlen-length(rtrim(name, '"AUTOCOLUMN_SEP"0123456789')),\
7892 0\
7893)\
7894";
larrybr33633862022-02-14 01:12:46 +00007895#endif
larrybr42de1c52022-02-13 22:18:22 +00007896 static const char * const zSetReps = "\
7897UPDATE ColNames AS t SET reps=\
7898(SELECT count(*) FROM ColNames d \
7899 WHERE substring(t.name,1,t.nlen-t.chop)=substring(d.name,1,d.nlen-d.chop)\
7900 COLLATE NOCASE\
7901)\
7902";
7903#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
7904 static const char * const zColDigits = "\
7905SELECT CAST(ceil(log(count(*)+0.5)) AS INT) FROM ColNames \
7906";
7907#endif
7908 static const char * const zRenameRank =
larrybr33633862022-02-14 01:12:46 +00007909#ifdef SHELL_COLUMN_RENAME_CLEAN
larrybr42de1c52022-02-13 22:18:22 +00007910 "UPDATE ColNames AS t SET suff="
7911 "iif(reps>1, printf('%c%0*d', '"AUTOCOLUMN_SEP"', $1, cpos), '')"
larrybr33633862022-02-14 01:12:46 +00007912#else /* ...RENAME_MINIMAL_ONE_PASS */
7913"WITH Lzn(nlz) AS (" /* Find minimum extraneous leading 0's for uniqueness */
7914" SELECT 0 AS nlz"
7915" UNION"
7916" SELECT nlz+1 AS nlz FROM Lzn"
7917" WHERE EXISTS("
7918" SELECT 1"
7919" FROM ColNames t, ColNames o"
7920" WHERE"
7921" iif(t.name IN (SELECT * FROM RepeatedNames),"
7922" printf('%s"AUTOCOLUMN_SEP"%s',"
7923" t.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,t.cpos),2)),"
7924" t.name"
7925" )"
7926" ="
7927" iif(o.name IN (SELECT * FROM RepeatedNames),"
7928" printf('%s"AUTOCOLUMN_SEP"%s',"
7929" o.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,o.cpos),2)),"
7930" o.name"
7931" )"
7932" COLLATE NOCASE"
7933" AND o.cpos<>t.cpos"
7934" GROUP BY t.cpos"
7935" )"
7936") UPDATE Colnames AS t SET"
7937" chop = 0," /* No chopping, never touch incoming names. */
7938" suff = iif(name IN (SELECT * FROM RepeatedNames),"
7939" printf('"AUTOCOLUMN_SEP"%s', substring("
7940" printf('%.*c%0.*d',(SELECT max(nlz) FROM Lzn)+1,'0',1,t.cpos),2)),"
7941" ''"
7942" )"
larrybr42de1c52022-02-13 22:18:22 +00007943#endif
7944 ;
7945 static const char * const zCollectVar = "\
7946SELECT\
7947 '('||x'0a'\
7948 || group_concat(\
7949 cname||' TEXT',\
7950 ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\
7951 ||')' AS ColsSpec \
7952FROM (\
7953 SELECT cpos, printf('\"%w\"',printf('%.*s%s', nlen-chop,name,suff)) AS cname \
7954 FROM ColNames ORDER BY cpos\
7955)";
larrybr33633862022-02-14 01:12:46 +00007956 static const char * const zRenamesDone =
7957 "SELECT group_concat("
7958 " printf('\"%w\" to \"%w\"',name,printf('%.*s%s', nlen-chop, name, suff)),"
7959 " ','||x'0a')"
7960 "FROM ColNames WHERE suff<>'' OR chop!=0"
7961 ;
larrybr42de1c52022-02-13 22:18:22 +00007962 int rc;
7963 sqlite3_stmt *pStmt = 0;
7964 assert(pDb!=0);
7965 if( zColNew ){
7966 /* Add initial or additional column. Init db if necessary. */
7967 if( *pDb==0 ){
7968 if( SQLITE_OK!=sqlite3_open(zCOL_DB, pDb) ) return 0;
7969#ifdef SHELL_COLFIX_DB
7970 if(*zCOL_DB!=':')
larrybr33633862022-02-14 01:12:46 +00007971 sqlite3_exec(*pDb,"drop table if exists ColNames;"
7972 "drop view if exists RepeatedNames;",0,0,0);
larrybr42de1c52022-02-13 22:18:22 +00007973#endif
7974 rc = sqlite3_exec(*pDb, zTabMake, 0, 0, 0);
7975 rc_err_oom_die(rc);
7976 }
7977 assert(*pDb!=0);
7978 rc = sqlite3_prepare_v2(*pDb, zTabFill, -1, &pStmt, 0);
7979 rc_err_oom_die(rc);
7980 rc = sqlite3_bind_text(pStmt, 1, zColNew, -1, 0);
7981 rc_err_oom_die(rc);
7982 rc = sqlite3_step(pStmt);
7983 rc_err_oom_die(rc);
7984 sqlite3_finalize(pStmt);
7985 return 0;
7986 }else if( *pDb==0 ){
7987 return 0;
7988 }else{
7989 /* Formulate the columns spec, close the DB, zero *pDb. */
7990 char *zColsSpec = 0;
7991 int hasDupes = db_int(*pDb, zHasDupes);
7992#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
7993 int nDigits = (hasDupes)? db_int(*pDb, zColDigits) : 0;
7994#else
7995# define nDigits 2
7996#endif
7997 if( hasDupes ){
larrybr33633862022-02-14 01:12:46 +00007998#ifdef SHELL_COLUMN_RENAME_CLEAN
larrybr42de1c52022-02-13 22:18:22 +00007999 rc = sqlite3_exec(*pDb, zDedoctor, 0, 0, 0);
8000 rc_err_oom_die(rc);
larrybr33633862022-02-14 01:12:46 +00008001#endif
larrybr42de1c52022-02-13 22:18:22 +00008002 rc = sqlite3_exec(*pDb, zSetReps, 0, 0, 0);
8003 rc_err_oom_die(rc);
8004 rc = sqlite3_prepare_v2(*pDb, zRenameRank, -1, &pStmt, 0);
8005 rc_err_oom_die(rc);
8006 sqlite3_bind_int(pStmt, 1, nDigits);
8007 rc = sqlite3_step(pStmt);
8008 sqlite3_finalize(pStmt);
8009 assert(rc==SQLITE_DONE);
8010 }
8011 assert(db_int(*pDb, zHasDupes)==0); /* Consider: remove this */
8012 rc = sqlite3_prepare_v2(*pDb, zCollectVar, -1, &pStmt, 0);
8013 rc_err_oom_die(rc);
8014 rc = sqlite3_step(pStmt);
8015 if( rc==SQLITE_ROW ){
8016 zColsSpec = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
8017 }else{
8018 zColsSpec = 0;
8019 }
larrybr33633862022-02-14 01:12:46 +00008020 if( pzRenamed!=0 ){
8021 if( !hasDupes ) *pzRenamed = 0;
8022 else{
8023 sqlite3_finalize(pStmt);
8024 if( SQLITE_OK==sqlite3_prepare_v2(*pDb, zRenamesDone, -1, &pStmt, 0)
8025 && SQLITE_ROW==sqlite3_step(pStmt) ){
8026 *pzRenamed = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
8027 }else
8028 *pzRenamed = 0;
8029 }
8030 }
larrybr42de1c52022-02-13 22:18:22 +00008031 sqlite3_finalize(pStmt);
8032 sqlite3_close(*pDb);
8033 *pDb = 0;
8034 return zColsSpec;
8035 }
8036}
8037
drh2ce15c32017-07-11 13:34:40 +00008038/*
8039** If an input line begins with "." then invoke this routine to
8040** process that line.
8041**
8042** Return 1 on error, 2 to exit, and 0 otherwise.
8043*/
8044static int do_meta_command(char *zLine, ShellState *p){
8045 int h = 1;
8046 int nArg = 0;
8047 int n, c;
8048 int rc = 0;
drh5df84282019-08-17 19:45:25 +00008049 char *azArg[52];
drh2ce15c32017-07-11 13:34:40 +00008050
dan6b046be2018-01-09 15:25:55 +00008051#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00008052 if( p->expert.pExpert ){
8053 expertFinish(p, 1, 0);
8054 }
dan6b046be2018-01-09 15:25:55 +00008055#endif
dan43efc182017-12-19 17:42:13 +00008056
drh2ce15c32017-07-11 13:34:40 +00008057 /* Parse the input line into tokens.
8058 */
drh5df84282019-08-17 19:45:25 +00008059 while( zLine[h] && nArg<ArraySize(azArg)-1 ){
drh2ce15c32017-07-11 13:34:40 +00008060 while( IsSpace(zLine[h]) ){ h++; }
8061 if( zLine[h]==0 ) break;
8062 if( zLine[h]=='\'' || zLine[h]=='"' ){
8063 int delim = zLine[h++];
8064 azArg[nArg++] = &zLine[h];
8065 while( zLine[h] && zLine[h]!=delim ){
8066 if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
8067 h++;
8068 }
8069 if( zLine[h]==delim ){
8070 zLine[h++] = 0;
8071 }
8072 if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
8073 }else{
8074 azArg[nArg++] = &zLine[h];
8075 while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
8076 if( zLine[h] ) zLine[h++] = 0;
8077 resolve_backslashes(azArg[nArg-1]);
8078 }
8079 }
drh5df84282019-08-17 19:45:25 +00008080 azArg[nArg] = 0;
drh2ce15c32017-07-11 13:34:40 +00008081
8082 /* Process the input line.
8083 */
8084 if( nArg==0 ) return 0; /* no tokens, no error */
8085 n = strlen30(azArg[0]);
8086 c = azArg[0][0];
drh13c20932018-01-10 21:41:55 +00008087 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +00008088
8089#ifndef SQLITE_OMIT_AUTHORIZATION
8090 if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
8091 if( nArg!=2 ){
8092 raw_printf(stderr, "Usage: .auth ON|OFF\n");
8093 rc = 1;
8094 goto meta_command_exit;
8095 }
8096 open_db(p, 0);
8097 if( booleanValue(azArg[1]) ){
8098 sqlite3_set_authorizer(p->db, shellAuth, p);
drhb97e2ad2021-08-26 18:31:39 +00008099 }else if( p->bSafeModePersist ){
8100 sqlite3_set_authorizer(p->db, safeModeAuth, p);
drh2ce15c32017-07-11 13:34:40 +00008101 }else{
8102 sqlite3_set_authorizer(p->db, 0, 0);
8103 }
8104 }else
8105#endif
8106
drhe37c0e12018-01-06 19:19:50 +00008107#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
8108 if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
danfd0245d2017-12-07 15:44:29 +00008109 open_db(p, 0);
drhb97e2ad2021-08-26 18:31:39 +00008110 failIfSafeMode(p, "cannot run .archive in safe mode");
drhd0f9cdc2018-05-17 14:09:06 +00008111 rc = arDotCommand(p, 0, azArg, nArg);
danfd0245d2017-12-07 15:44:29 +00008112 }else
8113#endif
8114
drh2ce15c32017-07-11 13:34:40 +00008115 if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
8116 || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
8117 ){
8118 const char *zDestFile = 0;
8119 const char *zDb = 0;
8120 sqlite3 *pDest;
8121 sqlite3_backup *pBackup;
8122 int j;
drha50bffb2018-12-08 01:09:14 +00008123 int bAsync = 0;
drh69ed38a2018-05-14 00:23:08 +00008124 const char *zVfs = 0;
drhb97e2ad2021-08-26 18:31:39 +00008125 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00008126 for(j=1; j<nArg; j++){
8127 const char *z = azArg[j];
8128 if( z[0]=='-' ){
drh69ed38a2018-05-14 00:23:08 +00008129 if( z[1]=='-' ) z++;
8130 if( strcmp(z, "-append")==0 ){
8131 zVfs = "apndvfs";
8132 }else
drha50bffb2018-12-08 01:09:14 +00008133 if( strcmp(z, "-async")==0 ){
8134 bAsync = 1;
8135 }else
drh2ce15c32017-07-11 13:34:40 +00008136 {
8137 utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
8138 return 1;
8139 }
8140 }else if( zDestFile==0 ){
8141 zDestFile = azArg[j];
8142 }else if( zDb==0 ){
8143 zDb = zDestFile;
8144 zDestFile = azArg[j];
8145 }else{
drha50bffb2018-12-08 01:09:14 +00008146 raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
drh2ce15c32017-07-11 13:34:40 +00008147 return 1;
8148 }
8149 }
8150 if( zDestFile==0 ){
8151 raw_printf(stderr, "missing FILENAME argument on .backup\n");
8152 return 1;
8153 }
8154 if( zDb==0 ) zDb = "main";
drh69ed38a2018-05-14 00:23:08 +00008155 rc = sqlite3_open_v2(zDestFile, &pDest,
8156 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
drh2ce15c32017-07-11 13:34:40 +00008157 if( rc!=SQLITE_OK ){
8158 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
drh9e804032018-05-18 17:11:50 +00008159 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00008160 return 1;
8161 }
drha50bffb2018-12-08 01:09:14 +00008162 if( bAsync ){
8163 sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
8164 0, 0, 0);
8165 }
drh2ce15c32017-07-11 13:34:40 +00008166 open_db(p, 0);
8167 pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
8168 if( pBackup==0 ){
8169 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
drh9e804032018-05-18 17:11:50 +00008170 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00008171 return 1;
8172 }
8173 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
8174 sqlite3_backup_finish(pBackup);
8175 if( rc==SQLITE_DONE ){
8176 rc = 0;
8177 }else{
8178 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
8179 rc = 1;
8180 }
drh9e804032018-05-18 17:11:50 +00008181 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00008182 }else
8183
8184 if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
8185 if( nArg==2 ){
8186 bail_on_error = booleanValue(azArg[1]);
8187 }else{
8188 raw_printf(stderr, "Usage: .bail on|off\n");
8189 rc = 1;
8190 }
8191 }else
8192
8193 if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
8194 if( nArg==2 ){
8195 if( booleanValue(azArg[1]) ){
8196 setBinaryMode(p->out, 1);
8197 }else{
8198 setTextMode(p->out, 1);
8199 }
8200 }else{
8201 raw_printf(stderr, "Usage: .binary on|off\n");
8202 rc = 1;
8203 }
8204 }else
8205
drh37407122021-07-23 18:43:58 +00008206 /* The undocumented ".breakpoint" command causes a call to the no-op
8207 ** routine named test_breakpoint().
8208 */
8209 if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
8210 test_breakpoint();
8211 }else
8212
drh2ce15c32017-07-11 13:34:40 +00008213 if( c=='c' && strcmp(azArg[0],"cd")==0 ){
drhb97e2ad2021-08-26 18:31:39 +00008214 failIfSafeMode(p, "cannot run .cd in safe mode");
drh2ce15c32017-07-11 13:34:40 +00008215 if( nArg==2 ){
8216#if defined(_WIN32) || defined(WIN32)
8217 wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
8218 rc = !SetCurrentDirectoryW(z);
8219 sqlite3_free(z);
8220#else
8221 rc = chdir(azArg[1]);
8222#endif
8223 if( rc ){
8224 utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
8225 rc = 1;
8226 }
8227 }else{
8228 raw_printf(stderr, "Usage: .cd DIRECTORY\n");
8229 rc = 1;
8230 }
8231 }else
8232
drh2ce15c32017-07-11 13:34:40 +00008233 if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
8234 if( nArg==2 ){
8235 setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
8236 }else{
8237 raw_printf(stderr, "Usage: .changes on|off\n");
8238 rc = 1;
8239 }
8240 }else
8241
8242 /* Cancel output redirection, if it is currently set (by .testcase)
8243 ** Then read the content of the testcase-out.txt file and compare against
8244 ** azArg[1]. If there are differences, report an error and exit.
8245 */
8246 if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
8247 char *zRes = 0;
8248 output_reset(p);
8249 if( nArg!=2 ){
8250 raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
8251 rc = 2;
8252 }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
8253 raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
8254 rc = 2;
8255 }else if( testcase_glob(azArg[1],zRes)==0 ){
8256 utf8_printf(stderr,
8257 "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
8258 p->zTestcase, azArg[1], zRes);
drhf30d3452017-10-17 13:44:46 +00008259 rc = 1;
drh2ce15c32017-07-11 13:34:40 +00008260 }else{
8261 utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
8262 p->nCheck++;
8263 }
8264 sqlite3_free(zRes);
8265 }else
8266
8267 if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
drhb97e2ad2021-08-26 18:31:39 +00008268 failIfSafeMode(p, "cannot run .clone in safe mode");
drh2ce15c32017-07-11 13:34:40 +00008269 if( nArg==2 ){
8270 tryToClone(p, azArg[1]);
8271 }else{
8272 raw_printf(stderr, "Usage: .clone FILENAME\n");
8273 rc = 1;
8274 }
8275 }else
8276
drh37407122021-07-23 18:43:58 +00008277 if( c=='c' && strncmp(azArg[0], "connection", n)==0 ){
8278 if( nArg==1 ){
8279 /* List available connections */
8280 int i;
8281 for(i=0; i<ArraySize(p->aAuxDb); i++){
8282 const char *zFile = p->aAuxDb[i].zDbFilename;
8283 if( p->aAuxDb[i].db==0 && p->pAuxDb!=&p->aAuxDb[i] ){
8284 zFile = "(not open)";
8285 }else if( zFile==0 ){
8286 zFile = "(memory)";
8287 }else if( zFile[0]==0 ){
8288 zFile = "(temporary-file)";
8289 }
8290 if( p->pAuxDb == &p->aAuxDb[i] ){
8291 utf8_printf(stdout, "ACTIVE %d: %s\n", i, zFile);
8292 }else if( p->aAuxDb[i].db!=0 ){
8293 utf8_printf(stdout, " %d: %s\n", i, zFile);
8294 }
8295 }
8296 }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){
8297 int i = azArg[1][0] - '0';
8298 if( p->pAuxDb != &p->aAuxDb[i] && i>=0 && i<ArraySize(p->aAuxDb) ){
8299 p->pAuxDb->db = p->db;
8300 p->pAuxDb = &p->aAuxDb[i];
8301 globalDb = p->db = p->pAuxDb->db;
8302 p->pAuxDb->db = 0;
8303 }
8304 }else if( nArg==3 && strcmp(azArg[1], "close")==0
8305 && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){
8306 int i = azArg[2][0] - '0';
8307 if( i<0 || i>=ArraySize(p->aAuxDb) ){
8308 /* No-op */
8309 }else if( p->pAuxDb == &p->aAuxDb[i] ){
8310 raw_printf(stderr, "cannot close the active database connection\n");
8311 rc = 1;
8312 }else if( p->aAuxDb[i].db ){
8313 session_close_all(p, i);
8314 close_db(p->aAuxDb[i].db);
8315 p->aAuxDb[i].db = 0;
8316 }
8317 }else{
8318 raw_printf(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n");
8319 rc = 1;
8320 }
8321 }else
8322
drh2ce15c32017-07-11 13:34:40 +00008323 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
drh60081a02020-08-26 19:07:18 +00008324 char **azName = 0;
8325 int nName = 0;
8326 sqlite3_stmt *pStmt;
drh60081a02020-08-26 19:07:18 +00008327 int i;
drh2ce15c32017-07-11 13:34:40 +00008328 open_db(p, 0);
drh60081a02020-08-26 19:07:18 +00008329 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
8330 if( rc ){
8331 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh2ce15c32017-07-11 13:34:40 +00008332 rc = 1;
drh60081a02020-08-26 19:07:18 +00008333 }else{
8334 while( sqlite3_step(pStmt)==SQLITE_ROW ){
8335 const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
8336 const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
drh621a5e02021-12-16 17:35:27 +00008337 if( zSchema==0 || zFile==0 ) continue;
drh60081a02020-08-26 19:07:18 +00008338 azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
drhe3e25652021-12-16 13:29:28 +00008339 shell_check_oom(azName);
drh60081a02020-08-26 19:07:18 +00008340 azName[nName*2] = strdup(zSchema);
8341 azName[nName*2+1] = strdup(zFile);
8342 nName++;
8343 }
drh2ce15c32017-07-11 13:34:40 +00008344 }
drh60081a02020-08-26 19:07:18 +00008345 sqlite3_finalize(pStmt);
8346 for(i=0; i<nName; i++){
8347 int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
8348 int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
8349 const char *z = azName[i*2+1];
8350 utf8_printf(p->out, "%s: %s %s%s\n",
8351 azName[i*2],
8352 z && z[0] ? z : "\"\"",
8353 bRdonly ? "r/o" : "r/w",
8354 eTxn==SQLITE_TXN_NONE ? "" :
8355 eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
8356 free(azName[i*2]);
8357 free(azName[i*2+1]);
8358 }
8359 sqlite3_free(azName);
drh2ce15c32017-07-11 13:34:40 +00008360 }else
8361
drh7df01192018-04-28 12:43:16 +00008362 if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
drheb7f2a02018-09-26 18:02:32 +00008363 static const struct DbConfigChoices {
8364 const char *zName;
8365 int op;
8366 } aDbConfig[] = {
drhb945bcd2019-12-31 22:52:10 +00008367 { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
8368 { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL },
8369 { "dqs_dml", SQLITE_DBCONFIG_DQS_DML },
drh0a6873b2019-06-14 21:25:25 +00008370 { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
drhb945bcd2019-12-31 22:52:10 +00008371 { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
drh0a6873b2019-06-14 21:25:25 +00008372 { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
drh11d88e62019-08-15 21:27:20 +00008373 { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
drh0a6873b2019-06-14 21:25:25 +00008374 { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
drhb945bcd2019-12-31 22:52:10 +00008375 { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
8376 { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
drh0a6873b2019-06-14 21:25:25 +00008377 { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
8378 { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
drh0a6873b2019-06-14 21:25:25 +00008379 { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
drhb945bcd2019-12-31 22:52:10 +00008380 { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
drhb77da372020-01-07 16:09:11 +00008381 { "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA },
dan07312a62019-06-21 14:05:27 +00008382 { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA },
drh7df01192018-04-28 12:43:16 +00008383 };
8384 int ii, v;
8385 open_db(p, 0);
8386 for(ii=0; ii<ArraySize(aDbConfig); ii++){
8387 if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
8388 if( nArg>=3 ){
8389 sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
8390 }
8391 sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
drhb945bcd2019-12-31 22:52:10 +00008392 utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
drh7df01192018-04-28 12:43:16 +00008393 if( nArg>1 ) break;
8394 }
8395 if( nArg>1 && ii==ArraySize(aDbConfig) ){
8396 utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
8397 utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
8398 }
8399 }else
8400
8401 if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008402 rc = shell_dbinfo_command(p, nArg, azArg);
8403 }else
8404
dan1b162162019-04-27 20:15:15 +00008405#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00008406 if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){
8407 open_db(p, 0);
danb9b71db2019-04-25 16:20:40 +00008408 rc = recoverDatabaseCmd(p, nArg, azArg);
dan68cb86e2019-04-20 20:57:28 +00008409 }else
dan1b162162019-04-27 20:15:15 +00008410#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
dan68cb86e2019-04-20 20:57:28 +00008411
drh2ce15c32017-07-11 13:34:40 +00008412 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
drh8e9297f2020-03-25 12:50:13 +00008413 char *zLike = 0;
8414 char *zSql;
drh2ce15c32017-07-11 13:34:40 +00008415 int i;
8416 int savedShowHeader = p->showHeader;
drhf213b332018-07-05 17:35:46 +00008417 int savedShellFlags = p->shellFlgs;
drhc1962192020-10-12 16:54:28 +00008418 ShellClearFlag(p,
8419 SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
8420 |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
drh2ce15c32017-07-11 13:34:40 +00008421 for(i=1; i<nArg; i++){
8422 if( azArg[i][0]=='-' ){
8423 const char *z = azArg[i]+1;
8424 if( z[0]=='-' ) z++;
8425 if( strcmp(z,"preserve-rowids")==0 ){
8426#ifdef SQLITE_OMIT_VIRTUALTABLE
8427 raw_printf(stderr, "The --preserve-rowids option is not compatible"
8428 " with SQLITE_OMIT_VIRTUALTABLE\n");
8429 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00008430 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00008431 goto meta_command_exit;
8432#else
8433 ShellSetFlag(p, SHFLG_PreserveRowid);
8434#endif
8435 }else
8436 if( strcmp(z,"newlines")==0 ){
8437 ShellSetFlag(p, SHFLG_Newlines);
8438 }else
drhc1962192020-10-12 16:54:28 +00008439 if( strcmp(z,"data-only")==0 ){
8440 ShellSetFlag(p, SHFLG_DumpDataOnly);
8441 }else
8442 if( strcmp(z,"nosys")==0 ){
8443 ShellSetFlag(p, SHFLG_DumpNoSys);
8444 }else
drh2ce15c32017-07-11 13:34:40 +00008445 {
8446 raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
8447 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00008448 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00008449 goto meta_command_exit;
8450 }
drh2ce15c32017-07-11 13:34:40 +00008451 }else{
dan78a9d752021-05-25 11:39:14 +00008452 /* azArg[i] contains a LIKE pattern. This ".dump" request should
8453 ** only dump data for tables for which either the table name matches
8454 ** the LIKE pattern, or the table appears to be a shadow table of
8455 ** a virtual table for which the name matches the LIKE pattern.
8456 */
8457 char *zExpr = sqlite3_mprintf(
8458 "name LIKE %Q ESCAPE '\\' OR EXISTS ("
8459 " SELECT 1 FROM sqlite_schema WHERE "
8460 " name LIKE %Q ESCAPE '\\' AND"
8461 " sql LIKE 'CREATE VIRTUAL TABLE%%' AND"
8462 " substr(o.name, 1, length(name)+1) == (name||'_')"
8463 ")", azArg[i], azArg[i]
8464 );
8465
8466 if( zLike ){
8467 zLike = sqlite3_mprintf("%z OR %z", zLike, zExpr);
8468 }else{
8469 zLike = zExpr;
8470 }
drh2ce15c32017-07-11 13:34:40 +00008471 }
8472 }
dan68cb86e2019-04-20 20:57:28 +00008473
drh2ce15c32017-07-11 13:34:40 +00008474 open_db(p, 0);
dan68cb86e2019-04-20 20:57:28 +00008475
drhc1962192020-10-12 16:54:28 +00008476 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
8477 /* When playing back a "dump", the content might appear in an order
8478 ** which causes immediate foreign key constraints to be violated.
8479 ** So disable foreign-key constraint enforcement to prevent problems. */
8480 raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
8481 raw_printf(p->out, "BEGIN TRANSACTION;\n");
8482 }
drh2ce15c32017-07-11 13:34:40 +00008483 p->writableSchema = 0;
8484 p->showHeader = 0;
8485 /* Set writable_schema=ON since doing so forces SQLite to initialize
drh067b92b2020-06-19 15:24:12 +00008486 ** as much of the schema as it can even if the sqlite_schema table is
drh2ce15c32017-07-11 13:34:40 +00008487 ** corrupt. */
8488 sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
8489 p->nErr = 0;
drh8e9297f2020-03-25 12:50:13 +00008490 if( zLike==0 ) zLike = sqlite3_mprintf("true");
8491 zSql = sqlite3_mprintf(
dan78a9d752021-05-25 11:39:14 +00008492 "SELECT name, type, sql FROM sqlite_schema AS o "
drh8e9297f2020-03-25 12:50:13 +00008493 "WHERE (%s) AND type=='table'"
8494 " AND sql NOT NULL"
8495 " ORDER BY tbl_name='sqlite_sequence', rowid",
8496 zLike
8497 );
8498 run_schema_dump_query(p,zSql);
8499 sqlite3_free(zSql);
drhc1962192020-10-12 16:54:28 +00008500 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
8501 zSql = sqlite3_mprintf(
dan78a9d752021-05-25 11:39:14 +00008502 "SELECT sql FROM sqlite_schema AS o "
drhc1962192020-10-12 16:54:28 +00008503 "WHERE (%s) AND sql NOT NULL"
8504 " AND type IN ('index','trigger','view')",
8505 zLike
8506 );
8507 run_table_dump_query(p, zSql);
8508 sqlite3_free(zSql);
8509 }
drh8e9297f2020-03-25 12:50:13 +00008510 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00008511 if( p->writableSchema ){
8512 raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
8513 p->writableSchema = 0;
8514 }
8515 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
8516 sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
drhc1962192020-10-12 16:54:28 +00008517 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
8518 raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
8519 }
drh2ce15c32017-07-11 13:34:40 +00008520 p->showHeader = savedShowHeader;
drhf213b332018-07-05 17:35:46 +00008521 p->shellFlgs = savedShellFlags;
drh2ce15c32017-07-11 13:34:40 +00008522 }else
8523
8524 if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
8525 if( nArg==2 ){
8526 setOrClearFlag(p, SHFLG_Echo, azArg[1]);
8527 }else{
8528 raw_printf(stderr, "Usage: .echo on|off\n");
8529 rc = 1;
8530 }
8531 }else
8532
8533 if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
8534 if( nArg==2 ){
drhe2ca99c2018-05-02 00:33:43 +00008535 p->autoEQPtest = 0;
drhb4e50392019-01-26 15:40:04 +00008536 if( p->autoEQPtrace ){
8537 if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
8538 p->autoEQPtrace = 0;
8539 }
drh2ce15c32017-07-11 13:34:40 +00008540 if( strcmp(azArg[1],"full")==0 ){
drhada70452017-12-21 21:02:27 +00008541 p->autoEQP = AUTOEQP_full;
8542 }else if( strcmp(azArg[1],"trigger")==0 ){
8543 p->autoEQP = AUTOEQP_trigger;
drhb4e50392019-01-26 15:40:04 +00008544#ifdef SQLITE_DEBUG
drhe2ca99c2018-05-02 00:33:43 +00008545 }else if( strcmp(azArg[1],"test")==0 ){
8546 p->autoEQP = AUTOEQP_on;
8547 p->autoEQPtest = 1;
drhb4e50392019-01-26 15:40:04 +00008548 }else if( strcmp(azArg[1],"trace")==0 ){
8549 p->autoEQP = AUTOEQP_full;
8550 p->autoEQPtrace = 1;
8551 open_db(p, 0);
drh067b92b2020-06-19 15:24:12 +00008552 sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0);
drhb4e50392019-01-26 15:40:04 +00008553 sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
8554#endif
drh2ce15c32017-07-11 13:34:40 +00008555 }else{
mistachkinb71aa092018-01-23 00:05:18 +00008556 p->autoEQP = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00008557 }
8558 }else{
drhb4e50392019-01-26 15:40:04 +00008559 raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
drh2ce15c32017-07-11 13:34:40 +00008560 rc = 1;
8561 }
8562 }else
8563
8564 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
8565 if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
8566 rc = 2;
8567 }else
8568
8569 /* The ".explain" command is automatic now. It is largely pointless. It
8570 ** retained purely for backwards compatibility */
8571 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
8572 int val = 1;
8573 if( nArg>=2 ){
8574 if( strcmp(azArg[1],"auto")==0 ){
8575 val = 99;
8576 }else{
8577 val = booleanValue(azArg[1]);
8578 }
8579 }
8580 if( val==1 && p->mode!=MODE_Explain ){
8581 p->normalMode = p->mode;
8582 p->mode = MODE_Explain;
8583 p->autoExplain = 0;
8584 }else if( val==0 ){
8585 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
8586 p->autoExplain = 0;
8587 }else if( val==99 ){
8588 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
8589 p->autoExplain = 1;
8590 }
8591 }else
8592
dan6b046be2018-01-09 15:25:55 +00008593#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00008594 if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
drhfe463172021-12-16 17:57:21 +00008595 if( p->bSafeMode ){
8596 raw_printf(stderr,
8597 "Cannot run experimental commands such as \"%s\" in safe mode\n",
8598 azArg[0]);
8599 rc = 1;
8600 }else{
8601 open_db(p, 0);
8602 expertDotCommand(p, azArg, nArg);
8603 }
dan43efc182017-12-19 17:42:13 +00008604 }else
dan6b046be2018-01-09 15:25:55 +00008605#endif
dan43efc182017-12-19 17:42:13 +00008606
drhd985f722019-06-05 14:29:53 +00008607 if( c=='f' && strncmp(azArg[0], "filectrl", n)==0 ){
8608 static const struct {
8609 const char *zCtrlName; /* Name of a test-control option */
8610 int ctrlCode; /* Integer code for that option */
8611 const char *zUsage; /* Usage notes */
8612 } aCtrl[] = {
drhd985f722019-06-05 14:29:53 +00008613 { "chunk_size", SQLITE_FCNTL_CHUNK_SIZE, "SIZE" },
drh18a4bbd2020-12-17 15:17:42 +00008614 { "data_version", SQLITE_FCNTL_DATA_VERSION, "" },
drhd985f722019-06-05 14:29:53 +00008615 { "has_moved", SQLITE_FCNTL_HAS_MOVED, "" },
8616 { "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" },
drh18a4bbd2020-12-17 15:17:42 +00008617 { "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" },
8618 /* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/
8619 { "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" },
drh541ef2c2020-04-20 16:21:30 +00008620 { "reserve_bytes", SQLITE_FCNTL_RESERVE_BYTES, "[N]" },
drh18a4bbd2020-12-17 15:17:42 +00008621 { "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" },
8622 { "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" },
8623 /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/
drhd985f722019-06-05 14:29:53 +00008624 };
8625 int filectrl = -1;
8626 int iCtrl = -1;
drh4245e042019-06-13 13:52:46 +00008627 sqlite3_int64 iRes = 0; /* Integer result to display if rc2==1 */
8628 int isOk = 0; /* 0: usage 1: %lld 2: no-result */
drhd985f722019-06-05 14:29:53 +00008629 int n2, i;
8630 const char *zCmd = 0;
drh541ef2c2020-04-20 16:21:30 +00008631 const char *zSchema = 0;
drhd985f722019-06-05 14:29:53 +00008632
8633 open_db(p, 0);
8634 zCmd = nArg>=2 ? azArg[1] : "help";
8635
drh541ef2c2020-04-20 16:21:30 +00008636 if( zCmd[0]=='-'
8637 && (strcmp(zCmd,"--schema")==0 || strcmp(zCmd,"-schema")==0)
8638 && nArg>=4
8639 ){
8640 zSchema = azArg[2];
8641 for(i=3; i<nArg; i++) azArg[i-2] = azArg[i];
8642 nArg -= 2;
8643 zCmd = azArg[1];
8644 }
8645
drhd985f722019-06-05 14:29:53 +00008646 /* The argument can optionally begin with "-" or "--" */
8647 if( zCmd[0]=='-' && zCmd[1] ){
8648 zCmd++;
8649 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
8650 }
8651
8652 /* --help lists all file-controls */
8653 if( strcmp(zCmd,"help")==0 ){
8654 utf8_printf(p->out, "Available file-controls:\n");
8655 for(i=0; i<ArraySize(aCtrl); i++){
8656 utf8_printf(p->out, " .filectrl %s %s\n",
8657 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
8658 }
8659 rc = 1;
8660 goto meta_command_exit;
8661 }
8662
8663 /* convert filectrl text option to value. allow any unique prefix
8664 ** of the option name, or a numerical value. */
8665 n2 = strlen30(zCmd);
8666 for(i=0; i<ArraySize(aCtrl); i++){
8667 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
8668 if( filectrl<0 ){
8669 filectrl = aCtrl[i].ctrlCode;
8670 iCtrl = i;
8671 }else{
8672 utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n"
8673 "Use \".filectrl --help\" for help\n", zCmd);
8674 rc = 1;
8675 goto meta_command_exit;
8676 }
8677 }
8678 }
8679 if( filectrl<0 ){
8680 utf8_printf(stderr,"Error: unknown file-control: %s\n"
8681 "Use \".filectrl --help\" for help\n", zCmd);
8682 }else{
8683 switch(filectrl){
8684 case SQLITE_FCNTL_SIZE_LIMIT: {
8685 if( nArg!=2 && nArg!=3 ) break;
8686 iRes = nArg==3 ? integerValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00008687 sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
drhd985f722019-06-05 14:29:53 +00008688 isOk = 1;
8689 break;
8690 }
8691 case SQLITE_FCNTL_LOCK_TIMEOUT:
8692 case SQLITE_FCNTL_CHUNK_SIZE: {
8693 int x;
8694 if( nArg!=3 ) break;
8695 x = (int)integerValue(azArg[2]);
drh541ef2c2020-04-20 16:21:30 +00008696 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008697 isOk = 2;
8698 break;
8699 }
8700 case SQLITE_FCNTL_PERSIST_WAL:
8701 case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
8702 int x;
8703 if( nArg!=2 && nArg!=3 ) break;
8704 x = nArg==3 ? booleanValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00008705 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008706 iRes = x;
8707 isOk = 1;
8708 break;
8709 }
drh18a4bbd2020-12-17 15:17:42 +00008710 case SQLITE_FCNTL_DATA_VERSION:
drhd985f722019-06-05 14:29:53 +00008711 case SQLITE_FCNTL_HAS_MOVED: {
8712 int x;
8713 if( nArg!=2 ) break;
drh541ef2c2020-04-20 16:21:30 +00008714 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008715 iRes = x;
8716 isOk = 1;
8717 break;
8718 }
8719 case SQLITE_FCNTL_TEMPFILENAME: {
8720 char *z = 0;
8721 if( nArg!=2 ) break;
drh541ef2c2020-04-20 16:21:30 +00008722 sqlite3_file_control(p->db, zSchema, filectrl, &z);
drhd985f722019-06-05 14:29:53 +00008723 if( z ){
8724 utf8_printf(p->out, "%s\n", z);
8725 sqlite3_free(z);
8726 }
8727 isOk = 2;
8728 break;
8729 }
drh541ef2c2020-04-20 16:21:30 +00008730 case SQLITE_FCNTL_RESERVE_BYTES: {
8731 int x;
8732 if( nArg>=3 ){
8733 x = atoi(azArg[2]);
8734 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8735 }
8736 x = -1;
8737 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8738 utf8_printf(p->out,"%d\n", x);
8739 isOk = 2;
8740 break;
8741 }
drhd985f722019-06-05 14:29:53 +00008742 }
8743 }
8744 if( isOk==0 && iCtrl>=0 ){
8745 utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
8746 rc = 1;
8747 }else if( isOk==1 ){
drhe2500762019-06-13 14:07:41 +00008748 char zBuf[100];
8749 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
8750 raw_printf(p->out, "%s\n", zBuf);
drhd985f722019-06-05 14:29:53 +00008751 }
8752 }else
8753
drh2ce15c32017-07-11 13:34:40 +00008754 if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
8755 ShellState data;
drh2ce15c32017-07-11 13:34:40 +00008756 int doStats = 0;
8757 memcpy(&data, p, sizeof(data));
8758 data.showHeader = 0;
8759 data.cMode = data.mode = MODE_Semi;
8760 if( nArg==2 && optionMatch(azArg[1], "indent") ){
8761 data.cMode = data.mode = MODE_Pretty;
8762 nArg = 1;
8763 }
8764 if( nArg!=1 ){
8765 raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
8766 rc = 1;
8767 goto meta_command_exit;
8768 }
8769 open_db(p, 0);
8770 rc = sqlite3_exec(p->db,
8771 "SELECT sql FROM"
8772 " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
drh067b92b2020-06-19 15:24:12 +00008773 " FROM sqlite_schema UNION ALL"
8774 " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
drh2ce15c32017-07-11 13:34:40 +00008775 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
drh69935c02021-06-25 11:14:10 +00008776 "ORDER BY x",
drhf83d5012021-05-03 13:35:00 +00008777 callback, &data, 0
drh2ce15c32017-07-11 13:34:40 +00008778 );
8779 if( rc==SQLITE_OK ){
8780 sqlite3_stmt *pStmt;
8781 rc = sqlite3_prepare_v2(p->db,
drh067b92b2020-06-19 15:24:12 +00008782 "SELECT rowid FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00008783 " WHERE name GLOB 'sqlite_stat[134]'",
8784 -1, &pStmt, 0);
8785 doStats = sqlite3_step(pStmt)==SQLITE_ROW;
8786 sqlite3_finalize(pStmt);
8787 }
8788 if( doStats==0 ){
8789 raw_printf(p->out, "/* No STAT tables available */\n");
8790 }else{
drh067b92b2020-06-19 15:24:12 +00008791 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00008792 data.cMode = data.mode = MODE_Insert;
8793 data.zDestTable = "sqlite_stat1";
drhf83d5012021-05-03 13:35:00 +00008794 shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
drh2ce15c32017-07-11 13:34:40 +00008795 data.zDestTable = "sqlite_stat4";
drhf83d5012021-05-03 13:35:00 +00008796 shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
drh067b92b2020-06-19 15:24:12 +00008797 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00008798 }
8799 }else
8800
8801 if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
8802 if( nArg==2 ){
8803 p->showHeader = booleanValue(azArg[1]);
drhc0605082020-06-05 00:54:27 +00008804 p->shellFlgs |= SHFLG_HeaderSet;
drh2ce15c32017-07-11 13:34:40 +00008805 }else{
8806 raw_printf(stderr, "Usage: .headers on|off\n");
8807 rc = 1;
8808 }
8809 }else
8810
8811 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
drh98aa2ab2018-09-26 16:53:51 +00008812 if( nArg>=2 ){
drhe93f8262018-10-11 16:53:37 +00008813 n = showHelp(p->out, azArg[1]);
drh98aa2ab2018-09-26 16:53:51 +00008814 if( n==0 ){
8815 utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
8816 }
8817 }else{
8818 showHelp(p->out, 0);
8819 }
drh2ce15c32017-07-11 13:34:40 +00008820 }else
8821
8822 if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
drhccb37812020-03-09 15:39:39 +00008823 char *zTable = 0; /* Insert data into this table */
larrybr738d7b92022-01-13 21:22:54 +00008824 char *zSchema = "main"; /* within this schema */
drhccb37812020-03-09 15:39:39 +00008825 char *zFile = 0; /* Name of file to extra content from */
drh2ce15c32017-07-11 13:34:40 +00008826 sqlite3_stmt *pStmt = NULL; /* A statement */
8827 int nCol; /* Number of columns in the table */
8828 int nByte; /* Number of bytes in an SQL string */
8829 int i, j; /* Loop counters */
8830 int needCommit; /* True to COMMIT or ROLLBACK at end */
8831 int nSep; /* Number of bytes in p->colSeparator[] */
8832 char *zSql; /* An SQL statement */
8833 ImportCtx sCtx; /* Reader context */
8834 char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
drhccb37812020-03-09 15:39:39 +00008835 int eVerbose = 0; /* Larger for more console output */
8836 int nSkip = 0; /* Initial lines to skip */
8837 int useOutputMode = 1; /* Use output mode to determine separators */
drh2ce15c32017-07-11 13:34:40 +00008838
drhb97e2ad2021-08-26 18:31:39 +00008839 failIfSafeMode(p, "cannot run .import in safe mode");
drhccb37812020-03-09 15:39:39 +00008840 memset(&sCtx, 0, sizeof(sCtx));
larrybr6ac9a5c2021-10-28 19:49:23 +00008841 sCtx.z = sqlite3_malloc64(120);
8842 if( sCtx.z==0 ){
8843 import_cleanup(&sCtx);
8844 shell_out_of_memory();
8845 }
drhccb37812020-03-09 15:39:39 +00008846 if( p->mode==MODE_Ascii ){
8847 xRead = ascii_read_one_field;
8848 }else{
8849 xRead = csv_read_one_field;
8850 }
8851 for(i=1; i<nArg; i++){
8852 char *z = azArg[i];
8853 if( z[0]=='-' && z[1]=='-' ) z++;
8854 if( z[0]!='-' ){
8855 if( zFile==0 ){
8856 zFile = z;
8857 }else if( zTable==0 ){
8858 zTable = z;
8859 }else{
8860 utf8_printf(p->out, "ERROR: extra argument: \"%s\". Usage:\n", z);
8861 showHelp(p->out, "import");
8862 rc = 1;
8863 goto meta_command_exit;
8864 }
8865 }else if( strcmp(z,"-v")==0 ){
8866 eVerbose++;
larrybr738d7b92022-01-13 21:22:54 +00008867 }else if( strcmp(z,"-schema")==0 && i<nArg-1 ){
8868 zSchema = azArg[++i];
drhccb37812020-03-09 15:39:39 +00008869 }else if( strcmp(z,"-skip")==0 && i<nArg-1 ){
8870 nSkip = integerValue(azArg[++i]);
8871 }else if( strcmp(z,"-ascii")==0 ){
8872 sCtx.cColSep = SEP_Unit[0];
8873 sCtx.cRowSep = SEP_Record[0];
8874 xRead = ascii_read_one_field;
8875 useOutputMode = 0;
8876 }else if( strcmp(z,"-csv")==0 ){
8877 sCtx.cColSep = ',';
8878 sCtx.cRowSep = '\n';
8879 xRead = csv_read_one_field;
8880 useOutputMode = 0;
8881 }else{
8882 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", z);
8883 showHelp(p->out, "import");
8884 rc = 1;
8885 goto meta_command_exit;
8886 }
8887 }
8888 if( zTable==0 ){
8889 utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
8890 zFile==0 ? "FILE" : "TABLE");
8891 showHelp(p->out, "import");
8892 rc = 1;
drh2ce15c32017-07-11 13:34:40 +00008893 goto meta_command_exit;
8894 }
drh2ce15c32017-07-11 13:34:40 +00008895 seenInterrupt = 0;
drh2ce15c32017-07-11 13:34:40 +00008896 open_db(p, 0);
drhccb37812020-03-09 15:39:39 +00008897 if( useOutputMode ){
8898 /* If neither the --csv or --ascii options are specified, then set
8899 ** the column and row separator characters from the output mode. */
8900 nSep = strlen30(p->colSeparator);
8901 if( nSep==0 ){
8902 raw_printf(stderr,
8903 "Error: non-null column separator required for import\n");
8904 rc = 1;
8905 goto meta_command_exit;
8906 }
8907 if( nSep>1 ){
8908 raw_printf(stderr,
8909 "Error: multi-character column separators not allowed"
8910 " for import\n");
8911 rc = 1;
8912 goto meta_command_exit;
8913 }
drh2ce15c32017-07-11 13:34:40 +00008914 nSep = strlen30(p->rowSeparator);
drhccb37812020-03-09 15:39:39 +00008915 if( nSep==0 ){
8916 raw_printf(stderr,
8917 "Error: non-null row separator required for import\n");
8918 rc = 1;
8919 goto meta_command_exit;
8920 }
8921 if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator,SEP_CrLf)==0 ){
8922 /* When importing CSV (only), if the row separator is set to the
8923 ** default output row separator, change it to the default input
8924 ** row separator. This avoids having to maintain different input
8925 ** and output row separators. */
8926 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8927 nSep = strlen30(p->rowSeparator);
8928 }
8929 if( nSep>1 ){
8930 raw_printf(stderr, "Error: multi-character row separators not allowed"
8931 " for import\n");
8932 rc = 1;
8933 goto meta_command_exit;
8934 }
8935 sCtx.cColSep = p->colSeparator[0];
8936 sCtx.cRowSep = p->rowSeparator[0];
drh2ce15c32017-07-11 13:34:40 +00008937 }
8938 sCtx.zFile = zFile;
8939 sCtx.nLine = 1;
8940 if( sCtx.zFile[0]=='|' ){
8941#ifdef SQLITE_OMIT_POPEN
8942 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
drhccb37812020-03-09 15:39:39 +00008943 rc = 1;
8944 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008945#else
8946 sCtx.in = popen(sCtx.zFile+1, "r");
8947 sCtx.zFile = "<pipe>";
drh97767842020-05-29 19:39:35 +00008948 sCtx.xCloser = pclose;
drh2ce15c32017-07-11 13:34:40 +00008949#endif
8950 }else{
8951 sCtx.in = fopen(sCtx.zFile, "rb");
drh97767842020-05-29 19:39:35 +00008952 sCtx.xCloser = fclose;
drh2ce15c32017-07-11 13:34:40 +00008953 }
drh2ce15c32017-07-11 13:34:40 +00008954 if( sCtx.in==0 ){
8955 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
drhccb37812020-03-09 15:39:39 +00008956 rc = 1;
dan07ed9c12021-11-02 14:01:41 +00008957 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008958 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008959 }
larrybr738d7b92022-01-13 21:22:54 +00008960 /* Below, resources must be freed before exit. */
drhccb37812020-03-09 15:39:39 +00008961 if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
8962 char zSep[2];
8963 zSep[1] = 0;
8964 zSep[0] = sCtx.cColSep;
8965 utf8_printf(p->out, "Column separator ");
8966 output_c_string(p->out, zSep);
8967 utf8_printf(p->out, ", row separator ");
8968 zSep[0] = sCtx.cRowSep;
8969 output_c_string(p->out, zSep);
8970 utf8_printf(p->out, "\n");
8971 }
8972 while( (nSkip--)>0 ){
8973 while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
drhccb37812020-03-09 15:39:39 +00008974 }
larrybrce0b5e42022-01-14 16:29:45 +00008975 zSql = sqlite3_mprintf("SELECT * FROM \"%w\".\"%w\"", zSchema, zTable);
drh2ce15c32017-07-11 13:34:40 +00008976 if( zSql==0 ){
drh97767842020-05-29 19:39:35 +00008977 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00008978 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00008979 }
8980 nByte = strlen30(zSql);
8981 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8982 import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
8983 if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
larrybrce0b5e42022-01-14 16:29:45 +00008984 char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\".\"%w\"",
8985 zSchema, zTable);
larrybr58a53d62022-02-10 03:21:48 +00008986 sqlite3 *dbCols = 0;
larrybr33633862022-02-14 01:12:46 +00008987 char *zRenames = 0;
larrybr58a53d62022-02-10 03:21:48 +00008988 char *zColDefs;
drh2ce15c32017-07-11 13:34:40 +00008989 while( xRead(&sCtx) ){
larrybra0337272022-02-11 13:40:25 +00008990 zAutoColumn(sCtx.z, &dbCols, 0);
drh2ce15c32017-07-11 13:34:40 +00008991 if( sCtx.cTerm!=sCtx.cColSep ) break;
larrybr4c5c6212022-02-11 01:21:09 +00008992 }
larrybr33633862022-02-14 01:12:46 +00008993 zColDefs = zAutoColumn(0, &dbCols, &zRenames);
8994 if( zRenames!=0 ){
larrybra0337272022-02-11 13:40:25 +00008995 utf8_printf((stdin_is_interactive && p->in==stdin)? p->out : stderr,
larrybr33633862022-02-14 01:12:46 +00008996 "Columns renamed during .import %s due to duplicates:\n"
8997 "%s\n", sCtx.zFile, zRenames);
8998 sqlite3_free(zRenames);
larrybra0337272022-02-11 13:40:25 +00008999 }
larrybr58a53d62022-02-10 03:21:48 +00009000 assert(dbCols==0);
9001 if( zColDefs==0 ){
drh2ce15c32017-07-11 13:34:40 +00009002 sqlite3_free(zCreate);
drh97767842020-05-29 19:39:35 +00009003 import_cleanup(&sCtx);
drh2ce15c32017-07-11 13:34:40 +00009004 utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
drhccb37812020-03-09 15:39:39 +00009005 rc = 1;
9006 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00009007 }
larrybr58a53d62022-02-10 03:21:48 +00009008 zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs);
drhccb37812020-03-09 15:39:39 +00009009 if( eVerbose>=1 ){
9010 utf8_printf(p->out, "%s\n", zCreate);
9011 }
drh2ce15c32017-07-11 13:34:40 +00009012 rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
drh2ce15c32017-07-11 13:34:40 +00009013 if( rc ){
larrybrce0b5e42022-01-14 16:29:45 +00009014 utf8_printf(stderr, "%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
9015 sqlite3_free(zCreate);
drh97767842020-05-29 19:39:35 +00009016 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00009017 rc = 1;
9018 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00009019 }
larrybrce0b5e42022-01-14 16:29:45 +00009020 sqlite3_free(zCreate);
drh2ce15c32017-07-11 13:34:40 +00009021 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9022 }
9023 sqlite3_free(zSql);
9024 if( rc ){
9025 if (pStmt) sqlite3_finalize(pStmt);
9026 utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
drh97767842020-05-29 19:39:35 +00009027 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00009028 rc = 1;
9029 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00009030 }
9031 nCol = sqlite3_column_count(pStmt);
9032 sqlite3_finalize(pStmt);
9033 pStmt = 0;
9034 if( nCol==0 ) return 0; /* no columns, no error */
9035 zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
9036 if( zSql==0 ){
drh97767842020-05-29 19:39:35 +00009037 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00009038 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00009039 }
larrybrce0b5e42022-01-14 16:29:45 +00009040 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\".\"%w\" VALUES(?",
larrybr738d7b92022-01-13 21:22:54 +00009041 zSchema, zTable);
drh2ce15c32017-07-11 13:34:40 +00009042 j = strlen30(zSql);
9043 for(i=1; i<nCol; i++){
9044 zSql[j++] = ',';
9045 zSql[j++] = '?';
9046 }
9047 zSql[j++] = ')';
9048 zSql[j] = 0;
drhccb37812020-03-09 15:39:39 +00009049 if( eVerbose>=2 ){
9050 utf8_printf(p->out, "Insert using: %s\n", zSql);
9051 }
drh2ce15c32017-07-11 13:34:40 +00009052 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9053 sqlite3_free(zSql);
9054 if( rc ){
9055 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9056 if (pStmt) sqlite3_finalize(pStmt);
drh97767842020-05-29 19:39:35 +00009057 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00009058 rc = 1;
9059 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00009060 }
9061 needCommit = sqlite3_get_autocommit(p->db);
9062 if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
9063 do{
9064 int startLine = sCtx.nLine;
9065 for(i=0; i<nCol; i++){
9066 char *z = xRead(&sCtx);
9067 /*
9068 ** Did we reach end-of-file before finding any columns?
9069 ** If so, stop instead of NULL filling the remaining columns.
9070 */
9071 if( z==0 && i==0 ) break;
9072 /*
9073 ** Did we reach end-of-file OR end-of-line before finding any
9074 ** columns in ASCII mode? If so, stop instead of NULL filling
9075 ** the remaining columns.
9076 */
9077 if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
9078 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
9079 if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
9080 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
9081 "filling the rest with NULL\n",
9082 sCtx.zFile, startLine, nCol, i+1);
9083 i += 2;
9084 while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
9085 }
9086 }
9087 if( sCtx.cTerm==sCtx.cColSep ){
9088 do{
9089 xRead(&sCtx);
9090 i++;
9091 }while( sCtx.cTerm==sCtx.cColSep );
9092 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
9093 "extras ignored\n",
9094 sCtx.zFile, startLine, nCol, i);
9095 }
9096 if( i>=nCol ){
9097 sqlite3_step(pStmt);
9098 rc = sqlite3_reset(pStmt);
9099 if( rc!=SQLITE_OK ){
9100 utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
9101 startLine, sqlite3_errmsg(p->db));
drhccb37812020-03-09 15:39:39 +00009102 sCtx.nErr++;
9103 }else{
9104 sCtx.nRow++;
drh2ce15c32017-07-11 13:34:40 +00009105 }
9106 }
9107 }while( sCtx.cTerm!=EOF );
9108
drh97767842020-05-29 19:39:35 +00009109 import_cleanup(&sCtx);
drh2ce15c32017-07-11 13:34:40 +00009110 sqlite3_finalize(pStmt);
9111 if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
drhccb37812020-03-09 15:39:39 +00009112 if( eVerbose>0 ){
9113 utf8_printf(p->out,
9114 "Added %d rows with %d errors using %d lines of input\n",
9115 sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
9116 }
drh2ce15c32017-07-11 13:34:40 +00009117 }else
9118
9119#ifndef SQLITE_UNTESTABLE
9120 if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
9121 char *zSql;
9122 char *zCollist = 0;
9123 sqlite3_stmt *pStmt;
9124 int tnum = 0;
drh491c5be2019-10-18 15:58:50 +00009125 int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */
9126 int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
drh2ce15c32017-07-11 13:34:40 +00009127 int i;
drh48d219a2018-04-23 18:38:48 +00009128 if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
9129 utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
9130 " .imposter off\n");
drh491c5be2019-10-18 15:58:50 +00009131 /* Also allowed, but not documented:
9132 **
9133 ** .imposter TABLE IMPOSTER
9134 **
9135 ** where TABLE is a WITHOUT ROWID table. In that case, the
9136 ** imposter is another WITHOUT ROWID table with the columns in
9137 ** storage order. */
drh2ce15c32017-07-11 13:34:40 +00009138 rc = 1;
9139 goto meta_command_exit;
9140 }
9141 open_db(p, 0);
drh48d219a2018-04-23 18:38:48 +00009142 if( nArg==2 ){
9143 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
9144 goto meta_command_exit;
9145 }
drh491c5be2019-10-18 15:58:50 +00009146 zSql = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00009147 "SELECT rootpage, 0 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00009148 " WHERE name='%q' AND type='index'"
9149 "UNION ALL "
drh067b92b2020-06-19 15:24:12 +00009150 "SELECT rootpage, 1 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00009151 " WHERE name='%q' AND type='table'"
9152 " AND sql LIKE '%%without%%rowid%%'",
9153 azArg[1], azArg[1]
9154 );
drh2ce15c32017-07-11 13:34:40 +00009155 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9156 sqlite3_free(zSql);
9157 if( sqlite3_step(pStmt)==SQLITE_ROW ){
9158 tnum = sqlite3_column_int(pStmt, 0);
drh491c5be2019-10-18 15:58:50 +00009159 isWO = sqlite3_column_int(pStmt, 1);
drh2ce15c32017-07-11 13:34:40 +00009160 }
9161 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00009162 zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
9163 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9164 sqlite3_free(zSql);
9165 i = 0;
drhe85e1da2021-10-01 21:01:07 +00009166 while( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00009167 char zLabel[20];
9168 const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
9169 i++;
9170 if( zCol==0 ){
9171 if( sqlite3_column_int(pStmt,1)==-1 ){
9172 zCol = "_ROWID_";
9173 }else{
9174 sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
9175 zCol = zLabel;
9176 }
9177 }
drh491c5be2019-10-18 15:58:50 +00009178 if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){
9179 lenPK = (int)strlen(zCollist);
9180 }
drh2ce15c32017-07-11 13:34:40 +00009181 if( zCollist==0 ){
9182 zCollist = sqlite3_mprintf("\"%w\"", zCol);
9183 }else{
9184 zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
9185 }
9186 }
9187 sqlite3_finalize(pStmt);
drh491c5be2019-10-18 15:58:50 +00009188 if( i==0 || tnum==0 ){
9189 utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
9190 rc = 1;
9191 sqlite3_free(zCollist);
9192 goto meta_command_exit;
9193 }
9194 if( lenPK==0 ) lenPK = 100000;
drh2ce15c32017-07-11 13:34:40 +00009195 zSql = sqlite3_mprintf(
drh491c5be2019-10-18 15:58:50 +00009196 "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
9197 azArg[2], zCollist, lenPK, zCollist);
drh2ce15c32017-07-11 13:34:40 +00009198 sqlite3_free(zCollist);
9199 rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
9200 if( rc==SQLITE_OK ){
9201 rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
9202 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
9203 if( rc ){
9204 utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
9205 }else{
9206 utf8_printf(stdout, "%s;\n", zSql);
9207 raw_printf(stdout,
drh491c5be2019-10-18 15:58:50 +00009208 "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
9209 azArg[1], isWO ? "table" : "index"
drh2ce15c32017-07-11 13:34:40 +00009210 );
9211 }
9212 }else{
9213 raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
9214 rc = 1;
9215 }
9216 sqlite3_free(zSql);
9217 }else
9218#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
9219
9220#ifdef SQLITE_ENABLE_IOTRACE
9221 if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
9222 SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
9223 if( iotrace && iotrace!=stdout ) fclose(iotrace);
9224 iotrace = 0;
9225 if( nArg<2 ){
9226 sqlite3IoTrace = 0;
9227 }else if( strcmp(azArg[1], "-")==0 ){
9228 sqlite3IoTrace = iotracePrintf;
9229 iotrace = stdout;
9230 }else{
9231 iotrace = fopen(azArg[1], "w");
9232 if( iotrace==0 ){
9233 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
9234 sqlite3IoTrace = 0;
9235 rc = 1;
9236 }else{
9237 sqlite3IoTrace = iotracePrintf;
9238 }
9239 }
9240 }else
9241#endif
9242
9243 if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
9244 static const struct {
9245 const char *zLimitName; /* Name of a limit */
9246 int limitCode; /* Integer code for that limit */
9247 } aLimit[] = {
9248 { "length", SQLITE_LIMIT_LENGTH },
9249 { "sql_length", SQLITE_LIMIT_SQL_LENGTH },
9250 { "column", SQLITE_LIMIT_COLUMN },
9251 { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
9252 { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
9253 { "vdbe_op", SQLITE_LIMIT_VDBE_OP },
9254 { "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
9255 { "attached", SQLITE_LIMIT_ATTACHED },
9256 { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
9257 { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER },
9258 { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
9259 { "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
9260 };
9261 int i, n2;
9262 open_db(p, 0);
9263 if( nArg==1 ){
9264 for(i=0; i<ArraySize(aLimit); i++){
9265 printf("%20s %d\n", aLimit[i].zLimitName,
9266 sqlite3_limit(p->db, aLimit[i].limitCode, -1));
9267 }
9268 }else if( nArg>3 ){
9269 raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
9270 rc = 1;
9271 goto meta_command_exit;
9272 }else{
9273 int iLimit = -1;
9274 n2 = strlen30(azArg[1]);
9275 for(i=0; i<ArraySize(aLimit); i++){
9276 if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
9277 if( iLimit<0 ){
9278 iLimit = i;
9279 }else{
9280 utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
9281 rc = 1;
9282 goto meta_command_exit;
9283 }
9284 }
9285 }
9286 if( iLimit<0 ){
9287 utf8_printf(stderr, "unknown limit: \"%s\"\n"
9288 "enter \".limits\" with no arguments for a list.\n",
9289 azArg[1]);
9290 rc = 1;
9291 goto meta_command_exit;
9292 }
9293 if( nArg==3 ){
9294 sqlite3_limit(p->db, aLimit[iLimit].limitCode,
9295 (int)integerValue(azArg[2]));
9296 }
9297 printf("%20s %d\n", aLimit[iLimit].zLimitName,
9298 sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
9299 }
9300 }else
9301
9302 if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
9303 open_db(p, 0);
9304 lintDotCommand(p, azArg, nArg);
9305 }else
9306
9307#ifndef SQLITE_OMIT_LOAD_EXTENSION
9308 if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
9309 const char *zFile, *zProc;
9310 char *zErrMsg = 0;
drhb97e2ad2021-08-26 18:31:39 +00009311 failIfSafeMode(p, "cannot run .load in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009312 if( nArg<2 ){
9313 raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
9314 rc = 1;
9315 goto meta_command_exit;
9316 }
9317 zFile = azArg[1];
9318 zProc = nArg>=3 ? azArg[2] : 0;
9319 open_db(p, 0);
9320 rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
9321 if( rc!=SQLITE_OK ){
9322 utf8_printf(stderr, "Error: %s\n", zErrMsg);
9323 sqlite3_free(zErrMsg);
9324 rc = 1;
9325 }
9326 }else
9327#endif
9328
9329 if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
drhb97e2ad2021-08-26 18:31:39 +00009330 failIfSafeMode(p, "cannot run .log in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009331 if( nArg!=2 ){
9332 raw_printf(stderr, "Usage: .log FILENAME\n");
9333 rc = 1;
9334 }else{
9335 const char *zFile = azArg[1];
9336 output_file_close(p->pLog);
drha92a01a2018-01-10 22:15:37 +00009337 p->pLog = output_file_open(zFile, 0);
drh2ce15c32017-07-11 13:34:40 +00009338 }
9339 }else
9340
9341 if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
drhe40f2862022-01-31 14:14:29 +00009342 const char *zMode = 0;
9343 const char *zTabname = 0;
9344 int i, n2;
larrybrcc4d55c2022-02-01 02:50:45 +00009345 ColModeOpts cmOpts = ColModeOpts_default;
drhe40f2862022-01-31 14:14:29 +00009346 for(i=1; i<nArg; i++){
9347 const char *z = azArg[i];
9348 if( optionMatch(z,"wrap") && i+1<nArg ){
larrybrcc4d55c2022-02-01 02:50:45 +00009349 cmOpts.iWrap = integerValue(azArg[++i]);
drhca1776b2022-02-01 12:28:17 +00009350 }else if( optionMatch(z,"ww") ){
9351 cmOpts.bWordWrap = 1;
larrybrcc4d55c2022-02-01 02:50:45 +00009352 }else if( optionMatch(z,"wordwrap") && i+1<nArg ){
9353 cmOpts.bWordWrap = (u8)booleanValue(azArg[++i]);
drhe40f2862022-01-31 14:14:29 +00009354 }else if( optionMatch(z,"quote") ){
larrybrcc4d55c2022-02-01 02:50:45 +00009355 cmOpts.bQuote = 1;
drhe40f2862022-01-31 14:14:29 +00009356 }else if( optionMatch(z,"noquote") ){
larrybrcc4d55c2022-02-01 02:50:45 +00009357 cmOpts.bQuote = 0;
drhe40f2862022-01-31 14:14:29 +00009358 }else if( zMode==0 ){
9359 zMode = z;
drhca1776b2022-02-01 12:28:17 +00009360 /* Apply defaults for qbox pseudo-mods. If that
larrybrcc4d55c2022-02-01 02:50:45 +00009361 * overwrites already-set values, user was informed of this.
9362 */
9363 if( strcmp(z, "qbox")==0 ){
9364 ColModeOpts cmo = ColModeOpts_default_qbox;
9365 zMode = "box";
9366 cmOpts = cmo;
larrybrcc4d55c2022-02-01 02:50:45 +00009367 }
drhe40f2862022-01-31 14:14:29 +00009368 }else if( zTabname==0 ){
9369 zTabname = z;
9370 }else if( z[0]=='-' ){
9371 utf8_printf(stderr, "unknown option: %s\n", z);
9372 utf8_printf(stderr, "options:\n"
9373 " --noquote\n"
9374 " --quote\n"
larrybrcc4d55c2022-02-01 02:50:45 +00009375 " --wordwrap on/off\n"
drhca1776b2022-02-01 12:28:17 +00009376 " --wrap N\n"
9377 " --ww\n");
drhe40f2862022-01-31 14:14:29 +00009378 rc = 1;
9379 goto meta_command_exit;
9380 }else{
9381 utf8_printf(stderr, "extra argument: \"%s\"\n", z);
9382 rc = 1;
9383 goto meta_command_exit;
9384 }
9385 }
9386 if( zMode==0 ){
9387 if( p->mode==MODE_Column
9388 || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
9389 ){
larrybrcc4d55c2022-02-01 02:50:45 +00009390 raw_printf
9391 (p->out,
9392 "current output mode: %s --wrap %d --wordwrap %s --%squote\n",
9393 modeDescr[p->mode], p->cmOpts.iWrap,
9394 p->cmOpts.bWordWrap ? "on" : "off",
9395 p->cmOpts.bQuote ? "" : "no");
drhe40f2862022-01-31 14:14:29 +00009396 }else{
9397 raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
9398 }
drhe40f2862022-01-31 14:14:29 +00009399 zMode = modeDescr[p->mode];
9400 }
9401 n2 = strlen30(zMode);
9402 if( strncmp(zMode,"lines",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009403 p->mode = MODE_Line;
9404 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drhe40f2862022-01-31 14:14:29 +00009405 }else if( strncmp(zMode,"columns",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009406 p->mode = MODE_Column;
drhc0605082020-06-05 00:54:27 +00009407 if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){
9408 p->showHeader = 1;
9409 }
drh2ce15c32017-07-11 13:34:40 +00009410 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
larrybrcc4d55c2022-02-01 02:50:45 +00009411 p->cmOpts = cmOpts;
drhe40f2862022-01-31 14:14:29 +00009412 }else if( strncmp(zMode,"list",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009413 p->mode = MODE_List;
9414 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
9415 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drhe40f2862022-01-31 14:14:29 +00009416 }else if( strncmp(zMode,"html",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009417 p->mode = MODE_Html;
drhe40f2862022-01-31 14:14:29 +00009418 }else if( strncmp(zMode,"tcl",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009419 p->mode = MODE_Tcl;
9420 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
9421 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drhe40f2862022-01-31 14:14:29 +00009422 }else if( strncmp(zMode,"csv",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009423 p->mode = MODE_Csv;
9424 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
9425 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
drhe40f2862022-01-31 14:14:29 +00009426 }else if( strncmp(zMode,"tabs",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009427 p->mode = MODE_List;
9428 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
drhe40f2862022-01-31 14:14:29 +00009429 }else if( strncmp(zMode,"insert",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009430 p->mode = MODE_Insert;
drhe40f2862022-01-31 14:14:29 +00009431 set_table_name(p, zTabname ? zTabname : "table");
9432 }else if( strncmp(zMode,"quote",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009433 p->mode = MODE_Quote;
drhc6835732020-05-28 20:37:17 +00009434 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
9435 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drhe40f2862022-01-31 14:14:29 +00009436 }else if( strncmp(zMode,"ascii",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009437 p->mode = MODE_Ascii;
9438 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
9439 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
drhe40f2862022-01-31 14:14:29 +00009440 }else if( strncmp(zMode,"markdown",n2)==0 ){
drh30c54a02020-05-28 23:49:50 +00009441 p->mode = MODE_Markdown;
larrybrcc4d55c2022-02-01 02:50:45 +00009442 p->cmOpts = cmOpts;
drhe40f2862022-01-31 14:14:29 +00009443 }else if( strncmp(zMode,"table",n2)==0 ){
drh30c54a02020-05-28 23:49:50 +00009444 p->mode = MODE_Table;
larrybrcc4d55c2022-02-01 02:50:45 +00009445 p->cmOpts = cmOpts;
drhe40f2862022-01-31 14:14:29 +00009446 }else if( strncmp(zMode,"box",n2)==0 ){
drh0908e382020-06-04 18:05:39 +00009447 p->mode = MODE_Box;
larrybrcc4d55c2022-02-01 02:50:45 +00009448 p->cmOpts = cmOpts;
drhe40f2862022-01-31 14:14:29 +00009449 }else if( strncmp(zMode,"count",n2)==0 ){
drh5d88be82021-12-09 16:17:43 +00009450 p->mode = MODE_Count;
drhe40f2862022-01-31 14:14:29 +00009451 }else if( strncmp(zMode,"off",n2)==0 ){
drh5d88be82021-12-09 16:17:43 +00009452 p->mode = MODE_Off;
drhe40f2862022-01-31 14:14:29 +00009453 }else if( strncmp(zMode,"json",n2)==0 ){
drh30c54a02020-05-28 23:49:50 +00009454 p->mode = MODE_Json;
drh2ce15c32017-07-11 13:34:40 +00009455 }else{
9456 raw_printf(stderr, "Error: mode should be one of: "
drh0908e382020-06-04 18:05:39 +00009457 "ascii box column csv html insert json line list markdown "
drhca1776b2022-02-01 12:28:17 +00009458 "qbox quote table tabs tcl\n");
drh2ce15c32017-07-11 13:34:40 +00009459 rc = 1;
9460 }
9461 p->cMode = p->mode;
9462 }else
9463
drhb97e2ad2021-08-26 18:31:39 +00009464 if( c=='n' && strcmp(azArg[0], "nonce")==0 ){
9465 if( nArg!=2 ){
9466 raw_printf(stderr, "Usage: .nonce NONCE\n");
9467 rc = 1;
9468 }else if( p->zNonce==0 || strcmp(azArg[1],p->zNonce)!=0 ){
drhfe463172021-12-16 17:57:21 +00009469 raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n",
9470 p->lineno, azArg[1]);
drhb97e2ad2021-08-26 18:31:39 +00009471 exit(1);
drhe85e1da2021-10-01 21:01:07 +00009472 }else{
9473 p->bSafeMode = 0;
9474 return 0; /* Return immediately to bypass the safe mode reset
9475 ** at the end of this procedure */
drhb97e2ad2021-08-26 18:31:39 +00009476 }
drhb97e2ad2021-08-26 18:31:39 +00009477 }else
9478
drh2ce15c32017-07-11 13:34:40 +00009479 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
9480 if( nArg==2 ){
9481 sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
9482 "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
9483 }else{
9484 raw_printf(stderr, "Usage: .nullvalue STRING\n");
9485 rc = 1;
9486 }
9487 }else
9488
9489 if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
drh61fd4b92021-12-16 14:59:25 +00009490 const char *zFN = 0; /* Pointer to constant filename */
drhf30bbce2020-12-02 18:27:48 +00009491 char *zNewFilename = 0; /* Name of the database file to open */
9492 int iName = 1; /* Index in azArg[] of the filename */
9493 int newFlag = 0; /* True to delete file before opening */
dan1872c5b2021-12-02 14:16:30 +00009494 int openMode = SHELL_OPEN_UNSPEC;
9495
drh2ce15c32017-07-11 13:34:40 +00009496 /* Check for command-line arguments */
drhf30bbce2020-12-02 18:27:48 +00009497 for(iName=1; iName<nArg; iName++){
drh2ce15c32017-07-11 13:34:40 +00009498 const char *z = azArg[iName];
9499 if( optionMatch(z,"new") ){
9500 newFlag = 1;
drh3baed312018-03-08 18:14:41 +00009501#ifdef SQLITE_HAVE_ZLIB
drh1fa6d9f2018-01-06 21:46:01 +00009502 }else if( optionMatch(z, "zip") ){
dan1872c5b2021-12-02 14:16:30 +00009503 openMode = SHELL_OPEN_ZIPFILE;
drh1fa6d9f2018-01-06 21:46:01 +00009504#endif
9505 }else if( optionMatch(z, "append") ){
dan1872c5b2021-12-02 14:16:30 +00009506 openMode = SHELL_OPEN_APPENDVFS;
drhee269a62018-02-14 23:27:43 +00009507 }else if( optionMatch(z, "readonly") ){
dan1872c5b2021-12-02 14:16:30 +00009508 openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +00009509 }else if( optionMatch(z, "nofollow") ){
9510 p->openFlags |= SQLITE_OPEN_NOFOLLOW;
drh8d889af2021-05-08 17:18:23 +00009511#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +00009512 }else if( optionMatch(z, "deserialize") ){
dan1872c5b2021-12-02 14:16:30 +00009513 openMode = SHELL_OPEN_DESERIALIZE;
drh33746482018-12-13 15:06:26 +00009514 }else if( optionMatch(z, "hexdb") ){
dan1872c5b2021-12-02 14:16:30 +00009515 openMode = SHELL_OPEN_HEXDB;
drh6ca64482019-01-22 16:06:20 +00009516 }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
9517 p->szMax = integerValue(azArg[++iName]);
drh8d889af2021-05-08 17:18:23 +00009518#endif /* SQLITE_OMIT_DESERIALIZE */
drh2ce15c32017-07-11 13:34:40 +00009519 }else if( z[0]=='-' ){
9520 utf8_printf(stderr, "unknown option: %s\n", z);
9521 rc = 1;
9522 goto meta_command_exit;
drh61fd4b92021-12-16 14:59:25 +00009523 }else if( zFN ){
drhf30bbce2020-12-02 18:27:48 +00009524 utf8_printf(stderr, "extra argument: \"%s\"\n", z);
9525 rc = 1;
9526 goto meta_command_exit;
9527 }else{
drh61fd4b92021-12-16 14:59:25 +00009528 zFN = z;
drh2ce15c32017-07-11 13:34:40 +00009529 }
9530 }
dan1872c5b2021-12-02 14:16:30 +00009531
9532 /* Close the existing database */
9533 session_close_all(p, -1);
9534 close_db(p->db);
9535 p->db = 0;
9536 p->pAuxDb->zDbFilename = 0;
9537 sqlite3_free(p->pAuxDb->zFreeOnClose);
9538 p->pAuxDb->zFreeOnClose = 0;
9539 p->openMode = openMode;
9540 p->openFlags = 0;
9541 p->szMax = 0;
9542
drh2ce15c32017-07-11 13:34:40 +00009543 /* If a filename is specified, try to open it first */
drh61fd4b92021-12-16 14:59:25 +00009544 if( zFN || p->openMode==SHELL_OPEN_HEXDB ){
drhc320e062021-12-24 19:44:11 +00009545 if( newFlag && zFN && !p->bSafeMode ) shellDeleteFile(zFN);
drhb97e2ad2021-08-26 18:31:39 +00009546 if( p->bSafeMode
9547 && p->openMode!=SHELL_OPEN_HEXDB
drhc320e062021-12-24 19:44:11 +00009548 && zFN
9549 && strcmp(zFN,":memory:")!=0
drhb97e2ad2021-08-26 18:31:39 +00009550 ){
9551 failIfSafeMode(p, "cannot open disk-based database files in safe mode");
9552 }
drh61fd4b92021-12-16 14:59:25 +00009553 if( zFN ){
9554 zNewFilename = sqlite3_mprintf("%s", zFN);
9555 shell_check_oom(zNewFilename);
9556 }else{
9557 zNewFilename = 0;
9558 }
drh37407122021-07-23 18:43:58 +00009559 p->pAuxDb->zDbFilename = zNewFilename;
drhbe4ccb22018-05-17 20:04:24 +00009560 open_db(p, OPEN_DB_KEEPALIVE);
drh2ce15c32017-07-11 13:34:40 +00009561 if( p->db==0 ){
9562 utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
9563 sqlite3_free(zNewFilename);
9564 }else{
drh37407122021-07-23 18:43:58 +00009565 p->pAuxDb->zFreeOnClose = zNewFilename;
drh2ce15c32017-07-11 13:34:40 +00009566 }
9567 }
9568 if( p->db==0 ){
9569 /* As a fall-back open a TEMP database */
drh37407122021-07-23 18:43:58 +00009570 p->pAuxDb->zDbFilename = 0;
drh2ce15c32017-07-11 13:34:40 +00009571 open_db(p, 0);
9572 }
9573 }else
9574
drh13c20932018-01-10 21:41:55 +00009575 if( (c=='o'
9576 && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
9577 || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
drh2ce15c32017-07-11 13:34:40 +00009578 ){
drh4b0229a2021-02-17 13:19:22 +00009579 char *zFile = 0;
drha92a01a2018-01-10 22:15:37 +00009580 int bTxtMode = 0;
drh7a431002020-04-18 14:12:00 +00009581 int i;
9582 int eMode = 0;
9583 int bBOM = 0;
drh5415ab42020-04-23 20:45:46 +00009584 int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */
drh7a431002020-04-18 14:12:00 +00009585
drhb97e2ad2021-08-26 18:31:39 +00009586 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh7a431002020-04-18 14:12:00 +00009587 if( c=='e' ){
9588 eMode = 'x';
9589 bOnce = 2;
9590 }else if( strncmp(azArg[0],"once",n)==0 ){
9591 bOnce = 1;
drh13c20932018-01-10 21:41:55 +00009592 }
drh7a431002020-04-18 14:12:00 +00009593 for(i=1; i<nArg; i++){
9594 char *z = azArg[i];
9595 if( z[0]=='-' ){
9596 if( z[1]=='-' ) z++;
9597 if( strcmp(z,"-bom")==0 ){
9598 bBOM = 1;
9599 }else if( c!='e' && strcmp(z,"-x")==0 ){
9600 eMode = 'x'; /* spreadsheet */
9601 }else if( c!='e' && strcmp(z,"-e")==0 ){
9602 eMode = 'e'; /* text editor */
9603 }else{
9604 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n",
9605 azArg[i]);
9606 showHelp(p->out, azArg[0]);
9607 rc = 1;
9608 goto meta_command_exit;
9609 }
drh4b0229a2021-02-17 13:19:22 +00009610 }else if( zFile==0 && eMode!='e' && eMode!='x' ){
9611 zFile = sqlite3_mprintf("%s", z);
drhe3e25652021-12-16 13:29:28 +00009612 if( zFile && zFile[0]=='|' ){
drh4b0229a2021-02-17 13:19:22 +00009613 while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]);
9614 break;
9615 }
drh7a431002020-04-18 14:12:00 +00009616 }else{
9617 utf8_printf(p->out,"ERROR: extra parameter: \"%s\". Usage:\n",
9618 azArg[i]);
9619 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00009620 rc = 1;
drh4b0229a2021-02-17 13:19:22 +00009621 sqlite3_free(zFile);
drh2ce15c32017-07-11 13:34:40 +00009622 goto meta_command_exit;
9623 }
drh7a431002020-04-18 14:12:00 +00009624 }
drhe3e25652021-12-16 13:29:28 +00009625 if( zFile==0 ){
9626 zFile = sqlite3_mprintf("stdout");
9627 }
drh7a431002020-04-18 14:12:00 +00009628 if( bOnce ){
drh2ce15c32017-07-11 13:34:40 +00009629 p->outCount = 2;
9630 }else{
9631 p->outCount = 0;
9632 }
9633 output_reset(p);
drh04a28c32018-01-31 01:38:44 +00009634#ifndef SQLITE_NOHAVE_SYSTEM
drh7a431002020-04-18 14:12:00 +00009635 if( eMode=='e' || eMode=='x' ){
drh3c484e82018-01-10 22:27:21 +00009636 p->doXdgOpen = 1;
9637 outputModePush(p);
drh7a431002020-04-18 14:12:00 +00009638 if( eMode=='x' ){
9639 /* spreadsheet mode. Output as CSV. */
drh13c20932018-01-10 21:41:55 +00009640 newTempFile(p, "csv");
drh7a431002020-04-18 14:12:00 +00009641 ShellClearFlag(p, SHFLG_Echo);
drh13c20932018-01-10 21:41:55 +00009642 p->mode = MODE_Csv;
9643 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
9644 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
9645 }else{
drh7a431002020-04-18 14:12:00 +00009646 /* text editor mode */
drh13c20932018-01-10 21:41:55 +00009647 newTempFile(p, "txt");
drha92a01a2018-01-10 22:15:37 +00009648 bTxtMode = 1;
drh13c20932018-01-10 21:41:55 +00009649 }
drh4b0229a2021-02-17 13:19:22 +00009650 sqlite3_free(zFile);
9651 zFile = sqlite3_mprintf("%s", p->zTempFile);
drh13c20932018-01-10 21:41:55 +00009652 }
drh04a28c32018-01-31 01:38:44 +00009653#endif /* SQLITE_NOHAVE_SYSTEM */
drhe3e25652021-12-16 13:29:28 +00009654 shell_check_oom(zFile);
drh2ce15c32017-07-11 13:34:40 +00009655 if( zFile[0]=='|' ){
9656#ifdef SQLITE_OMIT_POPEN
9657 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
9658 rc = 1;
9659 p->out = stdout;
9660#else
9661 p->out = popen(zFile + 1, "w");
9662 if( p->out==0 ){
9663 utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
9664 p->out = stdout;
9665 rc = 1;
9666 }else{
drh7a431002020-04-18 14:12:00 +00009667 if( bBOM ) fprintf(p->out,"\357\273\277");
drh2ce15c32017-07-11 13:34:40 +00009668 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
9669 }
9670#endif
9671 }else{
drha92a01a2018-01-10 22:15:37 +00009672 p->out = output_file_open(zFile, bTxtMode);
drh2ce15c32017-07-11 13:34:40 +00009673 if( p->out==0 ){
9674 if( strcmp(zFile,"off")!=0 ){
9675 utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
9676 }
9677 p->out = stdout;
9678 rc = 1;
9679 } else {
drh7a431002020-04-18 14:12:00 +00009680 if( bBOM ) fprintf(p->out,"\357\273\277");
drh2ce15c32017-07-11 13:34:40 +00009681 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
9682 }
9683 }
drh4b0229a2021-02-17 13:19:22 +00009684 sqlite3_free(zFile);
drh2ce15c32017-07-11 13:34:40 +00009685 }else
9686
drh9cb02642019-02-28 20:10:52 +00009687 if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
9688 open_db(p,0);
9689 if( nArg<=1 ) goto parameter_syntax_error;
9690
9691 /* .parameter clear
9692 ** Clear all bind parameters by dropping the TEMP table that holds them.
9693 */
9694 if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
drh65c29fd2019-03-25 21:56:26 +00009695 sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
drh9cb02642019-02-28 20:10:52 +00009696 0, 0, 0);
9697 }else
9698
9699 /* .parameter list
9700 ** List all bind parameters.
9701 */
9702 if( nArg==2 && strcmp(azArg[1],"list")==0 ){
9703 sqlite3_stmt *pStmt = 0;
9704 int rx;
9705 int len = 0;
9706 rx = sqlite3_prepare_v2(p->db,
9707 "SELECT max(length(key)) "
drh65c29fd2019-03-25 21:56:26 +00009708 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drh9cb02642019-02-28 20:10:52 +00009709 if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
9710 len = sqlite3_column_int(pStmt, 0);
9711 if( len>40 ) len = 40;
9712 }
9713 sqlite3_finalize(pStmt);
9714 pStmt = 0;
9715 if( len ){
9716 rx = sqlite3_prepare_v2(p->db,
9717 "SELECT key, quote(value) "
drh65c29fd2019-03-25 21:56:26 +00009718 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drhe85e1da2021-10-01 21:01:07 +00009719 while( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
drh9cb02642019-02-28 20:10:52 +00009720 utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
9721 sqlite3_column_text(pStmt,1));
9722 }
9723 sqlite3_finalize(pStmt);
9724 }
9725 }else
9726
9727 /* .parameter init
9728 ** Make sure the TEMP table used to hold bind parameters exists.
9729 ** Create it if necessary.
9730 */
9731 if( nArg==2 && strcmp(azArg[1],"init")==0 ){
9732 bind_table_init(p);
9733 }else
9734
9735 /* .parameter set NAME VALUE
9736 ** Set or reset a bind parameter. NAME should be the full parameter
9737 ** name exactly as it appears in the query. (ex: $abc, @def). The
9738 ** VALUE can be in either SQL literal notation, or if not it will be
9739 ** understood to be a text string.
9740 */
9741 if( nArg==4 && strcmp(azArg[1],"set")==0 ){
9742 int rx;
9743 char *zSql;
9744 sqlite3_stmt *pStmt;
9745 const char *zKey = azArg[2];
9746 const char *zValue = azArg[3];
9747 bind_table_init(p);
9748 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009749 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00009750 "VALUES(%Q,%s);", zKey, zValue);
drhe3e25652021-12-16 13:29:28 +00009751 shell_check_oom(zSql);
drh9cb02642019-02-28 20:10:52 +00009752 pStmt = 0;
9753 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9754 sqlite3_free(zSql);
9755 if( rx!=SQLITE_OK ){
9756 sqlite3_finalize(pStmt);
9757 pStmt = 0;
9758 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009759 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00009760 "VALUES(%Q,%Q);", zKey, zValue);
drhe3e25652021-12-16 13:29:28 +00009761 shell_check_oom(zSql);
drh9cb02642019-02-28 20:10:52 +00009762 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9763 sqlite3_free(zSql);
9764 if( rx!=SQLITE_OK ){
9765 utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
9766 sqlite3_finalize(pStmt);
9767 pStmt = 0;
9768 rc = 1;
9769 }
9770 }
9771 sqlite3_step(pStmt);
9772 sqlite3_finalize(pStmt);
9773 }else
9774
9775 /* .parameter unset NAME
9776 ** Remove the NAME binding from the parameter binding table, if it
9777 ** exists.
9778 */
9779 if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
9780 char *zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009781 "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
drhe3e25652021-12-16 13:29:28 +00009782 shell_check_oom(zSql);
drh9cb02642019-02-28 20:10:52 +00009783 sqlite3_exec(p->db, zSql, 0, 0, 0);
9784 sqlite3_free(zSql);
9785 }else
9786 /* If no command name matches, show a syntax error */
9787 parameter_syntax_error:
9788 showHelp(p->out, "parameter");
9789 }else
9790
drh2ce15c32017-07-11 13:34:40 +00009791 if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
9792 int i;
9793 for(i=1; i<nArg; i++){
9794 if( i>1 ) raw_printf(p->out, " ");
9795 utf8_printf(p->out, "%s", azArg[i]);
9796 }
9797 raw_printf(p->out, "\n");
9798 }else
9799
drh569b1d92019-02-05 20:51:41 +00009800#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh3f83f592019-02-04 14:53:18 +00009801 if( c=='p' && n>=3 && strncmp(azArg[0], "progress", n)==0 ){
9802 int i;
drhfc4eeef2019-02-05 19:48:46 +00009803 int nn = 0;
drh3f83f592019-02-04 14:53:18 +00009804 p->flgProgress = 0;
9805 p->mxProgress = 0;
9806 p->nProgress = 0;
9807 for(i=1; i<nArg; i++){
9808 const char *z = azArg[i];
9809 if( z[0]=='-' ){
9810 z++;
9811 if( z[0]=='-' ) z++;
9812 if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009813 p->flgProgress |= SHELL_PROGRESS_QUIET;
drh3f83f592019-02-04 14:53:18 +00009814 continue;
9815 }
9816 if( strcmp(z,"reset")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009817 p->flgProgress |= SHELL_PROGRESS_RESET;
drh3f83f592019-02-04 14:53:18 +00009818 continue;
9819 }
9820 if( strcmp(z,"once")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009821 p->flgProgress |= SHELL_PROGRESS_ONCE;
drh3f83f592019-02-04 14:53:18 +00009822 continue;
9823 }
9824 if( strcmp(z,"limit")==0 ){
9825 if( i+1>=nArg ){
9826 utf8_printf(stderr, "Error: missing argument on --limit\n");
9827 rc = 1;
9828 goto meta_command_exit;
9829 }else{
9830 p->mxProgress = (int)integerValue(azArg[++i]);
9831 }
9832 continue;
9833 }
9834 utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
9835 rc = 1;
9836 goto meta_command_exit;
9837 }else{
drhfc4eeef2019-02-05 19:48:46 +00009838 nn = (int)integerValue(z);
drh3f83f592019-02-04 14:53:18 +00009839 }
9840 }
9841 open_db(p, 0);
drhfc4eeef2019-02-05 19:48:46 +00009842 sqlite3_progress_handler(p->db, nn, progress_handler, p);
drh3f83f592019-02-04 14:53:18 +00009843 }else
drh569b1d92019-02-05 20:51:41 +00009844#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
drh3f83f592019-02-04 14:53:18 +00009845
drh2ce15c32017-07-11 13:34:40 +00009846 if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
9847 if( nArg >= 2) {
9848 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
9849 }
9850 if( nArg >= 3) {
9851 strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
9852 }
9853 }else
9854
9855 if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
9856 rc = 2;
9857 }else
9858
9859 if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
drh60379d42018-12-13 18:30:01 +00009860 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +00009861 int savedLineno = p->lineno;
drhb97e2ad2021-08-26 18:31:39 +00009862 failIfSafeMode(p, "cannot run .read in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009863 if( nArg!=2 ){
9864 raw_printf(stderr, "Usage: .read FILE\n");
9865 rc = 1;
9866 goto meta_command_exit;
9867 }
drh30497f42020-08-26 10:50:48 +00009868 if( azArg[1][0]=='|' ){
drh9d59e3b2021-03-12 01:49:08 +00009869#ifdef SQLITE_OMIT_POPEN
9870 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
9871 rc = 1;
9872 p->out = stdout;
9873#else
drh30497f42020-08-26 10:50:48 +00009874 p->in = popen(azArg[1]+1, "r");
9875 if( p->in==0 ){
9876 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
9877 rc = 1;
9878 }else{
9879 rc = process_input(p);
9880 pclose(p->in);
9881 }
drh9d59e3b2021-03-12 01:49:08 +00009882#endif
larrybrd96bcc72021-09-17 21:12:47 +00009883 }else if( (p->in = openChrSource(azArg[1]))==0 ){
drh2ce15c32017-07-11 13:34:40 +00009884 utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
9885 rc = 1;
9886 }else{
drh60379d42018-12-13 18:30:01 +00009887 rc = process_input(p);
9888 fclose(p->in);
drh2ce15c32017-07-11 13:34:40 +00009889 }
drh60379d42018-12-13 18:30:01 +00009890 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +00009891 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +00009892 }else
9893
9894 if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
9895 const char *zSrcFile;
9896 const char *zDb;
9897 sqlite3 *pSrc;
9898 sqlite3_backup *pBackup;
9899 int nTimeout = 0;
9900
drhb97e2ad2021-08-26 18:31:39 +00009901 failIfSafeMode(p, "cannot run .restore in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009902 if( nArg==2 ){
9903 zSrcFile = azArg[1];
9904 zDb = "main";
9905 }else if( nArg==3 ){
9906 zSrcFile = azArg[2];
9907 zDb = azArg[1];
9908 }else{
9909 raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
9910 rc = 1;
9911 goto meta_command_exit;
9912 }
9913 rc = sqlite3_open(zSrcFile, &pSrc);
9914 if( rc!=SQLITE_OK ){
9915 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
drh9e804032018-05-18 17:11:50 +00009916 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009917 return 1;
9918 }
9919 open_db(p, 0);
9920 pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
9921 if( pBackup==0 ){
9922 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh9e804032018-05-18 17:11:50 +00009923 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009924 return 1;
9925 }
9926 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
9927 || rc==SQLITE_BUSY ){
9928 if( rc==SQLITE_BUSY ){
9929 if( nTimeout++ >= 3 ) break;
9930 sqlite3_sleep(100);
9931 }
9932 }
9933 sqlite3_backup_finish(pBackup);
9934 if( rc==SQLITE_DONE ){
9935 rc = 0;
9936 }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
9937 raw_printf(stderr, "Error: source database is busy\n");
9938 rc = 1;
9939 }else{
9940 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9941 rc = 1;
9942 }
drh9e804032018-05-18 17:11:50 +00009943 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009944 }else
9945
drh2ce15c32017-07-11 13:34:40 +00009946 if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
9947 if( nArg==2 ){
mistachkinb71aa092018-01-23 00:05:18 +00009948 p->scanstatsOn = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00009949#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
9950 raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
9951#endif
9952 }else{
9953 raw_printf(stderr, "Usage: .scanstats on|off\n");
9954 rc = 1;
9955 }
9956 }else
9957
9958 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
9959 ShellText sSelect;
9960 ShellState data;
9961 char *zErrMsg = 0;
drh667a2a22018-01-02 00:04:37 +00009962 const char *zDiv = "(";
drhceba7922018-01-01 21:28:25 +00009963 const char *zName = 0;
drh2ce15c32017-07-11 13:34:40 +00009964 int iSchema = 0;
drhceba7922018-01-01 21:28:25 +00009965 int bDebug = 0;
drhbbb29ec2020-10-12 14:56:47 +00009966 int bNoSystemTabs = 0;
drhceba7922018-01-01 21:28:25 +00009967 int ii;
drh2ce15c32017-07-11 13:34:40 +00009968
9969 open_db(p, 0);
9970 memcpy(&data, p, sizeof(data));
9971 data.showHeader = 0;
9972 data.cMode = data.mode = MODE_Semi;
9973 initText(&sSelect);
drhceba7922018-01-01 21:28:25 +00009974 for(ii=1; ii<nArg; ii++){
9975 if( optionMatch(azArg[ii],"indent") ){
9976 data.cMode = data.mode = MODE_Pretty;
9977 }else if( optionMatch(azArg[ii],"debug") ){
9978 bDebug = 1;
drhbbb29ec2020-10-12 14:56:47 +00009979 }else if( optionMatch(azArg[ii],"nosys") ){
9980 bNoSystemTabs = 1;
9981 }else if( azArg[ii][0]=='-' ){
9982 utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
9983 rc = 1;
9984 goto meta_command_exit;
drhceba7922018-01-01 21:28:25 +00009985 }else if( zName==0 ){
9986 zName = azArg[ii];
drh2ce15c32017-07-11 13:34:40 +00009987 }else{
drhbbb29ec2020-10-12 14:56:47 +00009988 raw_printf(stderr, "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
drhceba7922018-01-01 21:28:25 +00009989 rc = 1;
9990 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00009991 }
drh2ce15c32017-07-11 13:34:40 +00009992 }
drhceba7922018-01-01 21:28:25 +00009993 if( zName!=0 ){
drh067b92b2020-06-19 15:24:12 +00009994 int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0
drh346a70c2020-06-15 20:27:35 +00009995 || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
9996 || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
9997 || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
drh067b92b2020-06-19 15:24:12 +00009998 if( isSchema ){
drh2ce15c32017-07-11 13:34:40 +00009999 char *new_argv[2], *new_colv[2];
drhc22b7162018-01-01 20:11:23 +000010000 new_argv[0] = sqlite3_mprintf(
10001 "CREATE TABLE %s (\n"
drh2ce15c32017-07-11 13:34:40 +000010002 " type text,\n"
10003 " name text,\n"
10004 " tbl_name text,\n"
10005 " rootpage integer,\n"
10006 " sql text\n"
drh346a70c2020-06-15 20:27:35 +000010007 ")", zName);
drhe3e25652021-12-16 13:29:28 +000010008 shell_check_oom(new_argv[0]);
drh2ce15c32017-07-11 13:34:40 +000010009 new_argv[1] = 0;
10010 new_colv[0] = "sql";
10011 new_colv[1] = 0;
10012 callback(&data, 1, new_argv, new_colv);
drhc22b7162018-01-01 20:11:23 +000010013 sqlite3_free(new_argv[0]);
drh2ce15c32017-07-11 13:34:40 +000010014 }
drh2ce15c32017-07-11 13:34:40 +000010015 }
10016 if( zDiv ){
10017 sqlite3_stmt *pStmt = 0;
10018 rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
10019 -1, &pStmt, 0);
10020 if( rc ){
10021 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
10022 sqlite3_finalize(pStmt);
10023 rc = 1;
10024 goto meta_command_exit;
10025 }
10026 appendText(&sSelect, "SELECT sql FROM", 0);
10027 iSchema = 0;
10028 while( sqlite3_step(pStmt)==SQLITE_ROW ){
10029 const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
10030 char zScNum[30];
10031 sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
10032 appendText(&sSelect, zDiv, 0);
10033 zDiv = " UNION ALL ";
drhceba7922018-01-01 21:28:25 +000010034 appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
10035 if( sqlite3_stricmp(zDb, "main")!=0 ){
drhea38f4f2019-07-13 17:21:47 +000010036 appendText(&sSelect, zDb, '\'');
drh2ce15c32017-07-11 13:34:40 +000010037 }else{
drhceba7922018-01-01 21:28:25 +000010038 appendText(&sSelect, "NULL", 0);
drh2ce15c32017-07-11 13:34:40 +000010039 }
drhceba7922018-01-01 21:28:25 +000010040 appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0);
10041 appendText(&sSelect, zScNum, 0);
10042 appendText(&sSelect, " AS snum, ", 0);
10043 appendText(&sSelect, zDb, '\'');
10044 appendText(&sSelect, " AS sname FROM ", 0);
drhea38f4f2019-07-13 17:21:47 +000010045 appendText(&sSelect, zDb, quoteChar(zDb));
drh067b92b2020-06-19 15:24:12 +000010046 appendText(&sSelect, ".sqlite_schema", 0);
drh2ce15c32017-07-11 13:34:40 +000010047 }
10048 sqlite3_finalize(pStmt);
drhcc3f3d12019-08-17 15:27:58 +000010049#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
drh667a2a22018-01-02 00:04:37 +000010050 if( zName ){
10051 appendText(&sSelect,
10052 " UNION ALL SELECT shell_module_schema(name),"
drhe2754c12019-08-26 12:50:01 +000010053 " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
10054 0);
drh667a2a22018-01-02 00:04:37 +000010055 }
drhcde7b772018-01-02 12:50:40 +000010056#endif
drh2ce15c32017-07-11 13:34:40 +000010057 appendText(&sSelect, ") WHERE ", 0);
drhceba7922018-01-01 21:28:25 +000010058 if( zName ){
10059 char *zQarg = sqlite3_mprintf("%Q", zName);
mistachkinc158c072021-12-31 19:08:20 +000010060 int bGlob;
drhe3e25652021-12-16 13:29:28 +000010061 shell_check_oom(zQarg);
mistachkinc158c072021-12-31 19:08:20 +000010062 bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
10063 strchr(zName, '[') != 0;
drhceba7922018-01-01 21:28:25 +000010064 if( strchr(zName, '.') ){
drh2ce15c32017-07-11 13:34:40 +000010065 appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
10066 }else{
10067 appendText(&sSelect, "lower(tbl_name)", 0);
10068 }
mistachkin9d107262018-03-23 14:24:34 +000010069 appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0);
drh2ce15c32017-07-11 13:34:40 +000010070 appendText(&sSelect, zQarg, 0);
mistachkin9d107262018-03-23 14:24:34 +000010071 if( !bGlob ){
10072 appendText(&sSelect, " ESCAPE '\\' ", 0);
10073 }
drh2ce15c32017-07-11 13:34:40 +000010074 appendText(&sSelect, " AND ", 0);
10075 sqlite3_free(zQarg);
10076 }
drhbbb29ec2020-10-12 14:56:47 +000010077 if( bNoSystemTabs ){
10078 appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
10079 }
10080 appendText(&sSelect, "sql IS NOT NULL"
drh2ce15c32017-07-11 13:34:40 +000010081 " ORDER BY snum, rowid", 0);
drhceba7922018-01-01 21:28:25 +000010082 if( bDebug ){
10083 utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
10084 }else{
10085 rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
10086 }
drh2ce15c32017-07-11 13:34:40 +000010087 freeText(&sSelect);
10088 }
10089 if( zErrMsg ){
10090 utf8_printf(stderr,"Error: %s\n", zErrMsg);
10091 sqlite3_free(zErrMsg);
10092 rc = 1;
10093 }else if( rc != SQLITE_OK ){
10094 raw_printf(stderr,"Error: querying schema information\n");
10095 rc = 1;
10096 }else{
10097 rc = 0;
10098 }
10099 }else
10100
drh2ce15c32017-07-11 13:34:40 +000010101 if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
drhfda8e492020-12-04 16:04:45 +000010102 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
drhc0622a42020-12-04 01:17:57 +000010103 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
drh2ce15c32017-07-11 13:34:40 +000010104 }else
drh2ce15c32017-07-11 13:34:40 +000010105
10106#if defined(SQLITE_ENABLE_SESSION)
10107 if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
drh37407122021-07-23 18:43:58 +000010108 struct AuxDb *pAuxDb = p->pAuxDb;
10109 OpenSession *pSession = &pAuxDb->aSession[0];
drh2ce15c32017-07-11 13:34:40 +000010110 char **azCmd = &azArg[1];
10111 int iSes = 0;
10112 int nCmd = nArg - 1;
10113 int i;
10114 if( nArg<=1 ) goto session_syntax_error;
10115 open_db(p, 0);
10116 if( nArg>=3 ){
drh37407122021-07-23 18:43:58 +000010117 for(iSes=0; iSes<pAuxDb->nSession; iSes++){
10118 if( strcmp(pAuxDb->aSession[iSes].zName, azArg[1])==0 ) break;
drh2ce15c32017-07-11 13:34:40 +000010119 }
drh37407122021-07-23 18:43:58 +000010120 if( iSes<pAuxDb->nSession ){
10121 pSession = &pAuxDb->aSession[iSes];
drh2ce15c32017-07-11 13:34:40 +000010122 azCmd++;
10123 nCmd--;
10124 }else{
drh37407122021-07-23 18:43:58 +000010125 pSession = &pAuxDb->aSession[0];
drh2ce15c32017-07-11 13:34:40 +000010126 iSes = 0;
10127 }
10128 }
10129
10130 /* .session attach TABLE
10131 ** Invoke the sqlite3session_attach() interface to attach a particular
10132 ** table so that it is never filtered.
10133 */
10134 if( strcmp(azCmd[0],"attach")==0 ){
10135 if( nCmd!=2 ) goto session_syntax_error;
10136 if( pSession->p==0 ){
10137 session_not_open:
10138 raw_printf(stderr, "ERROR: No sessions are open\n");
10139 }else{
10140 rc = sqlite3session_attach(pSession->p, azCmd[1]);
10141 if( rc ){
10142 raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
10143 rc = 0;
10144 }
10145 }
10146 }else
10147
10148 /* .session changeset FILE
10149 ** .session patchset FILE
10150 ** Write a changeset or patchset into a file. The file is overwritten.
10151 */
10152 if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
10153 FILE *out = 0;
drhb97e2ad2021-08-26 18:31:39 +000010154 failIfSafeMode(p, "cannot run \".session %s\" in safe mode", azCmd[0]);
drh2ce15c32017-07-11 13:34:40 +000010155 if( nCmd!=2 ) goto session_syntax_error;
10156 if( pSession->p==0 ) goto session_not_open;
10157 out = fopen(azCmd[1], "wb");
10158 if( out==0 ){
drhe2754c12019-08-26 12:50:01 +000010159 utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
10160 azCmd[1]);
drh2ce15c32017-07-11 13:34:40 +000010161 }else{
10162 int szChng;
10163 void *pChng;
10164 if( azCmd[0][0]=='c' ){
10165 rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
10166 }else{
10167 rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
10168 }
10169 if( rc ){
10170 printf("Error: error code %d\n", rc);
10171 rc = 0;
10172 }
10173 if( pChng
10174 && fwrite(pChng, szChng, 1, out)!=1 ){
10175 raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
10176 szChng);
10177 }
10178 sqlite3_free(pChng);
10179 fclose(out);
10180 }
10181 }else
10182
10183 /* .session close
10184 ** Close the identified session
10185 */
10186 if( strcmp(azCmd[0], "close")==0 ){
10187 if( nCmd!=1 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +000010188 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +000010189 session_close(pSession);
drh37407122021-07-23 18:43:58 +000010190 pAuxDb->aSession[iSes] = pAuxDb->aSession[--pAuxDb->nSession];
drh2ce15c32017-07-11 13:34:40 +000010191 }
10192 }else
10193
10194 /* .session enable ?BOOLEAN?
10195 ** Query or set the enable flag
10196 */
10197 if( strcmp(azCmd[0], "enable")==0 ){
10198 int ii;
10199 if( nCmd>2 ) goto session_syntax_error;
10200 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
drh37407122021-07-23 18:43:58 +000010201 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +000010202 ii = sqlite3session_enable(pSession->p, ii);
10203 utf8_printf(p->out, "session %s enable flag = %d\n",
10204 pSession->zName, ii);
10205 }
10206 }else
10207
10208 /* .session filter GLOB ....
10209 ** Set a list of GLOB patterns of table names to be excluded.
10210 */
10211 if( strcmp(azCmd[0], "filter")==0 ){
10212 int ii, nByte;
10213 if( nCmd<2 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +000010214 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +000010215 for(ii=0; ii<pSession->nFilter; ii++){
10216 sqlite3_free(pSession->azFilter[ii]);
10217 }
10218 sqlite3_free(pSession->azFilter);
10219 nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
10220 pSession->azFilter = sqlite3_malloc( nByte );
10221 if( pSession->azFilter==0 ){
10222 raw_printf(stderr, "Error: out or memory\n");
10223 exit(1);
10224 }
10225 for(ii=1; ii<nCmd; ii++){
drhe3e25652021-12-16 13:29:28 +000010226 char *x = pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
10227 shell_check_oom(x);
drh2ce15c32017-07-11 13:34:40 +000010228 }
10229 pSession->nFilter = ii-1;
10230 }
10231 }else
10232
10233 /* .session indirect ?BOOLEAN?
10234 ** Query or set the indirect flag
10235 */
10236 if( strcmp(azCmd[0], "indirect")==0 ){
10237 int ii;
10238 if( nCmd>2 ) goto session_syntax_error;
10239 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
drh37407122021-07-23 18:43:58 +000010240 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +000010241 ii = sqlite3session_indirect(pSession->p, ii);
10242 utf8_printf(p->out, "session %s indirect flag = %d\n",
10243 pSession->zName, ii);
10244 }
10245 }else
10246
10247 /* .session isempty
10248 ** Determine if the session is empty
10249 */
10250 if( strcmp(azCmd[0], "isempty")==0 ){
10251 int ii;
10252 if( nCmd!=1 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +000010253 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +000010254 ii = sqlite3session_isempty(pSession->p);
10255 utf8_printf(p->out, "session %s isempty flag = %d\n",
10256 pSession->zName, ii);
10257 }
10258 }else
10259
10260 /* .session list
10261 ** List all currently open sessions
10262 */
10263 if( strcmp(azCmd[0],"list")==0 ){
drh37407122021-07-23 18:43:58 +000010264 for(i=0; i<pAuxDb->nSession; i++){
10265 utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName);
drh2ce15c32017-07-11 13:34:40 +000010266 }
10267 }else
10268
10269 /* .session open DB NAME
10270 ** Open a new session called NAME on the attached database DB.
10271 ** DB is normally "main".
10272 */
10273 if( strcmp(azCmd[0],"open")==0 ){
10274 char *zName;
10275 if( nCmd!=3 ) goto session_syntax_error;
10276 zName = azCmd[2];
10277 if( zName[0]==0 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +000010278 for(i=0; i<pAuxDb->nSession; i++){
10279 if( strcmp(pAuxDb->aSession[i].zName,zName)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010280 utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
10281 goto meta_command_exit;
10282 }
10283 }
drh37407122021-07-23 18:43:58 +000010284 if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){
10285 raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession));
drh2ce15c32017-07-11 13:34:40 +000010286 goto meta_command_exit;
10287 }
drh37407122021-07-23 18:43:58 +000010288 pSession = &pAuxDb->aSession[pAuxDb->nSession];
drh2ce15c32017-07-11 13:34:40 +000010289 rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
10290 if( rc ){
10291 raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
10292 rc = 0;
10293 goto meta_command_exit;
10294 }
10295 pSession->nFilter = 0;
10296 sqlite3session_table_filter(pSession->p, session_filter, pSession);
drh37407122021-07-23 18:43:58 +000010297 pAuxDb->nSession++;
drh2ce15c32017-07-11 13:34:40 +000010298 pSession->zName = sqlite3_mprintf("%s", zName);
drhe3e25652021-12-16 13:29:28 +000010299 shell_check_oom(pSession->zName);
drh2ce15c32017-07-11 13:34:40 +000010300 }else
10301 /* If no command name matches, show a syntax error */
10302 session_syntax_error:
drheb7f2a02018-09-26 18:02:32 +000010303 showHelp(p->out, "session");
drh2ce15c32017-07-11 13:34:40 +000010304 }else
10305#endif
10306
10307#ifdef SQLITE_DEBUG
10308 /* Undocumented commands for internal testing. Subject to change
10309 ** without notice. */
10310 if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
10311 if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
10312 int i, v;
10313 for(i=1; i<nArg; i++){
10314 v = booleanValue(azArg[i]);
10315 utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
10316 }
10317 }
10318 if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
10319 int i; sqlite3_int64 v;
10320 for(i=1; i<nArg; i++){
10321 char zBuf[200];
10322 v = integerValue(azArg[i]);
10323 sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
10324 utf8_printf(p->out, "%s", zBuf);
10325 }
10326 }
10327 }else
10328#endif
10329
10330 if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){
10331 int bIsInit = 0; /* True to initialize the SELFTEST table */
10332 int bVerbose = 0; /* Verbose output */
10333 int bSelftestExists; /* True if SELFTEST already exists */
10334 int i, k; /* Loop counters */
10335 int nTest = 0; /* Number of tests runs */
10336 int nErr = 0; /* Number of errors seen */
10337 ShellText str; /* Answer for a query */
10338 sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
10339
10340 open_db(p,0);
10341 for(i=1; i<nArg; i++){
10342 const char *z = azArg[i];
10343 if( z[0]=='-' && z[1]=='-' ) z++;
10344 if( strcmp(z,"-init")==0 ){
10345 bIsInit = 1;
10346 }else
10347 if( strcmp(z,"-v")==0 ){
10348 bVerbose++;
10349 }else
10350 {
10351 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
10352 azArg[i], azArg[0]);
10353 raw_printf(stderr, "Should be one of: --init -v\n");
10354 rc = 1;
10355 goto meta_command_exit;
10356 }
10357 }
10358 if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
10359 != SQLITE_OK ){
10360 bSelftestExists = 0;
10361 }else{
10362 bSelftestExists = 1;
10363 }
10364 if( bIsInit ){
10365 createSelftestTable(p);
10366 bSelftestExists = 1;
10367 }
10368 initText(&str);
10369 appendText(&str, "x", 0);
10370 for(k=bSelftestExists; k>=0; k--){
10371 if( k==1 ){
10372 rc = sqlite3_prepare_v2(p->db,
10373 "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
10374 -1, &pStmt, 0);
10375 }else{
10376 rc = sqlite3_prepare_v2(p->db,
10377 "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
10378 " (1,'run','PRAGMA integrity_check','ok')",
10379 -1, &pStmt, 0);
10380 }
10381 if( rc ){
10382 raw_printf(stderr, "Error querying the selftest table\n");
10383 rc = 1;
10384 sqlite3_finalize(pStmt);
10385 goto meta_command_exit;
10386 }
10387 for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
10388 int tno = sqlite3_column_int(pStmt, 0);
10389 const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
10390 const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
10391 const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
10392
drh621a5e02021-12-16 17:35:27 +000010393 if( zOp==0 ) continue;
10394 if( zSql==0 ) continue;
10395 if( zAns==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +000010396 k = 0;
10397 if( bVerbose>0 ){
drh2ce15c32017-07-11 13:34:40 +000010398 printf("%d: %s %s\n", tno, zOp, zSql);
drh2ce15c32017-07-11 13:34:40 +000010399 }
10400 if( strcmp(zOp,"memo")==0 ){
10401 utf8_printf(p->out, "%s\n", zSql);
10402 }else
10403 if( strcmp(zOp,"run")==0 ){
10404 char *zErrMsg = 0;
10405 str.n = 0;
10406 str.z[0] = 0;
10407 rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
10408 nTest++;
10409 if( bVerbose ){
10410 utf8_printf(p->out, "Result: %s\n", str.z);
10411 }
10412 if( rc || zErrMsg ){
10413 nErr++;
10414 rc = 1;
10415 utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
10416 sqlite3_free(zErrMsg);
10417 }else if( strcmp(zAns,str.z)!=0 ){
10418 nErr++;
10419 rc = 1;
10420 utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
10421 utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z);
10422 }
10423 }else
10424 {
10425 utf8_printf(stderr,
10426 "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
10427 rc = 1;
10428 break;
10429 }
10430 } /* End loop over rows of content from SELFTEST */
10431 sqlite3_finalize(pStmt);
10432 } /* End loop over k */
10433 freeText(&str);
10434 utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
10435 }else
10436
10437 if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
10438 if( nArg<2 || nArg>3 ){
10439 raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
10440 rc = 1;
10441 }
10442 if( nArg>=2 ){
10443 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
10444 "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
10445 }
10446 if( nArg>=3 ){
10447 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator,
10448 "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]);
10449 }
10450 }else
10451
10452 if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){
10453 const char *zLike = 0; /* Which table to checksum. 0 means everything */
10454 int i; /* Loop counter */
10455 int bSchema = 0; /* Also hash the schema */
10456 int bSeparate = 0; /* Hash each table separately */
10457 int iSize = 224; /* Hash algorithm to use */
10458 int bDebug = 0; /* Only show the query that would have run */
10459 sqlite3_stmt *pStmt; /* For querying tables names */
10460 char *zSql; /* SQL to be run */
10461 char *zSep; /* Separator */
10462 ShellText sSql; /* Complete SQL for the query to run the hash */
10463 ShellText sQuery; /* Set of queries used to read all content */
10464 open_db(p, 0);
10465 for(i=1; i<nArg; i++){
10466 const char *z = azArg[i];
10467 if( z[0]=='-' ){
10468 z++;
10469 if( z[0]=='-' ) z++;
10470 if( strcmp(z,"schema")==0 ){
10471 bSchema = 1;
10472 }else
10473 if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
10474 || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
10475 ){
10476 iSize = atoi(&z[5]);
10477 }else
10478 if( strcmp(z,"debug")==0 ){
10479 bDebug = 1;
10480 }else
10481 {
10482 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
10483 azArg[i], azArg[0]);
drhe2754c12019-08-26 12:50:01 +000010484 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +000010485 rc = 1;
10486 goto meta_command_exit;
10487 }
10488 }else if( zLike ){
10489 raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
10490 rc = 1;
10491 goto meta_command_exit;
10492 }else{
10493 zLike = z;
10494 bSeparate = 1;
drhcedfecf2018-03-23 12:59:10 +000010495 if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1;
drh2ce15c32017-07-11 13:34:40 +000010496 }
10497 }
10498 if( bSchema ){
drh067b92b2020-06-19 15:24:12 +000010499 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +000010500 " WHERE type='table' AND coalesce(rootpage,0)>1"
drh067b92b2020-06-19 15:24:12 +000010501 " UNION ALL SELECT 'sqlite_schema'"
drh2ce15c32017-07-11 13:34:40 +000010502 " ORDER BY 1 collate nocase";
10503 }else{
drh067b92b2020-06-19 15:24:12 +000010504 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +000010505 " WHERE type='table' AND coalesce(rootpage,0)>1"
10506 " AND name NOT LIKE 'sqlite_%'"
10507 " ORDER BY 1 collate nocase";
10508 }
10509 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
10510 initText(&sQuery);
10511 initText(&sSql);
10512 appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
10513 zSep = "VALUES(";
10514 while( SQLITE_ROW==sqlite3_step(pStmt) ){
10515 const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
drh621a5e02021-12-16 17:35:27 +000010516 if( zTab==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +000010517 if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
10518 if( strncmp(zTab, "sqlite_",7)!=0 ){
10519 appendText(&sQuery,"SELECT * FROM ", 0);
10520 appendText(&sQuery,zTab,'"');
10521 appendText(&sQuery," NOT INDEXED;", 0);
drh067b92b2020-06-19 15:24:12 +000010522 }else if( strcmp(zTab, "sqlite_schema")==0 ){
10523 appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +000010524 " ORDER BY name;", 0);
10525 }else if( strcmp(zTab, "sqlite_sequence")==0 ){
10526 appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
10527 " ORDER BY name;", 0);
10528 }else if( strcmp(zTab, "sqlite_stat1")==0 ){
10529 appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
10530 " ORDER BY tbl,idx;", 0);
drh175b8f02019-08-08 15:24:17 +000010531 }else if( strcmp(zTab, "sqlite_stat4")==0 ){
drh2ce15c32017-07-11 13:34:40 +000010532 appendText(&sQuery, "SELECT * FROM ", 0);
10533 appendText(&sQuery, zTab, 0);
10534 appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
10535 }
10536 appendText(&sSql, zSep, 0);
10537 appendText(&sSql, sQuery.z, '\'');
10538 sQuery.n = 0;
10539 appendText(&sSql, ",", 0);
10540 appendText(&sSql, zTab, '\'');
10541 zSep = "),(";
10542 }
10543 sqlite3_finalize(pStmt);
10544 if( bSeparate ){
10545 zSql = sqlite3_mprintf(
10546 "%s))"
10547 " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
10548 " FROM [sha3sum$query]",
10549 sSql.z, iSize);
10550 }else{
10551 zSql = sqlite3_mprintf(
10552 "%s))"
10553 " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
10554 " FROM [sha3sum$query]",
10555 sSql.z, iSize);
10556 }
drhe3e25652021-12-16 13:29:28 +000010557 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +000010558 freeText(&sQuery);
10559 freeText(&sSql);
10560 if( bDebug ){
10561 utf8_printf(p->out, "%s\n", zSql);
10562 }else{
drha10b9992018-03-09 15:24:33 +000010563 shell_exec(p, zSql, 0);
drh2ce15c32017-07-11 13:34:40 +000010564 }
10565 sqlite3_free(zSql);
10566 }else
10567
drh04a28c32018-01-31 01:38:44 +000010568#ifndef SQLITE_NOHAVE_SYSTEM
drh2ce15c32017-07-11 13:34:40 +000010569 if( c=='s'
10570 && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
10571 ){
10572 char *zCmd;
10573 int i, x;
drhb97e2ad2021-08-26 18:31:39 +000010574 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh2ce15c32017-07-11 13:34:40 +000010575 if( nArg<2 ){
10576 raw_printf(stderr, "Usage: .system COMMAND\n");
10577 rc = 1;
10578 goto meta_command_exit;
10579 }
10580 zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
drhe3e25652021-12-16 13:29:28 +000010581 for(i=2; i<nArg && zCmd!=0; i++){
drh2ce15c32017-07-11 13:34:40 +000010582 zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
10583 zCmd, azArg[i]);
10584 }
drhe3e25652021-12-16 13:29:28 +000010585 x = zCmd!=0 ? system(zCmd) : 1;
drh2ce15c32017-07-11 13:34:40 +000010586 sqlite3_free(zCmd);
10587 if( x ) raw_printf(stderr, "System command returns %d\n", x);
10588 }else
drh04a28c32018-01-31 01:38:44 +000010589#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
drh2ce15c32017-07-11 13:34:40 +000010590
10591 if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
drhada70452017-12-21 21:02:27 +000010592 static const char *azBool[] = { "off", "on", "trigger", "full"};
drha6e6cf22021-01-09 19:10:04 +000010593 const char *zOut;
drh2ce15c32017-07-11 13:34:40 +000010594 int i;
10595 if( nArg!=1 ){
10596 raw_printf(stderr, "Usage: .show\n");
10597 rc = 1;
10598 goto meta_command_exit;
10599 }
10600 utf8_printf(p->out, "%12.12s: %s\n","echo",
10601 azBool[ShellHasFlag(p, SHFLG_Echo)]);
10602 utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
10603 utf8_printf(p->out, "%12.12s: %s\n","explain",
10604 p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
10605 utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
drhe40f2862022-01-31 14:14:29 +000010606 if( p->mode==MODE_Column
10607 || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
10608 ){
larrybrcc4d55c2022-02-01 02:50:45 +000010609 utf8_printf
10610 (p->out, "%12.12s: %s --wrap %d --wordwrap %s --%squote\n", "mode",
10611 modeDescr[p->mode], p->cmOpts.iWrap,
10612 p->cmOpts.bWordWrap ? "on" : "off",
10613 p->cmOpts.bQuote ? "" : "no");
drhe40f2862022-01-31 14:14:29 +000010614 }else{
10615 utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
10616 }
drh2ce15c32017-07-11 13:34:40 +000010617 utf8_printf(p->out, "%12.12s: ", "nullvalue");
10618 output_c_string(p->out, p->nullValue);
10619 raw_printf(p->out, "\n");
10620 utf8_printf(p->out,"%12.12s: %s\n","output",
10621 strlen30(p->outfile) ? p->outfile : "stdout");
10622 utf8_printf(p->out,"%12.12s: ", "colseparator");
10623 output_c_string(p->out, p->colSeparator);
10624 raw_printf(p->out, "\n");
10625 utf8_printf(p->out,"%12.12s: ", "rowseparator");
10626 output_c_string(p->out, p->rowSeparator);
10627 raw_printf(p->out, "\n");
drha6e6cf22021-01-09 19:10:04 +000010628 switch( p->statsOn ){
10629 case 0: zOut = "off"; break;
10630 default: zOut = "on"; break;
10631 case 2: zOut = "stmt"; break;
10632 case 3: zOut = "vmstep"; break;
10633 }
10634 utf8_printf(p->out, "%12.12s: %s\n","stats", zOut);
drh2ce15c32017-07-11 13:34:40 +000010635 utf8_printf(p->out, "%12.12s: ", "width");
drh0285d982020-05-29 14:38:43 +000010636 for (i=0;i<p->nWidth;i++) {
drh2ce15c32017-07-11 13:34:40 +000010637 raw_printf(p->out, "%d ", p->colWidth[i]);
10638 }
10639 raw_printf(p->out, "\n");
10640 utf8_printf(p->out, "%12.12s: %s\n", "filename",
drh37407122021-07-23 18:43:58 +000010641 p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : "");
drh2ce15c32017-07-11 13:34:40 +000010642 }else
10643
10644 if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
10645 if( nArg==2 ){
drha6e6cf22021-01-09 19:10:04 +000010646 if( strcmp(azArg[1],"stmt")==0 ){
10647 p->statsOn = 2;
10648 }else if( strcmp(azArg[1],"vmstep")==0 ){
10649 p->statsOn = 3;
10650 }else{
10651 p->statsOn = (u8)booleanValue(azArg[1]);
10652 }
drh2ce15c32017-07-11 13:34:40 +000010653 }else if( nArg==1 ){
10654 display_stats(p->db, p, 0);
10655 }else{
drha6e6cf22021-01-09 19:10:04 +000010656 raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n");
drh2ce15c32017-07-11 13:34:40 +000010657 rc = 1;
10658 }
10659 }else
10660
10661 if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0)
10662 || (c=='i' && (strncmp(azArg[0], "indices", n)==0
10663 || strncmp(azArg[0], "indexes", n)==0) )
10664 ){
10665 sqlite3_stmt *pStmt;
10666 char **azResult;
10667 int nRow, nAlloc;
10668 int ii;
10669 ShellText s;
10670 initText(&s);
10671 open_db(p, 0);
10672 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
drh9e804032018-05-18 17:11:50 +000010673 if( rc ){
10674 sqlite3_finalize(pStmt);
10675 return shellDatabaseError(p->db);
10676 }
drh2ce15c32017-07-11 13:34:40 +000010677
10678 if( nArg>2 && c=='i' ){
10679 /* It is an historical accident that the .indexes command shows an error
10680 ** when called with the wrong number of arguments whereas the .tables
10681 ** command does not. */
10682 raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
10683 rc = 1;
drh9e804032018-05-18 17:11:50 +000010684 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +000010685 goto meta_command_exit;
10686 }
10687 for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
10688 const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
10689 if( zDbName==0 ) continue;
10690 if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0);
10691 if( sqlite3_stricmp(zDbName, "main")==0 ){
10692 appendText(&s, "SELECT name FROM ", 0);
10693 }else{
10694 appendText(&s, "SELECT ", 0);
10695 appendText(&s, zDbName, '\'');
10696 appendText(&s, "||'.'||name FROM ", 0);
10697 }
10698 appendText(&s, zDbName, '"');
drh067b92b2020-06-19 15:24:12 +000010699 appendText(&s, ".sqlite_schema ", 0);
drh2ce15c32017-07-11 13:34:40 +000010700 if( c=='t' ){
10701 appendText(&s," WHERE type IN ('table','view')"
10702 " AND name NOT LIKE 'sqlite_%'"
10703 " AND name LIKE ?1", 0);
10704 }else{
10705 appendText(&s," WHERE type='index'"
10706 " AND tbl_name LIKE ?1", 0);
10707 }
10708 }
10709 rc = sqlite3_finalize(pStmt);
drhe85e1da2021-10-01 21:01:07 +000010710 if( rc==SQLITE_OK ){
10711 appendText(&s, " ORDER BY 1", 0);
10712 rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
10713 }
drh2ce15c32017-07-11 13:34:40 +000010714 freeText(&s);
10715 if( rc ) return shellDatabaseError(p->db);
10716
10717 /* Run the SQL statement prepared by the above block. Store the results
10718 ** as an array of nul-terminated strings in azResult[]. */
10719 nRow = nAlloc = 0;
10720 azResult = 0;
10721 if( nArg>1 ){
10722 sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
10723 }else{
10724 sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
10725 }
10726 while( sqlite3_step(pStmt)==SQLITE_ROW ){
10727 if( nRow>=nAlloc ){
10728 char **azNew;
10729 int n2 = nAlloc*2 + 10;
10730 azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
drhe3e25652021-12-16 13:29:28 +000010731 shell_check_oom(azNew);
drh2ce15c32017-07-11 13:34:40 +000010732 nAlloc = n2;
10733 azResult = azNew;
10734 }
10735 azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
drhe3e25652021-12-16 13:29:28 +000010736 shell_check_oom(azResult[nRow]);
drh2ce15c32017-07-11 13:34:40 +000010737 nRow++;
10738 }
10739 if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
10740 rc = shellDatabaseError(p->db);
10741 }
10742
10743 /* Pretty-print the contents of array azResult[] to the output */
10744 if( rc==0 && nRow>0 ){
10745 int len, maxlen = 0;
10746 int i, j;
10747 int nPrintCol, nPrintRow;
10748 for(i=0; i<nRow; i++){
10749 len = strlen30(azResult[i]);
10750 if( len>maxlen ) maxlen = len;
10751 }
10752 nPrintCol = 80/(maxlen+2);
10753 if( nPrintCol<1 ) nPrintCol = 1;
10754 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
10755 for(i=0; i<nPrintRow; i++){
10756 for(j=i; j<nRow; j+=nPrintRow){
10757 char *zSp = j<nPrintRow ? "" : " ";
10758 utf8_printf(p->out, "%s%-*s", zSp, maxlen,
10759 azResult[j] ? azResult[j]:"");
10760 }
10761 raw_printf(p->out, "\n");
10762 }
10763 }
10764
10765 for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
10766 sqlite3_free(azResult);
10767 }else
10768
10769 /* Begin redirecting output to the file "testcase-out.txt" */
10770 if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
10771 output_reset(p);
drha92a01a2018-01-10 22:15:37 +000010772 p->out = output_file_open("testcase-out.txt", 0);
drh2ce15c32017-07-11 13:34:40 +000010773 if( p->out==0 ){
10774 raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
10775 }
10776 if( nArg>=2 ){
10777 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
10778 }else{
10779 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
10780 }
10781 }else
10782
10783#ifndef SQLITE_UNTESTABLE
drh35f51a42017-11-15 17:07:22 +000010784 if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010785 static const struct {
10786 const char *zCtrlName; /* Name of a test-control option */
10787 int ctrlCode; /* Integer code for that option */
drh38ed1ce2021-12-06 15:24:36 +000010788 int unSafe; /* Not valid for --safe mode */
drhef302e82017-11-15 19:14:08 +000010789 const char *zUsage; /* Usage notes */
drh2ce15c32017-07-11 13:34:40 +000010790 } aCtrl[] = {
drh38ed1ce2021-12-06 15:24:36 +000010791 { "always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" },
10792 { "assert", SQLITE_TESTCTRL_ASSERT, 1, "BOOLEAN" },
10793 /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, "" },*/
10794 /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "" },*/
10795 { "byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" },
10796 { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" },
10797 /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"" },*/
10798 { "imposter", SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"},
10799 { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,"" },
10800 { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN" },
10801 { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" },
10802 { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" },
drh0d9de992017-12-26 18:04:23 +000010803#ifdef YYCOVERAGE
drh38ed1ce2021-12-06 15:24:36 +000010804 { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE,0,"" },
drh0d9de992017-12-26 18:04:23 +000010805#endif
drh38ed1ce2021-12-06 15:24:36 +000010806 { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET " },
10807 { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" },
10808 { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" },
10809 { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" },
10810 { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" },
10811 { "sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" },
10812 { "tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" },
drh2ce15c32017-07-11 13:34:40 +000010813 };
10814 int testctrl = -1;
drhef302e82017-11-15 19:14:08 +000010815 int iCtrl = -1;
10816 int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */
10817 int isOk = 0;
drh2ce15c32017-07-11 13:34:40 +000010818 int i, n2;
mistachkinc6bc15a2017-11-21 21:14:32 +000010819 const char *zCmd = 0;
10820
drh2ce15c32017-07-11 13:34:40 +000010821 open_db(p, 0);
mistachkinc6bc15a2017-11-21 21:14:32 +000010822 zCmd = nArg>=2 ? azArg[1] : "help";
drh35f51a42017-11-15 17:07:22 +000010823
10824 /* The argument can optionally begin with "-" or "--" */
10825 if( zCmd[0]=='-' && zCmd[1] ){
10826 zCmd++;
10827 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
10828 }
10829
10830 /* --help lists all test-controls */
10831 if( strcmp(zCmd,"help")==0 ){
10832 utf8_printf(p->out, "Available test-controls:\n");
10833 for(i=0; i<ArraySize(aCtrl); i++){
drhef302e82017-11-15 19:14:08 +000010834 utf8_printf(p->out, " .testctrl %s %s\n",
10835 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
drh35f51a42017-11-15 17:07:22 +000010836 }
10837 rc = 1;
10838 goto meta_command_exit;
10839 }
drh2ce15c32017-07-11 13:34:40 +000010840
10841 /* convert testctrl text option to value. allow any unique prefix
10842 ** of the option name, or a numerical value. */
drh35f51a42017-11-15 17:07:22 +000010843 n2 = strlen30(zCmd);
drh2ce15c32017-07-11 13:34:40 +000010844 for(i=0; i<ArraySize(aCtrl); i++){
drh35f51a42017-11-15 17:07:22 +000010845 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010846 if( testctrl<0 ){
10847 testctrl = aCtrl[i].ctrlCode;
drhef302e82017-11-15 19:14:08 +000010848 iCtrl = i;
drh2ce15c32017-07-11 13:34:40 +000010849 }else{
drh35f51a42017-11-15 17:07:22 +000010850 utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
10851 "Use \".testctrl --help\" for help\n", zCmd);
10852 rc = 1;
10853 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +000010854 }
10855 }
10856 }
drhef302e82017-11-15 19:14:08 +000010857 if( testctrl<0 ){
drh35f51a42017-11-15 17:07:22 +000010858 utf8_printf(stderr,"Error: unknown test-control: %s\n"
10859 "Use \".testctrl --help\" for help\n", zCmd);
drh38ed1ce2021-12-06 15:24:36 +000010860 }else if( aCtrl[iCtrl].unSafe && p->bSafeMode ){
10861 utf8_printf(stderr,
10862 "line %d: \".testctrl %s\" may not be used in safe mode\n",
10863 p->lineno, aCtrl[iCtrl].zCtrlName);
10864 exit(1);
drh2ce15c32017-07-11 13:34:40 +000010865 }else{
10866 switch(testctrl){
10867
10868 /* sqlite3_test_control(int, db, int) */
10869 case SQLITE_TESTCTRL_OPTIMIZATIONS:
drh2ce15c32017-07-11 13:34:40 +000010870 if( nArg==3 ){
drhaf7b7652021-01-13 19:28:17 +000010871 unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
drh2ce15c32017-07-11 13:34:40 +000010872 rc2 = sqlite3_test_control(testctrl, p->db, opt);
drhef302e82017-11-15 19:14:08 +000010873 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010874 }
10875 break;
10876
10877 /* sqlite3_test_control(int) */
10878 case SQLITE_TESTCTRL_PRNG_SAVE:
10879 case SQLITE_TESTCTRL_PRNG_RESTORE:
drh2ce15c32017-07-11 13:34:40 +000010880 case SQLITE_TESTCTRL_BYTEORDER:
10881 if( nArg==2 ){
10882 rc2 = sqlite3_test_control(testctrl);
drhef302e82017-11-15 19:14:08 +000010883 isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
drh2ce15c32017-07-11 13:34:40 +000010884 }
10885 break;
10886
10887 /* sqlite3_test_control(int, uint) */
10888 case SQLITE_TESTCTRL_PENDING_BYTE:
10889 if( nArg==3 ){
10890 unsigned int opt = (unsigned int)integerValue(azArg[2]);
10891 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010892 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010893 }
10894 break;
10895
drh2e6d83b2019-08-03 01:39:20 +000010896 /* sqlite3_test_control(int, int, sqlite3*) */
10897 case SQLITE_TESTCTRL_PRNG_SEED:
10898 if( nArg==3 || nArg==4 ){
drh51755a72019-08-08 19:40:29 +000010899 int ii = (int)integerValue(azArg[2]);
drh2e6d83b2019-08-03 01:39:20 +000010900 sqlite3 *db;
drh41428a92019-08-12 16:25:11 +000010901 if( ii==0 && strcmp(azArg[2],"random")==0 ){
10902 sqlite3_randomness(sizeof(ii),&ii);
10903 printf("-- random seed: %d\n", ii);
10904 }
drh2e6d83b2019-08-03 01:39:20 +000010905 if( nArg==3 ){
10906 db = 0;
10907 }else{
10908 db = p->db;
10909 /* Make sure the schema has been loaded */
10910 sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);
10911 }
drh51755a72019-08-08 19:40:29 +000010912 rc2 = sqlite3_test_control(testctrl, ii, db);
drh2e6d83b2019-08-03 01:39:20 +000010913 isOk = 3;
10914 }
10915 break;
10916
drh2ce15c32017-07-11 13:34:40 +000010917 /* sqlite3_test_control(int, int) */
10918 case SQLITE_TESTCTRL_ASSERT:
10919 case SQLITE_TESTCTRL_ALWAYS:
drhef302e82017-11-15 19:14:08 +000010920 if( nArg==3 ){
10921 int opt = booleanValue(azArg[2]);
10922 rc2 = sqlite3_test_control(testctrl, opt);
10923 isOk = 1;
10924 }
10925 break;
10926
10927 /* sqlite3_test_control(int, int) */
10928 case SQLITE_TESTCTRL_LOCALTIME_FAULT:
drh2ce15c32017-07-11 13:34:40 +000010929 case SQLITE_TESTCTRL_NEVER_CORRUPT:
10930 if( nArg==3 ){
10931 int opt = booleanValue(azArg[2]);
10932 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010933 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010934 }
10935 break;
10936
drh171c50e2020-01-01 15:43:30 +000010937 /* sqlite3_test_control(sqlite3*) */
10938 case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
10939 rc2 = sqlite3_test_control(testctrl, p->db);
drh2a83c102020-01-01 23:02:35 +000010940 isOk = 3;
drh171c50e2020-01-01 15:43:30 +000010941 break;
10942
drh2ce15c32017-07-11 13:34:40 +000010943 case SQLITE_TESTCTRL_IMPOSTER:
10944 if( nArg==5 ){
10945 rc2 = sqlite3_test_control(testctrl, p->db,
10946 azArg[2],
10947 integerValue(azArg[3]),
10948 integerValue(azArg[4]));
drhef302e82017-11-15 19:14:08 +000010949 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010950 }
10951 break;
drh0d9de992017-12-26 18:04:23 +000010952
drh37ccfcf2020-08-31 18:49:04 +000010953 case SQLITE_TESTCTRL_SEEK_COUNT: {
10954 u64 x = 0;
10955 rc2 = sqlite3_test_control(testctrl, p->db, &x);
10956 utf8_printf(p->out, "%llu\n", x);
10957 isOk = 3;
10958 break;
10959 }
10960
drh0d9de992017-12-26 18:04:23 +000010961#ifdef YYCOVERAGE
drhf3c12562021-06-04 13:16:46 +000010962 case SQLITE_TESTCTRL_PARSER_COVERAGE: {
drh0d9de992017-12-26 18:04:23 +000010963 if( nArg==2 ){
10964 sqlite3_test_control(testctrl, p->out);
10965 isOk = 3;
10966 }
drhf3c12562021-06-04 13:16:46 +000010967 break;
10968 }
10969#endif
10970#ifdef SQLITE_DEBUG
10971 case SQLITE_TESTCTRL_TUNE: {
10972 if( nArg==4 ){
10973 int id = (int)integerValue(azArg[2]);
drh2d26cfc2021-06-04 13:40:26 +000010974 int val = (int)integerValue(azArg[3]);
10975 sqlite3_test_control(testctrl, id, &val);
10976 isOk = 3;
10977 }else if( nArg==3 ){
10978 int id = (int)integerValue(azArg[2]);
10979 sqlite3_test_control(testctrl, -id, &rc2);
10980 isOk = 1;
10981 }else if( nArg==2 ){
10982 int id = 1;
10983 while(1){
10984 int val = 0;
10985 rc2 = sqlite3_test_control(testctrl, -id, &val);
10986 if( rc2!=SQLITE_OK ) break;
10987 if( id>1 ) utf8_printf(p->out, " ");
10988 utf8_printf(p->out, "%d: %d", id, val);
10989 id++;
10990 }
10991 if( id>1 ) utf8_printf(p->out, "\n");
drhf3c12562021-06-04 13:16:46 +000010992 isOk = 3;
10993 }
10994 break;
10995 }
drh0d9de992017-12-26 18:04:23 +000010996#endif
dan779e9902021-07-28 18:13:28 +000010997 case SQLITE_TESTCTRL_SORTER_MMAP:
10998 if( nArg==3 ){
10999 int opt = (unsigned int)integerValue(azArg[2]);
11000 rc2 = sqlite3_test_control(testctrl, p->db, opt);
11001 isOk = 3;
11002 }
11003 break;
drh2ce15c32017-07-11 13:34:40 +000011004 }
11005 }
drhef302e82017-11-15 19:14:08 +000011006 if( isOk==0 && iCtrl>=0 ){
drhe2754c12019-08-26 12:50:01 +000011007 utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
drhef302e82017-11-15 19:14:08 +000011008 rc = 1;
11009 }else if( isOk==1 ){
11010 raw_printf(p->out, "%d\n", rc2);
11011 }else if( isOk==2 ){
11012 raw_printf(p->out, "0x%08x\n", rc2);
11013 }
drh2ce15c32017-07-11 13:34:40 +000011014 }else
11015#endif /* !defined(SQLITE_UNTESTABLE) */
11016
11017 if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
11018 open_db(p, 0);
11019 sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
11020 }else
11021
11022 if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
11023 if( nArg==2 ){
11024 enableTimer = booleanValue(azArg[1]);
11025 if( enableTimer && !HAS_TIMER ){
11026 raw_printf(stderr, "Error: timer not available on this system.\n");
11027 enableTimer = 0;
11028 }
11029 }else{
11030 raw_printf(stderr, "Usage: .timer on|off\n");
11031 rc = 1;
11032 }
11033 }else
11034
drh707821f2018-12-05 13:39:06 +000011035#ifndef SQLITE_OMIT_TRACE
drh2ce15c32017-07-11 13:34:40 +000011036 if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
drh707821f2018-12-05 13:39:06 +000011037 int mType = 0;
11038 int jj;
drh2ce15c32017-07-11 13:34:40 +000011039 open_db(p, 0);
drh707821f2018-12-05 13:39:06 +000011040 for(jj=1; jj<nArg; jj++){
11041 const char *z = azArg[jj];
11042 if( z[0]=='-' ){
11043 if( optionMatch(z, "expanded") ){
11044 p->eTraceType = SHELL_TRACE_EXPANDED;
11045 }
11046#ifdef SQLITE_ENABLE_NORMALIZE
11047 else if( optionMatch(z, "normalized") ){
11048 p->eTraceType = SHELL_TRACE_NORMALIZED;
11049 }
11050#endif
11051 else if( optionMatch(z, "plain") ){
11052 p->eTraceType = SHELL_TRACE_PLAIN;
11053 }
11054 else if( optionMatch(z, "profile") ){
11055 mType |= SQLITE_TRACE_PROFILE;
11056 }
11057 else if( optionMatch(z, "row") ){
11058 mType |= SQLITE_TRACE_ROW;
11059 }
11060 else if( optionMatch(z, "stmt") ){
11061 mType |= SQLITE_TRACE_STMT;
11062 }
11063 else if( optionMatch(z, "close") ){
11064 mType |= SQLITE_TRACE_CLOSE;
11065 }
11066 else {
11067 raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
11068 rc = 1;
11069 goto meta_command_exit;
11070 }
11071 }else{
11072 output_file_close(p->traceOut);
11073 p->traceOut = output_file_open(azArg[1], 0);
11074 }
drh2ce15c32017-07-11 13:34:40 +000011075 }
drh2ce15c32017-07-11 13:34:40 +000011076 if( p->traceOut==0 ){
11077 sqlite3_trace_v2(p->db, 0, 0, 0);
11078 }else{
drh707821f2018-12-05 13:39:06 +000011079 if( mType==0 ) mType = SQLITE_TRACE_STMT;
11080 sqlite3_trace_v2(p->db, mType, sql_trace_callback, p);
drh2ce15c32017-07-11 13:34:40 +000011081 }
drh2ce15c32017-07-11 13:34:40 +000011082 }else
drh707821f2018-12-05 13:39:06 +000011083#endif /* !defined(SQLITE_OMIT_TRACE) */
drh2ce15c32017-07-11 13:34:40 +000011084
drhe2b7a762019-10-02 00:25:08 +000011085#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhcc5979d2019-08-16 22:58:29 +000011086 if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){
11087 int ii;
drh8c754a32019-08-19 20:35:30 +000011088 int lenOpt;
drh5df84282019-08-17 19:45:25 +000011089 char *zOpt;
drhcc5979d2019-08-16 22:58:29 +000011090 if( nArg<2 ){
drh5df84282019-08-17 19:45:25 +000011091 raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
drhcc5979d2019-08-16 22:58:29 +000011092 rc = 1;
11093 goto meta_command_exit;
11094 }
11095 open_db(p, 0);
drh5df84282019-08-17 19:45:25 +000011096 zOpt = azArg[1];
11097 if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
drh8c754a32019-08-19 20:35:30 +000011098 lenOpt = (int)strlen(zOpt);
11099 if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){
drh5df84282019-08-17 19:45:25 +000011100 assert( azArg[nArg]==0 );
drh8c754a32019-08-19 20:35:30 +000011101 sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0);
drh5df84282019-08-17 19:45:25 +000011102 }else{
11103 for(ii=1; ii<nArg; ii++){
11104 sqlite3_create_module(p->db, azArg[ii], 0, 0);
11105 }
drhcc5979d2019-08-16 22:58:29 +000011106 }
11107 }else
11108#endif
11109
drh2ce15c32017-07-11 13:34:40 +000011110#if SQLITE_USER_AUTHENTICATION
11111 if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
11112 if( nArg<2 ){
11113 raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
11114 rc = 1;
11115 goto meta_command_exit;
11116 }
11117 open_db(p, 0);
11118 if( strcmp(azArg[1],"login")==0 ){
11119 if( nArg!=4 ){
11120 raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
11121 rc = 1;
11122 goto meta_command_exit;
11123 }
drhe2754c12019-08-26 12:50:01 +000011124 rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
11125 strlen30(azArg[3]));
drh2ce15c32017-07-11 13:34:40 +000011126 if( rc ){
11127 utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
11128 rc = 1;
11129 }
11130 }else if( strcmp(azArg[1],"add")==0 ){
11131 if( nArg!=5 ){
11132 raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
11133 rc = 1;
11134 goto meta_command_exit;
11135 }
drhaf2770f2018-01-05 14:55:43 +000011136 rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000011137 booleanValue(azArg[4]));
11138 if( rc ){
11139 raw_printf(stderr, "User-Add failed: %d\n", rc);
11140 rc = 1;
11141 }
11142 }else if( strcmp(azArg[1],"edit")==0 ){
11143 if( nArg!=5 ){
11144 raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
11145 rc = 1;
11146 goto meta_command_exit;
11147 }
drhaf2770f2018-01-05 14:55:43 +000011148 rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000011149 booleanValue(azArg[4]));
11150 if( rc ){
11151 raw_printf(stderr, "User-Edit failed: %d\n", rc);
11152 rc = 1;
11153 }
11154 }else if( strcmp(azArg[1],"delete")==0 ){
11155 if( nArg!=3 ){
11156 raw_printf(stderr, "Usage: .user delete USER\n");
11157 rc = 1;
11158 goto meta_command_exit;
11159 }
11160 rc = sqlite3_user_delete(p->db, azArg[2]);
11161 if( rc ){
11162 raw_printf(stderr, "User-Delete failed: %d\n", rc);
11163 rc = 1;
11164 }
11165 }else{
11166 raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
11167 rc = 1;
11168 goto meta_command_exit;
11169 }
11170 }else
11171#endif /* SQLITE_USER_AUTHENTICATION */
11172
11173 if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
11174 utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
11175 sqlite3_libversion(), sqlite3_sourceid());
drh0ed2fd82018-01-16 20:05:27 +000011176#if SQLITE_HAVE_ZLIB
11177 utf8_printf(p->out, "zlib version %s\n", zlibVersion());
11178#endif
11179#define CTIMEOPT_VAL_(opt) #opt
11180#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
11181#if defined(__clang__) && defined(__clang_major__)
11182 utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
11183 CTIMEOPT_VAL(__clang_minor__) "."
11184 CTIMEOPT_VAL(__clang_patchlevel__) "\n");
11185#elif defined(_MSC_VER)
11186 utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n");
11187#elif defined(__GNUC__) && defined(__VERSION__)
11188 utf8_printf(p->out, "gcc-" __VERSION__ "\n");
11189#endif
drh2ce15c32017-07-11 13:34:40 +000011190 }else
11191
11192 if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
11193 const char *zDbName = nArg==2 ? azArg[1] : "main";
11194 sqlite3_vfs *pVfs = 0;
11195 if( p->db ){
11196 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
11197 if( pVfs ){
11198 utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
11199 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
11200 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
11201 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
11202 }
11203 }
11204 }else
11205
11206 if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){
11207 sqlite3_vfs *pVfs;
11208 sqlite3_vfs *pCurrent = 0;
11209 if( p->db ){
11210 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
11211 }
11212 for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
11213 utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName,
11214 pVfs==pCurrent ? " <--- CURRENT" : "");
11215 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
11216 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
11217 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
11218 if( pVfs->pNext ){
11219 raw_printf(p->out, "-----------------------------------\n");
11220 }
11221 }
11222 }else
11223
11224 if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
11225 const char *zDbName = nArg==2 ? azArg[1] : "main";
11226 char *zVfsName = 0;
11227 if( p->db ){
11228 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
11229 if( zVfsName ){
11230 utf8_printf(p->out, "%s\n", zVfsName);
11231 sqlite3_free(zVfsName);
11232 }
11233 }
11234 }else
11235
drh2ce15c32017-07-11 13:34:40 +000011236 if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
drhc0622a42020-12-04 01:17:57 +000011237 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
11238 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x);
drh2ce15c32017-07-11 13:34:40 +000011239 }else
drh2ce15c32017-07-11 13:34:40 +000011240
11241 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
11242 int j;
11243 assert( nArg<=ArraySize(azArg) );
drh0285d982020-05-29 14:38:43 +000011244 p->nWidth = nArg-1;
drh76fc88f2021-10-02 16:39:16 +000011245 p->colWidth = realloc(p->colWidth, (p->nWidth+1)*sizeof(int)*2);
drh0285d982020-05-29 14:38:43 +000011246 if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory();
11247 if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
11248 for(j=1; j<nArg; j++){
drh2ce15c32017-07-11 13:34:40 +000011249 p->colWidth[j-1] = (int)integerValue(azArg[j]);
11250 }
11251 }else
11252
11253 {
11254 utf8_printf(stderr, "Error: unknown command or invalid arguments: "
11255 " \"%s\". Enter \".help\" for help\n", azArg[0]);
11256 rc = 1;
11257 }
11258
11259meta_command_exit:
11260 if( p->outCount ){
11261 p->outCount--;
11262 if( p->outCount==0 ) output_reset(p);
11263 }
drhb97e2ad2021-08-26 18:31:39 +000011264 p->bSafeMode = p->bSafeModePersist;
drh2ce15c32017-07-11 13:34:40 +000011265 return rc;
11266}
11267
larrybr8bc4cbc2021-09-10 00:58:46 +000011268/* Line scan result and intermediate states (supporting scan resumption)
drh2ce15c32017-07-11 13:34:40 +000011269*/
drh68911c22021-09-22 14:26:22 +000011270#ifndef CHAR_BIT
11271# define CHAR_BIT 8
11272#endif
larrybr8bc4cbc2021-09-10 00:58:46 +000011273typedef enum {
larrybr7e009842021-09-18 21:35:22 +000011274 QSS_HasDark = 1<<CHAR_BIT, QSS_EndingSemi = 2<<CHAR_BIT,
11275 QSS_CharMask = (1<<CHAR_BIT)-1, QSS_ScanMask = 3<<CHAR_BIT,
larrybra96bbe92021-09-10 19:45:22 +000011276 QSS_Start = 0
larrybr8bc4cbc2021-09-10 00:58:46 +000011277} QuickScanState;
larrybr7e009842021-09-18 21:35:22 +000011278#define QSS_SETV(qss, newst) ((newst) | ((qss) & QSS_ScanMask))
11279#define QSS_INPLAIN(qss) (((qss)&QSS_CharMask)==QSS_Start)
11280#define QSS_PLAINWHITE(qss) (((qss)&~QSS_EndingSemi)==QSS_Start)
larrybra96bbe92021-09-10 19:45:22 +000011281#define QSS_PLAINDARK(qss) (((qss)&~QSS_EndingSemi)==QSS_HasDark)
larrybr7e009842021-09-18 21:35:22 +000011282#define QSS_SEMITERM(qss) (((qss)&~QSS_HasDark)==QSS_EndingSemi)
drh2ce15c32017-07-11 13:34:40 +000011283
11284/*
larrybr8bc4cbc2021-09-10 00:58:46 +000011285** Scan line for classification to guide shell's handling.
11286** The scan is resumable for subsequent lines when prior
11287** return values are passed as the 2nd argument.
drh2ce15c32017-07-11 13:34:40 +000011288*/
larrybr8bc4cbc2021-09-10 00:58:46 +000011289static QuickScanState quickscan(char *zLine, QuickScanState qss){
11290 char cin;
larrybr7e009842021-09-18 21:35:22 +000011291 char cWait = (char)qss; /* intentional narrowing loss */
11292 if( cWait==0 ){
11293 PlainScan:
drhe85e1da2021-10-01 21:01:07 +000011294 assert( cWait==0 );
drhfd7abcd2021-09-22 13:43:16 +000011295 while( (cin = *zLine++)!=0 ){
larrybr8bc4cbc2021-09-10 00:58:46 +000011296 if( IsSpace(cin) )
11297 continue;
11298 switch (cin){
11299 case '-':
larrybr7e009842021-09-18 21:35:22 +000011300 if( *zLine!='-' )
11301 break;
11302 while((cin = *++zLine)!=0 )
11303 if( cin=='\n')
11304 goto PlainScan;
11305 return qss;
larrybr8bc4cbc2021-09-10 00:58:46 +000011306 case ';':
larrybra96bbe92021-09-10 19:45:22 +000011307 qss |= QSS_EndingSemi;
11308 continue;
larrybr8bc4cbc2021-09-10 00:58:46 +000011309 case '/':
11310 if( *zLine=='*' ){
11311 ++zLine;
larrybr7e009842021-09-18 21:35:22 +000011312 cWait = '*';
11313 qss = QSS_SETV(qss, cWait);
11314 goto TermScan;
larrybr8bc4cbc2021-09-10 00:58:46 +000011315 }
11316 break;
larrybra96bbe92021-09-10 19:45:22 +000011317 case '[':
11318 cin = ']';
11319 /* fall thru */
11320 case '`': case '\'': case '"':
larrybr7e009842021-09-18 21:35:22 +000011321 cWait = cin;
11322 qss = QSS_HasDark | cWait;
11323 goto TermScan;
larrybr8bc4cbc2021-09-10 00:58:46 +000011324 default:
11325 break;
11326 }
larrybr7e009842021-09-18 21:35:22 +000011327 qss = (qss & ~QSS_EndingSemi) | QSS_HasDark;
drh2ce15c32017-07-11 13:34:40 +000011328 }
larrybr7e009842021-09-18 21:35:22 +000011329 }else{
11330 TermScan:
drhfd7abcd2021-09-22 13:43:16 +000011331 while( (cin = *zLine++)!=0 ){
larrybr7e009842021-09-18 21:35:22 +000011332 if( cin==cWait ){
11333 switch( cWait ){
11334 case '*':
11335 if( *zLine != '/' )
11336 continue;
11337 ++zLine;
11338 cWait = 0;
11339 qss = QSS_SETV(qss, 0);
11340 goto PlainScan;
11341 case '`': case '\'': case '"':
11342 if(*zLine==cWait){
larrybr8d463ce2021-09-11 02:42:04 +000011343 ++zLine;
larrybr7e009842021-09-18 21:35:22 +000011344 continue;
11345 }
11346 /* fall thru */
11347 case ']':
11348 cWait = 0;
11349 qss = QSS_SETV(qss, 0);
11350 goto PlainScan;
11351 default: assert(0);
larrybr8bc4cbc2021-09-10 00:58:46 +000011352 }
11353 }
11354 }
drh2ce15c32017-07-11 13:34:40 +000011355 }
larrybr8bc4cbc2021-09-10 00:58:46 +000011356 return qss;
drh2ce15c32017-07-11 13:34:40 +000011357}
11358
11359/*
11360** Return TRUE if the line typed in is an SQL command terminator other
11361** than a semi-colon. The SQL Server style "go" command is understood
11362** as is the Oracle "/".
11363*/
larrybr8bc4cbc2021-09-10 00:58:46 +000011364static int line_is_command_terminator(char *zLine){
drh2ce15c32017-07-11 13:34:40 +000011365 while( IsSpace(zLine[0]) ){ zLine++; };
larrybr8bc4cbc2021-09-10 00:58:46 +000011366 if( zLine[0]=='/' )
11367 zLine += 1; /* Oracle */
11368 else if ( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o' )
11369 zLine += 2; /* SQL Server */
11370 else
11371 return 0;
larrybra96bbe92021-09-10 19:45:22 +000011372 return quickscan(zLine,QSS_Start)==QSS_Start;
drh2ce15c32017-07-11 13:34:40 +000011373}
11374
11375/*
drh56f17742018-01-24 01:58:49 +000011376** We need a default sqlite3_complete() implementation to use in case
11377** the shell is compiled with SQLITE_OMIT_COMPLETE. The default assumes
11378** any arbitrary text is a complete SQL statement. This is not very
11379** user-friendly, but it does seem to work.
11380*/
11381#ifdef SQLITE_OMIT_COMPLETE
danc86b23b2018-11-16 14:36:42 +000011382#define sqlite3_complete(x) 1
drh56f17742018-01-24 01:58:49 +000011383#endif
11384
11385/*
drh2ce15c32017-07-11 13:34:40 +000011386** Return true if zSql is a complete SQL statement. Return false if it
11387** ends in the middle of a string literal or C-style comment.
11388*/
11389static int line_is_complete(char *zSql, int nSql){
11390 int rc;
11391 if( zSql==0 ) return 1;
11392 zSql[nSql] = ';';
11393 zSql[nSql+1] = 0;
11394 rc = sqlite3_complete(zSql);
11395 zSql[nSql] = 0;
11396 return rc;
11397}
11398
11399/*
drhfc29a862018-05-11 19:11:18 +000011400** Run a single line of SQL. Return the number of errors.
drh2ce15c32017-07-11 13:34:40 +000011401*/
11402static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
11403 int rc;
11404 char *zErrMsg = 0;
11405
11406 open_db(p, 0);
11407 if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
drhfc4eeef2019-02-05 19:48:46 +000011408 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
drh2ce15c32017-07-11 13:34:40 +000011409 BEGIN_TIMER;
drha10b9992018-03-09 15:24:33 +000011410 rc = shell_exec(p, zSql, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000011411 END_TIMER;
11412 if( rc || zErrMsg ){
11413 char zPrefix[100];
drh3e46db22022-02-08 11:52:45 +000011414 const char *zErrorTail;
11415 const char *zErrorType;
11416 if( zErrMsg==0 ){
11417 zErrorType = "Error";
11418 zErrorTail = sqlite3_errmsg(p->db);
11419 }else if( strncmp(zErrMsg, "in prepare, ",12)==0 ){
11420 zErrorType = "Parse error";
11421 zErrorTail = &zErrMsg[12];
11422 }else if( strncmp(zErrMsg, "stepping, ", 10)==0 ){
11423 zErrorType = "Runtime error";
11424 zErrorTail = &zErrMsg[10];
11425 }else{
11426 zErrorType = "Error";
11427 zErrorTail = zErrMsg;
11428 }
drh2ce15c32017-07-11 13:34:40 +000011429 if( in!=0 || !stdin_is_interactive ){
11430 sqlite3_snprintf(sizeof(zPrefix), zPrefix,
drh3e46db22022-02-08 11:52:45 +000011431 "%s near line %d:", zErrorType, startline);
drh2ce15c32017-07-11 13:34:40 +000011432 }else{
drh3e46db22022-02-08 11:52:45 +000011433 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:", zErrorType);
drh2ce15c32017-07-11 13:34:40 +000011434 }
drh3e46db22022-02-08 11:52:45 +000011435 utf8_printf(stderr, "%s %s\n", zPrefix, zErrorTail);
11436 sqlite3_free(zErrMsg);
11437 zErrMsg = 0;
drh2ce15c32017-07-11 13:34:40 +000011438 return 1;
11439 }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
drh6d9f0342021-09-22 10:28:50 +000011440 char zLineBuf[2000];
11441 sqlite3_snprintf(sizeof(zLineBuf), zLineBuf,
11442 "changes: %lld total_changes: %lld",
larrybr10496f72021-06-23 16:07:20 +000011443 sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
drh6d9f0342021-09-22 10:28:50 +000011444 raw_printf(p->out, "%s\n", zLineBuf);
drh2ce15c32017-07-11 13:34:40 +000011445 }
11446 return 0;
11447}
11448
11449
11450/*
11451** Read input from *in and process it. If *in==0 then input
11452** is interactive - the user is typing it it. Otherwise, input
11453** is coming from a file or device. A prompt is issued and history
11454** is saved only if input is interactive. An interrupt signal will
11455** cause this routine to exit immediately, unless input is interactive.
11456**
11457** Return the number of errors.
11458*/
drh60379d42018-12-13 18:30:01 +000011459static int process_input(ShellState *p){
drh2ce15c32017-07-11 13:34:40 +000011460 char *zLine = 0; /* A single input line */
11461 char *zSql = 0; /* Accumulated SQL text */
11462 int nLine; /* Length of current line */
11463 int nSql = 0; /* Bytes of zSql[] used */
11464 int nAlloc = 0; /* Allocated zSql[] space */
drh2ce15c32017-07-11 13:34:40 +000011465 int rc; /* Error code */
11466 int errCnt = 0; /* Number of errors seen */
drh2ce15c32017-07-11 13:34:40 +000011467 int startline = 0; /* Line number for start of current input */
larrybr7e009842021-09-18 21:35:22 +000011468 QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */
drh2ce15c32017-07-11 13:34:40 +000011469
larrybrd48e88e2022-01-24 06:36:16 +000011470 if( p->inputNesting==MAX_INPUT_NESTING ){
11471 /* This will be more informative in a later version. */
11472 utf8_printf(stderr,"Input nesting limit (%d) reached at line %d."
11473 " Check recursion.\n", MAX_INPUT_NESTING, p->lineno);
11474 return 1;
11475 }
11476 ++p->inputNesting;
drh2c8ee022018-12-13 18:59:30 +000011477 p->lineno = 0;
drh60379d42018-12-13 18:30:01 +000011478 while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
drh2ce15c32017-07-11 13:34:40 +000011479 fflush(p->out);
drh60379d42018-12-13 18:30:01 +000011480 zLine = one_input_line(p->in, zLine, nSql>0);
drh2ce15c32017-07-11 13:34:40 +000011481 if( zLine==0 ){
11482 /* End of input */
drh60379d42018-12-13 18:30:01 +000011483 if( p->in==0 && stdin_is_interactive ) printf("\n");
drh2ce15c32017-07-11 13:34:40 +000011484 break;
11485 }
11486 if( seenInterrupt ){
drh60379d42018-12-13 18:30:01 +000011487 if( p->in!=0 ) break;
drh2ce15c32017-07-11 13:34:40 +000011488 seenInterrupt = 0;
11489 }
drh2c8ee022018-12-13 18:59:30 +000011490 p->lineno++;
larrybr7e009842021-09-18 21:35:22 +000011491 if( QSS_INPLAIN(qss)
larrybr8bc4cbc2021-09-10 00:58:46 +000011492 && line_is_command_terminator(zLine)
11493 && line_is_complete(zSql, nSql) ){
11494 memcpy(zLine,";",2);
11495 }
11496 qss = quickscan(zLine, qss);
11497 if( QSS_PLAINWHITE(qss) && nSql==0 ){
11498 if( ShellHasFlag(p, SHFLG_Echo) )
11499 printf("%s\n", zLine);
larrybrd797d6b2021-10-03 22:03:59 +000011500 /* Just swallow single-line whitespace */
11501 qss = QSS_Start;
larrybr8bc4cbc2021-09-10 00:58:46 +000011502 continue;
drh2ce15c32017-07-11 13:34:40 +000011503 }
drh1615c372018-05-12 23:56:22 +000011504 if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
drh2ce15c32017-07-11 13:34:40 +000011505 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
drh1615c372018-05-12 23:56:22 +000011506 if( zLine[0]=='.' ){
11507 rc = do_meta_command(zLine, p);
11508 if( rc==2 ){ /* exit requested */
11509 break;
11510 }else if( rc ){
11511 errCnt++;
11512 }
drh2ce15c32017-07-11 13:34:40 +000011513 }
larrybr81012162021-10-02 15:34:52 +000011514 qss = QSS_Start;
drh2ce15c32017-07-11 13:34:40 +000011515 continue;
11516 }
larrybrd797d6b2021-10-03 22:03:59 +000011517 /* No single-line dispositions remain; accumulate line(s). */
drh2ce15c32017-07-11 13:34:40 +000011518 nLine = strlen30(zLine);
11519 if( nSql+nLine+2>=nAlloc ){
larrybr31bffb42021-09-08 21:49:03 +000011520 /* Grow buffer by half-again increments when big. */
11521 nAlloc = nSql+(nSql>>1)+nLine+100;
drh2ce15c32017-07-11 13:34:40 +000011522 zSql = realloc(zSql, nAlloc);
drhe3e25652021-12-16 13:29:28 +000011523 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +000011524 }
drh2ce15c32017-07-11 13:34:40 +000011525 if( nSql==0 ){
11526 int i;
11527 for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
11528 assert( nAlloc>0 && zSql!=0 );
11529 memcpy(zSql, zLine+i, nLine+1-i);
drh2c8ee022018-12-13 18:59:30 +000011530 startline = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000011531 nSql = nLine-i;
11532 }else{
11533 zSql[nSql++] = '\n';
11534 memcpy(zSql+nSql, zLine, nLine+1);
11535 nSql += nLine;
11536 }
larrybra96bbe92021-09-10 19:45:22 +000011537 if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){
drh60379d42018-12-13 18:30:01 +000011538 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000011539 nSql = 0;
11540 if( p->outCount ){
11541 output_reset(p);
11542 p->outCount = 0;
drh13c20932018-01-10 21:41:55 +000011543 }else{
11544 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +000011545 }
drhb97e2ad2021-08-26 18:31:39 +000011546 p->bSafeMode = p->bSafeModePersist;
larrybrd797d6b2021-10-03 22:03:59 +000011547 qss = QSS_Start;
larrybr8bc4cbc2021-09-10 00:58:46 +000011548 }else if( nSql && QSS_PLAINWHITE(qss) ){
drh2ce15c32017-07-11 13:34:40 +000011549 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
11550 nSql = 0;
larrybrd797d6b2021-10-03 22:03:59 +000011551 qss = QSS_Start;
drh2ce15c32017-07-11 13:34:40 +000011552 }
11553 }
larrybr8bc4cbc2021-09-10 00:58:46 +000011554 if( nSql && QSS_PLAINDARK(qss) ){
drh60379d42018-12-13 18:30:01 +000011555 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000011556 }
11557 free(zSql);
11558 free(zLine);
larrybrd48e88e2022-01-24 06:36:16 +000011559 --p->inputNesting;
drh2ce15c32017-07-11 13:34:40 +000011560 return errCnt>0;
11561}
11562
11563/*
11564** Return a pathname which is the user's home directory. A
11565** 0 return indicates an error of some kind.
11566*/
11567static char *find_home_dir(int clearFlag){
11568 static char *home_dir = NULL;
11569 if( clearFlag ){
11570 free(home_dir);
11571 home_dir = 0;
11572 return 0;
11573 }
11574 if( home_dir ) return home_dir;
11575
11576#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
11577 && !defined(__RTP__) && !defined(_WRS_KERNEL)
11578 {
11579 struct passwd *pwent;
11580 uid_t uid = getuid();
11581 if( (pwent=getpwuid(uid)) != NULL) {
11582 home_dir = pwent->pw_dir;
11583 }
11584 }
11585#endif
11586
11587#if defined(_WIN32_WCE)
11588 /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
11589 */
11590 home_dir = "/";
11591#else
11592
11593#if defined(_WIN32) || defined(WIN32)
11594 if (!home_dir) {
11595 home_dir = getenv("USERPROFILE");
11596 }
11597#endif
11598
11599 if (!home_dir) {
11600 home_dir = getenv("HOME");
11601 }
11602
11603#if defined(_WIN32) || defined(WIN32)
11604 if (!home_dir) {
11605 char *zDrive, *zPath;
11606 int n;
11607 zDrive = getenv("HOMEDRIVE");
11608 zPath = getenv("HOMEPATH");
11609 if( zDrive && zPath ){
11610 n = strlen30(zDrive) + strlen30(zPath) + 1;
11611 home_dir = malloc( n );
11612 if( home_dir==0 ) return 0;
11613 sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
11614 return home_dir;
11615 }
11616 home_dir = "c:\\";
11617 }
11618#endif
11619
11620#endif /* !_WIN32_WCE */
11621
11622 if( home_dir ){
11623 int n = strlen30(home_dir) + 1;
11624 char *z = malloc( n );
11625 if( z ) memcpy(z, home_dir, n);
11626 home_dir = z;
11627 }
11628
11629 return home_dir;
11630}
11631
11632/*
11633** Read input from the file given by sqliterc_override. Or if that
11634** parameter is NULL, take input from ~/.sqliterc
11635**
11636** Returns the number of errors.
11637*/
11638static void process_sqliterc(
11639 ShellState *p, /* Configuration data */
11640 const char *sqliterc_override /* Name of config file. NULL to use default */
11641){
11642 char *home_dir = NULL;
11643 const char *sqliterc = sqliterc_override;
11644 char *zBuf = 0;
drh60379d42018-12-13 18:30:01 +000011645 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +000011646 int savedLineno = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000011647
11648 if (sqliterc == NULL) {
11649 home_dir = find_home_dir(0);
11650 if( home_dir==0 ){
11651 raw_printf(stderr, "-- warning: cannot find home directory;"
11652 " cannot read ~/.sqliterc\n");
11653 return;
11654 }
drh2ce15c32017-07-11 13:34:40 +000011655 zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
drhe3e25652021-12-16 13:29:28 +000011656 shell_check_oom(zBuf);
drh2ce15c32017-07-11 13:34:40 +000011657 sqliterc = zBuf;
11658 }
drh60379d42018-12-13 18:30:01 +000011659 p->in = fopen(sqliterc,"rb");
11660 if( p->in ){
drh2ce15c32017-07-11 13:34:40 +000011661 if( stdin_is_interactive ){
11662 utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
11663 }
drhb7c46aa2020-11-25 13:59:47 +000011664 if( process_input(p) && bail_on_error ) exit(1);
drh60379d42018-12-13 18:30:01 +000011665 fclose(p->in);
drhb7c46aa2020-11-25 13:59:47 +000011666 }else if( sqliterc_override!=0 ){
11667 utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
11668 if( bail_on_error ) exit(1);
drh2ce15c32017-07-11 13:34:40 +000011669 }
drh60379d42018-12-13 18:30:01 +000011670 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +000011671 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +000011672 sqlite3_free(zBuf);
11673}
11674
11675/*
11676** Show available command line options
11677*/
11678static const char zOptions[] =
drhda57d962018-03-05 19:34:05 +000011679#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhad7fd5d2018-03-05 20:21:50 +000011680 " -A ARGS... run \".archive ARGS\" and exit\n"
drhda57d962018-03-05 19:34:05 +000011681#endif
drh3baed312018-03-08 18:14:41 +000011682 " -append append the database to the end of the file\n"
drh2ce15c32017-07-11 13:34:40 +000011683 " -ascii set output mode to 'ascii'\n"
11684 " -bail stop after hitting an error\n"
11685 " -batch force batch I/O\n"
drh0908e382020-06-04 18:05:39 +000011686 " -box set output mode to 'box'\n"
drh2ce15c32017-07-11 13:34:40 +000011687 " -column set output mode to 'column'\n"
11688 " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
11689 " -csv set output mode to 'csv'\n"
drh8d889af2021-05-08 17:18:23 +000011690#if !defined(SQLITE_OMIT_DESERIALIZE)
drh6ca64482019-01-22 16:06:20 +000011691 " -deserialize open the database using sqlite3_deserialize()\n"
11692#endif
drh2ce15c32017-07-11 13:34:40 +000011693 " -echo print commands before execution\n"
11694 " -init FILENAME read/process named file\n"
11695 " -[no]header turn headers on or off\n"
11696#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
11697 " -heap SIZE Size of heap for memsys3 or memsys5\n"
11698#endif
11699 " -help show this message\n"
11700 " -html set output mode to HTML\n"
11701 " -interactive force interactive I/O\n"
drh30c54a02020-05-28 23:49:50 +000011702 " -json set output mode to 'json'\n"
drh2ce15c32017-07-11 13:34:40 +000011703 " -line set output mode to 'line'\n"
11704 " -list set output mode to 'list'\n"
11705 " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
drh30c54a02020-05-28 23:49:50 +000011706 " -markdown set output mode to 'markdown'\n"
drh8d889af2021-05-08 17:18:23 +000011707#if !defined(SQLITE_OMIT_DESERIALIZE)
drh6ca64482019-01-22 16:06:20 +000011708 " -maxsize N maximum size for a --deserialize database\n"
11709#endif
drhaf482572019-02-04 19:52:39 +000011710 " -memtrace trace all memory allocations and deallocations\n"
drh2ce15c32017-07-11 13:34:40 +000011711 " -mmap N default mmap size set to N\n"
11712#ifdef SQLITE_ENABLE_MULTIPLEX
11713 " -multiplex enable the multiplexor VFS\n"
11714#endif
11715 " -newline SEP set output row separator. Default: '\\n'\n"
drh0933aad2019-11-18 17:46:38 +000011716 " -nofollow refuse to open symbolic links to database files\n"
drhb97e2ad2021-08-26 18:31:39 +000011717 " -nonce STRING set the safe-mode escape nonce\n"
drh2ce15c32017-07-11 13:34:40 +000011718 " -nullvalue TEXT set text string for NULL values. Default ''\n"
11719 " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
11720 " -quote set output mode to 'quote'\n"
drhee269a62018-02-14 23:27:43 +000011721 " -readonly open the database read-only\n"
drhb97e2ad2021-08-26 18:31:39 +000011722 " -safe enable safe-mode\n"
drh2ce15c32017-07-11 13:34:40 +000011723 " -separator SEP set output column separator. Default: '|'\n"
drha90d84f2018-04-18 15:21:13 +000011724#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11725 " -sorterref SIZE sorter references threshold size\n"
11726#endif
drh2ce15c32017-07-11 13:34:40 +000011727 " -stats print memory stats before each finalize\n"
drh30c54a02020-05-28 23:49:50 +000011728 " -table set output mode to 'table'\n"
drh2fa78182020-10-31 18:58:37 +000011729 " -tabs set output mode to 'tabs'\n"
drh2ce15c32017-07-11 13:34:40 +000011730 " -version show SQLite version\n"
11731 " -vfs NAME use NAME as the default VFS\n"
11732#ifdef SQLITE_ENABLE_VFSTRACE
11733 " -vfstrace enable tracing of all VFS calls\n"
11734#endif
drh3baed312018-03-08 18:14:41 +000011735#ifdef SQLITE_HAVE_ZLIB
11736 " -zip open the file as a ZIP Archive\n"
11737#endif
drh2ce15c32017-07-11 13:34:40 +000011738;
11739static void usage(int showDetail){
11740 utf8_printf(stderr,
11741 "Usage: %s [OPTIONS] FILENAME [SQL]\n"
11742 "FILENAME is the name of an SQLite database. A new database is created\n"
11743 "if the file does not previously exist.\n", Argv0);
11744 if( showDetail ){
11745 utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
11746 }else{
11747 raw_printf(stderr, "Use the -help option for additional information\n");
11748 }
11749 exit(1);
11750}
11751
11752/*
drhe7df8922018-04-18 10:44:58 +000011753** Internal check: Verify that the SQLite is uninitialized. Print a
11754** error message if it is initialized.
11755*/
11756static void verify_uninitialized(void){
11757 if( sqlite3_config(-1)==SQLITE_MISUSE ){
drh8e02a182018-05-30 07:24:41 +000011758 utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
drhe7df8922018-04-18 10:44:58 +000011759 " initialization.\n");
11760 }
11761}
11762
11763/*
drh2ce15c32017-07-11 13:34:40 +000011764** Initialize the state information in data
11765*/
11766static void main_init(ShellState *data) {
11767 memset(data, 0, sizeof(*data));
11768 data->normalMode = data->cMode = data->mode = MODE_List;
11769 data->autoExplain = 1;
drh37407122021-07-23 18:43:58 +000011770 data->pAuxDb = &data->aAuxDb[0];
drh2ce15c32017-07-11 13:34:40 +000011771 memcpy(data->colSeparator,SEP_Column, 2);
11772 memcpy(data->rowSeparator,SEP_Row, 2);
11773 data->showHeader = 0;
11774 data->shellFlgs = SHFLG_Lookaside;
drhe7df8922018-04-18 10:44:58 +000011775 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000011776 sqlite3_config(SQLITE_CONFIG_URI, 1);
11777 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
11778 sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
11779 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
11780 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
11781}
11782
11783/*
11784** Output text to the console in a font that attracts extra attention.
11785*/
11786#ifdef _WIN32
11787static void printBold(const char *zText){
mistachkin43e86272020-04-09 15:31:22 +000011788#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000011789 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
11790 CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
11791 GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
11792 SetConsoleTextAttribute(out,
11793 FOREGROUND_RED|FOREGROUND_INTENSITY
11794 );
mistachkin43e86272020-04-09 15:31:22 +000011795#endif
drh2ce15c32017-07-11 13:34:40 +000011796 printf("%s", zText);
mistachkin43e86272020-04-09 15:31:22 +000011797#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000011798 SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
mistachkin43e86272020-04-09 15:31:22 +000011799#endif
drh2ce15c32017-07-11 13:34:40 +000011800}
11801#else
11802static void printBold(const char *zText){
11803 printf("\033[1m%s\033[0m", zText);
11804}
11805#endif
11806
11807/*
11808** Get the argument to an --option. Throw an error and die if no argument
11809** is available.
11810*/
11811static char *cmdline_option_value(int argc, char **argv, int i){
11812 if( i==argc ){
11813 utf8_printf(stderr, "%s: Error: missing argument to %s\n",
11814 argv[0], argv[argc-1]);
11815 exit(1);
11816 }
11817 return argv[i];
11818}
11819
11820#ifndef SQLITE_SHELL_IS_UTF8
dan39b6bd52021-03-04 18:31:07 +000011821# if (defined(_WIN32) || defined(WIN32)) \
11822 && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
drh2ce15c32017-07-11 13:34:40 +000011823# define SQLITE_SHELL_IS_UTF8 (0)
11824# else
11825# define SQLITE_SHELL_IS_UTF8 (1)
11826# endif
11827#endif
11828
11829#if SQLITE_SHELL_IS_UTF8
11830int SQLITE_CDECL main(int argc, char **argv){
11831#else
11832int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
11833 char **argv;
11834#endif
11835 char *zErrMsg = 0;
11836 ShellState data;
11837 const char *zInitFile = 0;
11838 int i;
11839 int rc = 0;
11840 int warnInmemoryDb = 0;
11841 int readStdin = 1;
11842 int nCmd = 0;
11843 char **azCmd = 0;
dan16a47422018-04-18 09:16:11 +000011844 const char *zVfs = 0; /* Value of -vfs command-line option */
drh1f22f622018-05-17 13:29:14 +000011845#if !SQLITE_SHELL_IS_UTF8
11846 char **argvToFree = 0;
11847 int argcToFree = 0;
11848#endif
drh2ce15c32017-07-11 13:34:40 +000011849
11850 setBinaryMode(stdin, 0);
11851 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
11852 stdin_is_interactive = isatty(0);
11853 stdout_is_console = isatty(1);
11854
mistachkin1e8487d2018-07-22 06:25:35 +000011855#if !defined(_WIN32_WCE)
11856 if( getenv("SQLITE_DEBUG_BREAK") ){
11857 if( isatty(0) && isatty(2) ){
11858 fprintf(stderr,
11859 "attach debugger to process %d and press any key to continue.\n",
11860 GETPID());
11861 fgetc(stdin);
11862 }else{
11863#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +000011864#if SQLITE_OS_WINRT
11865 __debugbreak();
11866#else
mistachkin1e8487d2018-07-22 06:25:35 +000011867 DebugBreak();
mistachkin43e86272020-04-09 15:31:22 +000011868#endif
mistachkin1e8487d2018-07-22 06:25:35 +000011869#elif defined(SIGTRAP)
11870 raise(SIGTRAP);
11871#endif
11872 }
11873 }
11874#endif
11875
drh2ce15c32017-07-11 13:34:40 +000011876#if USE_SYSTEM_SQLITE+0!=1
drhb3c45232017-08-28 14:33:27 +000011877 if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
drh2ce15c32017-07-11 13:34:40 +000011878 utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
11879 sqlite3_sourceid(), SQLITE_SOURCE_ID);
11880 exit(1);
11881 }
11882#endif
11883 main_init(&data);
drh501ea052018-02-15 01:03:37 +000011884
11885 /* On Windows, we must translate command-line arguments into UTF-8.
11886 ** The SQLite memory allocator subsystem has to be enabled in order to
11887 ** do this. But we want to run an sqlite3_shutdown() afterwards so that
11888 ** subsequent sqlite3_config() calls will work. So copy all results into
11889 ** memory that does not come from the SQLite memory allocator.
11890 */
drh4b18c1d2018-02-04 20:33:13 +000011891#if !SQLITE_SHELL_IS_UTF8
drh501ea052018-02-15 01:03:37 +000011892 sqlite3_initialize();
drh1f22f622018-05-17 13:29:14 +000011893 argvToFree = malloc(sizeof(argv[0])*argc*2);
drhe3e25652021-12-16 13:29:28 +000011894 shell_check_oom(argvToFree);
drh1f22f622018-05-17 13:29:14 +000011895 argcToFree = argc;
11896 argv = argvToFree + argc;
drh2ce15c32017-07-11 13:34:40 +000011897 for(i=0; i<argc; i++){
drh501ea052018-02-15 01:03:37 +000011898 char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
11899 int n;
drhe3e25652021-12-16 13:29:28 +000011900 shell_check_oom(z);
drh501ea052018-02-15 01:03:37 +000011901 n = (int)strlen(z);
11902 argv[i] = malloc( n+1 );
drhe3e25652021-12-16 13:29:28 +000011903 shell_check_oom(argv[i]);
drh501ea052018-02-15 01:03:37 +000011904 memcpy(argv[i], z, n+1);
drh1f22f622018-05-17 13:29:14 +000011905 argvToFree[i] = argv[i];
drh501ea052018-02-15 01:03:37 +000011906 sqlite3_free(z);
drh2ce15c32017-07-11 13:34:40 +000011907 }
drh501ea052018-02-15 01:03:37 +000011908 sqlite3_shutdown();
drh2ce15c32017-07-11 13:34:40 +000011909#endif
drh501ea052018-02-15 01:03:37 +000011910
drh2ce15c32017-07-11 13:34:40 +000011911 assert( argc>=1 && argv && argv[0] );
11912 Argv0 = argv[0];
11913
11914 /* Make sure we have a valid signal handler early, before anything
11915 ** else is done.
11916 */
11917#ifdef SIGINT
11918 signal(SIGINT, interrupt_handler);
mistachkinb4bab902017-10-27 17:09:44 +000011919#elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
11920 SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
drh2ce15c32017-07-11 13:34:40 +000011921#endif
11922
11923#ifdef SQLITE_SHELL_DBNAME_PROC
11924 {
11925 /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
11926 ** of a C-function that will provide the name of the database file. Use
11927 ** this compile-time option to embed this shell program in larger
11928 ** applications. */
11929 extern void SQLITE_SHELL_DBNAME_PROC(const char**);
drh37407122021-07-23 18:43:58 +000011930 SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename);
drh2ce15c32017-07-11 13:34:40 +000011931 warnInmemoryDb = 0;
11932 }
11933#endif
11934
11935 /* Do an initial pass through the command-line argument to locate
11936 ** the name of the database file, the name of the initialization file,
11937 ** the size of the alternative malloc heap,
11938 ** and the first command to execute.
11939 */
drhe7df8922018-04-18 10:44:58 +000011940 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000011941 for(i=1; i<argc; i++){
11942 char *z;
11943 z = argv[i];
11944 if( z[0]!='-' ){
drh37407122021-07-23 18:43:58 +000011945 if( data.aAuxDb->zDbFilename==0 ){
11946 data.aAuxDb->zDbFilename = z;
drh2ce15c32017-07-11 13:34:40 +000011947 }else{
11948 /* Excesss arguments are interpreted as SQL (or dot-commands) and
11949 ** mean that nothing is read from stdin */
11950 readStdin = 0;
11951 nCmd++;
11952 azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
drhe3e25652021-12-16 13:29:28 +000011953 shell_check_oom(azCmd);
drh2ce15c32017-07-11 13:34:40 +000011954 azCmd[nCmd-1] = z;
11955 }
11956 }
11957 if( z[1]=='-' ) z++;
11958 if( strcmp(z,"-separator")==0
11959 || strcmp(z,"-nullvalue")==0
11960 || strcmp(z,"-newline")==0
11961 || strcmp(z,"-cmd")==0
11962 ){
11963 (void)cmdline_option_value(argc, argv, ++i);
11964 }else if( strcmp(z,"-init")==0 ){
11965 zInitFile = cmdline_option_value(argc, argv, ++i);
11966 }else if( strcmp(z,"-batch")==0 ){
11967 /* Need to check for batch mode here to so we can avoid printing
11968 ** informational messages (like from process_sqliterc) before
11969 ** we do the actual processing of arguments later in a second pass.
11970 */
11971 stdin_is_interactive = 0;
11972 }else if( strcmp(z,"-heap")==0 ){
11973#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
11974 const char *zSize;
11975 sqlite3_int64 szHeap;
11976
11977 zSize = cmdline_option_value(argc, argv, ++i);
11978 szHeap = integerValue(zSize);
11979 if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
11980 sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
11981#else
11982 (void)cmdline_option_value(argc, argv, ++i);
11983#endif
drh2ce15c32017-07-11 13:34:40 +000011984 }else if( strcmp(z,"-pagecache")==0 ){
drhf573b4f2020-09-28 13:34:05 +000011985 sqlite3_int64 n, sz;
11986 sz = integerValue(cmdline_option_value(argc,argv,++i));
drh2ce15c32017-07-11 13:34:40 +000011987 if( sz>70000 ) sz = 70000;
11988 if( sz<0 ) sz = 0;
drhf573b4f2020-09-28 13:34:05 +000011989 n = integerValue(cmdline_option_value(argc,argv,++i));
11990 if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
11991 n = 0xffffffffffffLL/sz;
11992 }
drh2ce15c32017-07-11 13:34:40 +000011993 sqlite3_config(SQLITE_CONFIG_PAGECACHE,
11994 (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
11995 data.shellFlgs |= SHFLG_Pagecache;
11996 }else if( strcmp(z,"-lookaside")==0 ){
11997 int n, sz;
11998 sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
11999 if( sz<0 ) sz = 0;
12000 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
12001 if( n<0 ) n = 0;
12002 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
12003 if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
drhaf6d1af2021-08-09 17:37:58 +000012004 }else if( strcmp(z,"-threadsafe")==0 ){
drh9d16fb12021-08-09 17:45:00 +000012005 int n;
12006 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
12007 switch( n ){
drhaf6d1af2021-08-09 17:37:58 +000012008 case 0: sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); break;
12009 case 2: sqlite3_config(SQLITE_CONFIG_MULTITHREAD); break;
12010 default: sqlite3_config(SQLITE_CONFIG_SERIALIZED); break;
12011 }
drh2ce15c32017-07-11 13:34:40 +000012012#ifdef SQLITE_ENABLE_VFSTRACE
12013 }else if( strcmp(z,"-vfstrace")==0 ){
12014 extern int vfstrace_register(
12015 const char *zTraceName,
12016 const char *zOldVfsName,
12017 int (*xOut)(const char*,void*),
12018 void *pOutArg,
12019 int makeDefault
12020 );
12021 vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
12022#endif
12023#ifdef SQLITE_ENABLE_MULTIPLEX
12024 }else if( strcmp(z,"-multiplex")==0 ){
12025 extern int sqlite3_multiple_initialize(const char*,int);
12026 sqlite3_multiplex_initialize(0, 1);
12027#endif
12028 }else if( strcmp(z,"-mmap")==0 ){
12029 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
12030 sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
drha90d84f2018-04-18 15:21:13 +000012031#ifdef SQLITE_ENABLE_SORTER_REFERENCES
12032 }else if( strcmp(z,"-sorterref")==0 ){
12033 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
12034 sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz);
12035#endif
drh2ce15c32017-07-11 13:34:40 +000012036 }else if( strcmp(z,"-vfs")==0 ){
dan16a47422018-04-18 09:16:11 +000012037 zVfs = cmdline_option_value(argc, argv, ++i);
drh3baed312018-03-08 18:14:41 +000012038#ifdef SQLITE_HAVE_ZLIB
drh8682e122018-01-07 20:38:10 +000012039 }else if( strcmp(z,"-zip")==0 ){
12040 data.openMode = SHELL_OPEN_ZIPFILE;
12041#endif
12042 }else if( strcmp(z,"-append")==0 ){
12043 data.openMode = SHELL_OPEN_APPENDVFS;
drh8d889af2021-05-08 17:18:23 +000012044#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +000012045 }else if( strcmp(z,"-deserialize")==0 ){
12046 data.openMode = SHELL_OPEN_DESERIALIZE;
drh6ca64482019-01-22 16:06:20 +000012047 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
12048 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000012049#endif
drhee269a62018-02-14 23:27:43 +000012050 }else if( strcmp(z,"-readonly")==0 ){
12051 data.openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +000012052 }else if( strcmp(z,"-nofollow")==0 ){
12053 data.openFlags = SQLITE_OPEN_NOFOLLOW;
drhda57d962018-03-05 19:34:05 +000012054#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drh93b77312018-03-05 20:20:22 +000012055 }else if( strncmp(z, "-A",2)==0 ){
drhda57d962018-03-05 19:34:05 +000012056 /* All remaining command-line arguments are passed to the ".archive"
12057 ** command, so ignore them */
12058 break;
12059#endif
drh50b910a2019-01-21 14:55:03 +000012060 }else if( strcmp(z, "-memtrace")==0 ){
12061 sqlite3MemTraceActivate(stderr);
drhb7c46aa2020-11-25 13:59:47 +000012062 }else if( strcmp(z,"-bail")==0 ){
12063 bail_on_error = 1;
drhb97e2ad2021-08-26 18:31:39 +000012064 }else if( strcmp(z,"-nonce")==0 ){
12065 free(data.zNonce);
12066 data.zNonce = strdup(argv[++i]);
12067 }else if( strcmp(z,"-safe")==0 ){
12068 /* no-op - catch this on the second pass */
drh2ce15c32017-07-11 13:34:40 +000012069 }
12070 }
drhe7df8922018-04-18 10:44:58 +000012071 verify_uninitialized();
12072
dan16a47422018-04-18 09:16:11 +000012073
drhd11b8f62018-04-25 13:27:07 +000012074#ifdef SQLITE_SHELL_INIT_PROC
12075 {
12076 /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name
12077 ** of a C-function that will perform initialization actions on SQLite that
12078 ** occur just before or after sqlite3_initialize(). Use this compile-time
12079 ** option to embed this shell program in larger applications. */
12080 extern void SQLITE_SHELL_INIT_PROC(void);
12081 SQLITE_SHELL_INIT_PROC();
12082 }
12083#else
dan16a47422018-04-18 09:16:11 +000012084 /* All the sqlite3_config() calls have now been made. So it is safe
12085 ** to call sqlite3_initialize() and process any command line -vfs option. */
12086 sqlite3_initialize();
drhd11b8f62018-04-25 13:27:07 +000012087#endif
12088
dan16a47422018-04-18 09:16:11 +000012089 if( zVfs ){
12090 sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
12091 if( pVfs ){
12092 sqlite3_vfs_register(pVfs, 1);
12093 }else{
12094 utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
12095 exit(1);
12096 }
12097 }
12098
drh37407122021-07-23 18:43:58 +000012099 if( data.pAuxDb->zDbFilename==0 ){
drh2ce15c32017-07-11 13:34:40 +000012100#ifndef SQLITE_OMIT_MEMORYDB
drh37407122021-07-23 18:43:58 +000012101 data.pAuxDb->zDbFilename = ":memory:";
drh2ce15c32017-07-11 13:34:40 +000012102 warnInmemoryDb = argc==1;
12103#else
12104 utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
12105 return 1;
12106#endif
12107 }
12108 data.out = stdout;
drh8682e122018-01-07 20:38:10 +000012109 sqlite3_appendvfs_init(0,0,0);
drh2ce15c32017-07-11 13:34:40 +000012110
12111 /* Go ahead and open the database file if it already exists. If the
12112 ** file does not exist, delay opening it. This prevents empty database
12113 ** files from being created if a user mistypes the database name argument
12114 ** to the sqlite command-line tool.
12115 */
drh37407122021-07-23 18:43:58 +000012116 if( access(data.pAuxDb->zDbFilename, 0)==0 ){
drh2ce15c32017-07-11 13:34:40 +000012117 open_db(&data, 0);
12118 }
12119
12120 /* Process the initialization file if there is one. If no -init option
12121 ** is given on the command line, look for a file named ~/.sqliterc and
12122 ** try to process it.
12123 */
12124 process_sqliterc(&data,zInitFile);
12125
12126 /* Make a second pass through the command-line argument and set
12127 ** options. This second pass is delayed until after the initialization
12128 ** file is processed so that the command-line arguments will override
12129 ** settings in the initialization file.
12130 */
12131 for(i=1; i<argc; i++){
12132 char *z = argv[i];
12133 if( z[0]!='-' ) continue;
12134 if( z[1]=='-' ){ z++; }
12135 if( strcmp(z,"-init")==0 ){
12136 i++;
12137 }else if( strcmp(z,"-html")==0 ){
12138 data.mode = MODE_Html;
12139 }else if( strcmp(z,"-list")==0 ){
12140 data.mode = MODE_List;
12141 }else if( strcmp(z,"-quote")==0 ){
12142 data.mode = MODE_Quote;
drh9191c702020-08-17 09:11:21 +000012143 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma);
12144 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +000012145 }else if( strcmp(z,"-line")==0 ){
12146 data.mode = MODE_Line;
12147 }else if( strcmp(z,"-column")==0 ){
12148 data.mode = MODE_Column;
drh30c54a02020-05-28 23:49:50 +000012149 }else if( strcmp(z,"-json")==0 ){
12150 data.mode = MODE_Json;
12151 }else if( strcmp(z,"-markdown")==0 ){
12152 data.mode = MODE_Markdown;
12153 }else if( strcmp(z,"-table")==0 ){
12154 data.mode = MODE_Table;
drh0908e382020-06-04 18:05:39 +000012155 }else if( strcmp(z,"-box")==0 ){
12156 data.mode = MODE_Box;
drh2ce15c32017-07-11 13:34:40 +000012157 }else if( strcmp(z,"-csv")==0 ){
12158 data.mode = MODE_Csv;
12159 memcpy(data.colSeparator,",",2);
drh3baed312018-03-08 18:14:41 +000012160#ifdef SQLITE_HAVE_ZLIB
drh1fa6d9f2018-01-06 21:46:01 +000012161 }else if( strcmp(z,"-zip")==0 ){
12162 data.openMode = SHELL_OPEN_ZIPFILE;
12163#endif
12164 }else if( strcmp(z,"-append")==0 ){
12165 data.openMode = SHELL_OPEN_APPENDVFS;
drh8d889af2021-05-08 17:18:23 +000012166#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +000012167 }else if( strcmp(z,"-deserialize")==0 ){
12168 data.openMode = SHELL_OPEN_DESERIALIZE;
drh6ca64482019-01-22 16:06:20 +000012169 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
12170 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000012171#endif
drh4aafe592018-03-23 16:08:30 +000012172 }else if( strcmp(z,"-readonly")==0 ){
12173 data.openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +000012174 }else if( strcmp(z,"-nofollow")==0 ){
12175 data.openFlags |= SQLITE_OPEN_NOFOLLOW;
drh2ce15c32017-07-11 13:34:40 +000012176 }else if( strcmp(z,"-ascii")==0 ){
12177 data.mode = MODE_Ascii;
drh2fa78182020-10-31 18:58:37 +000012178 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit);
12179 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record);
12180 }else if( strcmp(z,"-tabs")==0 ){
12181 data.mode = MODE_List;
12182 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Tab);
12183 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +000012184 }else if( strcmp(z,"-separator")==0 ){
12185 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
12186 "%s",cmdline_option_value(argc,argv,++i));
12187 }else if( strcmp(z,"-newline")==0 ){
12188 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
12189 "%s",cmdline_option_value(argc,argv,++i));
12190 }else if( strcmp(z,"-nullvalue")==0 ){
12191 sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
12192 "%s",cmdline_option_value(argc,argv,++i));
12193 }else if( strcmp(z,"-header")==0 ){
12194 data.showHeader = 1;
larrybrae509122021-09-10 01:45:20 +000012195 ShellSetFlag(&data, SHFLG_HeaderSet);
12196 }else if( strcmp(z,"-noheader")==0 ){
drh2ce15c32017-07-11 13:34:40 +000012197 data.showHeader = 0;
larrybrae509122021-09-10 01:45:20 +000012198 ShellSetFlag(&data, SHFLG_HeaderSet);
drh2ce15c32017-07-11 13:34:40 +000012199 }else if( strcmp(z,"-echo")==0 ){
12200 ShellSetFlag(&data, SHFLG_Echo);
12201 }else if( strcmp(z,"-eqp")==0 ){
drhada70452017-12-21 21:02:27 +000012202 data.autoEQP = AUTOEQP_on;
drh2ce15c32017-07-11 13:34:40 +000012203 }else if( strcmp(z,"-eqpfull")==0 ){
drhada70452017-12-21 21:02:27 +000012204 data.autoEQP = AUTOEQP_full;
drh2ce15c32017-07-11 13:34:40 +000012205 }else if( strcmp(z,"-stats")==0 ){
12206 data.statsOn = 1;
12207 }else if( strcmp(z,"-scanstats")==0 ){
12208 data.scanstatsOn = 1;
12209 }else if( strcmp(z,"-backslash")==0 ){
12210 /* Undocumented command-line option: -backslash
12211 ** Causes C-style backslash escapes to be evaluated in SQL statements
12212 ** prior to sending the SQL into SQLite. Useful for injecting
12213 ** crazy bytes in the middle of SQL statements for testing and debugging.
12214 */
12215 ShellSetFlag(&data, SHFLG_Backslash);
12216 }else if( strcmp(z,"-bail")==0 ){
drhb7c46aa2020-11-25 13:59:47 +000012217 /* No-op. The bail_on_error flag should already be set. */
drh2ce15c32017-07-11 13:34:40 +000012218 }else if( strcmp(z,"-version")==0 ){
12219 printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
12220 return 0;
12221 }else if( strcmp(z,"-interactive")==0 ){
12222 stdin_is_interactive = 1;
12223 }else if( strcmp(z,"-batch")==0 ){
12224 stdin_is_interactive = 0;
12225 }else if( strcmp(z,"-heap")==0 ){
12226 i++;
drh2ce15c32017-07-11 13:34:40 +000012227 }else if( strcmp(z,"-pagecache")==0 ){
12228 i+=2;
12229 }else if( strcmp(z,"-lookaside")==0 ){
12230 i+=2;
drhaf6d1af2021-08-09 17:37:58 +000012231 }else if( strcmp(z,"-threadsafe")==0 ){
12232 i+=2;
drhb97e2ad2021-08-26 18:31:39 +000012233 }else if( strcmp(z,"-nonce")==0 ){
12234 i += 2;
drh2ce15c32017-07-11 13:34:40 +000012235 }else if( strcmp(z,"-mmap")==0 ){
12236 i++;
drh50b910a2019-01-21 14:55:03 +000012237 }else if( strcmp(z,"-memtrace")==0 ){
12238 i++;
drha90d84f2018-04-18 15:21:13 +000012239#ifdef SQLITE_ENABLE_SORTER_REFERENCES
12240 }else if( strcmp(z,"-sorterref")==0 ){
12241 i++;
12242#endif
drh2ce15c32017-07-11 13:34:40 +000012243 }else if( strcmp(z,"-vfs")==0 ){
12244 i++;
12245#ifdef SQLITE_ENABLE_VFSTRACE
12246 }else if( strcmp(z,"-vfstrace")==0 ){
12247 i++;
12248#endif
12249#ifdef SQLITE_ENABLE_MULTIPLEX
12250 }else if( strcmp(z,"-multiplex")==0 ){
12251 i++;
12252#endif
12253 }else if( strcmp(z,"-help")==0 ){
12254 usage(1);
12255 }else if( strcmp(z,"-cmd")==0 ){
12256 /* Run commands that follow -cmd first and separately from commands
12257 ** that simply appear on the command-line. This seems goofy. It would
12258 ** be better if all commands ran in the order that they appear. But
12259 ** we retain the goofy behavior for historical compatibility. */
12260 if( i==argc-1 ) break;
12261 z = cmdline_option_value(argc,argv,++i);
12262 if( z[0]=='.' ){
12263 rc = do_meta_command(z, &data);
12264 if( rc && bail_on_error ) return rc==2 ? 0 : rc;
12265 }else{
12266 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000012267 rc = shell_exec(&data, z, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000012268 if( zErrMsg!=0 ){
12269 utf8_printf(stderr,"Error: %s\n", zErrMsg);
12270 if( bail_on_error ) return rc!=0 ? rc : 1;
12271 }else if( rc!=0 ){
12272 utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
12273 if( bail_on_error ) return rc;
12274 }
12275 }
drhda57d962018-03-05 19:34:05 +000012276#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drh93b77312018-03-05 20:20:22 +000012277 }else if( strncmp(z, "-A", 2)==0 ){
drhda57d962018-03-05 19:34:05 +000012278 if( nCmd>0 ){
12279 utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
12280 " with \"%s\"\n", z);
12281 return 1;
12282 }
drhbe4ccb22018-05-17 20:04:24 +000012283 open_db(&data, OPEN_DB_ZIPFILE);
drh93b77312018-03-05 20:20:22 +000012284 if( z[2] ){
12285 argv[i] = &z[2];
drhd0f9cdc2018-05-17 14:09:06 +000012286 arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
drh93b77312018-03-05 20:20:22 +000012287 }else{
drhd0f9cdc2018-05-17 14:09:06 +000012288 arDotCommand(&data, 1, argv+i, argc-i);
drh93b77312018-03-05 20:20:22 +000012289 }
drhda57d962018-03-05 19:34:05 +000012290 readStdin = 0;
12291 break;
12292#endif
drhb97e2ad2021-08-26 18:31:39 +000012293 }else if( strcmp(z,"-safe")==0 ){
12294 data.bSafeMode = data.bSafeModePersist = 1;
drh2ce15c32017-07-11 13:34:40 +000012295 }else{
12296 utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
12297 raw_printf(stderr,"Use -help for a list of options.\n");
12298 return 1;
12299 }
12300 data.cMode = data.mode;
12301 }
12302
12303 if( !readStdin ){
12304 /* Run all arguments that do not begin with '-' as if they were separate
12305 ** command-line inputs, except for the argToSkip argument which contains
12306 ** the database filename.
12307 */
12308 for(i=0; i<nCmd; i++){
12309 if( azCmd[i][0]=='.' ){
12310 rc = do_meta_command(azCmd[i], &data);
danaff1a572020-11-17 21:09:56 +000012311 if( rc ){
12312 free(azCmd);
12313 return rc==2 ? 0 : rc;
12314 }
drh2ce15c32017-07-11 13:34:40 +000012315 }else{
12316 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000012317 rc = shell_exec(&data, azCmd[i], &zErrMsg);
danaff1a572020-11-17 21:09:56 +000012318 if( zErrMsg || rc ){
12319 if( zErrMsg!=0 ){
12320 utf8_printf(stderr,"Error: %s\n", zErrMsg);
12321 }else{
12322 utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
12323 }
12324 sqlite3_free(zErrMsg);
12325 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000012326 return rc!=0 ? rc : 1;
drh2ce15c32017-07-11 13:34:40 +000012327 }
12328 }
12329 }
drh2ce15c32017-07-11 13:34:40 +000012330 }else{
12331 /* Run commands received from standard input
12332 */
12333 if( stdin_is_interactive ){
12334 char *zHome;
drha9e4be32018-10-10 18:56:40 +000012335 char *zHistory;
drh2ce15c32017-07-11 13:34:40 +000012336 int nHistory;
12337 printf(
12338 "SQLite version %s %.19s\n" /*extra-version-info*/
12339 "Enter \".help\" for usage hints.\n",
12340 sqlite3_libversion(), sqlite3_sourceid()
12341 );
12342 if( warnInmemoryDb ){
12343 printf("Connected to a ");
12344 printBold("transient in-memory database");
12345 printf(".\nUse \".open FILENAME\" to reopen on a "
12346 "persistent database.\n");
12347 }
drha9e4be32018-10-10 18:56:40 +000012348 zHistory = getenv("SQLITE_HISTORY");
12349 if( zHistory ){
12350 zHistory = strdup(zHistory);
12351 }else if( (zHome = find_home_dir(0))!=0 ){
drh2ce15c32017-07-11 13:34:40 +000012352 nHistory = strlen30(zHome) + 20;
12353 if( (zHistory = malloc(nHistory))!=0 ){
12354 sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
12355 }
12356 }
12357 if( zHistory ){ shell_read_history(zHistory); }
drh56eb09b2017-07-11 13:59:07 +000012358#if HAVE_READLINE || HAVE_EDITLINE
12359 rl_attempted_completion_function = readline_completion;
12360#elif HAVE_LINENOISE
12361 linenoiseSetCompletionCallback(linenoise_completion);
12362#endif
drh60379d42018-12-13 18:30:01 +000012363 data.in = 0;
12364 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000012365 if( zHistory ){
drh5a75dd82017-07-18 20:59:40 +000012366 shell_stifle_history(2000);
drh2ce15c32017-07-11 13:34:40 +000012367 shell_write_history(zHistory);
12368 free(zHistory);
12369 }
12370 }else{
drh60379d42018-12-13 18:30:01 +000012371 data.in = stdin;
12372 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000012373 }
12374 }
danaff1a572020-11-17 21:09:56 +000012375 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000012376 set_table_name(&data, 0);
12377 if( data.db ){
drh37407122021-07-23 18:43:58 +000012378 session_close_all(&data, -1);
drh9e804032018-05-18 17:11:50 +000012379 close_db(data.db);
drh2ce15c32017-07-11 13:34:40 +000012380 }
drh37407122021-07-23 18:43:58 +000012381 for(i=0; i<ArraySize(data.aAuxDb); i++){
12382 sqlite3_free(data.aAuxDb[i].zFreeOnClose);
12383 if( data.aAuxDb[i].db ){
12384 session_close_all(&data, i);
12385 close_db(data.aAuxDb[i].db);
12386 }
12387 }
drh2ce15c32017-07-11 13:34:40 +000012388 find_home_dir(1);
drh536c3452018-01-11 00:38:39 +000012389 output_reset(&data);
12390 data.doXdgOpen = 0;
drh13c20932018-01-10 21:41:55 +000012391 clearTempFile(&data);
drh2ce15c32017-07-11 13:34:40 +000012392#if !SQLITE_SHELL_IS_UTF8
drh1f22f622018-05-17 13:29:14 +000012393 for(i=0; i<argcToFree; i++) free(argvToFree[i]);
12394 free(argvToFree);
drh2ce15c32017-07-11 13:34:40 +000012395#endif
drh0285d982020-05-29 14:38:43 +000012396 free(data.colWidth);
drhb97e2ad2021-08-26 18:31:39 +000012397 free(data.zNonce);
drh9e804032018-05-18 17:11:50 +000012398 /* Clear the global data structure so that valgrind will detect memory
12399 ** leaks */
12400 memset(&data, 0, sizeof(data));
drh2ce15c32017-07-11 13:34:40 +000012401 return rc;
12402}